Sometimes code quality feels like the weather: everyone talks about it, but no one ever does anything. Of course, that’s not from a lack of good will; most folks would love to have a week or two set aside to just clean things up. Unfortunately, that’s not how the world works. The best course of action is to sneak in a little clean up here, and a little there as part of normal work. Fortunately, that’s actually the best way to go about it. At SonarSource, we call it the Clean as You Code methodology, and we’ve found that this behavioral approach to code quality is as important as the tools developers use to track it.
The idea behind Clean as You Code is to ignore the quality of old code and focus exclusively on the quality of new changes. This may sound radical, but bear with me. Why focus exclusively on today’s changes? Because dredging up legacy code for the sole purpose of addressing code quality likely requires layers of approvals and perhaps business testing that may be difficult to get. But developers have absolute control over the quality of the code they’re writing now, and they’ll take pride in setting and enforcing high standards for that code. Focusing exclusively on the quality of new code works in both legacy and greenfield projects, and for all quality axes.
Let’s take test coverage as an example. Many developers are on projects that have lower test coverage than they would like. But stealing an hour here and there to add tests for random methods is generally a frustrating and ultimately futile endeavor. Instead, start with today’s changes. Make sure they’re fully covered and don’t release until they are. That’s it, that’s all that’s required. Covering those one or two methods — or even one or two lines — may feel like a drop in the bucket, but over time it will have a real impact. In fact, that’s been exactly our experience.
Since the early days of my company’s flagship product, we’ve had an internal standard of 80% unit test coverage. And yet in those early days, we routinely released with coverage in the ’60s. There was always the intent to write unit tests, but inevitably it was left to just before release. And then it became a scramble to find the biggest uncovered files and slog through their unfamiliar code to write tests. Among the problems with this approach was the fact that the developer who wrote the code often wasn’t the one who wrote its tests, and thus could never be quite sure of testing the right behavior. And of course, no one likes cleaning up after someone else.
In the end, it was a painful and ultimately ineffective routine; coverage didn’t break 80% until July 2014 — approximately seven years after the project started, and about a year and a half after we first formulated and adopted Clean as You code. You can see the October 2012 inflection point in this graph of project coverage (yes, the first few years of data are missing; victim of an early structural refactoring):
Today, we’re at 86% coverage and rising. The formula for getting there was simple:
- Set standards on the quality of New Code. Here “new” means anything added or updated in the New Code period.
- Define the New Code period. This is the scope of concern, i.e., how far back to go for the purposes of applying your New Code standards. We set it to since the last release.
- Don’t release unless your standards are met.
Of course, the first two steps are a lot easier than the last one, especially if meeting the standards is left to just before release. Every developer has likely felt pressure to push business changes into production sooner rather than later. That’s why this strategy is most effective when it’s applied as granularly as possible. Meeting the standards before release is the bare minimum, but it should also be a non-event.
We’ve found Clean as You Code to be most effective when applied:
- At the individual level — Good developers want to write good code. When developers take personal responsibility for the code they write today, it saves time in the long run and no one has to clean up after anyone else.
- At the pull request — If each individual PR meets your standards, sub-standard code will never be merged. That means no one will ever be pressed by management to release sub-standard code, because it simply won’t exist in the main code base.
But what about the crufty old code that exists in every project? You’re probably thinking that it doesn’t just magically disappear. But actually — gradually — it does. The graph above is the graph of overall code coverage on the project. By focusing on the coverage of New Code, we organically and automatically raised coverage on all code. This is not a one-off; your results will be the same. Over the course of a few years, normal change requests will lead you throughout the code base. Make sure the code you write for those changes is clean, and the rest will take care of itself.