At Highgroove, we are pragmatists. While we value writing clean, maintainable, and extensible code, we also value shipping features for our clients in tight iterations.
Sometimes it feels like achieving both of these goals is simply not possible … and yet focusing on either one at the expense of the other is not satisfactory either.
To achieve a balance, we aim to periodically refactor our code: improve or restructure it without affecting its external function.
More after the break.
Red, green, refactor: When developing new features, we usually use a test-driven development process. We write a test that describes some yet undeveloped behavior, watch it fail, write a small amount of code to make it pass, and finally improve the code while keeping the full test suite passing. Not only does this help us maintain correctly functioning code, it tends to drive good design from the start.
Responding to change: Highgroove does not do ivory tower development. We develop features quickly, deliver them, and get feedback. That feedback can drive the next set of features. Refactoring is often required to add those new features without bogging down the codebase. Again, we depend on automated tests to make sure existing functionality remains correct as we restructure the code to facilitate change.
Too much refactoring?: Refactoring can also be something of a deep rabbit hole. It can be easy to start adding a small feature or fixing a minor bug, yet end up restructuring a large amount of tangentially related code … and spending a lot of time doing it! Some refactoring allows us to keep the pace of new feature development fast, but perfectionism is taking it too far. Where the balance lies is often hard to pinpoint, but it’s something we remember to seek during development.
How does refactoring play into your software development process? When do you do it? How do you know when to stop?