NDepend provides 82
different code metrics which are all explained on this page.
Several software development topics are addressed by these metrics, like:
- Code volume
with metrics such as number of Lines of Code,
number of IL instructions
or number of types of a namespace,
- Code quality
with Cyclomatic Complexity,
Nesting Depth
or number of parameters
of a method.
- Code coverage by tests with percentage coverage
or number of lines covered.
- Code commenting with percentage comment or number of lines of comment.
- Code structuring with number of callers/callees,
level
of components, ranking
of methods/types and Abstractness vs Instability metrics
for assemblies.
- Code object model metric with number of classes children
or depth of inheritance of a class.
Metrics constitute one
feature of NDepend amongst several others
features like comparing code base snapshots, digging in the structure of a code base through
visual artifact like matrix and graph, or defining active rules.
I would like to focus
here on some tricks to get the most of NDepend code metrics. Sometime the value
of a metric is an immediate indicator to detect code flaws. Methods with more
than 6 parameters and classes with a depth of inheritance greater than 8 are obviously
flaw.
But some other times, the
value of a code metric might be meaningless outside of some contextual information.
For example, a class 100% covered by tests is certainly a good thing. But this
information is more relevant for a large class with 300 lines of code than for
a mini-class with 10 lines of code.
The same for a large method
with 100 lines of code, this is a bad thing! But if the method has no
cyclomatic complexity (meaning if the method has no loop, if, else, switch,
try/catch…) this is not such a big deal since the method might still be easy to
understand and to maintain. On the other hand a small method with 10 lines of
code can become a real nightmare to maintain, especially if it is writing some fields.
To handle properly such
cases, we need to correlate different metrics and eventually some other
properties of the code base. This is possible in NDepend thanks to the Code
Query Language
flexibility.
For example you might
want to know which classes are more than 95% covered by tests but not 100
covered yet. To avoid noise, you might wish to focus on larger classes. With
CQL you can use an ORDER BY clause to sort classes by their number of lines of
code and a TOP clause to limit the number of match.

As you can see the query
result automatically contains all metrics involved in the CQL query and it is
up to you to append more metrics in the query. As a bonus you can see that for each metric displayed in the query result you’ll get statistical information like average and standard deviation.

Another example. Classes
that use many other types (in other words, classes that have a high Efferent
Coupling, Ce) are likely problematic. Indeed a high Ce often means too many responsibilities
for a class. Pinpointing classes with high Ce is easy.
But doing so, you will
certainly match primarily UI classes, like forms and controls. Indeed, UI frameworks
often foster classes with high Ce due to the need to have some kind of large
mediator classes to makes the different UI components communicate. You might
then want to discard forms and controls classes:
And this last screenshot
underlines a cool feature of CQL: the depth
of usage metrics. You can see
that each DeriveFrom XXX condition
leads to a DepthOfDeriveFrom XXX
metric. Obviously, here the values of this metric are N/A
since we especially ask for classes that are not deriving from XXX. But you can use this ability to
build depth of metrics usage on the
fly to know for example where are your UI forms and sort the list by their DepthOfDeriveFrom Form class.
The depth of usage trick is not limited to inheritance and you can use
it on the object creation usage with the condition DepthOfCreateA, on the writing field usage with the condition DepthOfIsWritingField and more generally
on any kind of usage with the condition DepthOfIsUsing
and DepthOsIsUsedBy.
As I explained previously
on this blog, the depth of usage trick
has several interesting applications such as getting all paths from a code
element A to another code element B
… or building some call
graph or class diagram as explained here.
