An Introduction to NDepend

No single person (or team) can know everything about a large codebase. Developers come and go, taking knowledge with them. Legacy code grows and mutates, as bugs are fixed and new features reluctantly touch old code. Deadlines loom, and changes aren’t adequately tested. Eventually, even when the code appears to be running okay, you’re never completely *sure where the land mines are. Experience has taught you that someone *will step on one… it’s just a matter of time.

That’s why we have certain tools and practices, like unit tests, regression testing, load testing, continuous build servers… the list goes on. We need information about what we’re doing, as close to when we’re doing it as possible, to minimize the chances of new code breaking the system. While CI ensures a clean build, and unit tests help ensure a clean execution, these tools don’t tell you much about the structure of your code, nor give an indication of methods and classes that are unhealthy or starting to stink. They give you a view of the trees around you, but not of the entire woods from 10,000 feet.

Contents

Why NDepend?

NDepend gives you the 10,000 foot view of your code. Some tools execute portions of your code and report back the results of execution (“dynamic” analysis). NDepend, on the other hand, parses your project and reports back statistics about the structure of your code (“static” analysis), including lengths of classes and methods, cyclomatic complexity, dead code, test coverage, etc. This information can help you determine how well your code is written, and help steer you in the direction of that which needs your attention most.

Patrick Smacchia’s timing couldn’t have been better, when he approached me about trying out the latest version of NDepend. I’d just been involved with a less than stellar release at work, the result of some broad-sweeping updates to some of our legacy code. Needless to say, the day after release was a blast, and I’m in the mood to learn more about what tools are available to help make the development life cycle more predictable, reliable, stable… sane.

This is my first walkthrough of NDepend, and I just want to share a few thoughts and features I found particularly interesting. This is definitely not comprehensive.

Getting Up and Running

Check out Getting started with NDepend. Patrick’s invested a lot in documentation, not just development, and it’s extremely helpful since NDepend is a bit overwhelming at first glance. But he obviously knows that, and you’ll encounter help in multiple forms along the way.

Register, download a small file, and unzip the contents to wherever you want to run it from (no installer). If you have a registration key (an XML file), drop it in the same unzipped directory, and you’re good to go.

ndepend installation directory

As you can see, the directory has a few executables in it. I’m interested in the main NDepend analysis tool right now, and its integration into VS, but you can find more information online about the Console (run NDepend options from the command line) and the PowerTools / API (write your own tools that incorporate and/or extend NDepend).

Check out the “BuildProcessResources” folder too, which has links to documentation about integrating NDepend into your build environment (MSBuild, TeamCity, TFS, and more). This opens up other possibilities. For example, you could automatically analyze the code-base after every build, and display it on an intranet. I suppose you could also run it before every build and, if the analysis shows a new critical error, cancel the build and send an email.

Visual Studio Integration

Not everyone using NDepend will need or have access to Visual Studio, so there’s the stand-alone VisualNDepend.exe. For developers though, it’s easier when everything you need is at your fingertips, and you don’t have to keep switching context between programs. Fortunately, NDepend integrates nicely into VS.

Run “NDepend.Install.VisualStudioAddin.exe” and select the versions of VS from which you want to access NDepend. It blends well into the existing environment, adding its own menu at the top, right-click capabilities in the editor window, and displaying other useful information in the standard VS panes.

My First Analysis

The first thing I did after installing the plugin was to just click the gray circle in the lower-right of the IDE and let it analyze the solution. Easy-peasy. One click to bring up a configuration screen, one more click to just analyze the whole solution. It’s very fast too. I picked a large solution with nearly 30 projects in it, spanning back several years, and it finished its analysis in well under a minute.

After the analysis completed, a few things happened.

First, it modified the solution file with the following block. If I understand the “GlobalSection” correctly, it’s just a hook that plugins can use to do some work when a solution is being loaded. Visual Studio uses it for various purposes like loading tests and build configuration info, and TFS and VSS use it too. Here, NDepend is just referencing an “ndproj” file that contains data regarding the current solution, NDepend options and rules applied to that solution, the output directory for the report, etc. If you want to remove it later, select “NDepend / Project / Detach Project” from within VS (or just delete those three lines in the text editor of your choice).

GlobalSection(NDepend) = preSolution  
    Project = ".\<name of project>.ndproj"
EndGlobalSection  

Second, it opened a report in my web browser. The nice thing about this is that the report is fully contained in a “NDependOut” directory inside your solution directory, in plain html and xml. You can zip it up and email it, commit it to source control and version it, parse it out with another tool, whatever…

ndepend report summary

Note the middle of the page above. There’s a note about limiting the number of violations to only recent ones. There’s a way to run the analysis, set the baseline to that “run”, and then just handle violations from that point on. While ideally you’d go back and clean all the old code up too, this at least allows you to get a process in place for handling new violations as they occur, without being completely overwhelmed. Dealing with the backlog could then be handled separately.

ndepend recent violations only suggestion

Lastly, it popped open the following window, inside VS. You can access all this stuff through the menu too, but the first few times through it’s nice to have it right in front of your face.

ndepend beginner what to do now

The Dashboard

The “View NDepend Dashboard” option above opens the dashboard, which is another nice VS integration. It kind of reminds me of the VS “start page”, where a lot of useful information is presented in its own tab.

While the report in the web browser does allow you to click on the various warnings, and it drills down to display the name and location of methods that caused the warnings, the dashboard is closer to the code, and allows you to open offending code right in the IDE. It displays a standard set of charts that track certain metrics, and you can quickly create (or remove) charts to track additional metrics.

I can guess what some of these mean (like # Types), while others I’d have to look up (Method Complexity). What I really wanted to do was see the code it was reporting, so I decided to check out the “Code Rules” pane in the dashboard first, seen below in the top-center.

ndepend report dashboard

Clicking the “Critical Rules Violated” link opens a “Queries and Rules Explorer” and loads it with all of the rules the app violates. Picking at random, I selected the “Methods too complex” rule, and a “Queries and Rules Edit” pane opened on the right with two pieces of information. The bottom portion shows the particular methods that violated the rules, but the top pane is particularly interesting. That’s the query that NDepend ran against the code in order to generate these particular warnings. The syntax is NDepend’s own, and it’s called CQLinq. Very exciting stuff.. more on that below.

ndepend report dashboard critical rules violated

Back in the dashboard, I selected the “Rules Violated” link this time, and further selected “Types with too many fields” in the bottom pane, which replaced the list of methods on the right with a list of types (classes) that broke the rule. Clicking any one of them brought me directly to the class in question, opening the file in the VS editor.

ndepend report dashboard rules violated selection made

NDepend ships with hundreds of predefined rules like these ones, to get you started. The third button in the “NDepend Beginner” window just opens the Queries and Rules Explorer (seen immediately above this). Later on, when you or your team comes to an agreement on what’s acceptable and what’s not, you can customize individual rules and save them, disable them, or create new ones.

CQLinq

I love LINQ. It’s been around for years, so if you haven’t even heard of it, you must not be doing much development. If you want to get your hands dirty, the 101 LINQ Samples is a great resource from MSDN.

It’s possible for anyone to adapt the LINQ syntax to work with their own data store. For example, LINQ to XML allows you to traverse and query an XML file. LINQ to SQL supports querying databases, and LINQ to Objects supports manipulating collections (lists) of data. In all cases, one of the strengths of LINQ is that its syntax remains very similar. But someone has to write the adapter that allows those similar queries to be translated as necessary behind the scenes, to abstract away some of the details from the developer.

NDepend has its own flavor of LINQ, the CQLinq syntax. The source code for your project is treated like any other source of data, and you can use CQLinq to query it in a variety of ways. Notice in the screen shots above, that when I selected something on the left, I’m presented with the query on the right that NDepend is running. We’re actually shown the exact CQLinq syntax used to define the particular rule.

Here’s the rule for “Methods with too many parameters”. The predefined queries are commented well, so you can hopefully understand what it’s doing. This is a simple one. It looks for all methods with more than 5 parameters, and reports the method name and the number of parameters in its signature.

// <Name>Methods with too many parameters</Name>
warnif count > 0 from m in JustMyCode.Methods where  
 m.NbParameters > 5
 orderby m.NbParameters descending
select new { m, m.NbParameters }

// Methods where NbParameters > 5 might be painful to call
// and might degrade performance. You should prefer using
// additional properties/fields to the declaring type to
// handle numerous states. Another alternative is to provide
// a class or structure dedicated to handle arguments passing
// (for example see the class System.Diagnostics.ProcessStartInfo
// and the method System.Diagnostics.Process.Start(ProcessStartInfo))
// See the definition of the NbParameters metric here
// http://www.ndepend.com/Metrics.aspx#NbParameters

If you have a lot of legacy code, and too many methods with over 5 parameters, you can just modify the query. Increase it to 10 to show the worst of the worst. Limit it to a single namespace. So you’re given a starting point, and then you can modify the rules as needed.

Queries can be much more sophisticated than the one above. Here’s one called “Methods too complex”. It reports methods that are excessively complex, most likely due to too many possible branches of logic. This sort of thing happens when one method keeps getting added to and added to over time, without anyone refactoring it out into more manageable chunks.

// <Name>Methods too complex</Name>
warnif count > 0 from m in JustMyCode.Methods where  
  m.CyclomaticComplexity > 20 ||
  m.ILCyclomaticComplexity > 40 ||
  m.ILNestingDepth > 5
  orderby m.CyclomaticComplexity descending,
          m.ILCyclomaticComplexity descending,
          m.ILNestingDepth descending
select new { m, m.CyclomaticComplexity,  
                m.ILCyclomaticComplexity,
                m.ILNestingDepth  }

// Methods where CyclomaticComplexity > 20
// or ILCyclomaticComplexity > 40
// or ILNestingDepth > 4
// are hard to understand and maintain
// and should be split in smaller methods.
// See the definition of the complexity metrics here:
// http://www.ndepend.com/Metrics.aspx#CC
// http://www.ndepend.com/Metrics.aspx#ILCC
// http://www.NDepend.com/Metrics.aspx#ILNestingDepth

Searching Through Your Codebase

I think most people who use VS would agree that the search feature is crippled. I’ve never gotten used to the stupid design decision to mangle it and dock it in the corner of the editor window.

With NDepend, press Alt+C to search for classes or Alt+M to search for methods (alternatively, go to NDepend / Search, and check out the search options).

While I’m at it, here’s a list of shortcuts:

ndepend keyboard shortcuts

You can type in a class or method to search for and see results listed below as you type.

ndepend search type by name

If you want to further modify the query, just click on “Edit Query” to open an editor. Changes you make to the query are executed as you go, so you can see changes in the bottom pane.

ndepend search type by name refine query

Here I decided that the name was not exactly “BaseModel”, but did have “Base” somewhere in the name, and was in an assembly with the name “Common” in it. The results were updated accordingly.

ndepend search type by name refine query modified

The only downside to the search is that, if you add a new class and then try to search for it, you’ll have to rebuild the solution (to generate new .pdb files) and then re-run the NDepend analysis to pick up on the changes. But when I’m searching for classes, it’s usually the stuff created ages ago, not the stuff I created last week.

Other Resources

If you or someone on your team has an interest in code analysis, or you’ve just decided it’s time to find the hidden land mines in your codebase, then this is the tool for you. The sky’s the limit, but you’ll need to invest some time to get the most out of it.

There’s a lot of inline and online help and other resources too, fortunately, such as:

I hope you found this useful, especially if you’re researching analysis tools or looking at NDepend specifically. Feel free to leave a comment below!

Disclaimer: In the interest of full disclosure, and in accordance with FTC 16 CFR, Part 255, I received the product mentioned above free of charge from the author. I only recommend products I personally find useful. All opinions are my own, unless otherwise noted.

Subscribe to Weekly Updates!

Get an email with the latest posts, once per week...
* indicates required