Confuddled Colleagues
This follows on from my previous post on nTier. This was originally part of my first article, though it all became a bit lengthy - mainly due to the fact I ramble on like a 90 year old war veteran. I would highly recommend checking out my previous post before reading this one.
An issue that tends to confuse some developers is the difference between namespaces and assemblies and where each of the layers in an nTier architecture belong in your code repository. When I write code, I always try to make an early decision what other uses it has and its purpose, and place it in the relevant namespace / assembly within my repository.
Namespaces provide a convenient way to store and group your custom types. They are a hierarchical method of grouping types in your repository and the same namespace (or sub-trees of that namespace) can reside in more than one assembly.
Assemblies, on the other hand, are physical files that can be included in your projects. The main benefit to using separate assemblies is to minimize the size of a project or solution, whilst gaining maximum code re-usage.
Assemblies can of course be registered in the Global Assembly Cache (GAC) too. The GAC is a repository of compiled .Net assemblies that are available to the .Net Framework. All of the core .Net assemblies are located in here. I have found very little use in deploying custom assemblies to it over the years, though I imagine it would be very handy for development teams that have strict practices and use a common set of custom assemblies (that do not change often).
If your namespaces and assemblies are organised correctly you should have a nice efficient code repository, which can, in time, dramatically speed up development and minimize the amount of code included in projects that isn't used.
nTier, Namespaces and Assemblies.
While your Data Access Layer (DAL) and other generic objects should be placed in root namespaces 99% of the time, your Business Logic Layer (BLL) and Presentation Layer (PL) should be placed in namespaces that relate to how your products are sold. Different companies have different corporate aims - for example, if working for a digital design agency who write bespoke websites for multiple clients, each BLL and PL may be completely bespoke, while using the generic DAL:
Data Access Layer - [MyCompany].Core.Data
Business Logic Layer - [MyCompany].Clients.[Client].[AppName].Business
Presentation Layer - [MyCompany].Clients.[Client].[AppName].Presentation
Here we see three different namespaces in three different assemblies. This structure gives you a very robust way to store your custom built objects - you can cater for multiple clients, and multiple applications per client.
The next example is based on, say, an in-house development team where there are no external clients to cater for - all applications are developed for "MyCompany". You will notice that the DAL is named exactly the same.
Data Access Layer - [MyCompany].Core.Data
Business Logic Layer - [MyCompany].Apps.[AppName].Business
Presentation Layer - [MyCompany].Apps.[AppName].Presentation
Again, we see three different namespaces all in their own assembly.
This example could be extended further to include [Department], much like the digital design agency example above for [Client], though I have not come across the need for this kind of separation at the time of writing, nor do I imagine a development team would give two applications in different departments the same name. I suppose there could be two versions of the same application being developed separately for different departments... though it would be a logistical nightmare to maintain!
I also tend to develop a few additional assemblies as well:
[MyCompany].Core.Windows
[MyCompany].Core.Windows.Services
[MyCompany].Core.Web
They are all in the [MyCompany].Core namespace, but are compiled independently of each other in separate assemblies. The reason for this is that while they contain generic, core functionality (like user controls, extension methods, helper classes etc), they are specific to a type of project. We would have no use for the code in [MyCompany].Core.Windows in a web application, for example, and therefore including it in a web project would be pointless.
So, you've seen examples of using the same root namespace over different assemblies. There may also be times when you might want to create two types in the same namespace, but in different assemblies. Say, for example, a client has asked you to develop a number of websites dedicated to animals - each website is dedicated to an individual animal. You create an assembly with a root namespace of MyCompany.Clients.MyClient.Animals. The assembly contains both a "Dog" type and a "Cat" type. Because you have no need for a "Dog" type when developing the "Cat" website, you may want to separate the two classes in to two different assemblies, but keep them in the same namespace. The types would be organised as follows:
MyCompany.Clients.MyClient.Animals.Dog - Assembly1
MyCompany.Clients.MyClient.Animals.Cat - Assembly2
Each type would be compiled in to a separate assembly in order to reduce the project footprint. This is entirely possible, though rarely done in practice.
And so my rambling ends. This post was just intended as a brief summary (and a reference for myself when working remotely) of namespaces and assemblies - it's by no means an official pattern or practice, but it tends to serve me well when designing solutions.
An issue that tends to confuse some developers is the difference between namespaces and assemblies and where each of the layers in an nTier architecture belong in your code repository. When I write code, I always try to make an early decision what other uses it has and its purpose, and place it in the relevant namespace / assembly within my repository.
Namespaces provide a convenient way to store and group your custom types. They are a hierarchical method of grouping types in your repository and the same namespace (or sub-trees of that namespace) can reside in more than one assembly.
Assemblies, on the other hand, are physical files that can be included in your projects. The main benefit to using separate assemblies is to minimize the size of a project or solution, whilst gaining maximum code re-usage.
Assemblies can of course be registered in the Global Assembly Cache (GAC) too. The GAC is a repository of compiled .Net assemblies that are available to the .Net Framework. All of the core .Net assemblies are located in here. I have found very little use in deploying custom assemblies to it over the years, though I imagine it would be very handy for development teams that have strict practices and use a common set of custom assemblies (that do not change often).
If your namespaces and assemblies are organised correctly you should have a nice efficient code repository, which can, in time, dramatically speed up development and minimize the amount of code included in projects that isn't used.
nTier, Namespaces and Assemblies.
While your Data Access Layer (DAL) and other generic objects should be placed in root namespaces 99% of the time, your Business Logic Layer (BLL) and Presentation Layer (PL) should be placed in namespaces that relate to how your products are sold. Different companies have different corporate aims - for example, if working for a digital design agency who write bespoke websites for multiple clients, each BLL and PL may be completely bespoke, while using the generic DAL:
Data Access Layer - [MyCompany].Core.Data
Business Logic Layer - [MyCompany].Clients.[Client].[AppName].Business
Presentation Layer - [MyCompany].Clients.[Client].[AppName].Presentation
Here we see three different namespaces in three different assemblies. This structure gives you a very robust way to store your custom built objects - you can cater for multiple clients, and multiple applications per client.
The next example is based on, say, an in-house development team where there are no external clients to cater for - all applications are developed for "MyCompany". You will notice that the DAL is named exactly the same.
Data Access Layer - [MyCompany].Core.Data
Business Logic Layer - [MyCompany].Apps.[AppName].Business
Presentation Layer - [MyCompany].Apps.[AppName].Presentation
Again, we see three different namespaces all in their own assembly.
This example could be extended further to include [Department], much like the digital design agency example above for [Client], though I have not come across the need for this kind of separation at the time of writing, nor do I imagine a development team would give two applications in different departments the same name. I suppose there could be two versions of the same application being developed separately for different departments... though it would be a logistical nightmare to maintain!
I also tend to develop a few additional assemblies as well:
[MyCompany].Core.Windows
[MyCompany].Core.Windows.Services
[MyCompany].Core.Web
They are all in the [MyCompany].Core namespace, but are compiled independently of each other in separate assemblies. The reason for this is that while they contain generic, core functionality (like user controls, extension methods, helper classes etc), they are specific to a type of project. We would have no use for the code in [MyCompany].Core.Windows in a web application, for example, and therefore including it in a web project would be pointless.
So, you've seen examples of using the same root namespace over different assemblies. There may also be times when you might want to create two types in the same namespace, but in different assemblies. Say, for example, a client has asked you to develop a number of websites dedicated to animals - each website is dedicated to an individual animal. You create an assembly with a root namespace of MyCompany.Clients.MyClient.Animals. The assembly contains both a "Dog" type and a "Cat" type. Because you have no need for a "Dog" type when developing the "Cat" website, you may want to separate the two classes in to two different assemblies, but keep them in the same namespace. The types would be organised as follows:
MyCompany.Clients.MyClient.Animals.Dog - Assembly1
MyCompany.Clients.MyClient.Animals.Cat - Assembly2
Each type would be compiled in to a separate assembly in order to reduce the project footprint. This is entirely possible, though rarely done in practice.
And so my rambling ends. This post was just intended as a brief summary (and a reference for myself when working remotely) of namespaces and assemblies - it's by no means an official pattern or practice, but it tends to serve me well when designing solutions.