Your concern is correct. Typically, packages are named by either inclusion or inheritance. I'm going to make up a more realistic example. Let's say we are building an online shop.
Inclusion
You first pick a namespace for your project. In the business world, you often see namespaces with the company name first, to distinguish proprietary modules from CPAN ones. So the project's namespace could be:
OurCompany::Shop
Then probably the main class or module for the application is called the same, so we have a
OurCompany/Shop.pm
We will have a bunch of things that we need to make an online shop. If our project is MCV, there are controllers and models and stuff like that. So we might have these things:
OurCompany::Shop::Controller::ProductSearch
OurCompany::Shop::Controller::Cart
OurCompany::Shop::Controller::Checkout
OurCompany::Shop::Model::Database
All of those map to modules direcly.
OurCompany/Shop/Controller/ProductSearch.pm
OurCompany/Shop/Controller/Cart.pm
OurCompany/Shop/Controller/Checkout.pm
OurCompany/Shop/Model/Database.pm
But there is no OurCompany::Controller as a base class. That name is just a namespace to sort things into.
Then there are some things that are just there, and get used by OurCompany::Shop, like the Session engine.
OurCompany::Shop::Session
Those go on the first level after the project, unless they are very specific.
Now of course there is some kind of engine behind the session system. Let's say we are fancy and use Redis for our sessions. If we implement the communication ourselves (which we wouldn't because CPAN has done that already), we would stick that implementation into
OurCompany::Shop::Session::Engine::Redis
The only thing that uses this module is OurCompany::Shop::Session under the hood. The main application doesn't even know what engine is used. Maybe you don't have Redis on your development machine, so you are using plain files.
OurCompany::Shop::Session::Engine::File
Both of them are there, they belong to ::Session, but they don't get used by any other part of the system, so we file them away where they belong to.
Inheritance
We will also have Products1. The base product class could be this.
OurCompany::Shop::Product
And there is a file for it.
OurCompany/Shop/Product.pm
Just that this base product never gets used directly by the shop, other than checking that certain things have to have ::Product in their inheritance tree (that's an isa check). So this is different from ::Session, which gets used directly.
But of course we sell different things, and they have different properties. All of them have prices, but shoes have sizes and hard drives have a capacity. So we create subclasses.
OurCompany::Shop::Product::Shoe
OurCompany::Shop::Product::HardDrive
And those have their own files.
OurCompany/Shop/Product/Shoe.pm
OurCompany/Shop/Product/HardDrive.pm
We might also distinguish between a mechanical HardDrive and an SSD, so we make an ::SSD subclass.
OurCompany::Shop::Product::HardDrive::SSD
OurCompany/Shop/Product/HardDrive/SSD.pm
So basically things are put in the same namespace if they belong to each other. Here's a tree view of our lib.
.
└── OurCompany
├── Shop
│ ├── Controller
│ │ ├── Cart.pm
│ │ ├── Checkout.pm
│ │ └── ProductSearch.pm
│ ├── Model
│ │ └── Database.pm
│ ├── Product
│ │ ├── HardDrive
│ │ │ └── SSD.pm
│ │ ├── HardDrive.pm
│ │ └── Shoe.pm
| ├── Product.pm
│ └── Session.pm
│ │ └── Engine.pm
│ │ ├── File.pm
│ │ └── Redis.pm
└── Shop.pm
To sum up:
- For your main module, the file name is the last part of the project's package name. Everything else goes under there.
- Stuff that belongs together gets grouped under one namespace.
- Stuff that inherits from something goes under that something's namespace.
- Stuff that only gets used by one specific thing goes under that thing.
Never append things together like MyProject::AB to indicate that it belongs to MyProject::A. Always use namespace separators to organize your namespaces. Consider this, which looks just plain wrong:
OurCompany::ShopProductShoe
1) It might be that we also have a backoffice application that also uses the same product classes. In that case, we might have them as OurCompany::Product, and they get used by two different projects, OurCompany::Shop and OurCompany::BackOffice.