Static Analysis for the Build Machine?
Editorial Note: I originally wrote this post for the NDepend blog. You can check out the original here, at their site. While you’re over there, download a trial of NDepend if you want to see some quantification of the tech debt in your codebase.
I remember my earliest experiences with static analysis. Probably a decade ago, I started to read about it during grad school and to poke around with it at work. Immediately, I knew I had discovered a powerful advantage for programmers. These tools automated knowledge.
While I felt happy to share the knowledge with coworkers, their lack of interest didn’t disappoint me. After all, it felt as though I had some sort of trade secret. If those around me chose not to take advantage, I would shine by comparison. (I have since, I’d like to think, matured a bit.) Static analysis became my private competitive advantage — Sabermetrics for programmers.
So as you can imagine, running it on the build machine would not have occurred to me. And that assumes a sophisticated enough setup that doing so made sense (not really the case back then). Static analysis was my ace in the hole for writing good code — a personal choice and technique.
Fast forward a decade. I have now grown up, worked with many more teams, and played many more roles. And, of course, the technological landscape has changed. All of that combined to cause a complete reversal of my opinion. Static analysis and its advantages matter far too much not to use it on the build machine. Today, I’d like to expand on that a bit.
What Does It Mean to Have Static Analysis on the Build Machine?
First point of expansion should be to mention what this means. In the general sense, this means that the machine responsible for assembling your code into something deployable executes static analysis on said code. Back when I first discovered static analysis, this would have meant pulling the code from source on that machine, running the analysis and building it. These days, hopefully your build involves more automation than this.
To get a bit more detailed, a commit may trigger your build machine to kick off a build. That could just mean compiling your code and packing it into a deployable format. But shops commonly do other things, such as execute automated unit tests and check on code coverage. And you can add static analysis to the mix.
You can certainly get creative with how you do this. But two common (and not mutually exclusive) approaches include having the build generate a code health report and failing the build on egregious violations.
Big and Visible
You might reasonably wonder at this point, “why should I care?” I’ll talk a bit about the value added by each approach to static analysis. First up, let’s consider why building a report automatically matters.
The world of management consulting offers an interesting way to reason about team improvement. Before you can meaningfully improve something, you need to figure out how to measure it. That way, you know where you started and how far you’ve come.
Creating big and visible displays of such measures takes advantage of a form of the observer effect to move things along. Simply being watched can spur behavior change and improvement. I can recall a powerful example of this occurring with a team that had insufficient access to its product owner for making judgement calls. They simply drew a graph of the hours each day that he spent around the team and took no other action. Just seeing that presumably triggered the PO’s sense of gamification. Whatever happened, he started spending more time with the team.
By having your build generate a code quality/metric report, you can expect similar trends in your group’s codebase. If you pick a few strategic metrics or charts to display prominently, look for some movement in the right direction. Frankly, this dovetails nicely into the radiators/dashboards that many teams have already.
Once you have introduced a code quality dashboard and thus socialized the idea of static analysis, you might want to go one step further. By that, I mean you might want to add some teeth to static analysis checks and fail the build on egregious violations.
Coming in cold, this may seem excessive. But don’t forget that, by the time you implement this, the team has become familiar with the analysis reports. That means that folks discuss the metrics and their significance. It means that you’ve realized benefits from the observer effect and from those conversations. And it means that static analysis has become part of your culture,
By the time all of this takes place, the team will likely find this a natural progression. They will want the build to fail on something like a dependency cycle or a high risk code change. A failing build represents an early warning signal for a problem. You want to fail fast rather than have some mistake like this work its way in to become entrenched.
If you put this in place, you may find that it becomes as indispensable as running the unit test suite. Unit tests guard against regressions and unexpected behavior at runtime. Static analysis guards against possible runtime problems and definite code quality problems.
NDepend Build Machine Edition
A the beginning of this post, I mentioned that I initially viewed static analysis as my private, professional advantage. I remember the same thing when I discovered NDepend. I relentlessly applied its wisdom to my code and learned from its guidance. And I delighted in how I impressed at code review time, both with what I had done and with my knowledge of architectural best practices.
But then I grew and matured, and started to occupy leadership roles. I became less focused on my own personal improvement and more focused on leveling up those around me and helping organizations. As my mindset shifted, I desperately wanted to get the static analysis wisdom out of my head and tool chest and to somewhere that it could benefit the team.
When the build machine version of NDepend came along, I recall feeling legitimately excited. Now I had a guaranteed way to start conversations about code quality. And implementing automatically generated reports and build failures came almost immediately afterward.
If you have yet to apply the guidance of static analysis to your team’s codebase, you should go do that as soon as possible. And if you have yet to get that wisdom out of the individuals’ IDEs and onto your build machine, you should also do that as soon as possible.