All projects start out with the best of intentions when it comes to keeping the codebase in a clean state. But as the code grows beyond its original intention, it inevitably takes on technical debt. Luckily, there are ways to track that debt with tools like NDepend.
I’d heard of NDepend on a few occasions over the years, but never had the opportunity to play with it before. So when Patrick, NDepend’s founder and lead developer, offered me a chance to try it out, I jumped on the opportunity.
NDepend works on any type of .NET project. I’m always keen to experiment with serverless and so I gave it a go on an Azure Functions project.
Serverless functions tend to be on the small side but that doesn’t mean there isn’t a case to be made for a tool like NDepend. Writing clean serverless code is much like writing clean code in any other type of project.
Installation and Configuration
NDepend can be used in a few different ways. The Visual Studio extension keeps you close to the code. But if you don’t want to install another extension, the standalone version, Visual NDepend, is packed with all the same great features.
There’s also a console version of NDepend if that’s what suits you best. It seems like every day more of .NET is moving to the command line, and NDepend is no exception.
Once you’ve chosen how you’ll run it, the next thing you need to do is create an NDepend project. It can refer to all the assemblies in your solution, or only to those you decide are worthy of being analysed. Once the project is created, NDepend performs an analysis of your project with its built-in rules. And that’s where the fun begins.
The dashboard is at the centre of everything NDepend does. It provides you with a full breakdown of your project, from types analysis, to method complexity and potential issues that need to be investigated.
My favourite feature of the dashboard is the ability to compare the current results against the results at different points in the past. Inevitably, deadlines force us into taking decisions that we regret later on. By comparing current results against results from the past, you can see when and where the project started going sideways, so that you can avoid making the same mistake again.
Applying NDepend to Serverless Functions
With everything installed and configured, I had a look at the results NDepend came up with for my Azure Functions sample project. It’s a fairly small project, but even so, the method complexity and analysis rules came up with a few interesting suggestions:
Avoid types with poor cohesion Nested types should not be visible Avoid namespaces mutually dependent
There aren’t any major issues in that list, but I chose to address them now, while the codebase is still relatively small. It’ll keep the project on track as it continues to grow. I could also run NDepend in a build pipeline to gate successful builds behind it if I ever find myself in a situation demanding it.
The dependency graph is one of NDepend’s most distinguishing and useful features. A serverless application, composed of many functions, shared code, and external dependencies can quickly lead to dependency conflicts. The dependency graph provides you with a visual cue to see what depends on what, and how to re-structure the code to get out of trouble.
Although the project on which I generated the graph is small, it paints a clear picture of the assemblies used throughout the application. This seems invaluable in a larger project, where dependency conflicts are a fact of life.
There is no doubt that NDepend makes for more maintainable .NET projects. It’ll find problems with your code, show you what’s being used where, and tell you when things started straying from the beaten path. A large Azure Functions project, which contains many Function apps, each with many functions, will clearly benefit from its use.
Things aren’t so clear cut when it comes to smaller projects where a Function app is complementary to the rest of your technology stack rather than the centerpiece. You should still plan on integrating NDepend to your project sooner rather than later if you want to grow your functions code base moving into the future.
You can’t go wrong by using NDepend. There is no downside to running it, and it’ll keep your project growing in the right direction.