NDepend – “SQL” for your code

Some time ago I received an offer for a NDepend Professional license. I was vary at first since Credibility and Free Stuff is hard to mix together, but I accepted it because it was on my list of tools to play around with anyway. It took me several months to actually use it in a real application, but here are some thoughts about it. Again, I received the license for free but the posting here is unbiased.

I guess unbiased reviews need to start with something negative to support the claim that the review is truly unbiased Smile So to roll with it, let me say that you shouldn’t judge the product by it’s homepage which sadly looks like a 2003-ish WebForms site. The application itself isn’t the best looking one either, but it has fancy colors and stuff. It also looks like 2003-Windows XP Luna when in 2011 we’ve moved back a bit to clean, serious, calm colors. But well, again, this is about the product.

My first question when looking at commercial software is of course: What problem does it try to solve, and is that problem really a problem?

NDepend is an analyzer to find some flaws that easily fall through the cracks: High Cyclomatic Complexity (which is not a problem when the code is still fresh in your head, but causes nightmares 6 months down the road when you need to find a bug in it). Dependencies with more dependencies with more dependencies with more… Comparing two code bases for a list of all changed methods.

It does a lot more, but what I was interested right now was their Code Query language, CQL. It’s like SQL, but for code.

For example, I’ve analyzed the Code, added a public method, analyzed again and the performed a “SELECT METHODS WHERE WasAdded AND IsPublic”. As a result, I get a list of all newly added Public methods:

image

What problem does this solve? It solved the problem of Diff Tools being unaware what they are diffing. Let’s say you merge a large commit that has 200 changed files. You glance at them and see that there’s tons and tons of tab vs. spaces changes, many added code comments, some refactoring. It’s a very bad signal to noise ratio when in reality you are mainly concerned with “How did functionality change?”. Of course, you can now easily say “One change per commit. Commit Messages are enough documentation. Do not commit both functional and semantic changes” and you are right – but this is not how the real world works.

Maybe you don’t even know the code base because your predecessor didn’t do a good job documenting stuff or even checking stuff into source control and now you have two codebases (one possibly a result of decompiling the assembly) and need to get an overview.

The CQL Query edit window has IntelliSense which is really helpful, but not without it’s flaws: “SELECT methods  WHERE  WasAdded” does not work, it needs METHODS to be uppercase. Also there seems to be no "SELECT * WHERE WasAdded”

The one thing I really dislike about this feature though is that it’s relatively complex to setup: Ideally I’d just love to tell NDepend “Here’s two Visual Studio solutions and/or assemblies, please analyze them and show me a list of functional differences”. Specialized tools like Inca are available to make that easier of course.

Methods with a lot of instructions

You can query for a lot of really neat stuff, like the number of IL Instructions:

SELECT TYPES FROM ASSEMBLIES "SWiki" WHERE NbILInstructions > 300 ORDER BY NbILInstructions DESC

image

This is a LOT more useful than lines of code (which is also possible) because I can easily write very terse but unneccessarily complex code among the line of this:

for (int i = 0, y = 1, z = 13; i++ < 10 && ++y < 8; CallSomeMethod(i, y, z)) ;

Only to save a few lines while still writing insanely crappy code that would make a C++ developer proud.

Methods called by many other methods

What else can we query by? Most Used Methods is nice, ignoring .net Framework assemblies and Properties:

SELECT TOP 50 METHODS WHERE !IsInFrameworkAssembly AND !IsPropertyGetter AND !IsPropertySetter  ORDER BY MethodCa DESC

image

This is different from running a profiler, because this analyzes all the theoretical calls: There’s 23 places in my source where a certain constructor is called. Sadly there seems to way to get the Method Name as well as the Signature… Note that this is NOT a profiler thing: Just because the ctor is called in 23 different places does not mean that it needs to be performance critical because no statement how often it is called is made. This list is not a “Where to optimize speed next”, it’s a “Do we have any methods that should be abstracted away a bit more?” thing.

Classes implementing an Interface

MSDN has a list of derived classes on certain base classes, but it lacks this for Interfaces. Quick, tell me which classes implement IPrincipal? The MSDN Page does not show, but NDepend does:

image

I was looking for ages for a way to “Query” MSDN like that, and NDepend does it once you created a project to analyze all the .net Framework assemblies (and any additional ones of course).

Comparing SharePoint 2007 to 2010

As NDepend works against assemblies rather than source code, you can run analysis of SharePoint 2007 DLLs, then the SharePoint 2010 ones. The result is a full report about public API changes.

Even better: Run analysis before and after installing a Hotfix and see what actually changed and analyze your custom code precisely for these changes.

What about existing Code Analysis and Resharper users?

Now, I’m using Visual Studio 2010 Premium with Code Analysis and ReSharper which means that a lot of the simple mistakes are already caught without NDepend: Making Fields readonly, marking assemblies CLSCompliant, methods that don’t use “this” could be static, methods with way too many dependencies etc. pp.

For some of the more common problems, users of Code Analysis should better write their own rules so that they run on every build. But when it comes for just quickly querying the code prior to a refactor (How much stuff is affected?) or just for finding stuff (I wonder what ActionResults ASP.net MVC has, and which ones we’ve added?) NDepend is a great resource.