There's no question that Visual Studio is a class-leading tool for building large applications. The IDE is incredibly helpful to coders, and the .Net framework lends itself to managing dependencies among components and classes in large applications. In addition, Visual Studio is designed to be extended by third-party tools that can make it even better. NDepend is one of these tools; its purpose is to analyze large applications and expose information that's typically hidden deep inside your code.
Installation and getting started
The NDepend web site shows some great screen shots with all manner of graphs and charts and reports, so naturally, you want to see that stuff for your code, too, right? Good news: installation is a piece of cake. Just unzip into a directory, add the license file, and you're ready to start your first analysis.
When you start the NDepend Startup shows a screen reminiscent of Visual Studio (start screen). Create a new project, point it at a Visual Studio solution file, and let NDepend do its thing. Zero to more graphs than you can shake a stick at in about four minutes:
For my first test, I loaded up CSLA and ran NDepend's analysis. When you run NDepend's analysis in the VisualNDepend GUI tool, it writes a report in HTML with all the graphs you see in the screenshot above and more. In addition, the report will show you some metrics, dependencies, and warnings.
This is where the analysis starts to get interesting. There's a section in the report called "CQL Queries and Constraints", where NDepend lists violations of constraints it's found during the analysis. "CQL" stands for Code Query Language, and this is one of the real hidden gems of NDepend. It turns out that NDepend isn't just boiling your code down into data so it can draw graphs -- it also lets you query that data with a SQL-like language.
If you've ever used FxCop, you'll be familiar with the idea behind CQL constraints. Like FxCop warnings, the idea here is to flag code that probably needs some help. Unlike FxCop, though, the constraints you see popping out in the report are constructed like SQL queries. Here's one of the simpler examples:
// <Name>Methods too big (NbLinesOfCode)</Name>
WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE NbLinesOfCode > 30 ORDER BY NbLinesOfCode DESC
// METHODS WHERE NbLinesOfCode > 30 are extremely complex and
// should be split in smaller methods
// (except if they are automatically generated by a tool).
// See the definition of the NbLinesOfCode metric here http://www.ndepend.com/Metrics.aspx#NbLinesOfCode
A few points of note here:
- NDepend comes with over 100 of these queries, including 20 samples showing how to construct custom queries.
- Yes, you can write your own queries!
- Note the URL in the comments above -- there are quite a few new terms you'll find yourself wading through as you dive into NDepend, so take advantage of the excellent online explainations. For example, the page above is part of a whole page that explains the code metrics that NDepend tracks. Be sure to check out the Metrics cheat sheet, too.
- The results of these constraints don't indicate specific problems -- they indicate conditions that could be problems. It's still up to you to check out the specifics.
Needless to say, I had to try out the CQL queries. The thought of creating my own CQL queries sounded pretty cool -- even though I wasn't exactly sure what I wanted to look for! The View menu has an option to "Reset Views to work with the CQL language" which switches the IDE around and presents a treeview with queries in it.
This handling of views is somewhat different from the way we're used to working with windows in Visual Studio -- whereas Visual Studio lets you open, close, dock and pin tool windows one at a time, NDepend re-arranges the whole collection of windows at once to suit each type of activity you might want to undertake. If the NDepend GUI were integrated into Visual Studio, this would probably be quite awkward, but in the standalone NDepend GUI, it's pretty easy to get used to.
I decided to create a query showing namespaces with very little code in them. Probably not the most useful method, but I figured it might be interesting to see some little-used namespaces. Creating the query is easy - you end up with a pretty basic edit window:
I noticed a few quirks while working in this window:
- There is autocomplete in the query editor window, but it's not as slick as the autocomplete you're used to in Visual Studio. It's pretty easy to screw a query up enough, for example, that the code parser just gives up. You should get used to this pretty soon, though - it didn't take me too long.
- Browsing from query to query could be a little easier if there was a preview pane of some sort. While stumbling through my first query, I wanted to browse a bunch of queries to see examples. I found I had to "edit" each query, then "cancel" to go back to the treeview to find the next one. It would be nice if I could click each query and see the edit view for that query in a preview window.
- The biggest feature I wished for, though, was a fast, easy way to run my query and see the results without running the whole analysis and report again. It turns out that there's a window that was hiding in a tabset behind the class browser, and this window actually shows results in real-time as you make changes to the query. Way cool, but it took me a bit to realize it was there.
In any event, within a few minutes, I'd created a constraint, and it was yielding results:
// <Name>A sample constraint</Name>
WARN IF Count > 0 IN
SELECT NAMESPACES WHERE NbILInstructions < 500 ORDER BY NbLinesOfCode ASC
In case you're wondering, I would probably use either NbILInstructions or NbLinesOfCode in both the WHERE and the ORDER BY clauses for a "real" query, but I wanted to play around with both of these as long as I was experimenting.
NDepend integrated into your process
The interactive UI is where you'll spend your time while you're learning NDepend, but this tool is designed to integrate into your build process, too. Once you've got CQL constraints set up the way you want, you want to keep an eye on your project to make sure it stays healthy over time. NDepend can integrate into your MSBuild, NAnt, or CruiseControl.Net build process so you've got up-to-date information all the time.
Another obvious use of NDepend is to support refactoring. While the CQL constraints show you places where you probably should consider refactoring, the dependency matrices and graphs help you understand the relationships that exist in your code so that you can refactor effectively. Given that NDepend has access to your .Net code only, dependency analysis won't help track dependencies into other systems, stored procedures, and so on.
Is NDepend right for you?
NDepend can do some things that no other product can touch. These capabilities are seriously amazing, and are a testament not only to this tool, but also to the extensibility of the .Net framework.
But how is it going to make you a better developer?
If your organization values code quality, you're hopefully already familiar with the principles behind the default CQL constraints. Most of these measurements are understood by most developers in an abstract way, but it's usually really difficult to make these judgements objectively. Not anymore. Now you can use NDepend to help keep your code architecturally clean.
There are a few places where NDepend makes a lot of sense:
- Big code bases. These systems can be very complex and brittle, so improvements in stability help a lot. It's also nice to have some extra tool support when working with big code bases.
- Commercial code or public APIs. If you sell your software, your code needs to be top-notch, and NDepend can help with that.
- As a code review or teaching tool. Like code reviews, NDepend can help teach new developers how to build more reliable, more maintainable systems.
If you need every advantage to keep your code base healthy, you should check out this tool. If you're good, this tool will make you better.