Chapter 15

Analyzing Applications Using Architecture Explorer and Dependency Graphs

What's In This Chapter?

  • Exploring the Architecture Explorer
  • Using the Architecture Explorer to understand existing code
  • Visualizing existing code using dependency graphs

Wrox.com Code Downloads for this Chapter

The wrox.com code downloads for this chapter are found at www.wrox.com/remtitle.cgi?isbn=1118314081 on the Download Code tab. The files are in the Chapter 15 download folder and individually named as shown throughout this chapter.

Every software developer has been in the following situation at some point in time: You have just started a new job with a new company, and you're expecting to go in and write some brand-new, fancy application. You are up to speed on some of the latest coding technologies, methodologies, and languages. You arrive for work ready to sit down and use everything you know to crank out some code to help the company succeed.

And then it happens. There is a legacy system that was built several years ago that must be updated. You are the lucky developer who has been assigned to make that update—never mind that you have no idea or concept of how the application works, the inner workings of the calls between different objects, or how it interacts with other third-party add-ins.

Before Visual Studio 2010 Ultimate, the only solution to this problem was to get your hands dirty in the code. You would have to open up the code files and start tracing (as best you could) how the logic flows between the different classes and components that make up the application. Maybe you would even try (as best you could) to diagram out the logic flow on a piece of scratch paper.

Visual Studio 2010 Ultimate changed all that with the introduction of the Architecture Explorer tool, and Visual Studio Ultimate 2012 has added even more functionality to make exploring your application easier. Using Architecture Explorer, you can quickly learn more about your current application by visualizing the organization and relationships among the various parts. By using Architecture Explorer in conjunction with dependency graphs, a developer is able to analyze an existing system and quickly understand it. These tools also enable the developer to find areas in the application that should be improved or modified.

This chapter examines both Architecture Explorer and dependency graphs. The chapter begins with a discussion about the Architecture Explorer tool, what it is, and how it was designed to be used. From there, you learn about using Architecture Explorer and how you can use it to drill down into your existing application.

After that, you learn how to take the information from Architecture Explorer and make it graphical by turning it into a dependency diagram. Dependency diagrams are a nice way to graphically view your code, as well as code contained in other managed DLLs (such as the .NET Framework). In Visual Studio Ultimate 2012, dependency graphs have received some nice enhancements, including the ability to visualize code without the use of Architecture Explorer. In this chapter you find out how to utilize those features and learn about the Code Index, a new back-end database for dependency graphs that helps speed the visualization process.

Understanding the Code Base

Though the example used through this chapter is rather simplistic, it works well to introduce the different capabilities of Architecture Explorer and dependency diagrams. So, let's take a look at the code base used throughout this chapter so that later sections will make more sense.

Figure 15.1 shows the projects and code files that make up the sample solution.

This solution is made up of two project files:

  • FirstProject—This project contains two class files, FirstClass.cs and SecondClass.cs. The FirstClass.cs class file contains two methods, Method1 and Method2. The SecondClass.cs class file contains one method, Method3.
  • SecondProject—This project contains one class file, ThirdClass.cs. The ThirdClass.cs class file contains three methods: Method4, Method5, and Method6.

Getting confused yet? Let's add to it a little more:

  • Method1 calls Method3 and Method2.
  • Method2 calls Method1.
  • Method3 doesn't call any other methods.
  • Method4 calls Method1.
  • Method5 calls Method3.
  • Method6 doesn't call any other methods.

Whew! All of that sounds just a little bit confusing, and this is only a contrived solution with two projects and three classes. Imagine what it would seem like with a real software solution, with hundreds of projects, and thousands of classes and methods. As you are about to learn, though, Architecture Explorer and dependency graphs are going to help with the understanding of any project, both small and large.

Architecture Explorer Basics

In Visual Studio Ultimate 2012, you use Architecture Explorer to drill down into your existing code, which enables you to select the code you want to visualize using a dependency graph. You can use Architecture Explorer to browse existing source code open in Visual Studio Ultimate 2012, as well as browse compiled managed code located in .dll or .exe files. You can extend Architecture Explorer with third-party tools, providing the capability to browse other domains of code or other items. After you have drilled down into your code and selected the items you are interested in, you can turn that information into a dependency graph.


Note
The Architecture Explorer is only available in Visual Studio Ultimate 2012, and will work on any managed code from .NET 2.0 onward.

Understanding the Architecture Explorer Window

To open Architecture Explorer, open Visual Studio Ultimate 2012. From the main menu of Visual Studio, select View ⇒ Architecture Explorer. Alternatively, from the main menu of Visual Studio, you can select Architecture ⇒ Windows ⇒ Architecture Explorer.


Note
The shortcut keys for opening Architecture Explorer are Ctrl+/ and Ctrl+R.

Figure 15.2 shows an initial view of Architecture Explorer.

Architecture Explorer represents structures as nodes and relationships as links. As you browse through your code base using Architecture Explorer, nodes are displayed in successive columns to the right. The first column in Figure 15.2 shows the initial domains and views that are available for browsing. Selecting a domain or view causes a new node to appear to the right with the results of that selection.


Note
You can browse all the way to the level of statements for Visual C# and Visual Basic projects. For other languages, you can browse to the procedure level.

When you select a node in a column, the next column shows node information that is logically related to the selection made in the initial column. For example, selecting a class in a column shows the members of that class in the following column. You have the capability to select multiple nodes in multiple columns and then display that information as a dependency graph.

Architecture Explorer Options

As you can see in Figure 15.2, there are four options (represented as icons) available on the left side of the Architecture Explorer window.

The first option provides the capability to create a new dependency graph document from all the nodes currently selected in Architecture Explorer. To include only the nodes in the current column, you can press and hold the Ctrl key before clicking this option.

The second option enables you to add the selected nodes from Architecture Explorer to an existing dependency graph that is currently visible in Visual Studio. As with the first option, to include only the nodes that are in the current column, you can press and hold the Ctrl key before clicking this option.

The third option enables you to export the information from Architecture Explorer into a .dgml file. A Directed Graph Markup Language (DGML) file is the XML schema used to define a dependency graph. Selecting this option exports all the information open, in all of the columns, into a .dgml file that you can view at a later date.

The fourth option resets Architecture Explorer to its initial state, cleaning up the window and enabling you to start from the beginning.

Navigating through Architecture Explorer

To begin navigating through Architecture Explorer, select one of the rows in the first column. You have several options.

Under the Visual Studio column heading you can choose to view the information in your solution either by classes or through a solution view, which enables you to view the different files in your solution. If you don't want to drill down through all the files in a solution, you can click the Select Files option and open only the files you are interested in.

For this example, let's navigate through the code using the Class View options. In Architecture Explorer, select Class View under Visual Studio <My Solution>. This opens a new column to the right of the selected column, displaying a list of all the different namespaces in the solution, as shown in Figure 15.3.

In Figure 15.3, you see that the two namespaces currently in the solution (FirstProject and SecondProject) are displayed on the right of the screen.

Obviously, for a large project, you could have many namespaces, which could result in a large scrolling list in this column. The list box at the top of the column enables you to filter the information in this column. For example, if you only wanted to see namespaces that began with “Second,” you could type Second in the list box, press Enter, and the contents of the column would be filtered, as shown in Figure 15.4.

Notice the differences between Figure 15.3 and Figure 15.4. Figure 15.3 displays all the namespaces in the solution. Figure 15.4 displays only the namespaces that match the filter expression. Also, notice the filter icon that is added in the lower right of the column, giving a visual indication that the column is currently being filtered.


Note
When you type in a filter, a substring search is performed. For example, if you enter c for the filter statement, it matches on both FirstProject and SecondProject.

To clear the filtering on a column, simply delete the filter statement and press Enter. This removes the filter and displays the entire contents of the column.

From the namespace column, you can navigate into the different classes contained in a particular namespace. Selecting the FirstProject namespace opens a new column to the right, containing the classes contained in the FirstProject namespace—in this case, FirstClass and SecondClass. As mentioned previously, you have the capability to filter on this column by entering your filter criteria into the list box at the top of the column. You also have the capability to filter based on different categories and properties.

Click the filter button located to the left of the filter list box at the top of the column. This displays all the possible categories and properties that can be filtered on, as shown in Figure 15.5.

For this particular column on classes, you have the following filter options:

  • Class
  • Is Abstract
  • Is Final
  • Is Public
  • Icon

You have the option of selecting one or multiple filter options, allowing you to drill down into the information contained in the column in a variety of ways.

Exploring Options for Namespaces

In addition to the filtering options mentioned previously, you have another option for controlling what is displayed in a column. In Figure 15.5, just to the left of the column containing the classes, there is a collapsed column labeled Types. Clicking that collapsed column expands it, as shown in Figure 15.6.

This column provides a variety of options for determining what is initially displayed in the column. The first section is the Node Navigation section. By default, the Types node is selected, which shows all the different available types—in this case, FirstClass and SecondClass. You have the capability to select the following nodes for display:

  • Classes
  • Delegates
  • Enums
  • Interfaces
  • Members
  • Modules
  • Namespaces
  • Structs
  • Typedefs
  • Types
  • Unions

You can select multiple nodes by holding down the Ctrl key while you select the nodes. Each time you select a node, the column to the right recalculates with the new data to display.

You have the capability to organize the link types into two categories: outbound and inbound. These categories describe the direction of the link in relation to the currently selected node.

An outbound link points from the currently selected node to the next related node. For example, say that you have currently selected the FirstProject namespace. If you select All Outbound under Outbound Navigation, the two classes, FirstClass and SecondClass, are displayed. FirstClass and SecondClass exist in the FirstProject namespace, and, as such, are the next related nodes beneath the FirstProject namespace.

You have the following options for Outbound Navigation:

  • All Outbound
  • Contains

An inbound link points from a previously related node to the currently selected node. For example, say that you have currently selected the FirstProject namespace. If you select All InBound under Inbound Navigation, the solution file MySolution is displayed in the next column. MySolution exists above the FirstProject namespace from a hierarchical perspective.

The following options exist for Inbound Navigation:

  • All Inbound
  • Contained By
  • Namespace Reference Source

You also have the capability to perform Analysis and Grouping options. Using the Analysis options, you can look for circular references or hubs (for example, classes) that are not being called or used. The Grouping options also enable you to group by container or properties.

The following options exist for Analysis:

  • Circular References
  • Find Hubs
  • Unreferenced Nodes

The following options exist for Grouping:

  • Group by Containers
  • Group by Properties

Exploring Options for Classes

Previously, you learned about some of the Node Navigation options from a namespace perspective. Let's continue the example by selecting the FirstClass class in Architecture Explorer to see what Node Navigation options are from a class perspective. Figure 15.7 shows Architecture Explorer after the FirstClass class has been selected.

By default, Node Navigation defaults to Members. As you can see in Figure 15.7, FirstClass has only two members: two methods named Method1 and Method2. As you might expect, the filtering options at the top of the column work the same as they have in previous columns. However, now that you are working on a class level as opposed to a namespace level, you have different navigation options.

From the Node Navigation options, you can view any of the following information about the selected class:

  • Classes
  • Delegates
  • Enums
  • Generic Arguments
  • Generic Parameters
  • Interfaces
  • Members
  • Structs
  • Types

Outbound Navigation has several more options available to it, as you would expect. Classes can inherit from other classes, implement interfaces, and have attributes. The following are the Outbound Navigation options:

  • All Outbound
  • Contains
  • Generic Arguments
  • Generic Parameters
  • Implements
  • Inherits From
  • Uses Attribute

Inbound Navigation also has more options, including the following:

  • All Inbound
  • Contained By
  • Inherited By
  • Used By

The Analysis patterns and Grouping options are the same as before.

Exploring Options for Members

For this example, drill down one more level to look at some of the Node Navigation options available at a member level. In Architecture Explorer, select the Method1 method, as shown in Figure 15.8.

As you would expect, the Node Navigation options have changed again. By default, when you select a method, the resulting column in Architecture Explorer shows all the outbound calls that method makes (that is, all the methods that the selected method uses).

From a Node Navigation perspective, you can view any of the following information about the selected method:

  • Classes
  • Generic Arguments
  • Generic Parameters
  • Methods
  • Parameters
  • Types

Outbound Navigation has several more options available to it, as you would expect. The following are the Outbound Navigation options:

  • All Outbound
  • Calls
  • Contains
  • Function Pointers
  • Generic Arguments
  • Generic Parameters
  • Parameters
  • Return Types
  • Uses Attribute

Inbound Navigation also has more options, including the following:

  • All Inbound
  • Called By
  • Contained By
  • Function Pointers
  • Property Gets
  • Property Sets

The Analysis patterns and Grouping options are the same as before.

Dependency Graphs

They say a picture is worth a thousand words, and dependency graphs prove that saying. Architecture Explorer is invaluable for its capability to drill down into the code base, but it can also present so much information that it can be a bit overwhelming as well. Given its capability to continuously scroll to the right, you could become confused after doing an intense, deep drill-down. Wouldn't it be nice to be able to visualize the information from Architecture Explorer? Dependency graphs enable you to do just that.

You can use a dependency graph to explore the relationships and organization of an existing code base. These graphs make it easy to understand code that is new or unfamiliar to you. The relationships on the graph make it readily apparent how different areas of code relate to one another and can show you how a change to one area of code could cause potential issues for other areas of the code. You have multiple ways to view your dependency graph information.


Note
A dependency graph shows only those dependencies in code that have gone through a successful build. Any code that did not build successfully does not appear on the dependency graph.

 


Note
Dependency graphs are also referred to as directed graphs. The two terms are used interchangeably.

Creating the First Dependency Graph

You actually have several different options for creating a dependency graph. Because the first half of this chapter has dealt with Architecture Explorer, let's continue that thread so you can see how you can create dependency graphs from Architecture Explorer. Later, you learn how you can create dependency graphs, without using Architecture Explorer, to get a quick overview of your source code or compiled code.

Previously, using Architecture Explorer, you learned how to drill down into your source code. You saw how to select the FirstProject namespace, the FirstClass class, and the Method1 method. From here, let's select Method2 and Method3 in Architecture Explorer.

To display this information as a dependency graph, simply click the Create a New Graph Document button on the Architecture Explorer window. This takes all the information selected in Architecture Explorer and displays it as a dependency graph, as shown in Figure 15.9.

As you can see, this graph provides an easy-to-understand graphical overview of the information contained in Architecture Explorer. You can see that the FirstProject namespace contains the FirstClass class. The FirstClass class contains two methods: Method1 and Method2. Method1 makes references to both Method2 and Method3. Also, you can see that Method2 makes reference to Method1.

But the dependency graph can do much more than just show the layout of method calls. By hovering the mouse over a node in the graph, you can view detailed information about that node. Figure 15.10 shows the information that is displayed for Method1 when you hover the mouse over the Method1 node.

This information shows the type of function this is (in this case, a method). It shows the assembly where this method resides, along with namespace and type information. It also shows helpful information such as whether the method is static, and if it is a public or private method. All this information can help you understand your code base better, without requiring that you open a code file.

However, if you want to view the code file for a particular node, that is easy to do from the dependency graph. You simply right-click the node and select Go To ⇒ Go To Definition from the context menu to open the code file associated with the selected node.

You can easily add more nodes to an existing dependency graph. Let's say you create an initial dependency graph using Architecture Explorer. Now, let's say that you want to add more nodes to the graph to make it more detailed. Select the nodes you want to add in Architecture Explorer and then click the Add Selected Nodes to Existing Graph button on the left-hand side of the Architecture Explorer window. This adds the selected nodes to the existing graph.

Creating a Dependency Graph without Architecture Explorer

You also have the capability to create a dependency graph without even opening Architecture Explorer. This can be very handy when you want to analyze the entire code base of your code without having to worry about drilling down through particular elements using Architecture Explorer. For example, you can drag and drop a .NET assembly onto a blank diagram and it automatically decomposes the assembly for you.

From the main menu of Visual Studio 2010, select Architecture ⇒ Generate Dependency Graph. This provides you with two options for generating your dependency graph:

  • For Solution—This option generates a dependency graph based off the current open solution.
  • For Include File—This option generates a dependency graph based off a C++ include file.

Figure 15.11 shows an example of a dependency graph generated using the For Solution option.

Each project generates its own assemblies, which, in the example project, would be FirstProject.exe and SecondProject.exe. In addition, there is a reference to an Externals assembly, which includes the references and calls into the .NET Framework. Though the black-and-white picture might not show it well, the legend is color-coded to help you easily understand the different aspects of your dependency graph.

Navigating through Your Dependency Graph

You may be thinking that the information shown in Figure 15.11 is nice, but it is not that helpful. It sure would be nice if you could drill down into the dependency graph in a manner similar to how you drill down into information in Architecture Explorer. Well, guess what? You can!

By clicking the arrow icon located at the top-left of a node, you can expand the node to view the detailed information in that node, as shown in Figure 15.12. The arrow icon will become visible when you mouse-over the node.

FirstProject.exe is comprised of the FirstProject namespace. The namespace contains three classes: FirstClass, SecondClass, and Program. FirstClass contains two methods: Method1 and Method2. SecondClass contains one method: Method3.

The dependency graph shows the interactions between the different methods. It also shows that the SecondProject.exe assembly makes calls to Method3 in the SecondClass class. To view exactly which object is making this call, you can expand the information for that assembly on the dependency graph.


Note
The information displayed in Figure 15.12 is the same information displayed in Figure 15.9, just in a different format. You can format a dependency graph using a variety of different options.

The next question you might have is whether you can drill down into that external node. The answer is, yes! Using a dependency graph, you can drill down into external assemblies (such as the .NET Framework). This is an incredibly powerful tool. You now have the capability to delve into the .NET Framework and map how all the objects and methods interact with each other, enabling you to come to a much better and deeper understanding of how the .NET Framework works. Figure 15.13 shows an example of this.

You also have the capability to interact with your dependency graph by right-clicking the graph and selecting from a variety of context menu options. You will recognize many of the options from Architecture Explorer. The exact options depend on what is selected on the dependency graph.

You can select a specific node on a graph and then choose the Select menu option from the context menu. This enables you to do the following:

  • Select all incoming links to the selected node
  • Select all outgoing links from the selected node
  • Select both incoming and outgoing links from the selected node
  • Select all connected nodes to the selected node
  • Select all children of the selected node

You have the capability to add groups and categories to the graph, enabling you to organize the graph in a more readable fashion.

Refer to Figure 15.12 to see another nice feature of dependency graphs, which is the capability to apply different analyzers to the information on the graph. You saw these analyzers before when you worked with Architecture Explorer, but they make even more sense when you see them in conjunction with the dependency graph.

From the Legend, click the Add button, select Analyzer, and then select Circular References. This analyzer looks for circular references, or infinite loops, in your graph. When those references are found, it highlights them (in red) on the dependency graph, instantly bringing them to your attention, as shown in Figure 15.14.

A second analyzer that is available is the Find Hubs analyzer. This analyzer shows which hubs are Node Property in the top 25 percent of high-connected nodes. This is a quick-and-easy way to see which hubs are involved with a majority of the work in the application.

A third analyzer that is available is the Unreferenced Nodes analyzer. This analyzer highlights any nodes that are not referenced by any other nodes. They are orphans. This is a good way to find areas of the code that are not being used either because of oversight or because they are no longer needed.

Dependency Graph Legend

In the upper-right corner of each dependency graph is the legend (see Figure 15.11). You can use the legend to help you understand all the different components that make up the dependency graph. One nice feature of the legend is that it is completely customizable, which means you can control the shapes and colors that are used on the graph, thus enabling you to customize the graph to your needs.

For the dependency graph shown in Figure 15.11, if you were to click the Add button on the legend, you would have the following four options that could be added to the graph:

  • Node Property
  • Node Category
  • Link Property
  • Link Category

Each of these options has sub-options underneath it that you can add to the legend. To see these suboptions, you will need to expand the nodes in the diagram, where they look similar to Figure 15.12. For Node Property, the options are the following:

  • Is Abstract
  • Is Final
  • Is Private
  • Is Public
  • Is Static
  • StrongName
  • Error
  • File Path
  • Group
  • Circular References

For Node Category, the options are the following:

  • Assembly
  • Class
  • Method
  • Namespace
  • Externals
  • FileSystem.Category.FileOfType.exe

For Link Property, the options are the following:

  • Circular Link
  • Weight

And, finally, for Link Category, the option is the following:

  • Calls

When you have added a new item to the legend, you can customize its appearance. You can click the icon in the legend and select from the following four customization options:

  • Background—This lets you select a color for the background of the node.
  • Stroke—This selects the color that outlines the node.
  • Foreground—This sets the text color in the node.
  • Icons—This enables you to select from a variety of icons to add into the node itself.

Dependency Graph Toolbar

You can use the dependency graph toolbar to modify the look and feel of a dependency graph. At the far left of the toolbar are the zoom controls. As you can imagine, a dependency graph can grow to be quite large. These tools enable you to zoom into and out of areas of the graph that you are interested in. You can use the drop-down list box to fit the graph to the page or to select pre-specified zoom options. You can also use the scroll wheel on the mouse to zoom in and out of the graph, and there is a scale located at the top left of the graph that you can use for zooming, as well as a button to fit to diagram to the screen. Figure 15.15 shows the dependency graph toolbar.

You use the next five toolbar icons to specify the directional flow of the dependency graph. These options include (reading from left to right) Left-to-Right, Right-to-Left, Top-to-Bottom, and Bottom-to-Top. The third option (a Top-to-Bottom flow) is the default. Simply click the appropriate button on the toolbar and the dependency graph re-orients itself. The fifth option is the Quick Clusters view. This view shows the nodes as clusters or hubs. In this view, the graph is arranged with the most-dependent nodes near the center, and the least-dependent nodes at the outer edges of the clusters of hubs.

The final button on the toolbar provides the capability to control when cross-group links are shown. A cross-group link represents a relationship between two nodes, located in different groups. By default, cross-group links are shown only on selected nodes. Using this button, you can make a change to show all cross-group links on the graph or to hide all cross-group links on the graph.

Dependency Graph Enhancements in Visual Studio 2012

One of the mandates with visualization in Visual Studio 2012 was to make visualization easier to use, as well as improve responsiveness. Earlier in this chapter you saw how visualization has been made easier to use. Now it's time to see how dependency graphs have been made better and faster.

You might have noticed while working through the examples earlier in this chapter that the graphs were much more responsive than in Visual Studio 2010.

When you generated a dependency graph for the entire solution, you probably saw the window in Figure 15.16 open.

When you generate a dependency graph, the first thing that happens is the solution is built. Next, the assemblies are indexed and stored in a SQL Server localdb database. This database is referred to as the Code Index. Then, the graph is built using the indexed information from the Code Index. Although this means the initial visualization of the graph takes longer to generate, after you start working with the graph you can very quickly drill down into elements or add new elements to the graph.

Zooming in and out of a dependency graph is much faster now as well. In Visual Studio 2010, the entire graph was stored in memory, which meant that a large graph could take up a lot of memory, causing the entire computer to slow down. In Visual Studio 2012, that is no longer the case. Through the use of the Code Index, only the portion of the graph that is being utilized at the time is brought into memory, making it much more responsive.

As just mentioned, the Code Index is created when the dependency graph is initially generated. It is possible to prepopulate the index during the automated build process, using build tasks. To do this, you need to make use of the Visual Studio Visualization and Modeling SDK, which is freely available from Microsoft.


Note
For more information on the Visual Studio Visualization and Modeling SDK, see the MSDN information available at http://archive.msdn.microsoft.com/vsvmsdk.

You can view the contents of the Code Index using Server Explorer in Visual Studio 2012. Open the Server Explorer window in Visual Studio 2012. Right-click the Data Connections icon and select Add Connection from the context menu. This opens the Choose Data Source window. Select Microsoft SQL Server, then click the Continue button. This opens the Add Connection window, shown in Figure.

Figure 15.17

15.17

In the Server Name field, enter (localdb)v11.0. Select the database named Repository. This is the Code Index database. Click OK to close the window and connect to the Code Index. Figure 15.18 shows a list of tables from the Code Index. At this point, you can open the tables to view the data collected by the indexing.

Summary

This chapter examined both Architecture Explorer and dependency graphs. The chapter started off discussing Architecture Explorer, why you would want to use it, and how to use it. From there, you walked through an example of using Architecture Explorer so you could become familiar with many of its features.

The discussion then moved on to dependency graphs. You learned how dependency graphs can be created with information from Architecture Explorer, as well as directly from solutions. You also learned about dependency graphs in depth and how to use all the options available. Finally, you looked at some of the enhancements to dependency graphs in Visual Studio 2012, including the use of the Code Index to speed performance.

Chapter 16 is the final chapter on the architecture tools available in Visual Studio Ultimate 2012. Chapter 16 looks at layer diagrams, how they are built, and how they are useful in dividing your code base into understandable sections, as well as how they can be used as a validation tool during the build process.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset