DaedTech

Stories about Software

By

Adding Static Analysis to Your Team’s DNA

Editorial note: I originally wrote this post for the NDepend blog.  You can check out the original here, at their site.  While you’re there, download NDepend and play with adding it to your team’s build.

Stop me if this sounds familiar.  (Well, not literally.  I realize that asynchronous publication makes it hard for you to actually stop me as I type.  Indulge me the figure of speech.)  You work on a codebase for a long time, all the while having the foreboding sense of growing messiness.  One day, perhaps when you have a bit of extra time, you download a static analyzer to tell you “how bad.”

Then you have an experience like a holiday-time binge eater getting on a scale on January 1st.  As the tool crunches its results, you wince in anticipation.  Next, you get the results, get depressed, and then get busy correcting them.  Unlike shedding those holiday pounds, you can often fix the most egregious errors in your codebase in a matter of days.  So you make those fixes, pat yourself on the back, and forget all about the static analyzer, perhaps letting your trial expire or leaving it to sit on the shelf.

If you’re wondering how I got in your head, consider that I see this pattern in client shops frequently.  They regard static analysis as a one time cleanup effort, to be implemented as a small project every now and then.  Then, they resolve to carry the learning forward to avoid making similar mistakes.  But, in a vacuum, they rarely do.

A Better Course of Action: Incorporate the Tool

For the remainder of the post, I’ll refer to NDepend, both because of my familiarity with it and because it seems entirely appropriate for the NDepend blog.  But the principles here could apply to many static analyzers or other types of tools.

Simply put, you should not forget the tool.  On the contrary, you should expand your relationship with it.  You should add it to your build and to your process as a developer.

This approach requires very little effort.  At a bare minimum, you can modify your build to generate a report and run the tool prior to each commit.  Doing this tightly integrates code quality and trends into your development process.  They become constant fixtures, rather than periodic, one-off projects.

But that covers the “how” and not so much the “why.”  Let’s address that in the remainder of the post.  What benefits do you realize from using NDepend on a continuous basis?

Read More

By

Learning to Love The Linq Any() Method

There is a Linq extension method that I managed to miss for a long time: Any(). It’s fairly natural to miss this, I believe, since the paradigm of collections tends to be fully ingrained in our way of doing things. That is, if I want to see if any members of a collection match a certain criteria, I do something like this:

bool doesDirectExist = false;
foreach (var myFeature in features)
    doesDirectExist |= myFeature.ID == "Direct";

I cycle through my collection of features looking for “Direct” and, if I find one, the boolean flag is flipped to true. Otherwise, it remains false. If I wanted to get a little more efficient, I could break if the flag got flipped or do this in a two-condition while loop.

This hearkens back to the days of storing values in simple arrays in older languages than C# and before the existence of IEnumerable, foreach() and other such constructs. For those of us who learned this way, iterate and check is quite natural.

But then, Linq came along and gave us the handy-dandy Where(Func<T, bool>) extension method:

bool doesDirectExist = features.Where(f => f.ID == "Direct").Count() > 0;

This accomplishes the same thing, but as a one-liner. That in and of itself is nice, but it gets doubly nice when you consider that the short-circuit optimization is built in to the implementation of Where(). Where() returns an enumeration, which is more or less a collection (yes, yes, I understand that it’s not really, but that’s how we tend to regard it), so the natural seeming thing to do is query it for a count. I remained content with this for a long time, until I discovered Any().

I can achieve the same thing with:

bool doesDirectExist = features.Where(f => f.ID == "Direct").Any();

This is a lot more semantically clear. I’m not really interested in an integer comparison — I want to know whether there are any features matching my criteria. It may not seem important, but cutting down on noise in the code is very important for promoting readability since, in the excellent words of Grady Booch, “clean code reads like well-written prose.” In other words, this code says “do any features exist where the id is equal to ‘direct’?” as opposed to “is the count of features with id equal to ‘direct’ greater than zero?” The former reads a lot more conversationally than the latter.

But, we have one more improvement to make here:

bool doesDirectExist = features.Any(f => f.ID == "Direct");

In terms of prose-like, conversational reading, this is pretty much still “do any features exist where the id is equal to ‘direct’?” The “where” is implied here, I would say. But, now the code is more succinct, and there is one fewer method call. Brevity is generally good.

I’ve been using this for a while now, but I still encounter old code of mine where I wasn’t aware of this little gem and I encounter code written by others who aren’t aware of it. So, if you’re one of those people, be aware of it now and use in good health!

By the way, if you liked this post and you're new here, check out this page as a good place to start for more content that you might enjoy.