.NET Projects: Analyzing Code with NDepend

Introduction

In previous articles to this series, I’ve shown how one can set up source control, structure a project, automate builds with NAnt, and analyze resulting code with FxCop.

  • compile code - NAnt
  • run unit tests
  • perform code analysis - FxCop
  • generate documentation
  • create distributable packages

Following my overall plans in building as robust a software solution as possible, I’ve decided to start collecting various metrics from my code base after each build. To that end, it’s time for NDepend to join the party.

What is NDepend?

NDepend is a code analysis tool, built to analyze .NET assemblies. It performs static analysis, meaning it can examine compiled code without actually running it. This quote from the homepage sums it up rather nicely:

NDepend is a tool that simplifies managing a complex .NET code base. Architects and developers can analyze code structure, specify design rules, plan massive refactoring, do effective code reviews and master evolution by comparing different versions of the code.

http://www.ndepend.com/

During analysis, NDepend collects various metrics about the code base under scrutiny. There is a full listing - more than 60! - of metrics on the NDepend site. Some of these metrics are:

  • lines of code
  • cyclomatic complexity
  • cohesion
  • coupling

After performing an analysis, NDepend generates a report, showing the results. These results can help you locate and reduce cohesion and coupling problems through refactoring. This can result in a streamlined code base with fewer interdependencies between different components.

NDepend compared to FxCop

The two have different purposes, but used together, they can be a powerful duo.

FxCop works at a lower level on your code - it is more of a correctness checker for individual lines of code, according to the framework design guidelines. In contrast, NDepend gives you a high-level view of your application, showing the interactions at the namespace, class, and function levels. Essentially, the overall organization of your project.

Like FxCop, NDepend is not by any means a replacement for code reviews. It is still necessary to eyeball code now and again, but both of these tools can help to reduce the manual process involved.

I believe FxCop and NDepend are complimentary tools. There is a small overlap in their functionality, but otherwise they are good to have working side by side when developing applications.

Using NDepend

The NDepend package includes a GUI application, VisualNDepend.exe. It can be used to create, analyze, and view results for your NDepend projects. In this case, I mean you create a “project” within NDepend that contains references to the assemblies to be analyzed, as well as project-specific settings. I’ll illustrate these further along.

NDepend

* note that all of the images in this review can be clicked on to view larger versions.

The VisualNDepend start screen is pretty straightforward. On the top-right, there is a panel with link to some getting started videos - they are worth the time! The next panel down has buttons to install NDepend addins for Reflector and Visual Studio 2005/2008. The bottom panel panel shows any available updates to the software, with buttons to download the newer version or to view the release notes.

On the left is a list of recent NDepend projects, with options to open or create a project, do a “quick project” (lets you do an ad hoc kind of analysis, without creating a project specifically), and compare two versions of your code base (great way to see how your own project evolves).

To start this off, I’ll show how to create a new project. Just click the Create Project option in the left panel.

Adding analysis targets to a new project

To take a quick way out of this step, you can specify the Visual Studio solution (.sln) to analyze, but it’s for VS 2005 or later. Otherwise, you can take the slightly longer route and specify the (.dll, .exe) files to be analyzed. If matching .pdb files are in the same location, they will automatically be referenced as well - you do not need to select them yourself. The PDBs are not essential to NDepend doing it’s work, but they do have a use in providing extra information such as lines of code. If the PDBs are included, you get more detailed results. As an extra convenience, you can drag and drop files/folders from Windows Explorer into the respective panes, so you don’t have to browse for them through NDepend.

The upper section is shown or hidden by clicking the View/Hide Folders button. It is automatically populated with the folders where your selected assemblies are located. The Tier Assembly section on the lower right list assemblies that are directly referenced by the ones being analyzed. This listing cannot be directly modified, although it does change based on what assemblies are selected for analysis.

Now that some targets have been added, it’s time to do run the analysis. Just click the green arrow up in the toolbar. Depending on the size of your codebase, this process may take a few seconds, or a few minutes.

NDepend after completing analysis

When you analyze a project in VisualNDepend, there is a LOT of information to take in at the end. The first few times, it’s easy to feel a little overwhelmed, but give it a while, and it will start making sense! I’ll break this down and discuss each of the sections in more detail. I’ll go through each of the panels in clockwise fashion, starting at the upper-right corner.

Metrics

The metrics view

This view shows how parts of your code compare based on different metrics. The assemblies under analysis are divided by thick yellow lines, and the assembly name is shown, underlined, in the upper left corner of the assembly’s zone. Namespaces within an assembly are separated by thin yellow lines.

Throughout this view you will see a number of large ovals, most of which are composed of smaller ovals. The larger ones represent classes, and the smaller ones within represent class methods. Hovering the mouse pointer over any one of the ovals will show the name of the namespace, class, and method being hovered.

You can change which metric is being used to compare the code base. There is a Metric dropdown list at the top of the metrics view - just change the selection there and the metrics view will change accordingly. Some of the metrics in that list are lines of code, number of methods, and cyclomatic complexity.

You can also change the level at which the metric view works. By default, it is at the method level, but you can change another dropdown - labeled Level - to view metrics at the field, type, namespace, and assembly levels. Each successive option shows less detail about the same sections under analysis - you will see totals rather than the breakdown at lower levels.

Between the level and metric dropdowns, you can get a very deep look into your application!

Dependencies

The dependency matrix

This is a really neat feature. It shows the dependencies between components of your code. It starts at the namespace level, and it can be drilled down to the field level.

Along the top are the assemblies of your application - the items being examined. Down the left side is a list of assemblies - those of your application, at the top, with shades of yellow for background, and any external assemblies (framework, third-party, etc) used by your application, with blue and white backgrounds. You can click the plus signs to expand namespaces and classes, and contract them as well when clicking the minus signs.

The diagonal line indicates where the same items along the top and the side intersect…There’s no point in comparing a particular namespace with itself, is there?

Hovering over any cell highlights the row and column of the grid that intersect on that cell. Hovering any of the items listed on the side or top of the grid highlights that row or column, respectively. This is very useful to keep you visually oriented.

A cell can have one of three colours, described as follows:

  • blue cells indicate an item listed along the side is used in some way by the matching item along the top.
  • green cells indicate an item along the side is somehow using the matching item on the top.
  • black cells indicate a cyclic dependency, where each item uses the other. This is generally not a good thing…Consider it a red flag (or in this case, a black flag! :P) of tight coupling in your code. Fortunately for me, there are none in my application, but it could certainly happen in bigger, or poorly designed, code bases.

The blue and green cells essentially show the same dependency from opposing points of view. Regardless of the cell’s colour, the number within indicates the number of times (namespaces, classes, methods) one item is used by the other. An empty cell means there is no dependency between the two items.

If you have a number of cyclic dependencies, over several cells, that are bound to each other, a thin red border will be drawn to show the dependency cycle containing those relationships. The box can be just a few cells in size, or it can be huge, potentially up to the full size of the code under analysis. The NDepend website has a screenshot of the .NET framework under analysis, and there is a very large red box in the dependencies view!

If you right-click any cell with dependencies, you get a small menu of possible actions based on that cell. Double-clicking the cell drills down into the relationship, showing more detail. You can click the green arrows at the top of this view at any time to move back and forward between views. Single-left-clicking a cell shows a boxes-and-arrows diagram of the dependency - very handy.

Looking at the diagram above, it is easy to see that my web project is making direct use of my data layer, something that is generally worth avoiding in an n-tier application. So to find out the details of that use, I can single-click the cell where those assemblies intersect.

Boxes and arrows diagram of DataAccess dependency in Web

The generated boxes and arrows diagram pinpoints the usage of my data layer by the web layer. Now I know where I have to go to tease apart that dependency.

There is a Weight on Cells dropdown at the top of this view that, when changed, will update the matrix. The numbers will reflect the type of metric selected. The options include types, methods, and fields. Another way to control the amount of detail to see!

Using the drill down capability, you can get into a detailed view of dependencies. I think that is where the name of this software is coming from!

Code Query Language

Code Query Language (CQL) is a custom querying language that strongly resembles SQL. It can be used to retrieve and display more detailed information about the assemblies being analyzed. When you create a new project in VisualNDepend, the software automatically adds some standard CQL queries to the project. CQL was created specifically for NDepend, but a full specification is publicly available on the NDepend website.

The use of this functionality becomes apparent when you want to collect some specific details about your code, such as which functions or classes are not used at all, or which functions are not well-documented, or which functions are very long or complex…The list goes on. This can be helpful to enforce coding standards for the project. You can get much more from these than the standard metrics can provide.

Some of these queries can be very subjective (such as preferred method length, or percentage of comments), depending on your preferences and project requirements. They can be tailored as you please, and you can write your own - all the queries defined for a project are stored in the project file. And if you are at all familiar with SQL, you should be fine to write CQL! The official site has an in-depth CQL reference.

The CQL panel

Note the columns that are shown, particularly the #Items columns which indicate how many items have been caught by a particular query. The green dot means all OK for that category, yellow means you have some work to do! So if the screenshot above is any indication, I may have some work cut out for me!

Clicking one of the categories on the left side updates the right-hand panel, which contains queries specific to the category. When one of the queries is clicked, the class browser panel is updated to show the items that violate the current constraint. Double-clicking a query allows you to edit it, so you can tailor the constraints to your preferences.

The CQL panel - editing a query

Clicking the Save button saves the updated query in your NDepend project file, whereas Cancel aborts any changes.

You can use the standard queries as they are, or customize the constraints to your preferences or project requirements. You can even write your own CQL queries, if you require specific constraints.

Class Browser

The Class Browser

The class browser is a folding treeview of all the namespaces, classes, methods, and fields in your application. By expanding nodes in the treeview, you can drill down into your application’s architecture. Hovering over any of the namespaces, classes, or methods listed in the treeview will highlight the matching item in the metrics view, if it is open. It will also update the info panel, mentioned below.

.NET Framework namespaces used from within your application are also included in this view, differentiated by text color. The text in blue represents namespaces external to the subject assemblies, black text represents the assemblies being analyzed. You can drill down into those too. Interestingly, the view only shows the classes and methods being used by your application. Just as well, I guess, considering the size of the framework!

Info

The Info view

The Info panel shows some basic metrics about the currently hovered item in either the Metrics view, Dependencies view, or the Class Browser. The information displayed includes lines of code, lines of comments, and number of methods and fields. This window gives a distilled view of what would be in the final report after analysis. You can get more granular detail by drilling down in the Class Browser as described above.

Generated Report

In addition to the interactive results, VisualNDepend also generates a group of XML files containing the results of the analysis. These files are then merged and converted to a single report in HTML format, including images. The original XML files are retained though. When an analysis has been completed, the matching report is automatically opened in your default web browser.

The Report options panel

There is a section in the project properties (shown above) within VisualNDepend where you can choose to use the standard report, or to specify your own custom XSL file to create the final report. If you use the standard report, you can specify what sections to be included, and the order they should appear in. If you go the custom route, you will have to handle these details yourself.

NDepend also generates some useful images to be used in the final report, some of which I’ll show below, based on my project.

Abstractness vs Instability diagram

Abstractness refers to how reusable or extensible the assembly is. This is often helped by using interfaces and/or base classes within an assembly. Instability refers to how much an assembly is used via its public interface (not referring to interface classes here). Less instability means an assembly is widely used, where more instability is a sign of a little-used assembly. If an assembly were stable and widely used, then changing its public interface would cause a lot of breaking changes.

The two red zones indicate extreme relationships between the two axes, which I’ll try to summarize here:

  • zone of uselessness - the assembly is overall very abstract, but is not used much.
  • zone of pain - the assembly is not very abstract and is widely used, making changes difficult, or painful.

It’s generally good for your assemblies have something of a balance between the two extremes, so along, or near, the diagonal line is a good place to be. This can’t always be helped if you are using external assemblies, such as from the .NET framework or third-party assemblies, as you won’t have much control over those. But even then, it’s no reason to panic if any assemblies - your own or external ones - are in either of the two zones, as this chart is just to make you aware of the situation. It’s not saying that you must take action on those wayward assemblies.

Namespace-level boxes and arrows diagram

I like this one…it is essentially a static representation of the dependency matrix in VisualNDepend, in that it shows the dependencies of the namespaces involved in your application. The blue boxes are your own namespaces, while the yellow ones are from the .NET framework, or third-party assemblies. Despite not showing the numbers that the Dependency Matrix does, this diagram does nicely sum up your code’s namespace usage.

As demonstrated in the section on the Dependencies view, my web layer is directly using my data layer. That fact is very apparent in this boxes and arrows diagram, staring me in the face, reminding me to resolve that issue!

The standard report also includes summaries of common metrics (for the whole project, and broken down by namespace and type), a table listing the dependencies in your application, and results of CQL queries in your project file (standard ones plus any custom ones).

For a report on a real-world application, have a look at the NUnit sample report… The boxes and arrows diagram is downright scary, and the abstractness vs instability diagram is something interesting too. If you take a look at the sample report, you will get a much better idea of what it includes than I could ever describe!

Integration with Reflector

NDepend’s start screen provides the option to install NDepend addins for Reflector and Visual Studio 2005/2008. This adds an NDepend context menu to those applications, which you can use to jump straight to NDepend. I’ll demonstrate with Reflector.

Do as you normally would in Reflector: load up a set of assemblies to analyze. For the purpose of this example, I’ll load up the .NET 1.0 assemblies. When assemblies are loaded, right-click in the open space to see the NDepend addition to the context menu.

The NDepend context menu in Reflector

The Go to VisualNDepend item is pretty obvious (it opens a new instance of NDepend), but there is a submenu just below, which has several more options, and yet more submenus. The additional submenus provide quick access to specific CQL queries - could be convenient! You could just click the View external dependencies on matrix option, and the currently loaded assemblies will be added to an NDepend quick project, and you can run an analysis pretty quickly this way.

I would note that I have a pretty good desktop PC here, and NDepend took a few minutes to analyze the .NET 1.0 assemblies - who knows how long it would take to analyze .NET 2.0! Or even 3.5, I’m not even going to try it…Beware!

The Visual Studio integration is pretty similar, so I won’t go into it here.

Adding NDepend Task to Automated Build

Besides the VisualNDepend GUI application, the NDepend package also includes a command-line tool, NDepend.Console.exe. With the use of this tool, NDepend reports can easily be generated from the command line, and, indeed, a build script. The NDepend site has a reference of the command-line parameters to use.

Like with the FxCop task shown in my previous article, it is not difficult to add an NDepend target to a NAnt build file. My wadmt.build includes the following target, which just uses the exec task to run the command-line tool.

<target name="analyze.ndepend">
    <property name="dir.build.output.ndepend" value="${dir.build.output}\NDepend\" />

    <mkdir dir="${dir.build.output.ndepend}" />

    <property name="ndepend.input" value="${directory::get-current-directory()}\wadmt.ndepend.xml" />

    <exec program="${dir.tools}\ndepend\NDepend.Console.exe" failonerror="false">
        <arg value="${ndepend.input}" />
    </exec>
</target>

Nothing complicated. The reference indicates that the only required parameter (which must be the first one, as well) is the location of the NDepend project file. Strangely, it must be an absolute path, not relative, so that is the reason I use the directory::get-current-directory() function, provided by NAnt, to determine the location of my NDepend project file. There are several optional parameters, which may appear in any order AFTER the single required one.

The result of the task is a report generated in the location specified in the project file. This report is the same as what the VisualNDepend tool would create - HTML with images.

Same as with FxCop, I chose to add the NDepend binaries to the tools folder of my project source repository. This allows me to do a single check-out and build, test, and analyze my project all in one step.

Get NDepend

NDepend is a commercial tool, with a licensing system for commercial use of the tool. There is also a time-limited version available for download, which may be used for short-term evaluation in the case of commercial usage. The free version may be used over a longer term by academic or open-source projects. The free edition also has some limitations, but they do not appear particularly onerous. There is a comparison table on the site.

The paid version starts at about $444 (USD) per license, but the individual price goes down when making volume purchases. Updates within a major version are free.

Conclusion

This was a brief look at NDepend, but hopefully I have suitably demonstrated the power of the tool. Heh, reading it now, it doesn’t seem all that brief to me!

I showed how one can use NDepend to select and analyze assemblies built in .NET, followed by examining the interactive results. I also talked a little bit about the generated report and its contents. Finally, a code snippet was shown to integrate NDepend analysis into a NAnt automated build.

NDepend is such a versatile tool, in the sheer amount of information it provides. Thanks to NDepend, you can quickly have a high-level view of the organization of your application. Functionality is provided to drill down to locate dependencies between application components, and gather information at more granular levels. Values are given for standard metrics such as lines of code and cyclomatic complexity.

Of course, there is much more material on the NDepend website…Have a look at the screenshots (plenty of them!), testimonials (quite a few of those too!), online demos, and finally some rather extensive documentation. And if you want to try the tool out for yourself, be sure to download the trial version!

Additional Reading

  • NDepend website - naturally, the most authoritative source of information on the tool will be on the official website. There are FAQs, tips, online demos, screenshots, and more.
  • Patrick on CodeBetter.com - technical blog of NDepend’s creator, Patrick Smacchia. Regular postings on features of the tool, often including useful CQL queries to use.
  • Hanselminutes Podcast 51 - Static Code Analysis with NDepend - Scott Hanselman does a podcast overview of NDepend, if podcasts are up your alley. They aren’t up mine, but there is an archive of podcasts with PDF transcripts, which does the job for me!

Disclaimer

Apologies if this review sounded like a commercial. I was given a free license for NDepend Pro, such that I could review it and spread the word. I’m not gushing over it just because it was free - I really do feel the tool has great utility! And many thanks go to Patrick Smacchia for his generosity.

Make a Comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>