Introduction and Disclaimer
I was asked around the middle of August if I would consider reviewing a product called NDepend; in exchange for which, I was given a free licence. I agreed to do this, providing I could review the product honestly and, this being agreed, what follows is my personal opinion of the software.
Conditions
I have a number of projects that I was interested in running this on. I won’t be running fair comparisons between projects to test the software; neither will I be comparing the software against other such software. This review will simply be my personal impression of how useful and easy to use this software is for the projects that I happened to use it for.
There are tutorial videos, documentation and a plethora of other resources on the web. I purposely stayed clear of these, with the exception of the 2 minute introductory video and “getting started” document described below.
Installation
Having downloaded the zip file, there are a couple of options, so I went looking and found this:
http://www.ndepend.com/docs/getting-started-with-ndepend#Part1
I had received two mails: one saying that the licence was on its way, and one with the licence and licence ID. The installation process is unnervingly fast (that is, it appeared to have done nothing):
But from launching VS, it clearly had done something:
Initial Run
The instructions state that you should attach a project to NDepend. I did this with the current project that I’m working on (my MVVM Cross game). It then gave me a few options; the Dashboard looks like this:
Speedwise, I have another solution with 104 projects in, and it took around 4 - 5 minutes to load. Subsequent loading of the project appears to take no additional time.
Features
Okay, so having had a play, I want to see if the product does what it says on the tin; here’s the tin: http://www.ndepend.com/features/default
There are 13 features listed here at the time of writing. Some are things such as: VS Integration, which I’m not strictly sure should count as a feature; it’s just what you would expect from a product such as this. I won’t go through all the features; however, I particularly interested in:
1. Complexity and Diagrams
2. Detect Dependency Cycles
3. Test Coverage Data
For each of these, I’ve indicated what I would like from the functionality, what the product claims, what I could find on my own, where I needed to contact NDepend (and the result), and what, in the end, is available.
Complexity and Diagrams
What the product claims: “Spot too complex code at a glance thanks to unique diagramming capabilities in the .NET world.”
What I want to see: A list of methods which are overly complex or long, in order of the length or complexity.
This seems quite a good one for NDepend; initially, I tried looking in the Metrics menu:
What appeared was, indeed, unique. It seems to generate a series of rectangles, the size of each representing the relative complexity of the method. I’m confident that it did identify the most complex, too:
My problem with this kind of display is that it doesn’t really tell you what you need to know. It looks good, you can zoom in and out, but when I first saw it, I misidentified the most complex method.
Double clicking on a square takes you to the code, as you’d expect, and your visual query remains as a tab. It also provides a little table, showing methods by complexity. Annoyingly, this doesn’t seem to be limited to my code:
It lets you output this to pretty much anything you can think of. All in all, pretty impressive and easily discoverable.
Dependency
What the product claims: “Detect Dependency Cycles: Get rid of dependency cycles between components to achieve higher code maintainability.”
What I want to see: A basic graph with a list of classes and their dependencies.
NDepend does offer a dependency graph. I’ve downloaded open source versions of this in the past, and even poorly implemented ones can be useful.
When you run a dependency graph, you get a very pleasant graph. You do have to do a bit of juggling with the dockable screens (I just docked them, and I’m not really sure why that isn’t the default - but they DON’T seem to stay docked after a restart!). Pressing Shift-Alt-Enter didn’t bring the graph to full size either; it simply brought my last code module to full screen.
Okay - so it definitely fulfils my basic requirements; but what else does it do?
You can switch from side, to top down view. You can right click a namespace and view the methods in a namespace. The box sizes are initially based on the sum complexity of the namespace. This is changeable, and you can, for example, have them based on the lines of code. This is definitely the killer feature IMHO.
Anything it doesn’t do, or doesn’t do well? The following is a list of things that sprung to mind while I was using it:
- Double clicking a node does nothing. TBH, I wouldn't really mind what it did - for example, you can right click and select: view internal dependency cycles, of maybe it should list the methods for that namespace.
- As the graph gets complex, there are overlapping dependency lines. On very complex projects, this basically renders this unreadable. Obviously, in such cases it may be unavoidable, but I have seen a few, where overlap is unnecessary. Maybe it would be better if the lines were straight, rather than curved?
- As you hover over the nodes in the dependency graph, very useful, context sensitive help boxes appear. However, getting to them before they fade away, as you leave the box, requires mouse dexterity of a level that I imagine Billy The Kid might have, if he were a computer programmer.
Test Coverage
To be clear, NDepend doesn’t generate code coverage data. It looked at first glance to me that it would, but it doesn’t. Having spoken to NDepend support, there are no plans for it to in the future. It will, however, import test coverage data from other applications that do. As far as I can see, all of the test coverage programs that it uses are commercial (including VS for premium and above).
At first, I was a little disappointed by this, but given that the product is called NDepend, and it does support reading coverage files, I felt a little like I was trying to judge a screwdriver by its ability to knock nails into a wall.
A Note on Usability and CQLINQ
Okay, so the UI does take a bit of getting used to, but once you start to get a feel for it, it makes sense. Each feature sparks of a new “Query Edit” window, which looks like this:
Initially, this annoyed me immensely. It’s not at all obvious what it’s for, and it just kind of hovers around the screen. Basically, this just allows you to export the result of the query to HTML, graph, etc… but then I tried changing it, and realised how cool this was.
Here’s an example of the code quality query for one of my projects:
Okay, so I have no methods that are “too big”. But what is that? When I click the rule, I get this:
As I said, my initial thought was that this was just annoying, but it’s not - it’s unbelievably good, because I can do this:
Woah! As I type, it updates with results of the code for a LINQ query (NDepend call this CQLINQ)! I can change anything:
Here I have a list of all types where the code is more than 10 lines and there is a method that starts with “Create”. Okay, it’s a daft example, but the potential is limitless. Well, maybe not limitless, but I can certainly envisage other uses for it.
On the downside, the intelli-sense is a bit laboured. Ctrl-Space sometimes works, and sometimes doesn’t, and brackets seem to appear when you don’t want them to.
Oddities and Bugs?
Yes, there were a couple. The first was that while I was browsing through the list of “structures that should be immutable”, I tried to select some code that it highlighted, and was rewarded with this:
Because of this, it’s hard to tell precisely what it’s moaning about, but best guess it an internal .Net assembly (given that I have no structures in my project).
There was the intelli-sense that I mentioned above.
Rules
One of the reasons I never got into using Resharper was that when I turned it on, the first thing it told me was to replace a statement such as this:
MyClass myClass = new MyClass();
With
var myClass = new MyClass();
Personally (and I know people disagree with this), I consider that to be bad advice.
An example of such a rule might be that “Pure methods should be tagged with the Pure attribute”. I appear to be following this; possibly because I have no “Pure” methods in this particular project. Incidentally, here’s what the NDepend online documentation says about that rule: (http://www.ndepend.com/defaultrules/q\_pure\_methods\_should\_be\_tagged\_with\_pureattribute.html):
My point is that these rules are, to some extent, a matter of opinion. Obviously, a function with fewer lines is better, and it’s good that it points out functions that exceed a certain length, or level of complexity; and it’s very good that this criteria can be changed and then save them. You can turn rules off, and they stay off, but I feel as though there should be some form of “Rule Wizard”, with a tree view where I can basically say: “Everything off”, and start from there.
Unlike Resharper, NDepend is only there when you ask it to be, and this is kind of its “Get out of jail free card” here. My functions might be 5,000 lines long, use randomly named global variables ranging from “a” to “z3” and have no comments, but it’ll only tell me when I specifically ask it to. This is a good thing, I don’t need something sitting in the background constantly tutting at me every time I miss a semi-colon; Visual Studio handles that already.
Conclusion
NDepend is a useful product.
It does, as far as I can tell, what it says on the tin (http://www.ndepend.com/features/), and then some. Unlike other VS plug-ins, I don’t mind having it there, because it’s quietly in the background.
It has at least two killer features. Both of which would make it worth the purchase price alone (around £240 at the time of writing).
Could it be better? Absolutely.
My main issue with it is the initial learning curve. It probably took me two or three hours to get an idea of what was happening, and why. That’s too long. There are lots of videos, training materials and even blog posts such as this, but it feels a little like the default is in advanced mode.
The windows, especially on my laptop screen, always seem to be in the way. You can dock them, but annoyingly they seem to constantly forget that you’ve done so.
Some time back, MS was talking about introducing a concept of Code Bubbles, but that never seemed to materialise. The display graph and popups in NDepend make me think that the devs saw the same promo videos that I did when they designed the interface. Although I’m not sure the graph quite works the way it was intended to.
In some respects, NDepend’s power seems to work against it. Since installing it, I’ve come across a number of scenarios that I would traditionally use the VS Find function, and NDepend has come to mind. I’ve started writing a CQLINQ statement and then found that I’d wasted half an hour or so. I don’t doubt that this will subside as I either use it more frequently, or stop using it as much because the novelty wears off.
Finally, there did appear to be one of two very minor bugs, such as the ones identified above.
Further discussion and addendum
It’s worth also mentioning that the response time from NDepend was very fast. Additionally, I sent this to NDepend for a review first, before posting. (I haven’t changed anything as a result of this - apart from this section, and a change to the wording in the rules comments to make my points clearer); amongst the points they made was that I missed the dependency cycle and matrix diagrams. Also, that I missed the search facility. I also made some suggestions, and found them to be surprisingly receptive.
I’d like to quickly review each point, starting with the search facility. It is a bit of a hidden gem. You can pretty much search of all the basics: size, name, complexity, etc, and it generates a basic query for you. I’m not sure this negates my earlier comment about wasting time trying to formulate a query, but it’s a start.
Regarding the dependency cycles and the matrix: I subsequently ran this query on my project, and it returned a single, “Extensions” namespace. Looking at the matrix didn’t particularly help and, to be honest, I’m still not totally sure what it tells me.
I will try to revisit this post in around 6 months time, and give details of whether I’m still using the product, any improvements, and whether I find it more, or less useful.