Larry Wall wrote in Programming Perl "We will encourage you to develop the three great virtues of a programmer: laziness, impatience, and hubris."
Laziness is defined as the quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful, and document what you wrote so you don't have to answer so many questions about it.
You don't have to work with a team for long to hear developers moan about the terrible legacy code they have to live with every day. Programmers clearly don't like to wade through the mire of legacy code to get their work done. Yet poorly factored code seems to accrete at an amazing rate around us, even on green field projects where we have the chance to do things right from the outset. Perhaps the virtue of laziness is also our achilles heel?
It seems strange that developers dislike poorly factored code so much and yet keep contributing to the problem. While it is true that business pressure can drive programmers to defer clean-up tasks that can be done later, we often don't refactor as mercilessly as we could. Is our tendency to laziness also contributing factor? Or perhaps we are merely waiting until we get a clearer sense of the shape we would like our code to be?
Not so many years ago it was writing unit tests that programmers tended to skip as an optional, do-later task. Over the last decade XP has helped shift that mindset. Now Test-Driven Development and suites of automated unit tests are considered good practice even by teams not following Agile development. Developers like the way that TDD helps them work in safe baby steps, solving one small problem at a time and getting a satisfying green bar as a signal of progress.
However in XP's Red-Green-Refactor cycle, Refactoring becomes that semi-optional step at the end that's easy to skimp on. We no longer defer writing tests because we have the Red-Green bar of our testing framework to keep us in check but there's nothing to give us that feedback on our refactoring. We can't easily tell whether enough refactoring has been done, if any.
How much refactoring is appropriate is a judgement call for the developers working on the code. We tend to have different tolerances for smelly code and of course major clean-up can be hard work so it's easy to be tempted to do light amount of cosmetic refactoring, renaming and shuffling things into smaller functions rather than tackling the larger structural issues. Is this where code rot sets in?
To combat our natural lazy tendencies, we look for process and routines that will help us stick to good practice. Many agile teams add columns to their boards for testing and code review. If we follow Michael Feather's advice, we could also add a column for preparatory Refactoring tasks before we start work on a story.
Rather than the classic XP Red-Green-Refactor cycle where we try to "Refactor Mercilessly" on our production code, Michael's idea is that the clean-up should be done first and by a different developer than the one adding the feature to foster scrutiny and communication about the design. This approach would help teams visualise refactoring work and make it a normal part of our planned work rather than an optional extra if we have time and energy to keep our code clean.
Nice post. I expressed similar thoughts here:
http://bit-builder.blogspot.com/2013/01/tests-or-clean-code-you-pick.html
Posted by: Justin Hewlett | 18 January 2013 at 06:06 AM