How to setup a new solution

Introduction

In this post I'll present a possible setup for a .NET solution which respects (as much as possible) the following aspects, patterns and software engineering practices

In most of the samples presented in this blog I'll adhere to this kind of solution setup (e.g. here and here)!

The solution should have as few external dependencies as possible. All external libraries (of course we don't count the .NET framework here) on which the solution is dependent should be (if possible) part of the solution tree. Then you can always (if you have your solution tree under source control -- and you definitely should!) check out the complete solution tree on any machine (e.g. on the build server or on a new developer machine) and just build the solution and run the unit tests without any further manual intervention needed.

Each project of the solution has a corresponding test project where you implement all your unit tests (and/or integration tests, acceptance tests, stress tests, etc.) for the respective project. So, if you have a project in the solution called Domain you should automatically have a additional project in the solution which you might call Domain.Tests.

Separation of Concern (SoC) suggests us to split the whole solution into several projects. I often have at least 3 types of projects. In a typical WinForms based application these might be

  • Domain - contains the domain model with it's domain entities, services, factories and repository interfaces
  • DataLayer - contains the NHibernate XML mapping files and the implementation of the repositories
  • Application (or PresentationLayer) - contains the application or presentation logic, the application shell, the views, presenters and/or application controllers

Of course each of those projects has a corresponding Tests project.

Depending on the complexity of the solution there might be even more projects.

Normally I have a Dev folder on one of my (local) hard disks. The Dev folder has at least two sub-folders OSS and Projects. In the OSS folder I have a copy of the source or binaries of all open source software I use in my projects. As you can see below I have downloaded Castle, NAnt, NHibernate, NUnit and the Rhino Tools.

 image

The green check marks on Castle, NHibernate and Rhino Tools show that these folders are under source control (SVN in this case) and that I have the most recent version of the source.

In the sub-folder Projects I put all the solutions we develop for our customers.

Sample Solution Structure

Now let's have a look at the structure of a sample solution. Let's assume that it's a WinForms based application and call the solution DemoSolution.

image

In the Projects folder I create a sub-folder with the same name as the solution, in this case DemoSolution. In this solution folder I create at least the two sub-folders SharedLibs and src.

The folder SharedLibs contains all the external assemblies my solution depends on (e.g. NHibernate, Castle, 3rd party WinForm Controls, etc.). The content of the SharedLibs folder varies depending on the needs of the solution. In the sample solution I have presented here we have the following files in this folder

image

Important: Each project of the solution which references one or several of those external libraries points to this SharedLibs folder! That is: never reference an assembly from the GAC (except the .NET libraries of course).

The folder src on the other hand contains our own source code for the solution. The Visual Studio solution file *.sln I put directly in the src folder. Normally the VS solution has the same name as the solution folder (in this case DemoSolution.sln). For each project of the VS solution I have one sub-folder. In this case we have 6 projects in the solution, three of them containing the code which makes up our application and the other 3 projects containing the code of the corresponding (unit-) tests.

Summary

I have presented you a possible structure for a solution you develop. This structure tries to satisfy various requirements implied by commonly used patterns and software engineering practices.

Blog Signature Gabriel .

Print | posted on Sunday, April 06, 2008 8:18 AM

Comments on this post

# re: How to setup a new solution

Requesting Gravatar...
great series - I have attempted to apply the principles above to the example cited at the beginning, and I have a couple of questions:
1. does the .cfg.xml file belong in the Application or DataLayer projects?
2. I have the Person.hbm.xml file in a folder called Mappings in the DataLayer project - all tests fail unless I add a mapping item to the cfg file, is this required or am I doing something wrong?
Left by Craig on Apr 16, 2008 9:03 AM

# re: How to setup a new solution

Requesting Gravatar...
@Craig:
1) good question. Normally it belongs to the data layer since the application layer wants to be agnostic of any persistance details. It is important that in the end this configuration file is located in the application directory (that is the folder where all your binaries are located)
2) you have to set their property to "embedded resource" and ensure that you add the assembly in which you have defined the mappings (i.e the hbm files) to the configuration when creating the nhibernate session factory. In the mapping files you must provide the fully qualified name of each class
Left by Gabriel Schenker on Apr 26, 2008 7:23 AM

# re: How to setup a new solution

Requesting Gravatar...
This is great advice! A couple things I would add:

* do you really need multiple test projects? in my experience I've found that just having 1 test project organized into folders provides me what I need, and it makes the build a lot faster.

* I like to differentiate the ShareLibs into /libs and /tools, /libs are libraries that we depend on at runtime and ship with our deliverables, /tools contains things like NAnt, Nunit and other tools that we use during development. This makes it easy to determine "the stuff you need" to deploy to production.
Left by Ben Scheirman on May 06, 2008 5:24 AM

# re: How to setup a new solution

Requesting Gravatar...
@Ben: well, it is certainly possible to have all tests in one single project. This will definitively increase the compilation speed. But on the other hand I like to at least separate the test concerning data access, domain model and presentation layer into distinct projects. That's just personal preferences.

Well separating tools and libs seems also a good solution to me. Again SharedLibs are my personal preferences.

There is always many solutions for a given problem...
Left by Gabriel Schenker on May 06, 2008 10:45 PM

# re: How to setup a new solution

Requesting Gravatar...
How different would you set up your solution if your project was an ASP.NET project as opposed to a WinForms project? Would there be much difference besides just having a Web Application project?
Left by todd brooks on May 07, 2008 9:50 AM

# re: How to setup a new solution

Requesting Gravatar...
@todd: not really! The Domain and DataLayer will be the same since there is nothing presentation layer specific in these two projects. So the only thing that will change is the application project. Possibly you will have a 'Web' project at it's place where you place all your view templates, controllers, css, java script, etc. (if you develop say an MS MVC or Monorail Web app)
Left by Gabriel Schenker on May 08, 2008 1:10 AM

# re: How to setup a new solution

Requesting Gravatar...
do you have a project template for vs for your solution? would suggest to create some templates for specific needs.
Left by Rainer Schuster on Sep 06, 2008 10:20 AM

Your comment:

 (will show your gravatar)
 
Please add 5 and 4 and type the answer here: