avatarKent Beck

Summary

The website content introduces a new programming workflow called "test & commit || revert," which emphasizes committing code only when tests pass and reverting changes if tests fail to maintain a green test suite continuously.

Abstract

The article describes an innovative approach to programming workflow known as "test & commit || revert" (TCR), developed as part of the "Limbo on the Cheap" project. This method involves immediately committing code when tests pass and reverting to the last successful test state if tests fail. Despite initial skepticism about its feasibility, the approach has proven effective, encouraging small, incremental changes and counteracting the Sunk Cost Fallacy by deleting incorrect code immediately. The method is particularly suitable for environments like Limbo, where thousands of programmers must maintain a stable codebase, and it promotes a culture of continuous green tests. The article encourages readers to experiment with TCR, emphasizing its educational value and potential to streamline development practices.

Opinions

  • The author initially disliked the idea of reverting code upon test failure but found it surprisingly effective.
  • It is acknowledged that while making mistakes is inevitable, having incorrect code instantly deleted can be beneficial in preventing wasted effort due to the Sunk Cost Fallacy.
  • The author suggests that the frustration of seeing code disappear is often offset by finding better, more incremental solutions.
  • The article posits that Test-Driven Development (TDD) is not viable in Limbo due to the impracticality of having numerous failing tests, which would hinder collaboration among thousands of programmers.
  • The author does not necessarily advocate for the superiority of TCR over other methods but rather encourages trying it out to gain insights and potentially improve one's programming workflow.

test && commit || revert

The new style versus test-driven development

As part of Limbo on the Cheap, we invented a new programming workflow. I introduced “test && commit”, where every time the tests run correctly the code is committed. Oddmund Strømme, the first programmer I’ve found as obsessed with symmetry as I am, suggested that if the tests failed the code should be reverted. I hated the idea so I had to try it.

The full command then is “test && commit || revert”. If the tests fail, then the code goes back to the state where the tests last passed.

I’m not arguing for “test && commit || revert” nor even describing its trade-offs. I’m saying it seems like it shouldn’t work at all, it does, and I hope you try it (if you’re the sort of person who just tries new programming workflows).

But, but…

I thought “test && commit || revert” wouldn’t work. How could you make progress if the tests always have to work? Don’t you make mistakes sometimes? What if you write a bunch of code and it just gets wiped out? Won’t you get frustrated?

The surprising answers are yes, you can actually write code this way. Yes, you make mistakes but actually it’s kind of nice to have incorrect code instantly deleted (counteracts Sunk Cost Fallacy). If you don’t want a bunch of code wiped out then don’t write a bunch of code between greens. Yes it can be frustrating to see code disappear but you almost always find a better, surer, more incremental way of doing the same thing.

Increments

Limbo scales technical collaboration by propagating tiny changes instantly. TDD won’t work in Limbo because each of a hundred thousand programmers can’t saddle all the other programmers with even one failed test. If thousands of tests are failing, then nobody knows what’s going on. The tests all have to pass before changes can propagate.

“Test && commit || revert” keeps all tests green. At the same time you can’t solve big problems in one small step, so what are the steps you take when using “test && commit || revert”?

Increments in TCR
  • Add test and pass. The goal here is to shorten the time between idea and some kind of test passing in some kind of way. Even writing part of the test is fine. Cheating is encouraged, as long as you don’t stop there.
  • Better passing. Once you have a test passing, replace the fake implementation with a real implementation, a little at a time if necessary.
  • Make hard changes easy. Rather than change four places in the code, introduce a helper function (a little at a time, natch) so you can change one place.

Violating any of these strategies results in the changes being instantly reverted, so you don’t have to worry about enforcing small diffs.

Try It

I don’t suggest you try “test && commit || revert” because it’s better than what you do now. I suggest you try it because:

  • It’s cheap.
  • You’re bound to learn something.

Pick a little project, even Fibonacci, and start developing. See how small you can make your changes. Some of those will still fail. See how to make those changes even smaller. Pay attention to the little bits of workflow you use frequently. See what you can apply to your “real” work.

Thanks again to Iterate for sponsoring this Code Camp, and to Oddmund Strømme, Lars Barlindhaug, and Ole Johannessen for digging in, thinking of TCR, trying it, and talking about it.

Tdd
Programming
Recommended from ReadMedium