Developers who have worked on large software projects are familiar with the challenges that those projects often face. Maintaining consistency and quality on any large code-base across a development team is difficult. Beyond the aesthetics of a coding standards document and the platitudes of a regular code review process, most team leads can struggle with how to visualize and improve the software that their team is producing. Static analysis, with tools such as FxCop, can be used to checklist conformance to a set of predetermined guidelines, but what happens when you need to visualize your solution at a deeper level?
That’s where NDepend comes in. By helping you to understand the relationships between software modules, both internally and externally, NDepend helps you not only find potential sources of bugs but also provides a rich visualization of how your projects are structured. Dependency graphs, a dependency matrix, statistical analysis, and code querying are just some of the features that will help you to navigate that large code-base in ways that previously seemed implausible.
NDepend is a powerful product. Nearly every time I use it I find a new feature I didn’t previously know existed. Often the tool has educated me on new techniques for understanding code quality and structure as much as it has provided the initial visualization I was seeking. Taking the time to understand the dependency matrix has brought to light several relationships that were the result of several disconnected re-factors; relationships none of our development team leads even knew existed.
The easiest way to start using NDepend is to ask it to analyze a Visual Studio solution. The initial report that is produced is self-explanatory and contains a good amount of high level information.
Prominently highlighted are four diagrams produced directly as a result of NDepend‘s analysis of the projects in the provided solution. The first diagram I always open is labeled Abstractness vs Instability. This plots each of the solution’s assemblies as a point on a graph measuring abstractness and instability simultaneously; with a sweet spot highlighted for assemblies that are both abstract and stable or concrete and unstable. The zones of uselessness and pain are displayed for assemblies exhibiting poor pairings of these traits. As you can see from the screenshot below, an analysis was run on a solution sorely in lack of abstraction. It’s worth understanding the zone of uselessness/zone of pain graph as it shows how balanced each of your assemblies are in terms of both providing concrete functionality while remaining sufficiently abstract. I often use it as a quick health check for systems I am asked to evaluate or maintain. It’s also a great way to open a code review as it provides a quickly recognizable lay of the land.
(click for larger image) (portions of this image have been blurred deliberately)
Depending upon the size of the solution being analyzed, the dependency graph might be too cluttered to be of immediate value. However, subsections of the dependency graph can be generated almost immediately for any method, class, or assembly. Selecting a method within the Class Browser pane allows a dependency graph to be generated showing both callers and callees for the target method. This can be a valuable aid when re-factoring to quickly visualize the effects a change may have on the system as a whole.
Right-clicking over an item in the graph provides a context menu from which you can navigate to the original source code or visualize the target in a variety of different ways:
More advanced concepts, such as efferent coupling, have associated help articles that not only explain the metric in question but give good examples of how the information may be used. Of particular interest are the built-in CQL (Code Query Language) rules that search for common issues within code by querying it as though it were a relational database. In this way many structural issues are highlighted in a single set of reports, each with descriptions of the problem being identified. Those queries form the perfect building blocks for writing my own queries and have provided an easy access into the rich functionality lying beneath.
Working for a large corporation, I am often asked to work on projects that are the results of acquisitions and mergers; code that has been touched by many hands. Design patterns that were adopted early in the development cycle might have been completely dropped or morphed by a subsequent team or as the result of an integration. While the code may be functional it is often far from maintainable. It is in these scenarios where a tool like NDepend really comes in handy. I can respond quickly to many of the questions often asked of a technical lead when evaluating proposed changes to a piece of software in terms of risk, technical debt, overall size and scope, as well as providing quick visual justifications and qualifications for assertions about “code quality”. Discussions of software quality can often lead to lengthy code review processes that take time (and therefore cost money) to enforce. Using a tool such as NDepend to highlight violations of coding policy or provide recommendations on valuable re-factoring can save time and bring structure to an otherwise unwieldy and costly process.