Visual Studio 2010: How to maintain control of your code using Layer Diagrams, custom MSBuild tasks, and work item integration
Over time, code starts to “smell bad” or “rot”. It evolves in ways that it wasn’t originally intended to evolve, and little hacks are sometimes made. VS 2010 fights this software atrophy via automation and integration with the overall application lifecycle, which will help you maintain control of your code.
One powerful tool at your disposal is layer diagrams. Layer diagrams allow you to draw your system’s architecture as it should be, map your code to it, and validate that your architectural design and your implementation do not deviate. For example, if you have a standard 3-tier architecture, you could create a layer diagram with 3 boxes: the presentation layer, the business layer, and the data layer. Arrows between the boxes indicate that it’s okay to take a dependency on the node that you’re pointing to. So you would probably draw an arrow from the presentation layer to the business layer and another arrow from the business layer to the data layer. Now, the cool part is that you can map your code to this diagram, and then validate whether this architecture is being followed. You can even set up the build to break if someone writes code in the presentation layer that inadvertently accesses the data layer directly instead of going through the business layer.
To create a new layer diagram, click on the “Architecture” menu item and select “New Diagram”. A dialog box will come up (see below); select “Layer Diagram”. (Full reference on creating layer diagrams is here).
Here is an example of a layer diagram. This diagram can be found in the code sample attached at the end of this post (it’s the PetShop.layerdiagram file under the PetShopModels project).
In this example diagram, we’ve modeled what our architecture should look like. Now, we need to map our code to the diagram. Drag and drop projects from the Solution Explorer or namespaces/classes from the Architecture Explorer onto the appropriate block on the diagram to map your code to the diagram. The number of items that are mapped to each block in the diagram will be displayed in the upper right-hand corner of the block. To view the mapped items, open the Layer Explorer (click on the “Architecture” menu item, select “Windows” and then “Layer Explorer”). For example, you can see from the diagram above that the Business block has 2 items mapped to it. When I open the Layer Explorer and select the Business block in the diagram, I see what those 2 items are; anything in the namespaces “PetShop.BLL” or “PetShop.OrderProcessor” is part of my business layer:
Now, I want to validate that my code meets the requirements of the architecture specified by my layer diagram. To do this, right-click on the layer diagram and select “Validate Architecture”. This analyzes whether your code conforms to the diagram. Note that it’s performing a static analysis, so if there is something that you are doing illegally at runtime, the tool won’t catch this.
If errors exist, they will be displayed in the Error List window in Visual Studio. In the example code, there are two errors:
There are several solutions to deal with errors, which can be easily applied by right-clicking the error:
- Change your layer diagram. Right-click on the error and select “Go to” and then “Layer Diagram”, and Visual Studio will take you back to the layer diagram to see the visualization of your architecture, with the offending blocks that caused the error selected. You could add a link between the blocks in your architecture if that makes sense.
- Change your code. Right-click on the error and select “Go to” and then choose the appropriate method. This will take you directly to the places in your code which are breaking the validation, so you can make a code change.
- Create a bug. Right-click on the error and select “Create Work Item” to create a work item in Team Foundation Server. Perhaps this problem is in someone else’s code (assign the bug to him/her), or you don’t have time to fix it right now. This integration with the work items in TFS allows you to log that this needs to be done. (Note that this option will only show up in the right-click menu if you are using TFS.)
- Suppress the error. Right-click on the error and select “Manage Validation Errors” and then “Suppress Errors” to suppress the error. Now, at first glance it may seem ridiculous to suppress the errors…doesn’t that defeat the point? But there’s actually a best practice around suppressing errors. When you first run the “Validate Architecture” tool on an existing codebase, you may get (for example) 100 errors. Well, with ship schedules and such, you may not have the luxury of refactoring your entire architecture right away. So, you might choose to suppress all errors except for perhaps the first 20 errors. Focus on fixing those first 20 architectural errors in your code. Then, in later milestones of your product, you can slowly add validation errors back in, so you can clean up your architecture bit by bit. Another best practice that some companies are using when getting started with Visual Studio 2010 is to run the “Validate Architecture” tool on their legacy system and suppress all existing errors, but then not allow any code with new validation errors to be checked in. So all new code will comply with the architecture.
The final piece of this is to use custom MSBuild tasks to integrate this validation process into your build. Integrating this architectural validation into your build makes it a regular part of your development process, rather than an extra task that you have to do manually.
To do this, open your build definition file from the Team Explorer window. Click on the “Process” option in the left-hand sidebar. Expand “Advanced”. For the “MSBuild Arguments” parameter, enter the value “/p:ValidateArchitecture=true”.
This MSBuild argument will be passed to all projects. However, projects will ignore it if they don’t recognize it, so it will be used only by modeling projects. (Layer diagrams always live inside modeling projects.) Now, it will validate the architecture on every build and cause a build break if validation errors are found.
In summary, layer diagrams allow you to define your ideal architecture, map your code assets to the architecture, and then validate that your implementation matches your architectural design. In tomorrow’s post, I’ll discuss how to better understand the problem domain for your system using UML tools.