Getting started with NDepend (part 1 of n)
A couple of months back I was offered a complimentary license to NDepend by a member of the NDepend team. The hope was, I believe, that if I liked the tool I would blog about it. As it happens, I like it very much. I am as unbiased as can be and feel that constructive criticism is the greatest motivator for improvement. I plan to share my opinions (both positive and negative) without remorse.
I plan to write a mini-series of posts on this topic, with this first one serving as a high level overview. In a recent post I mentioned that I was about to go live with a small eCommerce site based on the Nopcommerce open source application. The project is now in production and I need to do some refactoring to reduce the footprint, improve code quality (to my liking) etc. etc. Now is a good time to do it and NDepend will help in a big way – hopefully we’ll all learn something along the way.
Back to this post…so what is NDepend? Essentially NDepend (and it’s non .NET siblings, XDepend (Java) and CppDepend (C++)) is a static code analysis tool. The problem with static analysis, for many, is its inaccessibility. Analysis can get very technical very quickly and it can be difficult to reconcile low level technical details with higher-level concerns of the average developer. It often feels more theoretical (academia fodder) and less applicable to real-world development. Truth be told, the first time I loaded NDepend I got a sinking feeling in my stomach that I had no need for such a complex tool…look at the following screenshot and tell me you wouldn’t have thought the same:
Honest opinion time: I get the feeling that all of the data in the above screenshot is shown by default for its wow factor (and it kind of works!). This is waaaaaaaaaay too much information for one screen, but fortunately there are multiple (compartmentalized) views for the different functionality which makes life a lot easier.
What I’m getting at here is that because of its barrier to entry, the average developer probably doesn’t perform this kind of code analysis nearly as often or as thoroughly as they should. NDepend, has a relatively gentle learning curve and is far more accessible than any other similar tools that I have used before – professionally or academically :-)
To get us started I’m going to briefly describe what to me are the killer features that NDepend offers. The tool offers many other functions – I plan to concentrate on the subset that I use most often and will not have 100% coverage. In subsequent posts, I plan to dive a lot deeper and provide more informative and less anecdotal examples.
NDepend has its very own language – Code Query Language – which essentially allows you to query your codebase and find TONS of useful information. If you want to find all types with more than 20 fields (see below screenshot) there’s a query for that. If you want to find all methods with 100 IL instructions, you can do that too. The syntax is very much like that of TSQL (following a SELECT TOP FROM WHERE ORDER BY pattern) and you can really delve deep into your code. This is great for many reasons, and there are tons (~80) of built in metrics that use the CQL language. Most contain links to full explanations of where they metric came from and why you should care about them.
The below screenshot does show a query, but more accurately it shows a constraint. Constraints are used when you want to be notified when the number of results returned by a query reaches a certain threshold and uses the WARN IF COUNT IN syntax. The beauty of constraints is that they can be run proactively when you run your analysis, essentially notifying you every time a constraint is violated.
I’ll delve deeper into queries/constraints in another post, but this feature continues to amaze me. Built-in metrics include Code Quality/Design/Unused Code/Naming Conventions and a bunch of other groups and are relevant to every developer out there. If you do any kind of code review or design review, you’re going to love CQL. The ability to create your own queries/query groups or tailor the existing ones to your liking makes this feature extremely flexible.
2. Refactoring Support
This is a MASSIVE area to cover and I'm going to be brief in my description here with a view to writing a much more detailed posts about the ins and outs. Specifically, my next post in the series will address removing unneeded code from a solution, concentrating on how NDepend helps me to plan what to remove and where the dependencies lie. I think this is a pretty big point – NDepend allows me to plan my refactoring. Whereas most tools I use are developer centric allowing me to execute refactoring on various levels, NDepend allows me to take a more architect-centric and structured approach to my refactoring. As the saying goes: measure twice, cut once.
NDepend is true to its name and offers extremely deep insight into system dependencies including a Dependency Graph which is useful for a high level overview and a Dependency Matrix (above) which allows you to get knee deep into your system. For instance, in the screenshot below I have highlighted the intersection of the Nop.Common and Nop.Payment.Paypal assemblies. These assemblies do exactly what you would expect them to do. The info pane tells us that 17 methods of the Nop.Payment.Paypal assembly are using 51 members of the Nop.Common assembly.
Delving further into this graph, I can see exactly which methods and members are involved.
I am obviously enamored with NDepend’s refactoring capabilities but will stop here so that I don’t steal the thunder from a future post.
3. Build comparisons
Essentially, NDepend allows you to take two (NDepend) projects or two sets of assemblies and compare them side by side. Some high level statistics are provided allowing you to compare the #LOC, # Assemblies, #Types etc. in both builds. Modified assemblies are highlighted In the code tree and, as you’d expect, the tool gives you the ability to dive deeper and deeper to view which types were changed, which methods were added and removed between builds. Again, this is something I will look at more closely in an upcoming post. One of my favorite uses of this feature (this is highlighed in one of the videos on the NDepened website) is the ability to use a CQL query to determine which public methods were removed from the latest build. While there are tons of possible queries, this one is invaluable as it shows changes that break the public API of your system and therefore break backwards compatibility.
While NDepend allows the developer to delve into the system on the screen-level, it also automatically generated a HTML report on analysis which summarizes the findings in a manner that can easily be shared with team members, management etc. What you see on the report are an amalgamation of the information available within the application and appear to be very useful for code reviews, team meetings etc. This report contains exactly the kind of information I would want at hand if I were to buy assemblies from a third party. A sample report is available on the NDepend website (link).
The Little Things
There are a lot of awesome applications out there but to me what sets the great apart from the good is the attention to detail. These are a few of my favorite things:
- Apply an XSL style sheet to generated reports. That’s right – when running your analysis you can choose a stylesheet that will be applied to the analysis results. Sure, this is something that was probably relatively easy to implement…yet I can count on one hand the systems I have used that offered such a feature. Conversely, I cannot fathom the number of times I manually styled reports that didn’t provide such an option.
- Visual Studio/Reflector integration. Visual Studio integration is obvious and probably even necessary for the success of such a tool. Reflector integration is not. The developers could have ignored reflector altogether and few would have complained. But, they didn’t. Reflector is essentially the secret handshake separating good (.NET) developers from the rest and any developer worth their salt has used and probably still uses it. The ability
- Load DLLs from .sln file. This is tiny and most people won’t be nearly as excited about it as me. Most applications that analyze assemblies in some way (definitely most unit test runners i’ve played with) have you point the tool at a set of DLLs. While NDepend can do this, it also provides the mechanism to open a Visual Studio solution file and parses the necessary assemblies from there. This has two advantages – 1) it saves me time and effort and I am VERY lazy when it comes to this stuff 2) It makes sure i’m looking at the code that I need to look at and not an assembly that was removed from the solution six months ago but never actually deleted. Simple, but beautiful.
- In-built screenshots. Quite simply, there is a button that allows a snapshot to be taken of the current pane. If I am looking at the dependency matrix I get a screenshot of only the matrix, same for the dependency graph, etc. etc. It may seem small, but for an application which I assume is commonly used for reporting and documentation, this is a highly useful feature that most dev shops would have completely ignored. Maybe I’m biased because I used it a lot when preparing this post!
Things I would like to see improved/added
- Glitchy graphics. I’m not 100% certain if this is a function of the UI controls used within the application or the system on which I run NDepend. However, screen refreshing is terribly slow at times and is my biggest frustration with the application. Minimizing panes within the application can be a bit of a pain as toggling takes a few seconds to execute (by which time i’ve toggled 3 or 4 more times). I’ve also had major issues with NDepend’s graphics on Windows 7 though, having recently tried the beta of the next version it does appear that this is something that has been addressed.
- Documentation. Don’t get me wrong – there are some great tutorials on the website and Patrick Smacchia continuously blogs new and interesting uses for the tool. What I have not been able to find is a rough-and-ready screen-by-screen overview. sometimes i just want to know what the grey X symbolizes (crude and fictitious example). I don’t to sift through videos or blogs in order to find out.
- Tighter Visual Studio integration. While NDepend does offer context menu integration within Visual Studio I long for the day when constraint violations and useful metrics are displayed inline alongside the code in Visual Studio. While I definitely see NDepend as a standalone product rather than a VS add-in, I would love to have access to a number of its features within my regular workflow without having to switch between tools. To be fair, I have never submitted this request to the team, but plan to do so in the future.
- Automated Implementation of refactoring. I would completely understand if this is something the team does not want to do, but I would love the ability to execute as well as plan refactorings from within NDepend. For example, I already have the ability to view impact analysis of removing an assembly from my solution – it would be great to be able to pull the trigger and have NDepend remove this assembly reference, and perform some kind of conflict resolution on the dependent code. I’m thinking out loud here, and realize the complexity of what I’m asking, but it would be pretty awesome!
NDepend is an amazing tool in the refactoring arsenal. If Coderush/Resharper optimize the coding process I think NDepend optimizes the architectural process. It provides extremely deeps insight into the structure of a software system, probably more than any tool I have previously used. At over 400 dollars for a license (cheaper if bought in bulk) it may be difficult for lone programmers to justify the purchase for their pet projects – especially given that it will probably be used less frequently than other (coding-centric) refactoring tools. However, for software teams – especially agile teams that continuously refactor their codebase – I genuinely believe that a return on investment could be realized in a single sitting. I hope I don’t sound like a salesperson – this tool just gets all of the big things right and adds a layer of sheen that most applications just don’t have. Hopefully my more detailed posts will make this evident. Until next time…