About Namespace Hierarchies
Very often, when I'm on projects, I get asked about how namespace hierarchies should be structured. There isn't much literature available about it. So here goes:
Just Be Consistent
Of course there are several approaches to structuring namespaces, and I think there is no "Single Right Choice" that fits all. So you'll have to choose between alternatives. That is no problem, as long as you're consistent. The choice of namespace hierarchy type is one that will probably have to apply to all your company's projects.
Here are a few proposals for namespace hierarchies, or Namespace Patterns if you will. Pick your favorite. It is assumed that you're writing a client/server application in these cases. For other types of applications, other patterns may apply.
Let me illustrate by an example. Let's assume that your application, called ApplicationX, consists of the following layers:
- Web UI + Windows UI Layer
- Service Layer (Façade)
- Business Layer
- Data Access + Service Agents Layer
Besides these layers, there are typed DataSets and other objects that are common across the layers, so you could say there is a "vertical layer", a Common block.
Then the basic namespaces could look like so (of course the idea is to use the pattern as a starting point, and then extend it with the needs of your own organization and your application(s)):
Pattern #1: Layer-First
The Layer-First namespace pattern structures its hierarchy based on layers. The pattern is as follows:
Company name.Application name.Layer.Subsystem.Class
Example
CompanyX.ApplicationX.
- Web
- UI: contains the Web UI elements
- Security: dealing with Web-based security
- Windows
- UI: contains Windows UI elements (WinForms forms and controls)
- Security: dealing with Windows client-based security
- Services: contains Windows Services (previously known as NT Services)
- Services
- Entity classes (web services or Remoted objects) for the Service/Façade layer (for example, Orders, Invoices, Personnel)
- Security: dealing with service-layer security (auth&auth of requests, matching roles etc.)
- Business
- Entity classes for the Business layer
- DataAccess
- Entity classes for the Data Access sublayer
- ServiceAgents
- Entity classes for the Service Agents sublayer
- Common: Classes in the Common block; i.e. that must be accessible to all layers (such as DataSets etc.)
- Data: Common DataSets, data transfer objects
So, there would be a Web page called CompanyX.ApplicationX.Web.UI.Default, and a Web service called CompanyX.ApplicationX.Services.Orders as well as a business class CompanyX.ApplicationX.Business.Orders and a data access class CompanyX.ApplicationX.DataAccess.Orders, for example.
The hierarchy above is a good pattern, or template, if you want to group classes by layer.
Pattern #2: Subsystem-First
The Subsystem-First namespace pattern structures its hierarchy based on subsystems. The pattern is as follows:
Company name.Application name.Subsystem.Layer.Class
Example
CompanyX.ApplicationX.
- Web
- UI: contains the Web UI elements
- Security: dealing with Web-based security
- Windows
- UI: contains Windows UI elements (WinForms forms and controls)
- Security: dealing with Windows client-based security
- Services: contains Windows Services (previously known as NT Services)
- Security: contains classes that implement security on the Service/Façade layer
- Entity Name (such as Orders, Invoices, Personnel)
- Service: entity class for the Service/Façade layer
- Business: entity class(es) for the Business layer
- DataAccess: entity class(es) for the Data Access sublayer
- ServiceAgents: entity class(es) for the Service Agents sublayer
- Common: Classes in the Common block
- Data: Common DataSets, data transfer objects
So using this pattern, you would have a Web page called CompanyX.ApplicationX.Web.UI.Default (that doesn't change), and a Web service called CompanyX.ApplicationX.Orders.Service as well as a business class CompanyX.ApplicationX.Orders.Business and a data access class CompanyX.ApplicationX.Orders.DataAccess, for instance, or even a class CompanyX.ApplicationX.Orders.DataAccess.SqlServer and another one called CompanyX.ApplicationX.Orders.DataAccess.Oracle.
What is important among both patterns is that there is a clear separation between the layers. It is a good practice to map the layer structure onto the namespace structure. I've seen namespace designs where the data access layer is hierarchically under the business layer, so there would be a data access class called CompanyX.ApplicationX.Business.Orders.DataAccess, for instance. This is clearly bad as it is a logical mix of layers. It's almost like pouring Coca-Cola on your fries. They're good together, but should't be mixed on your plate...
OK, so what about Exceptions and Interfaces?
Another common question is where to put Exceptions, and where to put Interfaces. Many companies adopt the practice of putting exceptions in a separate Exceptions namespace, and Interfaces in their own Interface namespace. I don't think this is necessary. I think it's best to put either just where they belong. For example, an Exception that gets thrown by classes in the Business layer should itself be in the CompanyX.ApplicationX.Business namespace. In the same line of thinking, an Interface for data access classes should be defined in the CompanyX.ApplicationX.DataAccess namespace. It is then defined where it is used, just like the exceptions. This is also the way the .Net Framework places Exceptions and Interfaces in its hierarchy. I usually find that a good guideline: what does the .Net Framework do?
However, there are cases where it is not so obvious as in these examples. You may have Interfaces defined in the Service/Façade layer that must also be used on a disconnected (smart) client. That client is deployed independently of the Service layer, and so it must get its own copy of the Interfaces that the Service layer offers.
Make it Public
In that case, what you could do is create a CompanyX.ApplicationX.Public namespace that contains all elements that must be shared by the UI and Service/Façade layers. All elements (Exceptions, Interfaces, data transfer objects even maybe, if they need to be deployed all the way to the UI) are referenced and deployed in UI and Service/Façade projects. Of course it is important then that there are little changes to the classes in this namespace, or at least that the UI and Service projects are kept in sync.
Application Blocks
When designing your namespaces, you may run into cases where your team is going to write code for your app, when in fact that code is very likely to be reused. Examples are Web controls, Helper classes etc. A good idea then is to define separate projects for this reusable code, and to create Application Blocks for them. You may have a set of Helper classes, for example, say FileHelper, DirectoryHelper and StreamHelper. You could create a library called the File Handling Application Block and put the classes in there. The Application Block would get its own project, be deployed on all developer workstations and be referenced by all projects that need it, just like the Microsoft Application Blocks.
Of course, the namespace hierarchy would reflect the reusability of the code. You can tell that the CompanyX.ApplicationBlocks.FileHandling.FileHelper class isn't part of the CompanyX.ApplicationX project, and it keeps ApplicationX's namespace hierarchy cleaner.
What about Solution structure?
So, does all this namespace structuring affect how we structure Solutions? You better believe it.
I think a Visual Studio.Net Solution should mimic the namespace hierarchy as much as possible. So, if at all doable, I think there should be one project per namespace, that gets the name of that namespace. So CompanyX.ApplicationX.Web.UI.WebControls is a project name and a namespace name, for example. Pages in CompanyX.ApplicationX.Web.UI.Pages can be found in another project. And if you're looking for code in the CompanyX.ApplicationX.DataAccess namespace, you know in which project to look.
Project names and file system hierarchy
I guess the next question is then how to name project folders. Should the Orders data access class be found in the CompanyX.ApplicationX.DataAccess\bin folder or in ApplicationX\DataAccess\bin, or somewhere else?
I guess it doesn't matter much, as long as you're consistent. I prefer the first approach; it lists all your projects nicely in your Solution, and you don't have to dig three levels deep to find the implementation of a data access class. But that's a matter of personal preference, I guess. Maybe you have a different view on things, and for good reason--if so, please let's hear them!
Feedback is always welcome! You can leave your comments right here.