NDepend’s static code analysis: Noob Review
Today I am going to do something I have not done before. A couple months ago I was contacted by NDepend to play around
According to the website homepage, NDepend is the only Visual Studio extension that is able to tell us developers about created technical debt. This would then allow undoing the debt before it gets committed. The alleged debt is calculated based off a set of rules predefined using LINQ queries. We also can add our own queries.
Enough with introductions, let’s just get noobie!
I downloaded the latest version 2018.1.0 released on Wednesday you can find the link to the latest version here. on NDepend upon download presents itself as a ZIP archive containing some executables and a Visual Studio Extention installer.
As you can see below, the installer propose you to install the NDepend extension to Visual Studio versions all the way back to VS2010.
From there I just installed the extension using the licence key the NDepend team nicely offered me.
Let’s jump right into it
From now on I am going full improv. I will have no idea of what I am doing because that is what most people do when they get a new tool. That approach works when you know how to use a pencil and grab a pen for the first time. It might be a bit more entertaining if I do so with NDepend. Since it is a tool that should allow me to detect technical debt I will write an ok piece of code then some less ok code to see what happens.
First things first, I created a console project running on .Net Core. I am not seeing anything trigger automatically. Being used to Resharper, I check the toolbar and see an NDepend menu that was not there before.
Opening that menu I see that I can create an NDepend project which I do.
Once the project is created, it seems that I still cannot analyze my code. Not before attaching my solution to the NDepend project, which I do.
After attaching the project, I went back to run an analysis on my console app but I kept getting this error:
Turns out the NDepend project did not pick up the Visual Studio project. I then closed Visual Studio to reopen it yet I had the same error after loading the NDepend project and attempting to run the analysis again. Paying more attention to the error message this time, I noticed the error was about a reference to my solution not being loaded in NDepend. I thought that maybe the issue was with me not creating the NDepend project in my console app solution folder. I conjectured that maybe these errors occur because the NDepend project is not in the same directory as my solution. Probably a noob error on my end. So I went on to edit the NDepend project properties.
Above, you can see the NDepend project properties after I added the reference to my solution using the “Add Assemblies from VS solution(s)” button. It seems that it loaded the binary generated by the solution along with It also shows the 3rd-party binaries used by my solution,
System.Console. After that, I ran another analysis and it eventually worked as you can see below:
Now that I finally set up the static analysis properly I can dive into what it reveals from a basic “Hello World!” console app. After that first successful analysis run, I could see that the NDepend menu changed. A whole new world opened to me. As a first reflex, I opened the “Rules” submenu. From there I could see that a rule was violated.
What rule could Microsoft’s “Hello World!” code possibly have violated? Well, look down.
Class with no descendant should be sealed if possible. It is actually more of a warning. A cool bit that I noted is that you even get a more detailed description of the warning cause along with why you should consider it.
I always learned that whenever possible we should have as little warnings as possible so let’s clean that up and make our Program class sealed. After making the change, when I re-ran the analysis, I got the same result and broken rules as before. Also, there was a message telling me that my file
Program.cs was out of sync. I got a hunch and rebuilt the solution. Then the analysis result views updated.
Technical debt (feel free to skip this part)
Now that the code is green and clean. It is time to try and build some technical debt. If you are not familiar with that term I will try to sum it up for you. Technical debt is the implied cost of rework needed in the future when choosing a quick and easy solution over one that would be more thorough but would take more time. More often than not chosing the easy way will hit you back. It will hit you hard.
Let’s say you take a complex subject at school. You could put in place a system to cheat to get good grades. It is easy and does not require extensive preparation work. Yet you can get caught and lose everything. Also, the ink can ruin your cheatsheet. Or, you could learn that subject and try to do your best mastering it class after class, exercise after exercise. You will not necessarily feel the effort was worth it from the start but eventually it will pay off. Learning your subject from the start is hard but you get more confidence to build on top of. Building technical debt on purpose is basically cheating on your Geometry class from high school. Don’t cheat on your Geometry class.
Back on the dirty coding
I felt like I did not want to spend months writing the perfect imperfect piece of code so I just googled “c# bad practices” and opened the first result that came up. From there I just copied the method and adjusted it to be called in our
Main(). You can copy the code below if you are trying to reproduce the experiment.
Once the code ready, I rebuilt the solution and ran a new analysis.
In the post mentioned earlier, there are a few things wrong that are pointed at but some that would be unfair to criticize here. However, I will keep the points that I wish would have been picked up and were not.
What was found
Calculate()method is public yet accessed by only one method in a console app. I hoped I would see more from the actually copied code and not from how I access it in my
What was not found
- The use of the magic numbers 0.1, 0.5, 0.7, 1, 2, 3 and 4.
- Disrespect of the DRY principle with the same piece of logic written twice for discount calculation.
- An alleged bug where the calculated price is 0 when none of the
if-elseis matched (to be fair, it might be a valid business logic in some cases but a warning would be welcome).
It can be considered unfair to point these out and it might be. I will try to spend some time later to see whether it would be possible to create custom rules to spot any of these. That will definitely be a fun exercise. Feel free to try the same at home.
I originally planned on adding a section where I would try to get more warnings and errors but that would be outside the boundaries of what I want a Noob review to be. A follow-up post covering more complex cases and custom queries would be more fitting for a separate post anyway. Since there are loads of things currently happening in my life, that post might not happen for a while. That being said let’s wrap up with some pros and cons I noted during that quick take.
- NDepend provides a clear explanation of what rules are broken and where in your project.
- Don’t need an engineering degree to get started without a manual. I do have one so that might invalidate my comment so people without engineering degrees let me know if you found it hard to use without checking any guide.
- Have to re-open the NDepend project when restarting Visual Studio.
- Have to rebuild project when editing file to verify that no rule was violated or whether a violation was fixed. Also building the project does not automatically trigger NDepend’s analysis either.
- Not available on VSCode or VS for Mac.
Special note on customization
While people love to customize things I do not trust myself for writing a rules engine determining my code’s quality. I’m likely to make a mistake in there and not notice it. I may actually change it to a pro after experimenting with it more.
After that first experiment, I do not think I would use NDepend for my personal projects. The cons I pointed above outweight the pros in my opinion. I do believe that spending more time with NDepend could change my vision of it and maybe make me realise that it fits my needs more than I think. I am no evangelist nor influencer, even if I was or become one by the time you read this, you should not take this post as absolute truth. It is a Noob Review after all, it cannot be right nor fair. My piece of advice is to go and have a look for yourself. If your interest got piqued by this post, you should download NDepend and figure out whether it fits your needs. You can have a 14-day trial to play with it. Happy experimentation!