Monday, April 15, 2013

Code Map is a new Visual Studio 2012 feature which provides ability to navigate through the code by adding various visualization related support in Visual Studio. In this post we are discussing how code map helps us looking at the dependencies of projects in a solution and how it makes it easier to determine the external dependencies of a project or all projects in a solution.

Let's first look how code map helps us understanding the dependencies between projects in a solution. Visual Studio Solution Explorer allows us to see the dependencies of an individual project. It also allows us to view the build order of projects in a solution. The build order depends on project dependencies. Right click a project in Solution Explorer and you should see the following view:

The same option can be found in main menu. Just navigate through the Project menu as follows:

Selecting Project Dependencies from the context menu shows the following dialog. It displays the project's dependencies with other projects in the same solution. While we are here on this dialog, we can select any other project from the drop down and see its dependencies. We can also specify more dependencies. These dependencies would have an effect on build order, as well, discussed next.

The build order is affected by project dependencies. It's actually the other tab on the same dialog. We could directly come to this using the context menu shows before available for a project in solution explorer.

There is no way we can see the dependencies of project in a solution and with the external libraries (assemblies) in a single view. This gets really frustrating for more complex solutions involving many projects.

Project Dependencies Using Code Map
Let's see how code map helps making this job easier for us i.e. determining the dependencies of projects in a solution on each other and on external libraries. Please remember that Code map feature is not available in Visual Studio 2012 express edition. The full featured Code Map is only available in Visual Studio 2012 Ultimate Edition. Visual Studio 2012 Premium and Professional editions also allow limited read-only code map support.

If you have Visual Studio 2012 Ultimate edition, you should be able to find the following menu item. Actually this is the only step we need to generate dependencies between project assemblies.

Here Include File is available to support C++ projects. Since we don't have a C++ project in our solution, we see the following message if we select Include File option:

Selecting For Solution displays the dependencies between projects in a solution. The map is generated on a Pan & Zoom surface which can be dragged in any direction. Double clicking the view should zoom in which can also be done using the mouse wheel. There are other zoom options available on the view as well. It has a single node with title as Externals. This refers to the external libraries referred by all the projects. I think this is better than providing a separate Externals window for each project because that would just clutter the view without providing any extra help. We just need to see what external libraries our application depends upon and one node serves the purpose for this.

A similar map can be generated using the solution explorer. We can right click the solution file in the solution explorer and select Show on Code Map. Alternatively, we can select the new Show On Code Map button in Context Menu. The difference is that it would just show the dependencies between projects in the solution, hence no external dependency would be shown here. You can also notice the assembly nodes in light green. This is general convention in Visual Studio for code map that the results are shown in this color code. You can change the color in the Legend tool window.

We can clear the highlighting by using the following Layout menu. It updates the graph node to the original node format with the default icons.

If we add more assemblies in the solution and add references to the existing projects, we can update the new references from the context menu by selecting the assemblies. We can also show all the assemblies which references the current assemblies.

Yes this is direct graph where dependencies are shows with a single arrow. The head of arrow is towards the dependee side.

It might take some time to generate the graph depending on the size of your solution. For my solution, it just took a few seconds to generate the graph for showing the dependencies between projects in the solution. But it shows meaningful status messages as follows:

If we need to see which projects depend on a particular external library, we can just expand the Externals node. Just expanding the externals node would display all the external libraries used by the current solution. Select a particular external library and you should see all the projects depending on it. The dependency is shown by directed arrow towards this external library. In our Northwind solution, only the view model project is depending on Workflow API as we have an example for controlling the application flow using Windows WF. This is part of Workflow chapter of the book.

We can see the dependencies of a project. Here Northwind.ViewModel is dependent upon Northwind.Interfaces, Northwind.Application and external libraries. It is also a target of dependency for Northwind.UI.WPF.

Dependency Analyzers
In order to make our life more beautiful, the map also supports analyzers. We can see which of these assemblies are not directly referenced by any other assemblies. This is achieved through Unreferenced Nodes analyzers. We can also see which of these assemblies are hubs. According to Visual Studio hubs are nodes which are top 10% referenced node in the graph. This can be added in the map using Hubs analyzer. The map also supports circular dependency analysis using Circular References Analyzer.

Here is the definition of Hub nodes in Code Map. They are 10% of highly connected nodes.

Adding all these analyzers would update the code map of Northwind example project as follows. We can also include Legend to determine and possibly change the color coding for the convention. It seems that Unreferenced Nodes analyzer takes precedence over Hubs analyzer as the nodes which are hub and unreferenced nodes simultaneously, they are shown with Unreferenced color coding.

Editing DGML file [xml)
The dependencies between projects are generated using DGML [Directed Graph Markup Language]. This was introduced with Visual Studio 2010. We can view the DGML file for the dependencies between projects by following through the context menu available for the solution.

Alternatively we can view DGML of a graph by the following menu items available in View Menu. The menu item is available when a graph is currently being displayed in Visual Studio.

For Northwind MVVM project, the dependencies between projects is generated as follows:

Visual Studio also supports creating schema for an xml document. Just follow the following menu:

The following schema is generated. Please remember that this is not the actual schema for the DGML format. It is just generated based on the data in the current DGML file.

We can also edit the generated DGML file. The updates in DGML should be reflected in the visual map for dependencies between projects. Here we have update the Label of Externals node to Externals Libraries and the update is propagated to the visual map.

Sharing Map with Team
The map can also be shared across the team. We can copy it as an image and paste it for creating design documents. This can also be saved in XPS format for saving it and later viewing in image format. Visual Studio also supports directly attaching it to email and opens the default email client for you.

Tooltip for Dependencies
Code map also provides tooltip on the arrows describing he dependencies between source and target nodes. The dependencies are shown as categories. It also specifies the information about source and target nodes. This is really handy for complex maps. Here we are using the tooltip for dependency between Northwind.UI.WPF and External Libraries.

Namespaces and Types in an Assembly
Generally when we need to see the list of namespaces and types available in an assembly we take the help of Object Browser in Visual Studio. Below we have expanded Northwind.ViewModel assembly. Look at the details of expansion allowing us to dig as we seem necessary. When we expand the assembly node, it shows us the namespaces defined in an assembly and the relationships for the types in those namespaces. We can further expand it to see the types available in a namespace. If we are interested to see the details of members in a type, we just expand the type node. Hovering over a method shows the details about the method in a tooltip.

If there is any dependencies between types, it would show the dependencies between types. It would show the details in the similar tooltips. Here we see the types in Northwind.ViewModel namespace and the relationship between the containing types.

The code map shows the relationship between these types. It would also show the dependencies with other types in the same / different namespaces. It would also show the exact dependencies between typed in different assemblies. All of this is shown when we select a type in code map.

Updating Map with Code
Since Code map is the map of some code, it has to keep updated with the code. If you think any particular node needs to be refreshed, you can always re-fetch its children. Let's look at the following button on a container node.

Expanding Contributing Links
Code map allows to see the details of the links providing more insight into the dependencies. Clicking on the dependencies link shows the following options. This allows to navigate between source and target nodes, plus we can expand the nodes to see more dependencies between nodes.

Here we have selected to see the dependencies between assemblies in a separate window for and Northwind.Interfaces and External Libraries. Selecting a particular type shows the exact details of dependency.

Showing Related Assemblies
If some related assembly references are missing then code map supports adding them. Just follow the following menu.