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.

6 comments:

J. B. Rainsberger said...

Whenever I write a commit comment, I like it to answer the question, "What can the system now do that it couldn't do before?" If I can name more than one significant thing, then it's possible I've committed too much, and try to take smaller steps.

Josh Hurst said...

A problem I have (and it's one that commit-driven development may help solve) is that I have a goal in mind at the onset of my plunge, but by the end, I've made more changes than I had anticipated and there's no good way to break up the commit. Taking the time to mentally break apart the commit at the front end could only help me.

Anonymous said...

My way of looking at it is, if I go to do a blame on this line a few years from now, is there enough context to know what happened.

Kjetil Klaussen said...

@Rainsberger - Exactly! I think about the commit in the same way; What's the new features of the system. And I try to think about it in the context of the end user; If my comment would end up in the release notes, would it make sense to the customer?

@Hurst - Yeah, I have the same problem my self. Starting out implementing a new feature and then discover some smaller and bigger refactorings that I should have done on the way. But I find that writing that comment first makes it easier to focus on what I started out with. If I discover other things along the way, I make a note (on paper) and then see if I can tackle that in the next commit. For smaller refactorings I just do them along the way.

YvesHanoulle said...

I'm confused in how you do this. what tool do you have that allows you to do this?
or do you write it in your favorite editor and then after writing the copde copy paste it?

Kjetil Klaussen said...

@YvesHanoulle - We're using Subversion and Visual Studio. I'm using the AnkhSVN plugin for VS (http://ankhsvn.open.collab.net/), and in the 'pending changes' window I use enter the comment for my next commit when I start working on something. If I discover more things I should do or new things come up, I either do a commit with a "WIP:..." (Work In Progress) and then switch over, or if it's a quick fix that only span a file or two I'll commit those files separately and continue on my original work. If the new work item can wait, I just jot down the commit comment for that on paper and then enter that one in 'pending changes' as soon as I've committed what I was working on.