One of my favorite and most underused features introduced in VS 2010 was Layer Diagrams. It’s a really simple tool to learn and use, but amazingly powerful.
It’s a diagramming tool that allows you to draw a diagram consisting of boxes and arrows, where the boxes are meant to represent your layers/components, and the arrows represent dependencies. If you’ve ever been asked to whiteboard out the architecture/layers of your application, you probably got up to the whiteboard and drew some diagram with maybe a dozen boxes and some arrows. This is essentially what the layer diagram you create should look like. The real power comes from what you do after this. You can then drop actual code artifacts (assemblies, namespaces, classes, etc.) onto the boxes, and Visual Studio will automatically validate the diagram by inspecting your code and comparing the actual dependencies in the code to the ones in the layer diagram. If you’re code takes a dependency that is not represented in the layer diagram (e.g. The UI talks directly to the database instead of going through the middle-tier) Visual Studio will throw a validation error. You can easily include this in your TFS Build to fail the build when this happens. Let’s take a look at an actual example from my on-going hobby project.
I’m using a CQRS & Event Sourcing style architecture for this system, if I were to sketch it on a whiteboard (or in this case paper) it might look something like this:
To create a Visual Studio Layer Diagram you create a new Modeling Project, then add a Layer Diagram to it (Note: I believe this is a Visual Studio Ultimate only feature):
Then you simply pull up the toolbox and start drawing boxes and arrows (aka Layers and Dependencies)
This is the Layer Diagram I’ve been using that roughly matches the sketch at the start of this post:
You can choose any color you wish for the boxes, in this case I chose red to represent things that map to assemblies, Yellow represents Databases (this is just for illustration purposes only, there’s no code artifact you can drop in the yellow database boxes that you can validate dependencies against), and Blue represents the smaller pieces that may live inside of assemblies.
The last step is to associate code artifacts with the layers in the diagram. In the example above if you notice the little numbers in the upper right hand corner of each layer, that indicates how many code artifacts have been associated with each layer (you can view the details in the Layer Explorer window). To associate code artifacts with the layers you simply drag-drop them from either solution explorer or Architecture Explorer onto the Layers.
You can try to validate the diagram by right-clicking on the diagram canvas and choosing Validate Architecture. If you get validation errors they might look something like this:
In the above case I purposefully broke the diagram by deleting the dependency (arrow) between the Domain Layer and Events Shared Components. The selected error is telling me that the Game.AddPlayer method depends on the BaseEvent.AggregateId property, but that dependency is not represented in my diagram. The 2nd line of the errors points out specifically which layers are involved, the Domain Layer.Domain (which is the sub-layer – blue box – called Domain within the bigger red box Domain Layer) and the Event Shared Components.Events.
There is also a convenient feature where you can simply draw your layers, associate them with code artifacts, then right-click and select Generate Dependencies and it will inspect the code an automatically draw the arrows/dependencies onto the diagram for you so that it matches the actual dependency structure of the code.
I verified that this does in fact validate and then updated my TFS Build to automatically validate on every build by adding an MS Build argument in the Build Definition:
For the above Layer Diagram some of the “rules” that it enforces could be stated like so:
- UI shouldn't know about Events
- Query Side shouldn't know about Commands
- Domain shouldn't know about persistence (i.e. Event Repository)
- Event Repository shouldn't know about the Domain
- Events and Commands should be standalone classes with the only dependency on the Common assembly
- Common assembly should not depend on anything else
If any of these invariants are ever broken we’ll be made aware immediately by the broken build, and we can decide whether to update the Layer Diagram to represent the new architecture, or we can fix our changes to properly adhere to the chosen architectural rules.