NDepend

Improve your .NET code quality with NDepend

Using NDepend to Make You a Better Programmer

If you’re a software developer, particularly of the newly minted variety, the concept of static analysis might not seem approachable.  It sounds academic.  It sounds architect-y.  It sounds complicated.  I’ve seen this reaction from a lot of people in my career and I think that’s too bad.

If you delve into its complex depths, static analysis can be any and all of these things, but with the developers I mentor and coach, I like to introduce it as a game that makes you better at what you do.  You can use static analysis to give yourself feedback about your code that is both fast and anonymous, allowing you to improve via trial and error, rather than by soliciting feedback from people much more tenured than you and sometimes wincing as they lay into you a little.  And, perhaps best of all, you can calibrate the quality of your code with the broader development world, rather than just pleasing the guy who has hung around your company long enough to default his way into the “tech lead” role.

 

NDepend Rules

 

 

Take a look at some of the feedback that NDepend offers about your code.  “That method is too big” isn’t particularly intimidating, is it?  I mean, you might wonder at what you could do to compact a method, but it’s not some kind of esoteric rule written in gibberish.  You run NDepend on your code and you can see that there is some number of methods that the broader development community considers to be “too big.”

From there, you can start looking at ways to write smaller methods and to refactor some of your current ones to sneak in under the warning number.  This is the essence of gamification — you change the way you write code to get rid of the warnings.  You get better.  And it’s gratifying.

As you do this, another interesting thing starts to happen.  You start noticing that other developers continue to write large methods and when you run NDepend on their code, they light up the console with errors, whereas you do not with your code.  And so, you can have conversations with them that start with, “you know, this static analysis tool I’ve been using wants us to have smaller methods, and I’ve been working a lot on that, if you ever want a hand.”

You gain a reputation as being knowledgeable.  Before you know it, you can cite widely accepted static analysis rules and the design goals they imply.  You know these rules, and, via gamification, you have experience molding code to comply with them.  Even in cases where you might wind up overruled by the local team lead or architect, it’s no longer a simple matter of that person saying, “because I said so,” and just ending the conversation.  They have to engage with you and present cogent counter-arguments to your points.  You’re participating in important discussions in ways that you never have before.

If it sounds like I’m speaking from experience, I am.  Throughout my career, I’ve been relentless about figuring out ways to improve my craft, always trying to be a better programmer.  Early on, I was unsatisfied with a lot of arguments among developers around me that I knew boiled down to nothing more than personal preference, so I went out in search of empirical methods and broader knowledge, and that search brought me to static analysis.  I read about data and science behind particular choices in approaching software, and I schooled myself to adopt the approaches that had brought the best results.

Somewhere along that journey, I discovered NDepend and its effect on my approach to writing code was profound.  My methods shrank and became less complicated.  My architectural and design skills improved as I made it a point to avoid dependency cycles and needless coupling.  I boosted unit test coverage and learned well established language practices.  It was not long before people routinely asked me for design advice and code reviews.  And from there, it wasn’t long before I occupied actual lead and architect roles.

So, if you want to improve your craft and nudge your career along, don’t pass on static analysis, and don’t pass on NDepend.  NDepend is not just a tool for architects; it’s a tool for creating architects from the ranks of developers.  You’ll up your game, improve your craft, and even have some fun doing it.

Static Analysis : Code as Data

A lot of programmers have some idea of what static analysis is, as least superficially.  If I mention the term, what pops into your head?  Automatic enforcement of coding standards?  StyleCop or FXCop?  Cyclomatic complexity and Visual Studio’s “maintainability index?”  Maybe you’re deeply familiar with all of the subtleties and nuances of the technique.

Whatever your level of familiarity, I’d like to throw what might be a bit of a curve ball at you.  Static analysis is the idea of analyzing source code and byte code for various properties and reporting on those properties, but it’s also, philosophically, the idea of treating code as data.  This is deeply weird to us as application developers, since we’re very much used to thinking of source code as instructions, procedures, and algorithms.  But it’s also deeply powerful.

When you think of source code this way, typical static analysis use cases make sense.  FXCop asks questions along the lines of “How many private fields not prepended with underscores,” or, perhaps, “SELECT COUNT(class_field) FROM classes WHERE class_field NOT LIKE ‘_*’”  More design-focused source code analysis tools ask questions like “What is the cyclomatic complexity of my methods,” or, perhaps, “SELECT cyclomatic_complexity FROM Methods.”

But if code is data, and static analysis tools are sets of queries against that data, doesn’t it seem strange that we can’t put together and execute ad-hoc queries the way that you would with a relational (or other) database?  I mean, imagine if you built out some persistence store using SQL Server, and the only queries you were allowed were SELECT * from the various tables and a handful of others.  Anything beyond that, and you would have to inspect the data manually and make notes by hand.  That would seem arbitrarily and even criminally restrictive.  So why doesn’t it seem that way with our source code?  Why are we content not having the ability to execute arbitrary queries?

I say “we” but the reality is that I can’t include myself in that question, since I have that ability and I would consider having it taken away from me to be crippling.  My background is that of a software architect, but beyond that, I’m also a software craftsmanship coach, teacher, and frequent analyzer of codebases in a professional capacity, auditing a wide variety of them for various properties, characteristics, and trends.  If I couldn’t perform ad-hoc, situation-dependent queries against the source code, I would be far less effective in these roles.

My tools of choice for doing this are NDepend and its cousin JArchitect (for Java code bases).  Out of the box, they’re standard static analysis and architecture tools, but they also offer this incredibly powerful concept called CQLinq that is, for all intents and purposes, SQL for the ‘schema’ of source code.  In reality, CQLinq is actually a Linq provider for writing declarative code queries, but anyone that knows SQL (or functional programming or lamba expressions) will feel quite at home creating queries.

Let’s say, for instance, that you’re the architect for a C# code base and you notice a disturbing trend wherein the developers have taken to communicating between classes using global variables.  What course of action would you take to nip this in the bud?  I bet it would be something annoying for both you and them.  Perhaps you’d set a policy for a while where you audited literally every commit and read through to make sure they weren’t doing it.  Maybe you’d be too pressed for time and you’d appoint designated globals cops.  Or, perhaps you’d just send out a lot of angry, threatening emails?

Do you know what I would do?  I’d just write a single CQLinq query and add it to a step in my automated team build that executed static analysis code rules against all commits.  If the count of global variable invocations in the code base was greater after the commit than before it, the build would fail.  No need for anger, emails or time wasted checking over people’s shoulders, metaphorically or literally.

Want to see how easy a query like this would be to write?  Why don’t I show you…

That’s it. I write that query, set the build to run NDepend’s static analysis, and fail if there are warnings. No more sending out emails, pleading, nagging, threatening, wheedling, coaxing, or bottleneck code reviewing. And, most important of all, no more doing all of that and having problems anyway. One simple little piece of code, and you can totally automate preventing badness. And best of all, the developers get quick feedback and learn on their own.

As I’ve said, code is data at its core.  This is especially true if you’re an architect, responsible for the long term health of the code base.  You need to be able to assess characteristics and properties of that code, make decisions about it, and set precedent.  To accomplish this, you need powerful tooling for querying your code, and NDepend, with its CQLinq, provides exactly that.

NDepend version 6 insights

Welcome to the brand new NDepend blog! This blog will talk about NDepend of course, announcements, directions, features advanced usage, but this blog will also talk about related topics including, coding tricks, .NET static analysis, methodologies, theories behind features and .NET development tooling industry in general.

 

Choosing the right set of new features

Today I’d like to talk about the just released NDepend version 6. So far our major releases schedule followed the Microsoft Visual Studio release schedule, and Visual Studio 2015 is actually in Release Candidate period. NDepend v6 is the result of 18 months of hard work. After 11 years of development, NDepend reached a certain level of maturity. Yet there are still many new potential features and improvements possible. We found out that the most sensitive part for this version 6 was actually to chose carefully the set of new features and improvements we’d like to offer to users.  Hopefully, once version 5 was published in October 2013, we got inspiration from the Visual Studio User Voices and opened our NDepend User Voices.  As a matter of fact, version 6 new stuff reflects well the most demanded features that have just been marked as completed.

Build-Process Workflow Integration

Clearly users were asking loud for more NDepend integration into their build-process automated workflow.  So far, users were running NDepend.Console.exe, gathering the report and the information: is there any critical rule violated that should make our build fail? (this info can be obtained NDepend.Console.exe exit code). Users were asking about more information to be shown right inside their build-process tooling. There are many build-process technologies and the most demanded one were TFS, TeamCity and SonarQube. Hence we’ve collaborated with world-class experts of these technologies to deliver build-in integration. We hope that proposed integration will address most scenarios, and we are committed to support further versions and enhance the feature set.

Enhanced Visual Studio Integration

It was not surprising that users wanted more build-process integration since during the last year the bulk of our efforts were devoted to tooling for developers inside Visual Studio. NDepend was integrated in Visual Studio through the VS Addin technology because of a choice we’ve made in 2009. At that time VSIX (VS package technology) was immature and we had to support VS2008 and VS2005, hence VS Addin was the right choice. Time passing by made this initial choice less and less relevant, the VS Addin technology didn’t get any improvement from Microsoft and worth, implied a few glitches like random bug, but worth, the impossibility for VS to remember NDepend windows layout across execution. This was a pain for NDepend users and they ended up asking it loud on the User Voice to remember VS Windows Layout!

With version 6 NDepend relies on the VSIX technology to integrate in VS 2015, 2013, 2012 and 2010. (Should we mention that MS deprecated the VS Addin technology in VS 2015?). Anyway now thanks to VSIX we are able to offer a smoother and more reliable VS integration with windows layout remembering and with new features like the possibility to attach the NDepend project to a .suo file (and not only .sln file) and full support for NDepend commands keyboard-shortcut.

There were also 3 VS build featurettes proposed by various free VS extensions, and we figured out that ourselves were pretty much addicted to it. We decided to include them in the NDepend VS package, this way we will be sure to always have them at hand, and with a bit of luck, NDepend users will enjoy them too 🙂

Rule Improvements

.NET code ruling is the central feature of NDepend. We had many feedback from users about how to improve existing default code rules, mostly to reduce the number of false-positive reported. hence we’ve refactored around a third of default code rules based on their recommendations.

While doing so we figured out we have been a bit too geeky. This is great that NDepend code rules are actually editable C# LINQ queries that can contain some comments. But for many users this didn’t convey enough information about why a rule actually warns, why abiding by a specific rule will enhance their code, and how to fix a violation of the rule. Hence we’ve added the possibility to add 2 formatted texts in a NDepend rule source code comment through <Description> and <HowToFix> tags. This has been a great opportunity for us to write out about each default rule and provide users more explanations. Both in UI and in report, the user can chose to see the Description/HowToFix, or the rule C# LINQ source code.

Another need that users were asking loud in the User Voice, was the possibility to share some rule set among several NDepend projects. Typically a Company has several code bases analyzed each by a NDepend project, and what users want is a Company-level quality profile that can be applied to each code base. And taking account that NDepend makes easier than any other tool to define custom rules on .NET code, users wanted even more to define custom quality profile shareable. We addressed this need in NDepend v6 with the possibility to define rule files that can be shared among NDepend projects.

Code Metrics Visualization

NDepend already had code metrics visualization with treemaping and we decided to add coloring. The idea is that we can then visualize two code metrics, one represented by rectangle area, the other one represented by rectangle color. For example, the screenshot below shows NDepend version 6 code coverage by tests in a unique, yet convenient and accurate way.

  • Rectangles represent methods,
  • Rectangle area is proportional to # Lines of Code,
  • Rectangle color represents percentage code coverage by tests

ColoredTreemap

I hope this picture helps understand why we wanted to offer users this feature. At a glance, colored treemaping can help grasp information that would be hard to get through another mean. Despite the fact NDepend v6 code base is 82%+ covered by tests, we can identify aggregation of red rectangles that shed light on regions of code not enough covered by tests. I believe no other tooling can offer such level of details, and while developing this feature, I was really looking forward what it has to say about our own coverage & testing work!

And as usual we like to make the various NDepend features interact. Hence not only you can visualize any two of the many NDepend default code metrics set, you can visualize custom code metrics defined through C# LINQ queries, and you can also highlight the result set of a code rule or a code query. Hence if we query for complex methods, we can filter complex methods match on the colored treemap:

TreemapAndSelection

Let’s mention that since we think that code coverage by tests is one of the most important code quality data, we also added dedicated UI candies for it in code query result:

Improvements that had to be made

A product belongs to a constantly evolving environment. This means that with years, some features that were working fine need to be revisited. Several of such needed improvements / fixes have been achieved with NDepend version 6.

Support code generated by C# and VB.NET compiler: Version after version, C# and VB.NET languages increased the amount of syntax sugar offered to the user. It started with C#2 anonymous methods and iterators, followed with C#3 lambda and anonymous types and then C#5 async support. These language constructs constraint the compiler to generate extra methods and types. And since these constructs are pretty much used, numbers of these generated elements accumulate in the IL code. And NDepend mostly relies on IL code to get code information. Hence the NDepend code model included all these generated methods and types and this started annoying the user, mostly interested by its own code. NDepend now fixes this. Simply getting rid of these generated elements was not an option because they actually contains some user code. Hence we developed some heuristics to merge these generated elements in users classes and methods that contain the code that provokes the generation by the compiler. This way there is no compromise, all the code model data is preserved, including: Code metrics (# Lines of Code, Percentage Coverage, Cyclomatic Complexity…), dependencies and diff.

Better async support: The async language construct comes with a specificity that provoked some NDepend issues. The user code is actually embedded by the compiler in a generated method that overrides the virtual method IAsyncStateMachine.MoveNext(). Hence the IL code invoking this MoveNext() generated method is bound with the interface abstract method and not with the implementation. The calls toward the async method are then lost in IL … ans so in the NDepend code model. Thanks to the heuristics wrote for the previous point, NDepend analysis is now able to track properly callers of async methods.

Support for high-DPI: Nowadays hi-resolution monitors (like 4K monitors) become affordable and as a consequence, more and more developers work with high-DPI Windows settings. High DPI means that the density of pixels is higher and as a consequence more pixels are used to represent a graphical element (text, bitmap…). The NDepend UI is mostly based on Windows Form and GDI+ and these technologies don’t scale well by default when Windows is set with high DPI. Since some users started to ping us about this problem we decided to re-lift the whole NDepend UI to make it works with DPI settings from 100% to 250%. This has been the opportunity to enhance some graphical elements and to learn some Windows Form and GDI+ high-DPI practices. I’ll try to summarize these findings in a future blog post, because browsing the web, I can see that it is a pain for many developers.

Visual Studio Theming: From our production statistics most of users consume NDepend for Developer features from within Visual Studio. So far the NDepend UI themes didn’t fit perfectly the various Visual Studio default themes, this includes Light, Dark, Blue and VS2010 default themes. Hopefully NDepend menus/bars/docking… elements are based on the DevExpress WinForm library and their latest version included these themes (and some more). Hence upgrading to the highest version of this framework did the trick.

Analysis improvements: Some improvements had to be made concerning analysis. One of them concerns resolution of assemblies to analyze. A NDepend project references a set of directories and a set of assemblies names (without file extension). At analysis-time, assemblies to analyze locations are resolved from these two sets. If multiple copies of an assembly were found, either all copies had same bits and NDepend took one of them, either some copies were different and NDepend emitted an error resolving the assembly, because we use to consider this situation as a serious deployment problem. However with time, new technologies like Windows Phone or  Portable Class Libraries appeared, and they actually provoking such situation during valid scenario. Hence, when detecting such situation, NDepend v6 now uses an heuristic to resolve the proper assembly occurrence, based on the assembly version, assemblies referenced and file size.

 

 

We are very glad to have been able to pack all these in NDepend version 6.

We hope you’ll enjoy using this new version just as much as we enjoyed making it 🙂