I’m a fan of tools giving you insight into various code metrics, some of which can be worth keeping an eye on for long lived complex projects. In the .NET side of things, NDepend is one of the best in this regard. Until recently however, NDepend could not deal with C#’s compiler driven async-await stuff for a few metrics. NDepend 6 rectifies that.
C#’s async-await features does a lot of things under the hood. If you have an async method, and you await on a Task in that method, the compiler generates a state machine which does lots of lovely bits to make your code work properly. While this is somewhat transparent to the developer, it causes a lot of things to happen in terms of the IL that gets generated. NDepend (pre 6) deals with generated assemblies, so it sees that state machine and takes it into consideration. This throws metrics off as you suddenly work with more types, and have more fields that’s not directly visible in your source code (well, apart from the async keyword). Things like LCOM (Lack of Cohesion of Methods) considers the number of fields that are used by the number of methods in a class. Since the state machine works as a field, you can see how it can cause a problem.
NDepend 6 caters to these nuances. It reports accurate metrics evens when you’re using async-await. You get exactly the same numbers from the same code structure whether or not you’re using async-await. Considering most things involving I/O are moving to async-await, this is quite useful.
Here’s a very simple program:
We have two classes – SyncThing and AsyncThing that do exactly the same thing with the only difference being that one does its stuff asynchronously. NDepend pre v6 would get confused by this and report different numbers for things like LCOM, LCOMHS, etc. Here’s a screenshot of what NDepend v6 does:
We can see the numbers are exactly the same for SyncThing and AsyncThing. In other words, NDepend is now async aware, and awesomer than before :)