You have probably seen this meme offering services that could be any two of good, cheap, or fast:
When I first saw it, I only found it funny. But now I see how clever it is. It alludes to three kinds of expenses every software team has to think about: Quality, Money, Time.
Martin Fowler wrote a post a couple years back titled "Is High Quality Software Worth the Cost?". In summary:
users and customers can see what makes a software product have high external quality, but cannot tell the difference between higher or lower internal quality.
The last point, in particular, directly contradicts the meme, doesn't it?
Patrick Smacchia emailed a few years back asking me to try NDepend**, and I've been playing around with it through 2021.
NDepend is a tool focused on improving your .NET code quality.
Now if you search through the internet, you'll see a ton of posts talking about NDepend's features. So, I thought, for this post, I'd explore how the tool could possibly help you or your team write better code. And how a team could go about deciding whether they could benefit from NDepend.
Here are a few things about NDepend that I thought was cool:
Like every other debt, technical debt could be okay if we're responsible about it. The simplest way to reason about introducing low-quality code is to weigh its short-term benefits with long-term consequences.
Let's say you are working on prototype feature. Building the feature well would require you to either refactor some existing code or write some unclean code. If you choose to start with writing some unclean code, NDepend can now help you estimate how long it'll take to get that code in order.
It's not usually possible for a team to decide that they're gonna pay of all their technical debts in the next n days. It doesn't work that way. It's often wiser to first start by not introducing any new debt, and then identify patterns in existing well-written code, and then see how we could clean old code up. It takes time.
This is precisely the problem with .NET Analyzers. They are perfect if the code has near-zero debt, and also work just fine for new projects. But if you own a code base with a lot of technical debt, enabling all .NET Analyzer rules is sure to spit a gazillion warnings.
This is one place where NDepend shines. It allows you to look at new debt introduced over time by allowing you to compare with a "baseline". This makes it easier to write clean code incrementally.
.NET analyzers also encourage you to maintain code quality over the entire codebase. With NDepend, it makes it possible to prioritize certain portions of the code over the others instead.
NDepend also allows you to generate a bunch of graphs that can act as a map to your application. The way files are laid in project can tell you a lot about what's going on, but visualizations make it easier to create a mental model.
This is one of those features that even developers new to C# can appreciate.
Let's say I wanted to use MassTransit's SignalR integration. If I was new to MassTransit, I could clone the repository and look at the dependency graph.
The following graph tells me that MassTransit.SignalR
takes a dependency on MassTransit.ExtensionsDependencyInjectionIntegration
(the default Microsoft DI container).
If I wanted to know about where the ISendTransport
type is being used within MassTransit, the traditional Visual Studio way would be to use the references link above the type name:
But a graph can tell you a complete story:
This graph tells me that MassTransit.SignalR
does not use ISendEndpoint
directly or indirectly.
NDepend is not for everyone. And so, I've come up with two steps to help you evaluate if it will benefit you or your team, and a bonus third step to plan the first phase of improving code quality with your team.
The evaluation should ideally be done by a relatively senior engineer that cares about improving code quality and gets to have a say to that end.
*.ndproj
).Was NDepend able to reveal something you either did not know?
Was NDepend able to reveal something you knew but never had a chance to talk to your team about?
If you answered no to both questions, you're probably better off with plain .NET Analyzers at this point. You may re-evaluate NDepend better.
But if you answered yes, make a note of what NDepend revealed. You'll need it in step 3.
where i.WasAdded()
clause. Take enough time and go through issues and its corresponding "how to fix" recommendations.
Was NDepend able to flag issues that your team cares about?
Was NDepend able to flag issues you know your team should be caring about?
If the answer is no to both of the above issues, you won't need NDepend unless you want its visualizing capabilities.
But if you answered yes here, NDepend is probably going to be worth a shot.
At this point, you should have about 5 to 9 working days left on your NDepend evaluation period.
Get on a team call and try to have an honest discussion about code quality. Define your code quality as one of:
I'd only recommend NDepend for a team that falls in category #2.
If this is you, pick a portion of your codebase (it could be an assembly or a namespace) and decide which NDepend rules matter and which do not. It is possible that step I. of evaluation uncovered structural problems with the way the application was architected; if this is the case, talk about it on the call and decide next steps.
If the team is on #3, you might want to consider getting someone that could help the team. While NDepend might still help you, it cannot give you the sense of direction another experienced engineer can. (Besides, if a team is capable of saying it's not good enough, isn't it already on its path to getting better?)
I did not know what to do with NDepend when I started but I slowly began to appreciate it over time. It does not have a steep learning curve, but it does take a while to figure how it could fit into your workflow.
If you find yourself diving into new codebases ever so often my guess is that you'll appreciate this tool. On the other hand, if you know your codebase through and through, NDepend may or may not suit your specific needs but is certainly worth evaluating.
Lastly, if you've been considering NDepend, I hope this post helps you make the most of the free trial period.