Monday, October 1, 2012

Commit-Driven Development

Test-Driven Development, TDD, is the art of writing a test before you start implementing anything in the production code. TDD is often known as Test-First Development.

Behavior-Driven Development, BDD, is the art of describing a behavior in an executable format before you start implementing anything in the production code. Since these behavior-descriptions are often written as scenarios within a feature, BDD is also known as Scenario-Driven Development.

Commit-Driven Development is the art of writing a comment for your next commit before you start implementing. You could say it’s Comment-First Development.

So why all this emphasis on “Something”-First development? Does the order of things really matter that much? As it turns out; it really does. It helps you focus.

By writing a test first – before any of the logic is implemented – you say to yourself; this is what I’m going to do the next 5-10 minutes. I will focus solely on getting this test to past. Until then I will not do any refactoring or touch any other parts of the code base.

The same thing goes with a scenario; until this scenario pass, I will not focus on anything else. When the tests pass, I can rename classes/methods/variables, move methods in to new/other classes, extract smaller methods, and so on.

By writing the comment for the next commit first, you get the same benefit as test- and scenario-first; Focus. When you have a clean sheet with not pending, un-committed changes and you write that comment first, your telling yourself (and your subconscious) that this – and preferably only this – is what I will work on now.

If you get interrupted along the way and you lose track of what it was you actually was supposed to work on, you can just take a look on the commit comment and your right back on track.

When I leave the office I usually try to end the day with a failing test. I write the test, see it fail, and call it a day. Next morning I can just run the test suite and I know exactly where to start coding. The context switch gets really cheap. With the pending commit comment I also get the bigger picture of what I was working on; I know when I should be done and commit my changes.

Added benefit

There’s another side to writing the commit comment first; it makes it easier to write better comments.

When you write a commit comment after you’ve made all changes, it’s easy to fall into the I-did-this-then-that style of comment. Take a look at this fairly common change-log;

  • Fixed bug #123: Error when saving customer
  • Increased first name max length
  • Added field on customer
  • Added Cancel-button on customer list

Implicitly these comments say ‘I fixed bug…’, ‘I increased…’, etc. Problem is; I don’t care if you did it. I already know that from the change-log. What I want to know is; how does the behavior of the system differ from prior to this commit?

Writing the comment first – before you actually do something – makes it easier to compose comments where the focus is on the behavior of the system. You write the comments describing how the system should act when you’ll do the commit later on.

Here’s an attempt to re-write the comments above;

  • When the user tries to save a customer with an invalid email address, then an error message will be displayed (bug #123)
  • Max length of a customer first name increased from 64 to 256 characters
  • Corporate customers can be assigned a contact person
  • When loading the customer list takes too long, then clicking the Cancel-button will cancel any further loading. All customers loaded at the time of cancellation will be displayed in the list.

I don’t say that you couldn’t have written these commit comments even if you did it on the time of committing the changes. It’s just a lot easier to write them if you do it upfront. And it’s a lot easier to verify that you did what you set out to do, than it is to try to figure out what you’ve actually done when it’s time to commit.

When I write my commit comment I try to think of them as release notes. Preferably I could just extract all comments from the repository log since last deploy and paste them right into the release notes for the new deploy.

References

This blog post is highly influenced by Arialdo Martini and his excellent post “Preemptive commit comments”. If you haven’t already, please go read it now.