How do you structure your project -- details

Oren posted about his “2 project” solution structure recently. It seems that developers are caught on this preconceived notion that a Visual Studio project must be directly related to a compiled assembly. True, by default this is how Visual Studio based compilation works. If your solution has eight projects in it, there will be 8 assemblies output from it when you do Ctrl-Alt-B. Each assembly will also, by default, be named exactly as the project is named. You can change the naming by opening the project properties and altering it to differ from the project name there, but there is no way to break the 1:1 relationship between projects and assemblies.

I think that it’s because of this default behaviour that developers think in this manner. It doesn’t have to be this way though. In Visual Studio, projects are organizational groupings of code artifacts. Traditionally we have used these project containers to organize our application structures based on logical, and physical, layering that we have designed. By that, I mean we will create a project to define hard visible boundaries between each of our logical layers. As a result we end up with a project for data access, another for the user interface, one for utility classes, a project for services, and so on. These demarcations of logical layers are there to visibly indicate to the programmer that there is a boundary.

Some would argue that separate projects allow you to better enforce dependencies between them. You can initially setup your project structure and add the appropriate references between them. After that there no longer is a need to alter references, and this fact alone becomes the guardian against rogue layer interaction. Honestly, I can see and appreciate this point. In the past, I haven’t had much trust in my development teams and their ability to maintain proper layer separations. I’ve used project boundaries to comfort me in these times.

If you move all of your code into one project and use folders and namespaces to distinguish the layering in your application, there is nothing stopping you from quickly and easily corrupting the layering of your application. It’s easy to add a ‘using’ or ‘imports’ statement and quickly get the UI to directly reference the code in the repositories layer instead of the services layer. There’s no question about that. My question for you is this: What benefit does project based separation give you when I can simply hit Alt-Enter and have ReSharper add a reference to another assembly in a fraction of a second? Even with the hard layer separation that is provided by a project structure, it is still exceedingly simple to screw up that layering.

As Oren pointed out, the only sure fire way to stop this from happening is to start using something like NDepend. Developer diligence and self policing will go a long way as well, but if your project’s morale starts to drop off, or if you have a lot of junior types, diligence alone isn’t going to be enough. I think that the minimalist project approach does fantastic things for IDE performance, tool performance and code organization simplicity. I also thing that you need to evaluate your solution/project structure on a project by project basis. In some scenarios you may have no choice but to create many different projects. The key, I think, is in trying to keep that count at a bare minimum.

Like Ayende said in his post, I to am moving towards a two project solution as well. Actually, I’m moving to a three project solution, but only two of those have code files in them. For me it breaks down like this

  • MyCompany.MyApp
  • MyCompany.MyApp.Tests
  • MyCompany.MyApp.Build

The first two projects are fairly straight forward. The application project has any code that will need to be released to the production server and/or client PCs. The testing project holds, well, testing code which will not be released to production. The final project, which is for build artifacts, contains any files that assist in the compilation process. This project will include files that are never deployed to production. Some may be used as templates for creating files that are required in production. I’d like to do another post to fully explain the build project so let’s not get to deep into it here.

I first saw the Build project in something that JP was doing. I seem to remember him also saying that this was something that he’d picked up from Jay Flowers. At the time that I saw this I was trying my best to include the items I needed to run my build process in the MyCompany.MyApp project. To do this I was using a solution folder named ‘build’. As I added more and more items to the solution folder, I was want for more. I needed more structure, more control and better discoverability. The Build project is giving this to me.

In the Build project I employ roughly the following folder structure. I say roughly, because every application has different compilation, deployment and architectural needs. This is what I default to when starting, but rarely end up with when I end.

  • MyCompany.MyApp.Build

At the root of the project structure I have files relating to my nAnt (MSBuild if you like) script. This usually includes a *.build file (the nAnt script itself) and a b.bat file (the fast way to launch my nAnt script at the command line). Other things can happen into the root as well, but these two files are always there.

The Scripts folder is where I keep any scripting that is required by the build process to setup the environment. This would include vbs files that I have for creating virtual directories, application pools and other IIS related tasks. These scripts are all related to supporting environment configuration. Lots of the files that I put into this folder are found on the computers where I will run them. I include them here in the interest of maintaining the ability to download from source control everything that is needed to make the first compilation on a new computer work without needing to perform any installations.

The SQL folder is pretty self explanatory. Ì fraction it into on folder for DDL scripts and another folder for data scripts. The scripts in the data folder should only include information that is needed to prime the production database into the minimal working state required by the software. If you need to prime a database for testing purposes, those scripts should be kept somewhere else.

The templates folder is where I keep any files that are expanded and included in a release package. This usually means that I have all my configuration files in this folder. I regularly tokenize these files and use nAnt to insert values depending on the environment in use. My basic thought process is that any Xml based configuration file that exists in my application resides here. I’ll leave the discussion of the ramifications of this to another blog post.

So overall, I like a minimalist approach to solution and project structures. Two projects just isn’t enough for me though. I’d rather have that third one for my build/compilation/release artifacts.