August Architect: .NET Solution structure

Problem Statement

Last month, I blogged about organizing code in a source control system. We looked at how release units help us represent a domain context map to support domain-driven design and distributed application development. We recommended adopting a standard release unit layout so that your release process can be clearly understood and automated.

This month, we will take a deep dive into the release unit's trunk folder. I said before that trunk contains the latest version of the release unit code. How shall we organize our code inside trunk?

Objectives

As always, let's define our objectives:

  • Support domain-driven design philosophy
  • Support principles of object-oriented design
  • Support distributed application development
  • Support a structured, repeatable, and traceable release process

Release Units in .NET

Release Unit is a collection of folders and files that are released together. In .NET environment, this is achieved with a .NET solution that groups multiple projects together for the purposes of debug, compilation, and release. Hence, if you are working in .NET environment:

Each release unit should contain one and only one .NET solution.

.NET Solution Structure

Now, we are ready to take a look at a sample .NET solution structure that will help you implement principles of domain-driven design and object-oriented programming. For simplicity, let's assume our solution consists of a single web application and a command-line data setup utility. You will have no problems extending this approach to handle your own more sophisticated scenarios.

.NET Solution Structure

/doc - contains release unit's documentation.

/lib - contains release unit's pull dependencies. When your project uses a .NET assembly not part of your solution, place the assembly into the lib folder and reference it from there. It ensures that all projects in the same solution always use the same version of the dependent upon library and provides you with a clear way to upgrade the library to a new version should you decide to do so.

/Database - contains database creation and modification scripts, scripts to set up users and their permissions, load data files, etc. This folder may also include command-line batch files to set up the release unit on a local machine, build, integration or test server.

/Model - contains classes of the Domain Model, a central part of the release unit. This assembly describes what can be accomplished by the release unit in business terms. Keep the model free from infrastructural detail. It will help you achieve high levels of reuse and low costs of maintenance in your applications. Next month, we will take a look at how to organize your domain model to clearly identify all supported business scenarios and transactions. This is a big topic on its own, which certainly deserves a dedicated blog article.

/ModelUT - contains unit tests for the Domain Model classes.

/Persistence - implements a persistence mechanism for the release unit's domain model. I strongly recommend keeping persistence interfaces with the model itself since it shows how aggregates and entities are designed to be loaded into memory. The purpose of the persistence library is to implement persistence interfaces with your standard tools and techniques.

/PersistenceUT - contains configuration files and unit tests for the Persistence. In our case, these tests verify the release unit's persistence classes and their configuration files as well as the database. Strictly speaking, they are integration tests. However for the purposes of the domain modeling, we prefer to think about the whole domian model persistence as a black box.

/WebInfrastructure - contains web infrastructural classes which would otherwise be placed in the App_Code directory on the web site. Extracting these classes into a dedicated library allows them to be unit tested.

/WebInfrastructureUT - contains unit tests for the web infrastructural components.

/Web - contains a web application, a top application layer responsible not only for user interface but also for referencing and configuring all its depencies.

/WebUAT - contains user acceptance test scripts, such as Selenium or WatiN.

/WebLT - contains load testing projects, such as JMeter or LoadRunner.

/DataSetup - contains a command-line process to perform backroom administrative tasks.

/DataSetupUT - contains unit tests for the data setup components.

Dependencies

To better understand this sample solution structure, take a look at the package diagram below:

Package Diagram

Summary

  1. For each release unit, create a .NET solution file.
  2. Place all of your external pull dependencies into the lib folder.
  3. Keep your model classes free from any infrastructural detail.
  4. Make your top layer responsible for connecting and configuring all its dependencies.

Happy coding!

Welcome to ModelBlog

Thank you for visiting ModelBlog. We hope the time you spend with us will be both entertaining and worth your while. Have fun!

Authors

Search

Archive

Tags