At some point in your development career, you would have had an existing project dumped on you that you will have problems understanding and generally getting around the code. Those difficulties can be the result of some undocumented domain reasons, but could also be because of code smells. The code smells will also make the domain difficult to understand. This, I'm sure, will have been experienced by nearly every developer.
When this happens, the project that you are working on contains a large amount of technical debt. Every new developer on the project loses time trying to navigate their way around the confusing and smelly code. The project becomes infamous within your team and nobody wants to work on it. The code becomes unloved with no real owner. You need to repay some of the technical debt.
In the agile world, we should be refactoring and reviewing code bravely and regularly to improve it's quality and to reduce the number of code smells. This however can be difficult for a number of reasons:
- Confidence - "can I really change this code without breaking xy and z section of this application?"
- Reasoning - "Is renaming this method from "xyz" to "Xyz" really the correct thing to do?"
It's safe to assume that nobody is going to be completely sure of the above to questions in all circumstances. This is why it's becoming more and more common to use a code analysis tool to help you find any potential code smells, and advise you on how to fix them. A code analysis tool can be that advisor telling you what you can do to reduce your technical debt. It can also stop you from racking up a technical debt in the first place.
In this post, I'll be exploring NDepend, a powerful static code analysis tool that can highlight any smells in your code, and give me some good metrics about my code. I'll be running it against the latest a version of NerdDinner, which can be downloaded from here.
You can run through this walk-through as you are reading this post with NDepend. You can find installation instructions here.
NDepend examines compiled code to help you find any potential issues in the generated IL code - so if you are running NDepend outside of Visual Studio, make sure you build your project first.
nDepend 101 - Red / Yellow / Green code
So let's start with the basics. One of the coolest things about NDepend is the metrics that you can get at so quickly, without really doing much. After downloading and installing NDepend, you will see a new icon in your Visual Studio notification area indicating that NDepend is installed:
Now, we can fire up NDepend simply by clicking on this new icon and selecting the assemblies that we want to analyse:
We want to see some results straight away, so lets check "Run Analysis Now!". Go ahead and click ok when you are ready. This will then generate a html page with detailed results of the code analysis. The first time you run NDepend you will be presented with a dialogue advising you to view the NDepend Interactive UI Graph. We'll get to that in a moment - but first lets just see what NDepend's default rules thought of NerdDinner:
Yellow! This means that NerdDinner has actually done ok - we have some warnings but no critical code rule violations. If we had some serious code issues, this icon would turn red. These rules can be customised and new rules can be added, but we'll cover this later. So we now have a nice quick to view metric about the current state of our code.
This is a really basic measure, but it lets us know that something in our code, in it's current state, either passes or fails analysis by NDepend. You may be questioning the usefulness of this, but if your team knows that their code must pass analysis by NDepend, a little red / yellow / green icon becomes a useful and quick to see signal. Are my changes good or bad?
The Dependency graph allows you to visually see which libraries are reliant on each other. Useful if you want to know what will be effected if you change a library or swap it out for something else (you should be programming against interfaces anyway!):
By default, the graph is also showing you which library has the most number of lines of code. The bigger the box, the greater the lines of code. This sizing can also be changed to represent other factors of a library, such as the number of intermediate instructions. This lets you easily visualise information about your codebase.
Queries and Rules
Out of the box, NDepend will check all of your code against a set of pre-defined rules which can be customised. Violations of these rules can be treated as a warning, or as a critical error.
So NerdDinner has thrown up a few warnings from nDepend. Let's have a look at what these potential code smells are, and see how they can be actioned:
So, within our Code Quality rule group, NerdDinner has thrown up warnings against 3 rules. NDepend's rules are defined by using a linq query to analyse your code. Let's take a look at the query to find any methods that are too big:
It's quite self explanatory. We can easily alter this linq query if we want to change our rules - e.g. alter the number of lines of code necessary to trigger the warning. Looking at the results from the query:
NDepend has directed us to 2 methods that violate this rule. We can get to them by double clicking on them, so that we can start re-factoring them. It's worth stating here that a method that is too big potentially violates the single responsibility principle as it must be doing too much. It needs breaking up.
Using NDepend to enforce future change rules
A stand out feature of NDepend that I haven't seen anywhere else before is it's ability to execute rules against changes. I.e, you can tell NDepend to look at two different versions of the same dll, and check that only changes made meet a set of rules. This can be handy in situations where you cannot realistically go back and fix all of the previous warnings and critical violations. Whilst you can't expect your team to fix the old code smells, you at least expect them to be putting good clean code into the application from now onwards.
Again, NDepend comes with some really good sensible rules for this kind of situation:
Whilst there are plenty of tools out there to help you write clean, maintainable, non smelly code, NDepend does strike as a very powerful and highly customisable tool. It also stands out as it can be run within Visual Studio itself or as a standalone executable. This opens up the potential to it being run on a build server as part of a build process. I certainly have not done NDepend justice in this post as there is heaps more to it, so I would recommend downloading it and running it against that huge scary project that you hate making changes to.