A fellow MVP Patrick Smacchia is the developer of the .NET tool NDepend, which allows to analyze any .NET code base and helps dealing with code complexity. Since I have been using the tool on and off for a while now and recently very much for the development of our new Engine (a multiplatform engine in .NET), I was asked to write a little review about it. Why not, it is a great tool :) NDepend is probably most recognized for generating interesting looking Bubble Graph. For example our current early testing engine produces the following graph. This tells us where we need to refactor the most, simplify stuff, add more features, etc. Please note that we are currently heavily editing the engine every day and this graph changes almost completely every week. This Bubble Graph shows which methods in all of our 32 projects are currently public (blue). As you can see maybe the Helpers assembly on the left is mostly gray because we already made lots of stuff private/protected. This is just one example, there are many many metrics that can be displayed.
After extracting NDepend (there is no installer) you have a bunch of files in some directory. The most useful looking one is VisualNDepend.exe, which starts the GUI of NDepend. As you can see you can enable integration with Visual Studio 2005 and 2008 (no 2010 yet, but does not really matter, you can still start NDepend by yourself) and with the great Reflector tool. The integration via the addins just provides an easier way to load and inspect assemblies, you can do the same with Visual NDepend on your own.
The second thing I noticed was the "Getting Started" panel, which provides a great deal of help and especially tutorials on how to do things. This is kinda important for NDepend because it is not clear what you actually do with this tool, even after using it for a while. The bad thing about all the tutorials (all of them can be found online: http://www.ndepend.com/Features.aspx) is that they have no sound or voice, just boring text boxes popping up. But if you search for a feature or want to know how to do things, you will most likely find some useful information after a very short while. Also good is that all the information can be found at a central location and everything is linked nicely together. After using the tool a few times it is also not that hard to write own commands with the CQL (Code Query Language) inside NDepend, which is pretty much self explanatory and can be written very easily with Intellisense, for example:
SELECT METHODS WHERE NbLinesOfCode > 50 AND IsPublic
This selects all public methods with more than 50 lines of code in the Bubble Graph. Since only a handful methods will popup (in blue), it is easy to now go and refactor those methods if we really want to reduce the complexity of methods that have too many lines of code. You can obviously show many other things with NDepend, but I usually just go to the Features page or play around with the dropdownbox values until I find something that looks interesting for my assemblies (lines of code, il instructions, complexity, accessors, number of callers, etc.). Then on our "Refactoring Friday" we can use this data to make more clever decissions and refactor methods that really need refactoring and are actually used instead of refactoring anything that is not called much anyway and we should not care much about yet anyway.
VisualNDepend also shows some other interesting metrics. The Dependency Graph shows which assembly is required by which assembly and what assemblies they use in turn (until reaching mscorlib on the right usually). The cool thing is when investigating some assembly, e.g. in the Dependency Matrix, it will also be highlighted in the other views (e.g. Dependency Graph or the Bubble Graph in Metrics). The following image shows which assemblies are using Delta.Helpers and which assemblies it requires itself. Please note that most assembly loading happens dynamically in our engine, which NDepend does not show, so this is only partially useful for us. But for some rules, like every assembly should reference our base assembly Delta, we can easily check if any assembly does not follow this rule by hovering the mouse over Delta, which will highlight all assemblies that use it, the rest remains gray.
One final image I want to share is the Dependency Matrix, which shows which assembly is used by which other assembly. Since most assembly and type usage happens dynamically at load time, most of this matrix should be empty. As you can see some assemblies still have quite a lot of references. For some it makes sense because it it can be easier to use Utilities statically instead of defining an interface for every freaking method. This is why we have a few exceptions for static modules, which have almost no other assembly requirements, but are used by many assemblies. It is still easy to replace such assemblies, but they cannot be replaced at runtime like our dynamic modules. I will blog more about this in the future. For now NDepend helps us to see that some assemblies still have too many static references and others are ok. Next Friday we will focus and removing some more references in those assemblies, which still have too many dependencies we do not want. Until then the Dependency Matrix will probably look pretty much like this (more modules are coming and going every day however):