Skip to Main Content

Scott James Remnant is a big-league programmer.

At the Debian Linux project, he was the chief maintainer for some of the more critical pieces of Debian (and therefore Ubuntu and Mint) infrastructure, including the library compilation tool libtool and the software package management tool dpkg (basically, the program you use to install stuff).


He then became a developer manager for Ubuntu where he personally wrote Upstart, the system service Ubuntu now uses to boot up the computer. Today, Upstart is also used by RedHat and Google Chrome OS, among others.

He then moved on to work for Google, but he remains one of the four members of the Ubuntu Technical Board.

With all that in mind, his latest blog post is sure to raise some eyebrows. It's titled, "Revision Control and Unit Tests Considered Harmful". Historically, authors have used similar "Considered Harmful" titles when proposing the complete abandonment of a technology or methodology. While the actual content of Remnant's post is a bit less dramatic, he makes the case that revision control and unit testing put the developer into a counterproductive mindset.

Code is a fleeting thing. When we programmers begin building something, we tend to treat everything we write as temporary. And that's for some good reasons: software is very complex, and small nuances in business logic can have large cascading implications on the structure of its supporting code. Programmers don't come into projects with a complete map of how the code will be written, because that's pretty much beyond human ability. Instead, we iterate. We take a quick and dirty stab at a chunk of code, and then rewrite it once we see how the surrounding code takes shape. We iterate for robustness. We iterate for cleanness. We iterate for performance. The finished product (if software can ever be considered finished) is the result of an enormous aggregation of tinkering.

And this process can be fun. Developers who enjoy programming often call it "playing". The coding decisions we make are every bit as creative as they are technical, and it's fun to just dive in and start whipping up a storm of code, constantly revising what we've written as we go along. It can easily be the most personally rewarding aspect of the entire job, and it's why software developers tend to have so many hobby projects on the side. We also tend to get a lot done when we're in this state of mind, because we're 100% engaged in our work.

But part of what makes this fun is that it feels experimental and temporary. It feels like we can just try stuff, and, if it doesn't work out, then no biggie: just modify it, or throw it out and start over. We get an idea of which pieces of the code are more polished and stable, and which are more half-baked. We don't feel like we have to justify the entirety of what we've written at any given point in time, because it's just a work in progress within a work in progress. It's just a storm.

But when we're using a revision control system, meant to keep an archive of revisions we've made to the codebase over time, it kind of feels like we are having to justify the entirety of what we've written. When we commit a change to the revision repository, we're basically publishing the code. It's out there, permanently, for someone to read. Developers tend to be proud of their work, and this can be an asset in terms of the final product quality, but it can also be a curse. If I'm putting anything that looks like a stamp of approval on something I've written, it had better not be just a storm. It's got to be polished.

Even if revision control systems are meant to be used for snapshots of half-baked code, it still feels like we're putting a spotlight on it. There's still something in the back of the mind that says we'll look foolish if any of our code is shoddy. And if this is looming in the back of our minds, we won't be 100 percent engaged in our work. We'll be working on the code in a more compartmentalized fashion, spending more time thinking about coding and less time actually coding, which turns out to be less productive and no less prone to errors in the long run.

Unit tests are even worse in this regard. When we begin writing a unit test, we are basically asserting that we know exactly how that particular piece of code is supposed to work. This is one of the most stifling things we can do in a rapidly-developing project. It instantly kills the iterative process and encourages the developer to work around the existing APIs rather than adapting them to meet the needs of the surrounding code.

Engaged developers are productive developers, and little distractions are huge distractions. The most precious resource a software developer has is his immersion in his work. Projects do have plenty of important aspects aside from the code itself, but it's always worth weighing the benefits and costs before adding something to a developer's workflow.

In his conclusion, Remnant adds a bit of context to his arguments: although revision control and unit tests can be counterproductive early in the project's lifecycle, they can also be extremely useful to other developers down the road. He seems to suggest that a project should never begin with a mindset of revision control and unit testing, but that these things should be incorporated into a project as it exits the "storm" phase and begins to achieve some stability.<>