NDepend

Improve your .NET code quality with NDepend

A Test Coverage Primer for Managers

Managing Blind

Let me see if I can get in your head a little bit.  You manage a team of developers and it goes well at times.  But, at other times, not so much.  Deadlines slide past without a deliverable, weird things happen in production and you sometimes get deja vu when a bug comes in that you could swear the team fixed 3 months ago.

What do you do?  It’s a maddening problem because, even though you may once have been technical, you can’t really dive into the code and see what’s going on.  Are there systemic problems with the code base, or are you just experiencing normal growing pains?  Are the developers in your group painting an accurate picture of what’s going on?  Are they all writing good code?  Are they writing decent code?  Are any of them writing decent code?  Can you rely on them to tell you?

As I said, it’s maddening.  And it’s hard.  It’s like coaching a sports team where you’re not allowed to watch the game.  All you can do is rely on what the players tell you is going on in the game.

A Light in the Darkness

And then, you light upon a piece of salvation: automated unit tests.  They’re perfect because, as you’ll learn from modern boilerplate, they’ll help you guard against regressions, prevent field defects, keep your code clean and modular, and plenty more.  You’ve got to get your team to start writing tests and start writing them now.

But you weren’t born yesterday.  Just writing tests isn’t sufficient.  The tests have to be good.  And, so you light upon another piece of salvation: measuring code coverage.  This way, not only do you know that developers are writing tests, but you know that you’re covered.  Literally.  If 95% of your code base is covered, that probably means that you’re, like, 95% good, right?  Okay, you realize it’s maybe not quite that simple, but, still, it’s a nice, comforting figure.

Conversely, if you’re down at, say, 20% coverage, that’s an alarming figure.  That means that 80% of your code is not covered.  It’s the Wild West, and who knows what’s going on out there?  Right?  So the answer becomes clear.  Task a team member with instrumenting your build to measure automated test coverage and then dump it to a readout somewhere that you can monitor.

Time to call the code quality issue solved (or at least addressed), and move on to other matters.  Er, right?

Fools’ Gold?

I’ve managed software developers in the past, so I understand the disconcerting feeling that comes from not really being able to tell what’s happening under the covers.  These days, I’m living a little closer to the keyboard, and my living comes largely from coaching developers, and doing IT management consulting and gap analysis.  And a common gap is managers thinking that test coverage correlates a lot more strongly with well written, well tested code than it actually does.

Don’t get me wrong.  In a nice, clean code base, you’re likely to see extremely high test coverage figures.  But many managers get the cause and effect relationship backward.  Really well crafted code causes high coverage.  High coverage does not necessarily cause really well crafted code.

To understand the disconnect, consider the relatively common situation of purchasing a home.  In the USA, part of this process is a (generally) mandatory home inspection in which a licensed home inspector examines the house in detail, making note of any deficiencies, problems, dangers, etc, and giving a general report on what kind of shape the house is in.

Now, you’re no carpenter, and you certainly don’t understand what all the home inspector is doing.  But, you want to know if he’s doing a good job.  So, you introduce a metric.  You make note of how many rooms in the house he enters during his inspection.  If he doesn’t cover at least 90% of the rooms, he’s not doing great work.  If he only covers 20%, he’s terrible.

But the same problem arises.  The fact that he wandered through every room in the house does not mean he did a good inspection.  If he did a thorough inspection, the result will be that he covered a high percentage of rooms.  If he covered a high percentage of rooms, he may or may not have done a thorough inspection.

There Are No Shortcuts

So, what if you timed the inspector?  And, what if you introduced another metric in addition to code coverage to make it harder to game or to be wrong?  Well, that might help a bit, but there are no easy answers, really.  If you want to know whether the inspector does good work, hire another inspector or two, and triangulate.  If you want to know whether a test suite is good or not, you need to have someone with experience do a lot more digging and inspection of the code.  I know you don’t want to hear this because you’re picturing costs, but knowledge isn’t cheap.

I assess code bases a lot, and when looking at test suites, here are some questions I ask (and then answer):

  • What is the average number of asserts per method?  Way less than 1 means you might have useless tests.  Way more than 1 means you might have convoluted, brittle tests.
  • What percentage of test methods have a number of asserts other than 1?  This might indicate a flawed approach to testing.
  • What is the average size of a test method?  Large test methods tend to indicate brittle tests that people will abandon.
  • Do tests often refer to static/global state?  This may indicate an unreliable test suite.
  • Do tests have a lot of duplication?  This may indicate poorly written tests or even a poor design of production code.

I could go on, but you get the idea.  An important takeaway is that I say “may” and “might” in all of my explanations because, you know what?  Life isn’t simple.  These things may exist in your test code, and there may be a perfectly reasonable explanation.  Just as test coverage may or may not be indicative of code quality.

Detecting whether things are on the right track or not isn’t easy.  But the more metrics you have, and the more you use them as triggers for further investigation instead of quality gates, the better equipped you and your group will be.

Let’s Build a Metric 3: Compositeness

Last time, I talked through a little bit of housekeeping on the way to creating a metric that would be, uniquely, ours.  Nevermind the fact that, under the hood, the metric is still lines of code.  It now has a promising name and is expressed in the units we want.  And, I think that’s okay.  There is a lot of functionality and ground to cover in NDepend, so a steady, measurable pace makes sense.

It’s now time to start thinking about the nature of the metric to be created here, which is essentially a measure of time.  That’s pretty ambitious because it contains two components: defining a composite metric (recall that this is a mathematical transform on measured properties) and then tying it an observed outcome via experimentation.  In this series, I’m not assuming that anyone reading has much advanced knowledge about static analysis and metrics, so let’s get you to the point where you grok a composite metric.  We’ll tackle the experimentation a little later.

A Look at a Composite Metric

I could walk you through creating a second query under the “My Metrics” group that we created, but I also want this to be an opportunity to explore NDepend’s rich feature set.  So instead of that, navigate to NDpened->Metric->Code Quality->Types with Poor Cohesion.

Metric3

When you do that, you’re going to see a metric much more complicated than the one we defined in the “Queries and Rules Edit” window.  Here’s the code for it, comments and all.

There’s a good bit to process here.  The CQLinq code here is inspecting Types and providing data on Types.  “Type” here means any class or struct in your code base (well, okay, in my code base), along with a warning if you see anything that matches.  And, what does matching mean?  Well, looking at the compound conditional statement, a type matches if it has “LCOM” greater than .8 or “LCOMHS” greater than .95 and it also has more than 10 fields and 10 methods.  So, to recap, poor cohesion means that there are a good number of fields, a good number of methods, and… something… for these acronyms.

LCOM stands for “Lack [of] Cohesion of Methods.”  If you look up cohesion in the dictionary, you’ll find the second definition particularly suited for this conversation: “cohering or tending to cohere; well-integrated; unified.”  We’d say that a type is “cohesive” if it is unified in purpose or, to borrow from the annals of clean code, if it conforms to the single responsibility principle.  To get a little more concrete, consider an extremely cohesive class.

This class is extremely cohesive.  It has one field and three methods, and every method in the class operates on the field.  Type cohesion might be described as “how close do you get to every method operating on every field?”

Now, here’s the crux of our challenge in defining a composite metric: how do you take that anecdotal, qualitative description, and put a number to it?  How do you get from “wow, Recipe is pretty cohesive” to 0.0?

Well, this is where the mathematical transform part comes in.  Here is how NDepend calculates Lack of Cohesion of Methods (LCOM).

  • LCOM = 1 – (SUM(MF)/(M*F))

Where:

  • M is the number of methods in class (both static and instance methods are counted, it includes also constructors, properties getters/setters, events add/remove methods).
  • F is the number of instance fields in the class.
  • MF is the number of methods of the class accessing a particular instance field.
  • Sum(MF) is the sum of MF over all instance fields of the class.

Quantifying the Qualitative

Whoah.  Okay, let’s walk before we run.  It’ll be helpful to work backward from an already proposed formula.  What do we know by looking at this?

Well, at the very highest level, we’re talking about fields and methods in the class, and how they interact.  It’s easy enough to count the number of methods and fields — so far, so good.  MF, for a given field, the number of methods in the class that access that field, which means that Sum(MF) is the aggregate for all fields.  Sum(MF) will therefore be less than or equal to M*F.  They’re only equal in the case where every method accesses every field.

Thus the term SUM(MF)/(M*F) will range from 0 to 1, which means that the value of this metric ranges from 1 to 0.  1 is thus a perfectly non-cohesive class and 0 is a perfectly cohesive class.  Notice that I described Recipe as “0.0”?  If you run this metric on that class, you’ll see that it scores 0 for a “perfect cohesion score.”  And so, the goal here becomes obvious.  The creator of this metric wanted to come up with a way to describe cohesion normalized between 0 and 1 with a concept of bounded, “perfect” endpoints.

And this is the essence of compositeness, though to build such a metric, you create the transform rather than working backward to deduce the reasoning.  You start out with a qualitative evaluation and then think about a hypothesis for how you want to represent that data.  Is there a minimum?  A maximum?  Should the curve between them be linear?  Exponential?  Logarithmic?

It’s not a trivial line of thinking, by any stretch.  As it turns out, there isn’t even agreement, per se, on the best way to describe type cohesion.  You’ll notice that NDepend supports a secondary metric (that I intentionally omitted from the formula definition above for simplicity) for cohesion called LCOM HS, which stands for the “Henderson Sellers Lack of Cohesion of Methods.”  This is a slightly different algorithm for computing cohesion.  And man, if experts in the field can’t agree on the ideal metric, you can see that this is a tall order.  But hey, I didn’t say it’d be easy — just fun.

So, having seen a little bit more of NDepend and established a foundation for understanding a bit of the theory behind composite code metrics, I’ll leave off until next time, when I’ll dig a bit into how we can start reasoning about our own composite metric for “time to understand a method.”  Stay tuned because that will get interesting — I’ll go through a little bit more of NDepend and even get into Newtonian Mechanics a little.  But not too far.  I promise.

< Let’s Build a Metric 2: Getting the Units Right

Let’s Build a Metric 4: Science and Experiments >

Let’s Build a Metric 2: Getting the Units Right

Last time in this series, there was definitely some housekeeping to accomplish.  I laid the groundwork for the series by talking a bit of theory — what are code metrics and what is static analysis?  I also knocked out some more practical logistics such as taking you through how to get the code base I’m using as well as how to create and attach an NDepend project to it.  The culmination was the creation of our very own, tiny, and relatively useless code metric (useless since NDepend already provides the metric we ‘created’).

So, seems like a good next thing to do is make the metric useful, but there may be an interim step in there of at least making it original.  Let’s do that before we get to “useful.”  But even before that, I’m going to do a bit of housekeeping and tell you about the NDepend feature of managing the queries and rules in the Queries and Rules Explorer.

Group Housekeeping

Last time around, I created the “My Rules” group under “Samples of Custom rules.”  This was nice for illustrative purposes, but it’s not where I actually want it.  I want to bring it up on the same level as that, right after “Defining JustMyCode”.  To do that, you can simply drag it.  Dragging it will result in a black bar indicating where it will wind up:

 

Metrics2 (1)

 

 

Once I’ve finished, it’ll be parked where I want it, as shown below.  In the future, you can use this to move your groups around as you please.  It’s pretty intuitive.

 

Metrics2 (2)

Now, have you noticed that this is called “My Rules” and that’s a little awkward, since we’re actually defining a query.  We’re ultimately going to be trying to figure out how long it takes to comprehend a method, and that’s a query.  A rule would be “it should take less than 30 seconds to comprehend a method.”  We may play with making rules around this metric later, but for now, let’s give the group a more appropriate name.  NDepend is integrated with the expected keyboard shortcuts, so you can fire away with the “rename” shortcut, which is F2.  Do that while “My Rules” is highlighted, and you’ll get the standard rename behavior.

 

Metrics2 (3)

 

Let’s call it “My Metrics.”

 

Metrics2 (4)

Getting Units Right for Our Metric

Now, with various bits of housekeeping out of the way, let’s change the metric “Lines of Code” to be something else — something original.  Open it in the Queries and Rules Editor, and change its name by changing the XML doc comment above the query within the “Name” tag.  Let’s call it “Seconds to Comprehend a Method.”  It’s important in these queries to specify the units in the name of the metric so that it’s clear upon inspection what, exactly, is being measured.  The concept of units does not exist, per se, in NDepend so queries out of the box have titles like “# Source Files” and “# IL Instructions” to indicate that the unit is a count.

Metrics2 (5)

 

Now the title is looking good, but there’s a problem in the actual display of the metric on the side.  Take a look:

 

Metrics2 (6)

 

It seems like a metric called “seconds to comprehend a method” probably shouldn’t internally report in terms of “# of lines of code (LOC)”.  We probably want this to be “seconds.”  The way you can accomplish this is by taking advantage of the fact that, under the covers, what we’re doing in this file is taking advantage of the C# construct of “anonymous type.”

In C#, an anonymous type is one that is defined even as it is instantiated, having its property names, types, and ordering declared in-situ.  In an actual C# method, we might do something like:

That’s not how things work in NDepend, however.  For these queries and rules, we aren’t supplying declarations, per se, but rather returning an expression that the engine knows how to turn into graphical information at the bottom.  In our example, currently, we’re returning an anonymous type consisting of the method itself as the first property, followed by its name and then its number of lines of code.  This is translated in graphical format to what you see underneath the query editor automatically, with the values displayed as data and the property names as the headers.  So, to change the header, we need to change the property name.  Change this:

to this:

and observe the new display results.

Metrics2 (7)

Fluent versus Query Linq

Finally, there’s one more thing that I’m going to do here before we wrap up this post.  My strong preference over the years has been to use the fluent Linq syntax, rather than the query syntax, and based on what I see of the code written by others, I’m not alone.  So, let’s do a conversion here before we get too much further.

This code can be expressed, equivalently, as

Wrapping Up

So far, we’re taking it a little slow on making progress toward our killer, composite metric, but that’s somewhat by design.  These posts split purpose between building a cool metric, and walking you through NDepend in some detail.  In terms of the former goal, we went from having a metric that was just a repeat of one already supplied out of the box to one that is our own — at least at a casual inspection.  Next time around, we’ll actually start doing something that doesn’t just assume it takes one second to comprehend each line of a method.

From a “getting to know NDepend” point of view, we took a walk through creating, renaming, and moving query/rule groups around, and we started to get into CQLinq a little bit in terms of practical application and theory.  That’s a topic that will be visited more throughout the “Let’s Build a Metric” series, and one that we’ll pick right up with in the next post.

 

< Let’s Build a Metric 1: What’s in a Metric?

 

Let’s Build a Metric 3: Compositeness >

Let’s Build a Metric 1: What’s in a Metric?

A while back, I made a post on my blog announcing the commencement of a series on building a better, composite code metric.  Well, it’s time to get started!

But before I dive in headfirst, I think it’s important to set the scene with some logistics and some supporting theory.  Logistically, let’s get specific about the techs and code that I’m going to be using in this series.  To follow along, get yourself a copy of NDepend v6, which you can download here.  You can try to follow along if you have an older version of the tool, but caveat emptor, as I’ll be using the latest bits.  Secondly, I’m going to use a codebase of mine as a guinea pig for this development.  This codebase is Chess TDD on github and it’s what I use for my Chess TDD series on my blog and Youtube.  This gives us a controlled codebase, but one that is both active and non-trivial.

What are Static Analysis and Code Metrics, Anyway?

Now, onto the supporting theory.  Before we can build meaningful code metrics, it’s important to understand what static analysis is and what code metrics are.  Static analysis comes in many shapes and sizes.  When you simply inspect your code and reason about what it will do, you are performing static analysis.  When you submit your code to a peer to have her review, she does the same thing.  

Like you and your peer, compilers perform static analysis on your code, though, obviously, they do so in an automated fashion.  They check the code for syntax errors or linking errors that would guarantee failures, and they will also provide warnings about potential problems such as unreachable code or assignment instead of evaluation.  Products also exist that will check your source code for certain characteristics and stylistic guideline conformance rather than worrying about what happens at runtime.  In managed languages, products exist that will analyze your compiled IL or byte code and check for certain characteristics.   The common thread here is that all of these examples of static analysis involve analyzing your code without actually executing it.

The byproduct of this sort of analysis is generally some code metrics.  MSDN defines code metrics as, “a set of software measures that provide developers better insight into the code they are developing.”  I would add to that definition that code metrics are objective, observable properties of code.  The simplest example on that page is “lines of code” which is just, literally, how many lines of code there are in a given method or class.  Automated analysis tools are ideally suited for providing metrics quickly to developers.  NDepend provides a lot of them, as you can see here.

It’s important to make one last distinction before we move on: simple versus composite metrics.  An example of a simple metric is the aforementioned lines of code.  Look at a method, count the lines of code, and you’ve got the metric’s value.  A composite metric, on the other hand, is a higher level metric that you obtain by performing some kind of mathematical transform on one or more simple metrics.  As a straightforward example, let’s say that instead of just counting lines of code, you defined a metric that was “lines of code per method parameter.”  This would be a metric about methods in your code base that was computed by taking the number of lines of code and dividing them by the number of parameters to the method.

Is this metric valuable?  I honestly don’t know — I just made it up.  It’s interesting (though you’d have to do something about the 0 parameter case), but if I told you that it was important, the onus would be on me to prove it.  I mention this because it’s important to understand that composite metrics like Microsoft’s “maintainability index” are, at their core, just mathematical transforms on observable properties that the creator of the metric asserts you should care about.  There is often study and experimentation behind them, but they’re not unassailable measures of quality.

Let’s Look at NDepend Metrics

With the theory and back-story out of the way, let’s roll up our sleeves and get down to business.  You’re going to need NDepend installed now, so if you haven’t done that yet, check out the getting started guide.  Installing NDepend is beyond the scope of this series.

If you’re going to follow along with me, clone the Chess TDD codebase and open that up in Visual Studio.  The first thing we’re going to need to do is attach an NDepend project.  With the code base open, that will be your first option in the NDepend window.  I attached a project, named it “Chess Analysis” and saved the NDepend project file in the root folder of the project, alongside the .sln file.  This allows you to optionally source control it pretty easily and to keep track of it at a high level.

attach

Once you’ve created an attached the project, run an analysis.  You can do this by going to the NDepend menu, then selecting Analyze->Run Analysis.

analyze

Now, we’re going to take a look in the queries and rules explorer.  NDepend has a lot of cool features and out of the box functionality around metrics, but let’s dive into something specific right now, for this post.  We’ll get to a lot of the other stuff later in this series.  Navigate in the NDepend menu to Rule->View Explorer Panel.  This will open the queries and rules explorer.  Click the “Create Group” button and create a rule group called “My Rules.”

Create Rule

Now, right click on “My Rules” and select “Create Child Query,” which will bring up the queries and rules editor window.  There’s a bit of comment XML at the top, which is what will control the name of the rule as it appears in the explorer window.  Let’s change that to “Lines of Code.”  And, for the actual substance of the query, type:

It should look like this:

Create Rule

Congratulations! You’ve just created your first code metric. Nevermind the fact that lines of code is a metric almost as old as code itself and the fact that you didn’t actually create it. Kidding aside, there is a victory to be celebrated here. You have now successfully created a code metric and started capturing it.

Next time, we’ll start building an actual, new metric that NDepend isn’t already providing you out of the box. Stay tuned!

 

Let’s Build a Metric 2: Getting the Units Right >

A Software Architect’s Best Friend

To this day, I have a persistent nightmare about my time in college.  It’s always pretty similar.  I wake up and I have a final exam later in the day, but I’m completely unprepared.  And I don’t mean that I’m unprepared in the sense that I didn’t re-read chapter 4 enough times.  I mean that I realize I haven’t attended a single lecture, done a single homework assignment, or really even fully understood what, exactly, the course covers.  For all intents and purposes, I’m walking in to take the final exam for a class I haven’t taken.  The dream creates a feeling that I am deeply and fundamentally unprepared for life.

I’ve never encountered anything since college that has stuck with me quite as profoundly; I don’t dream of being unprepared for board meetings or talks or anything like that.  Perhaps this is because my brain was still developing when I was 20 years old, or something.  I’m not a psychologist, so I don’t know.  But what I do know is that the closest I came to having this feeling was in the role of software architect, responsible for a code base with many contributors.

If you’re an architect, I’m sure you know the feeling.  You’ve noticed junior developers introducing global variables on a few occasions and explained to them the perils of this practice, but do you really know they’re not still doing it?  Sure, you check from time to time, but there’s only one of you and it’s not like you can single-handedly monitor every commit to the code base.  You do like to go on vacation at least every now and then, right?  Or maybe you’ve shown your team a design pattern that will prevent redundancy and standardize what had been a hodgepodge approach.  You’ve monitored the situation for a few commits and noticed that they’re not getting it quite right, but you can live with what they’re doing… as long as it doesn’t get any further off the rails.

You get the point.  After all, you’re living it.  You don’t need me to tell you that it’s stressful being responsible for the health of a code base that’s changing faster than you can track in any level of detail.  If you’re anything like me, you love the role, but sometimes you long for the days when you were making your presence felt by hacking things and cranking out code.  Well, what if I told you there were a way to get back there while hanging onto your architect card… at least, to a degree?

You and I both know it — you’re not going to be spending 8+ hours a day working on feature implementations, but that doesn’t mean that you’re forever consigned to UML and meetings and that your hacking days are completely over.  And I’m not just talking about side projects at night.  It’s entirely appropriate for you to be writing prototyping code and it’s also entirely appropriate for you to write little plugins and scripts around your build that examine your team’s code base.  In fact, I might argue that this latter pursuit should be part of your job.

What do I mean, exactly, by this?  What does it mean to automate “examining your team’s code base?”  You might be familiar with this in its simplest forms, such as a build that fails if test coverage is too low or if there are compiler warnings.  But this concept is extremely extensible.  You don’t need to settle for rudimentary information about your team’s code.

NDepend is a tool that provides you with a lot of information out of the box as well as hooks with which to integrate that information into your team’s build.  You can see architectural concerns at a high level, such as how much you depend on external libraries and how internally coupled your modules are.  You can track more granular concerns such as average method complexity or class cohesion.  And you can automatically generate reports about these things, and more, with each build.  All of that comes built in.

But where things get really fun and really interesting is when you go beyond what comes out of the box and start to customize for your own, specific situation.  NDepend comes with an incredibly powerful feature called CQLinq that lets you ask very custom, specific questions about your code.  You can write a query to see how many new global variables your team is introducing.  You can see if your code base is getting worse, in terms of coupling.  And, you can even spend an afternoon or two putting together a complex CQLinq query to see if your team is implementing the pattern that you prototyped for them.

And not only can you see it — you can see it in style.  You can generate a custom report with clear, obvious visuals.  This sort of visualization isn’t just decoration.  It has the power to impact your team’s behavior in a meaningful way.  They can see when their checkins are making more things green and happy and when their checkins are making things red and angry.  They’ll modify their code accordingly and basically anonymously, since this feedback is automated.  They’ll like it because automated feedback won’t feel judgmental to them, and you’ll like it because you’ll know that they’re being funneled toward good architectural decisions even when you aren’t there.  Talk about peace of mind.

You’ll spend a few days getting to know NDepend, a few days tweaking the reports out of the box, and a few days hacking the CQLinq queries to guard your code base according to your standards.  And, from there on in, you’ll enjoy peace of mind and be freed to focus on other things that command your attention.  As an architect there are a thousand demands on your time.  Do yourself a favor and get rid of the ones that you can easily automate with the right tooling.

Why Should Managers Care About Static Analysis?

I’d like to talk a bit today about how, if you’re a dev manager for a team or teams that are responsible for .NET code bases, NDepend will help you lower your blood pressure and sleep better at night.  But first, bear with me as a I introduce and explain myself a bit.  It’ll be relevant.  I promise.

There’s been a relatively unique fluidity to my career, particularly in recent years.  The first 10 years or so of my professional career featured somewhat of a standard path from developer to management, with milestone stops along the way earning me designations like “senior” developer, team lead, and architect.  At the end of my salaried career, I had earned myself a CIO role, presiding over all development and IT operations for a company.  And, while I enjoyed the leadership responsibilities that came along with that sort of role, I ultimately decided to go off on my own into consulting, where I’d have more variety and a more fluid set of responsibilities.  These days, I do a combination of development coaching, management consulting, and content creation to earn my living.

The reason I mention all of this is that I’ve had success as a developer, architect, manager, and consultant to all of the above, and that multi-disciplined success has given me unique perspective on the interaction among those roles.  It’s shown me that, above all, what you need to be successful is the ability to trust your dev team.  But trust doesn’t come easily.  You didn’t get to where you are by blindly trusting anyone who tell you a pleasant story.

Here’s your essential conundrum as a manager.  You’re managing a team of intelligent humans that are doing things you don’t understand.  You can protest and claim to understand what they’re doing, but you don’t.  I learned this in my travels as a manager, even managing a team of .NET folks who turned to me to answer their toughest technical questions.  I may have had years and years of professional development on them, but I wasn’t there in the weeds with them, dealing with the challenges that they were, day in and day out.  I had to trust them because keeping my nose in their affairs didn’t scale.  So no matter how well you might understand the surrounding technologies and principles, you don’t understand what they’re doing at any given moment.

There’s a tendency toward entropy that kicks in when you’re managing people whose labor you don’t understand.  A lot of managers in this situation have to fight a panicky impulse to regain control via micromanagement.  I can’t really tell if they’re making good decisions in their coding, but I can make sure they’re getting in no later than 9, leaving no earlier than 5, writing at least 100 lines of code per day, and keeping unit test coverage about 90%.  You may laugh, but it’s a natural impulse, particularly in the face of a slipped deadline or low quality release.  The C-suite wants answers, and you’re caught in the middle, scrambling simultaneously to provide them and to figure out how to prevent this in the future.  You didn’t get ahead in your career through passivity, so the impulse is to seize control, even if perhaps you realize it’s a misguided impulse.

NDepend provides help here.  It allows you to keep an eye on metrics that aren’t obtuse if you structure things right.  I cannot overemphasize this caveat.  Renowned systems thinker W. Edwards Deming once explained that, “people with targets and jobs dependent upon meeting them will probably meet the targets – even if they have to destroy the enterprise to do it.”  Translated into our terms for this post, what this means is that if you measure your team’s productivity by them producing 100 lines of code per day, they will produce 100 lines of code per day, even if it means creating unstoppable death stars of terrible code.  So disabuse yourself of the notion that you can use this tool to evaluate your developers’ performance, and understand instead that you can use it to identify potential trouble spots in the code.

Pair with a developer or your team’s architect, and use NDepend’s phenomenal reporting capabilities to create a big, visible report on the state of your team’s code.  Here are some ideas for things that might interest you:

  • Which sections of the code are most heavily depended on, so that I can have a heads up when they are changed?
  • How coupled is a module to the rest of the code base?  So, for instance, if I wanted to swap in a new database solution, how hard would that be?
  • Are the most troublesome areas of the code base getting worse, staying the same, or improving?
  • Is the team’s development practice generally in line with commonly accepted good ideas?
  • What does the architecture of the code actually look like (as opposed to some design document that was written and may be out of date)?
  • Are there currently any code violations that the team has identified as critical mistakes?

When I was managing teams, I certainly would have been interested in the answers to these questions for strategic planning purposes.  How dependent you are on a database or whether a feature implementation has touched a dicey section of the code is valuable information for making important decisions (maybe it’s not worth considering a database switch and maybe we should add in more testing than usual for the upcoming release).

Not only can NDepend give you this information, but it can be integrated with your build to furnish it in a very clear, easy, and visible way.  Picture it integrated with your team’s build and delivered to your inbox in digest format on a daily basis.  This is possible to do with your build tool — you could work with the developers on your team to design a build customization where you can see if an area of the code is getting worse or how much coupling there is among the modules in the code.

Imagine it.  Instead of wondering whether your developers are actually working and whether they’re making good decisions, you can partner with them to keep you in the loop on important characteristics of the code, and also to keep you out of their hair for the details it’s better for them to worry about.  You get your information and early detection scheme, and they benefit from having an informed manager that asks intelligent questions only when it makes sense to do so.  And for you, that all adds up to better sleep and lower blood pressure.

Toward Bug Free Software: Lines of Defense

Hurrah!! Last week we released NDepend v6 RTM. Once again we relied on a 2 months private beta-testing period and a one month Release Candidate period to do our best to release a polished and stable product.

I’d like to talk about our lines of defense to fix as many bugs as possible. Except a few pieces of software in the world that can afford mathematical demonstrations to prove they are bug-free (like plane and some medical ones), all other pieces of software, including NDepend, rely on an empirical approach to chasing bugs and fixing them. An empirical approach is an evidence based approach that relies on direct observations and experimentation in the acquisition of new knowledge. An empirical approach will never lead to a bug-free product, but it can help a lot in keeping the number of bugs low, and make it so that bugs happen in rare enough situations that won’t have any impact on most user’s experience.

I could write many blog posts about each line of defense, after more than a decade applying them there is so much to say, but I want this post to be synthetic.

Production Crash Logs

Crashes are due to unhandled exceptions. Unhandled exceptions are due to situations at runtime that were unexpected, this typically includes:

  • null reference access,
  • division by zero,
  • disposed object accessed,
  • invalid cast,
  • wrong method call parameters,

A bug doesn’t necessarily lead to a crash, but a crash necessarily mean that there is a bug. Certainly the most important line of defense against bugs is to log all production crashes and relentlessly fix them all. The .NET Framework offers several unhandled exception access points, including:

In some environments like Visual Studio hosting, these access points don’t work and you’ll have to write code to catch all exceptions in all possible handlers of your program.

Of course some users are disconnected from internet, or behind a proxy, and you won’t get those production crashes. Our statistics show that this concerns only 20% of users at most. So being aware of 80% of all production crashes is certainly enough to have a good measure of what’s going wrong in a production. And because Windows and .NET are highly sophisticated technologies that are constantly evolving, you can expect plenty of issues that never occurred on your team’s machines! For example, the NDepend v6 Release Candidate Period shows us that users running NDepend v6 RC on a fresh Windows 8.1 or Windows 10 install, experienced crashes because of a P/Invoked win32 method that our code calls. Oddly enough this P/Invoked method behaves differently when .NET v3.5 is not installed on the machine!

The key to successful production crash logs, is to get as many useful data as possible per log. For example here is a production crash below we had a few week ago. When the same issue lead to several crash logs, we can start doing data mining on it. Do they all occur with the same stack trace? with the same high DPI resolution? on the same Windows platform version ? on the same machine only? Notice also the stack frames improved with IL offset retrieved with the StackFrame.GetILOffSet() method. Many times in the past, this alone lead us to the root cause.

ProductionCrash

 

You’ll notice that we only log crashes, we don’t have other forms of runtime logs, like logging every major event that happen (button clicked, panel opened, analysis started…). Our experience with logging events is that ultimately we logged too much or not enough of them. In both cases, the information that could help fixi a particular issue is then lost or hard to find. We found out that having verbose crash logs was enough. Sometime we can ask a user a question, like which action did you do just before the crash, but in the vast majority of real-world cases, this information is implicitly contained in the stack trace. For the same reason we don’t use remote debugging nor Windows dump files. In our context, custom and verbose production crash logs are enough.

Code Covered by Automatic Tests and Code Contracts

Not only are production crash logs an important line of defense, but they also demand just a few days of dedicated work to set up.

Having automatic tests is the second line of defense. Contrary to production crash log,s not only does it require a lot of work, but it even changes (forever) the way you write code. After a decade of writing automatic tests, a lot of conclusions can be made. In my attempt to remain synthetic in this post, let’s try to summarize the most relevant ones in a few points:

  • The number of tests is absolutely meaningless.  When it comes to unit/automatic tests, the king measure is the percentage of code covered by tests.
  • A high percentage of code covered by tests is not enough, everything that can be checked must be checked. In almost all literature related to unit testing, you’ll read that checks are assertions in unit test code. Few actually realize that assertions in the code itself are at least as important as assertions in unit-test code. There is a scientific terminology for assertions in code: Code Contracts. The important thing about code contracts is that they must fail both at manual-test time (see later) and at automatic-test time.
  • In NDepend, we use more than 20K simple Debug.Assert() in code. These are our contracts. Debug.Assert() are removed in production code. This is ok for us since we want maximum performance and having some sophisticated assertions at runtime can significantly slow down an application. Hence we decided to sacrifice an important line of defense in the name of performance. By using MS Code Contract that could let have assertions fail in production, we could increase the number and the accuracy of production crash logs. This is a choice you must make depending of your application. Let’s precise that NDepend.API actually supports MS Code Contract for its great ability to provide active documentation to users.
  • How much coverage is enough? My answer is 100%.
    • Typically, developers don’t want to lose time writing tests to cover say, properties getter and setter. My point is twofold: typically you can write higher level tests that will cover these + if these getters and setters contain assertions, this is even better.
    • Typically, developers claim that 10% of a class is difficult to test, it takes as much effort to test this 10% as it does to test the remaining 90%. Once again, they don’t want to lose time! My point is that this 10% of code is by definition not easily testable, as a consequence this code is both complex and not-well designed, and as a consequence it is certainly highly-bug-prone. So basically, the highest bug-prone portion of code ends up being not covered by automatic tests!! This is non-sense but this is the reality in most dev shops.
    • Typically, developers say that not everything is coverable by tests and I agree. Code calling blocking methods like MessageBox.Show() is just not coverable, this is why such calls must be mocked. Some other UI code can be especially tricky to test. The approach we use for this is that we designed our UIs in a way that the underlying code can be triggered by unit tests (some would say automated by tests) and then, we mostly rely on assertions in UI code itself to catch any potential regression. Of course when possible, assertions in tests are welcome and of course such UI code is highly decoupled from non-UI logic that has its own set of tests. Doing so has been proving work for our dev shop.
    • I’ll add that when a class or a group of classes are 100% covered by tests, experience shows that the innocent fact that suddenly a coverage hole appears, often means that there is a new problem, either in the code, in test code, or  in both. More often than not, we discovered regression bugs this way that were not caught by assertions. This is why we use tooling (aka NDepend) to check that all code that used to be 100% covered must remain 100% covered.
    • Last but not least, when a bug is fixed, if the fixed code portion is already covered by tests, it is easy to write assertions specific to the fix to avoid any regression in the future. And when most classes are 100% covered, more often than not it is a matter of minutes, or even seconds, to write such assertions.
  • If your application is successful enough, the code base will grow over the years. Finally, the biggest benefit you can expect from writing coverage-oriented automatic tests, is that the number of regression issues will remain under control because it won’t be proportional to the growing size of the code base. Keep in mind that only code covered by tests whose result is asserted somehow is protected by this line of defense.

Let’s illustrate this section with the NDepend 82.6% code coverage visualized with the NDepend metric view. We abide by our rules.

Coverage

Static Analysis and Code Review

I see static analysis as unit tests, but instead of exercising the code dynamically, static analysis exercises properties that can be inferred from the code. In the previous section for example, I wrote that if a class was 100% covered by tests, it must remain 100% covered by tests.  And I even underlined that if a hole suddenly pops up in this perfect coverage, more often than not, understanding the root cause of the hole will lead to a bug fix. This illustrates how static analysis is actually a line of defense against bugs.

In the previous analogy between static analysis and unit-tests, a test is actually a code rule. NDepend makes it easy to write custom code rules, it is just a matter of writing a C# LINQ query based on a fluent API, for example:

Code rules involving code coverage and diff after setting a baseline are especially suited to hunt regression bugs. But static analysis can handle many other properties of the code and it is not only related to bugs but also to code maintainability.

  • Code metrics: for example, methods with too many loops, if, else, switch, case… end up being non-understandable, hence non-maintainable. Counting these through the code metric Cyclomatic Complexity is a great way to assess when a method becomes too complex.
  • Dependencies: if the classes of your program are entangled, effects of any changes in the code becomes unpredictable. Static analysis can help to assess when classes and components are entangled.
  • Immutability: types that are used concurrently by several threads should be immutable, else you’ll have to protect state read/write access with complex lock strategies that will end up being un-maintainable. Static analysis can make sure that some classes remain immutable.
  • Dead code: dead code is code that can be removed safely, because it is not invoked anymore at runtime. Not only can it be removed, but it must be removed, because this extra code add unnecessary complexity to the program. Static analysis can find most of dead code in your program (yet not all).
  • API breaking change: if you present an API to your client, it is very easy to remove a public member without noticing and thus, breaking your clients code. Static analysis can compare two states of a program and can warn about this pitfall.
  • API usage: some APIs are intended to be used carefully. For example, a class that hold disposable fields must be itself disposable in general, except when the disposable field lifetime is not aligned with the class instances lifetime, which then sounds like a design problem.

The list of code properties that can be exercised by static analysis is endless. And the quoted ones refer to NDepend’s capabilities, some other tools like Resharper or CodeRush offer some other sorts of static analysis to warn about micro potential issues, like if a foreach variable is accessed from a closure for example, this can lead to major problems.

Static analysis is not only about directly finding bugs, but also about finding bug-prone situations that can decrease code understanding and maintainability.

Concerning code review, I don’t have much to say. This is static analysis except that the logic is statically checked by human instead of being checked by automatic rules. Thus it is highly imperfect and time consuming, yet we still practice it because experience shows that it helps finding issues that can hardly be found otherwise. The key to code review is to do it on bug-prone code, which include refactored code and new code that haven’t reached production yet.

Manual Tests and Beta Testing

No matter how good a team is at the previously explained lines of defense, if it fails at manual tests and beta testing, the end product will be buggy and ultimately unusable.

Because not all bugs lead to obvious crashes, tests done by humans are essential. For example, only a potential user can notice an incoherent numerical result in a UI.

Manual testing is like code review, highly imperfect and time consuming, and a team cannot capitalize on it. Yet, experience shows that it helps finding issue that can hardly be found otherwise.

We mentioned previously code contracts, they work hand in hand with manual tests. When, during a manual test session, I have the chance to break an assertion, this actually makes me happy 🙂 because I know that this is a great opportunity to fix a bug before it reaches the next release line.

Manual testing actually includes user feedback. Users are paying for a product and one main goal is to offer them a bug free product. Nevertheless, de-facto users are also testers and listening carefully to a user’s bug report and relentlessly struggling to fix them is an essential line of defense. Of course this does not only apply to bugs, but also to feature improvements, new feature suggestions, documentation gap, and much more, but these are another topics.

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 🙂