You happen to be one of those developers that either purchases Visual Studio Ultimate or works for an enterprise that had the foresight to give you Visual Studio Ultimate and although you can see the Architecture menu choice, you've never gone any farther than that. In this article, I'm going to illustrate a few of the things you can do to get started and get the most out of your Visual Studio investment.

The two tools I'm going to illustrate in Part 1 (this article) are the dependency graph and the layer diagram. The dependency graph is a visual representation of the dependencies among the various assemblies that make up your solution. The layer diagram is a means of illustrating your solution's layers and to enforce rules about how assemblies take on certain dependencies. For example, you wouldn't want a UI-layer element taking on a dependency to a data-layer element. Wouldn't it be nice if the build process could enforce that rule and if violated, fail the build? That's what the Layer Diagram provides and that's what I'll illustrate for you in this article.

There are a number of UML related tools that I will cover in Part 2. Microsoft has a nice support forum for Q&A on these tools and you can find that here: http://bit.ly/VSArchitecturalToolsForum. Figure 1 illustrates the QR Code for the link.

Figure 1: The QR Code for the VS Code Visualization and Modeling Tools Forum.
Figure 1: The QR Code for the VS Code Visualization and Modeling Tools Forum.

Dependence Graphs

Here's the scenario: You've been brought into a project to save the day! The previous developer has abruptly left the project and all you have is the source code. There's work to be done and you're not quite sure where to start. This is where the Dependency Graph (DG) becomes your best friend.

The DG gives you the ability to visualize the solution and specifically, the dependencies that make up the solution. What are the building blocks? What are the relationships among those building blocks? You can spend time spelunking through the Solution Explorer and you will have compiled data, but it's not likely that you will have much information. There's a lot of complex information to digest in a small amount of time. The most effective means to digest information is through data visualization. Everyone's familiar with the oft-quoted phrase, “A Picture is Worth a Thousand Words.” It is true and there's plenty of science to back that claim up. Think of the last time you sat through a presentation that was slide-deck heavy. Which ones stuck with you the most? The ones that were concentrated on text or the ones that relied more on pictures? There's a good book on the subject by Dan Roam called “Blah Blah Blah: What To Do When Words Don't Work.” That's what the DG does for you.

To get started, create a project in Visual Studio. For this article, I'll use an empty ASP.NET MVC Project. Once the project is created, I can generate a dependency graph. Figure 2 illustrates how that process starts.

Figure 2: The Architecture\Generate Dependency Graph Menu Option
Figure 2: The Architecture\Generate Dependency Graph Menu Option

Select the option for a Solution. The option for an Include file is for C++ projects.

Figure 3 illustrates what happens after you select the option to create a DG for the solution.

Figure 3: The Dependency Graph Generation Process
Figure 3: The Dependency Graph Generation Process

Figure 4 illustrates the initial graph.

Figure 4: The initial Dependency Graph
Figure 4: The initial Dependency Graph

Candidly, what you get to start with isn't all that impressive. But it does tell us a little information that's useful. For example, you know the solution is made up of a single DLL and that DLL has a number of external dependencies. These external dependencies are .NET Framework libraries and other non-specific application libraries. Figure 5 illustrates how to expand the graph to show more information.

Figure 5: The initial Dependency Graph can be expanded to show more detail.
Figure 5: The initial Dependency Graph can be expanded to show more detail.

Figure 6 illustrates the DG's expanded view. Notice that within the expansion, you can drill down through the dependencies. For example, let's assume that you're interested in which namespaces are contained in System.Web.

Figure 6: The Dependency Graph's expanded view
Figure 6: The Dependency Graph's expanded view

Figure 7 illustrates that further expanded view as well as the legend feature and several of the layout and analyzer options. For example, the DG can analyze for circular references and unreferenced items.

Figure 7: The Dependency Graph isn't just a static diagram; there are numerous other analytical capabilities as well.
Figure 7: The Dependency Graph isn't just a static diagram; there are numerous other analytical capabilities as well.

By now, you likely see the power that the Dependency Graph has to offer. At a glance, the Dependency Graph allows you to view your solution's building blocks and their dependencies from a sufficient altitude. With the DG tool, you can quickly document and prioritize your work and in that process, be more efficient and thereby, more productive.

The diagram itself can be saved to an image file. But wait...there's more! Let's assume that an area of interest is the WebApplication1.Controllers namespace. Figure 8 illustrates what happens when you right-click that item. Notice the ability to add comments and navigate to the definition.

Figure 8: For a particular namespace, at a glance, you can see the specific dependencies as well as being able to navigate to the definition.
Figure 8: For a particular namespace, at a glance, you can see the specific dependencies as well as being able to navigate to the definition.

Figure 9 illustrates the DG alongside the code after navigating to the code definition.

Figure 9: When you navigate to a definition, Visual Studio optimizes the experience by placing the code next to the Dependency Graph.
Figure 9: When you navigate to a definition, Visual Studio optimizes the experience by placing the code next to the Dependency Graph.

At a glance, the Dependency Graph allows you to view your solution's building blocks and their dependencies from a sufficient altitude.

Layer Diagrams

The Dependency Graph lets you quickly get an understanding of the application you've been asked to salvage. You discovered that core business and data logic was embedded in the WebApplication1.Controllers namespace. You have since re-factored that code. (For purposes of this article, the term layer is reserved for those things contained in the diagram. The word tier is reserved for the physical application code and components. In practice, the two terms are interchangeable.) Figure 10 illustrates the new Dependency Graph. Note the dependency that the business and data tiers have on System.Object and how that relationship is depicted in the Dependency Graph.

Figure 10: The new Dependency Graph with the business and data tier namespaces and classes as part of WebApplication1.dll.
Figure 10: The new Dependency Graph with the business and data tier namespaces and classes as part of WebApplication1.dll.

To avoid further architectural problems, you want to enforce the following rules:

  • WebApplication1.Controllers Namespace IS allowed to take a dependency on WebApplication1.BusinessTier.
  • WebApplication1.Controllers Namespace IS NOT allowed to take a dependency on WebApplication1.DataTier.
  • WebApplication1.BusinessTier IS allowed to take a dependency on WebApplication1.DataTier.
  • WebApplication1.DataTier IS NOT allowed to take a dependency on WebApplication1.BusinessTier.

This is straight-forward. You want to decouple the controller that serves up views from the data. It makes perfect sense for the controller to consume the business tier services. Although the business tier needs to interact with the data tier, the same cannot be said of the data tier with the business tier. In other words, the data transcends any specific business logic implementation. Wouldn't it be nice if, as part of the build process, these rules could be enforced? With the layer diagram, they can be enforced. The following is an illustration on how to make that happen.

To get started, you must first create a new diagram. Figure 11 illustrates how to start that process.

Figure 11: A New Diagram is created from the Architecture\New Diagram menu option.
Figure 11: A New Diagram is created from the Architecture\New Diagram menu option.

Figure 12 illustrates the Add New Diagram dialog box.

Figure 12: When a new diagram is created, the diagram is hosted in a modeling project under the current solution.
Figure 12: When a new diagram is created, the diagram is hosted in a modeling project under the current solution.

When a diagram is created, it's hosted in a Modeling Project under the current solution. If a Modeling Project doesn't exist, one will be created for you. From there, as you add new diagrams, you can choose which modeling project should host the new diagram. Figure 13 illustrates the newly added Modeling Project in the Solution Explorer.

Figure 13: The new Modeling Project hosted under the WebApplication1 Solution
Figure 13: The new Modeling Project hosted under the WebApplication1 Solution

Wouldn't it be nice, if, as part of the build process, these rules could be enforced? With the layer diagram, they can be.

With a new Modeling Project and Layer Diagram hosted in that project, let's create three layers:

  • Application
  • Business
  • Data

Figure 14 illustrates how to drag a layer from the Toolbox to the Layer Diagram Design Surface.

Figure 14: A layer diagram starts with dragging the layer object to the design surface.
Figure 14: A layer diagram starts with dragging the layer object to the design surface.

Figure 15 illustrates the layers: Application, Business, and Data. To rename a layer, simply click the text and start typing. Each layer can be sized to your preference.

Figure 15: The Web application's three logical layers: Application, Business, and Data .
Figure 15: The Web application's three logical layers: Application, Business, and Data .

The architecture is simple. The Web artifacts comprise the Application Layer. The two classes created earlier represent the Business and Data Tiers. Physically, for purposes of this article, the classes are contained in the WebApplication1.dll. In real practice, you would have these items hosted in their own projects as a result, deployed as their own DLLs. Just because things may be physically located in the same place, you can still mandate logical architectural constraints.

The next step is to create dependencies amongst the layers. Figure 16 illustrates how to create a dependency between layers.

Figure 16: Creating dependencies between layers starts with selecting the Dependency Item in the Toolbox.
Figure 16: Creating dependencies between layers starts with selecting the Dependency Item in the Toolbox.

The steps are as follows:

  1. Click the Dependency Item in the ToolBox.
  2. Click the first layer in the dependency relationship. DO NOT HOLD THE MOUSE DOWN! It may seem like the right thing is to drag the dependency item to the first object, because that's how Visio works. That's not how the Layer Diagram works.
  3. Click the second layer in the dependency relationship.

That's it! You've now established a relationship. Figure 17 illustrates the dependency between the Application and Business Layers.

Figure 17: The Layer Diagram now illustrates the Application Layer having a dependency on the Business Layer.
Figure 17: The Layer Diagram now illustrates the Application Layer having a dependency on the Business Layer.

The final step is to establish the dependency relationship between the Business and Data Layers.

Once the dependencies have been established, solution artifacts have to be mapped to their respective layers. Figure 18 illustrates how to map the Controllers Folder (and namespace) to the Application Layer. Note that once you drag the Controllers Folder, the number 4 will appear in the layer's upper right-hand corner. This means there are four artifacts in the layer. Figure 18 also illustrates how to get that detail.

Figure 18: Solution artifacts are mapped to layers by dragging the artifacts from the Solution Explorer and dropping them into their respective layers.
Figure 18: Solution artifacts are mapped to layers by dragging the artifacts from the Solution Explorer and dropping them into their respective layers.

With the Layer Diagram complete, you can now validate the architecture. Figure 19 illustrates that process and the results.

Figure 19: With the Layer Diagram, you can validate the solution against your logical architecture.
Figure 19: With the Layer Diagram, you can validate the solution against your logical architecture.

The architecture validation was successful, meaning that the solution's current state comports with the logical architecture rules set forth in the Layer Diagram. What if you added a dependency in a controller to the data layer? The following code snippet creates that dependency in the code:

public ActionResult About()
{
    var data = new DataTier.DataTier();

    return View();
}

Will the solution build successfully? Yes. Will the architecture validate? No. Figure 20 illustrates the error.

Figure 20: Architectural validation errors resulting from an Application Artifact taking a dependency on a Data Artifact.
Figure 20: Architectural validation errors resulting from an Application Artifact taking a dependency on a Data Artifact.

Why are there two errors in the Error List? One is for the reference and one is for the call. Another question you may have is why would the solution build? Out of the box, a Modeling Project won't validate on build. To get this behavior, you need to set the ValidateArchitecture property to True. Figure 21 illustrates how to do this. Once the property is set to True, architecture validation will occur on every build. If the architecture is invalid, the build will fail. If you remove the data reference from the controller and instead, add a reference to the Business Tier, the solution will successfully build because this is consistent with the logical architecture rules.

Figure 21: For a Modeling Project to validate on build, the ValidateArchitecture Property must be set to true.
Figure 21: For a Modeling Project to validate on build, the ValidateArchitecture Property must be set to true.

For each layer, there are three properties that you need to be familiar with. Their use is not required; however, to apply more sophisticated rules, you need to rely on them,

  • Forbidden Namespace Dependencies: Artifacts associated with this layer must not DEPEND on the specified namespaces.
  • Forbidden Namespaces: Artifacts associated with this layer must not BELONG to the specified namespaces.
  • Required Namespaces: Artifacts associated with this layer must BELONG to one of the specified namespaces.

Figure 22 illustrates how these properties work in this architecture.

Figure 22: Each layer can be equipped with three different namespace rules.
Figure 22: Each layer can be equipped with three different namespace rules.

In this architecture, based on the property settings in Figure 22, the following rules apply and will be enforced on each build:

  • The Application Layer's Artifacts must not depend on anything contained in the WebApplication1.DataTier Namespace.
  • The Application Layer's Artifacts must not be members of the WebApplication1.BusinessTier or DataTier Namespaces.
  • The Application Layer's artifacts must be members of the WebApplication1.Controllers Namespace

It may seem that the second and third rules are redundant. They aren't. In this case, the second rule is one of exclusion. In other words: The list of namespaces in the second rule are not valid home namespaces for artifacts in the application layer. That still leaves open the question of what the valid namespaces are for the artifact in the Application Layer. That's what the third rule specifies. In this case, the artifacts in the Application Layer must be members of the WebApplication1.Controllers namespace. The first rule means the Application Layer's artifacts must not depend on other artifacts that are members of the listed namespace.

Conclusion

This article illustrated the value that the Visual Studio Architectural Tools bring to your development efforts. The Dependency Graph is a great way to get a bird's-eye view of a solution and the artifacts and dependencies among those artifacts that comprise the solution. The Layer Diagram is a powerful tool that you can use to both document your solution's architecture rules and to ensure that your physical code complies with those architectural rules and constraints. In the next article of this two part series, I'll introduce you to the UML modeling tools that ship with Visual Studio.