Software Development
Blogs and Discussion
developer.*
Books Articles Blogs Subscribe d.* Gear About Home

Organizing .NET Namespaces

A couple months ago I posted the following entry on a discussion forum myself and some friends participate in. A buddy was asking for tips on how to transition this massive VB/COM+ project over to .NET and how he should start thinking about structuring functionality into namespaces assemblies. I'm just going to post it here in case it proves helpful for anyone else. I haven't really revised this post at all, so it may read sort of open-ended. Anyone with questions is welcome to ask.

Note that I have worked my entire IT career in the internet space, so that's the perspective from which this blurb derives. This may not be as relevant to people writing .NET apps for packaged and/or client-server apps.

Well I'll outline the way I've worked with namespaces up to this point. We decided a long time ago at {previous employer name removed} that unless we were going to be building packaged software deployed to millions of end-user machines, the GAC (Global Assembly Cache) is NOT the way to go. Instead, we employed a strategy to keep the AssemblyVersion numbers the same on all our assemblies and instead incrementing the AssemblyFileVersion. You can find both of these settings in the AssemblyInfo.cs of your namespace project. The AssemblyVersion is what other assemblies that reference your namespace will look at. If that number changes, then the referencing assembly blows up. But you as the developer still need to know what version of the assembly is deployed, and for that you use the AssemblyFileVersion attribute. Increment it every time a new version of the assembly is deployed.

The same goes for giving your assemblies a strong name. If you aren't going to put them in the GAC, and you will always be deploying them on in-house machines, then forget about strong naming.

Next, as for deciding what goes into the namespaces, I'm pretty strict where I currently work about designing namespaces such that if a disaster happened and we only had the source code files, we need to be able to recompile from scratch. This means no circular references amongst your namespaces such as:

Namespace A references Namespace B and vice versa

Indirectly, this actually leads to a purer form of OOA/D because you really have to use some interesting indirection to get to your end result...which is what design patterns are all about. You can't always avoid this gotcha, and refactoring namespaces to eliminate circular references can be a real bitch after they're all set up and running. Keep in mind that one assembly can contain multiple namespaces if you simply cannot decouple relationships. Just remember not to put too much functionality into one namespace or else it can become a bottleneck with concurrent projects.

I would recommend starting with the most fundamental part of your whole architecutre -- the data access layer. Chances are everything will need to access it, so start there. Put it in an assembly like CompanyName.Data.dll or some such. It's also handy to think about your namespace tree like ever refining nodes on a functionality tree.

Example (these are all namespaces):
CompanyName
CompanyName.Data
CompanyName.Common
CompanyName.Customer
CompanyName.Web.UI
CompanyName.Web.UI.Public
CompanyName.Web.UI.Private
CompanyName.Web.UI.Admin
CompanyName.Web.UI.Admin.Reports

and so on. The nodes lower in the tree can have visibility to the classes higher up, but the reverse must NEVER happen. You're always working from the general to the specific.

With regard to ASP.NET, every environment I've worked in has done JIT deployment over pre-compiled deployment. There are trade offs to both of course, but JIT seems to allow you to respond to changes quicker without having to deploy alot of unneccesary code. Additionally, all your assemblies will go in the \bin directory of the web server where the runtime will automatically find them when you instantiate objects from your code-behinds. One item in favor of pre-compiled is that, depending on the amount of traffic you're serving from your website, JIT compilation in real-time of code updates might actually crash the webserver if your traffic load is too high. I've seen it happen where I work now.

If you don't already have a copy, you simply MUST buy a copy of Applied .NET Framework Programming by Jeffrey Richter. While it doesn't cover design concepts, it's got more information than you'll ever need about the internals of the .NET Framework and CLR.

Categories: 

Great article. I have a

Great article.

I have a few questions that I was hoping you would answer.

1. I am a little confused by the differences between a .NET project, an assembly and a namespace. I know what each of these are, but it seems that I am constantly having to add references so that one assembly can see another.

2. In your example, did you create one project (CompanyName) and then create folders under the CompanyName project so that namespaces like CompanyName.Web.UI.Private can see CompanyName.Web.UI without adding references to CompanyName.Web.UI.Private?

3. Is there a way for CompanyName.Data to see CompanyName.Customer without adding references?

I am asking these question because I have created as separate projects:

CompanyName
CompanyName.Web.UI
CompanyName.Business
CompanyName.Data

On my current project I need to map the output of datareaders from my data classes to my business classes. This would suggest that I have a reference from Data to Business. I was always under the impression that it should be the other way around.

Thanks

Response

In order, here are my responses.

#1) You've said you know the difference between the three items you mention, but I'll re-iterate anyway so we're on the same page. I think of them like this:

Project = source code organized via a "project" file that is then included in a solution in Visual Studio.

Assembly = the compiled output of a project.

Namespace = a logical grouping of common functionality.

Given the above, one project can contain code belonging to multiple namespaces if necessary. And since the assembly is the compiled output of a project, so can the assembly.

#2) No. The way I've worked until very recently is to, as much as possible, create one project for every namespace I need. Similarly, if using VS.NET, only one project will go into a solution file. This keeps the code seperated out into the most cohesive chunks possible for ease of maintenance. I have had to combine namespaces into a single assembly before, and that might not be a problem if you work in a traditional build-n-ship software company. But I've found that it creates nightmares in a highly volatile web shop where multiple development efforts can bottleneck on the same project because too much functionality is tied up in it. The only time I would combine namespaces into a single assembly is to deal with an otherwise circular relationship that can't be factored out of the design....and that should almost never happen.

Having said that, I'm sure it's possible to get VS.NET to copy your built assemblies to a common directory from which all of your projects reference their dependent assemblies. Then when you build, all your other projects using that common directory will be automatically updated when you refresh their references or recompile them in turn. Similarly, you could create one monolithic solution file that contains all of your namespace projects, and specify the build order in the solution so that everything gets built at compile time. This has the pleasant side effect of also telling you when you've unwittingly introduced a circular reference somewhere. This is the strategy I've been using more recently since I've started working with .NET 2.0.

#3) If Assembly B needs to use classes in Assembly A, you have to add a reference. Your hunch is correct that your business class assemblies should reference the data namespace and not the other way around. Nor should you consider tightly coupling the data classes with the business classes as in compiling them into the same assembly. I'm not exactly sure what you mean when you say you map the output of your data readers to your business classes, but if your business classes are building statements or feeding sproc calls via the data layer to the database, they should be the ones handling the output of the data reader and then transforming that into a "state" class that's handed back to the caller from the application layer.

Feel free to post a pseudo-code example if you want.

Great...

Great article, well written and in total agreement with all my design principles.

Congrats...

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Recent comments

User login

About our advertising.

Atom Feed

developer.* Blogs also has an Atom feed, located at this url.

Click here for more information about Atom.

A Jolt Award Finalist
Software Creativity 2.0
Foreword by Tom DeMarco

Recent Posters

Based on most recent 60 days, sorted by # of posts and name.

Google
Web developer.*

Who's online

There are currently 0 users and 21 guests online.

Syndicate

Syndicate content
All views expressed by authors, bloggers, and commentors are their own and do not necessarily reflect the views of developer.* or its proprietors.
Click to read the Copyright Notice.

All content copyright ©2000-2005 by the individual specified authors (and where not specified, copyright by Read Media, LLC). Reprint or redistribute only with written permission from the author and/or developer.*.

www.developerdotstar.com