Agile Code - Design for Refactoring, Not Maintenance
Couple things happened today (Friday, of all days):
- My old blog hosting company sent a "we are shutting down" notice. Out of curiosity I clicked through and quickly found myself reading 5-year old posts. One of them was ranting about code maintenance.
- A friend tweeted a link to a blog post by Rohan Singh: Isn't All Coding About Being Too Clever? where he's also talking about maintainable code (with a different perspective).
This got me thinking...
In majority of software engineering literature, "maintainability" of code is hailed as sacred. It's easy to relate to the sentiment: no code gets written once and then forgotten. When you ship code, you give it birth, but the actual life of that code is only just starting. You want to make sure your code spends its life well -- goes to college, marries the right person, and makes the "parents" proud when other people have to deal with it (that's the maintenance part).
Except, much like with kids, your plans for your code almost never work out as initially intended. If you are smart enough you accept them just the way they turn out to be (at least - code, if not kids) , without trying to be a control freak. And that's where this obsession with "maintenance" can become a problem.
Unfortunately, when people think of maintainable code, instead of making it the simplest it can be and stepping back (which is what Rohan advocates, too) they try to predict how the code will be used. Code quickly gets overloaded with interfaces, abstract classes and over-engineered placeholders for conceived extension points -- all according to a long list of "design patterns" (I am looking at you, old-school Java developers!). If you guessed that such code is the opposite of its simplest form, then you have guessed right. What happens next time somebody needs to deal with that code? Don't expect any Thank You cards in the mail.
Designing software for "maintenance" is dangerous. A lot of people misinterpret this sentiment as "designing for future needs". We can't know what these needs will be. A much safer approach is to create the simplest code that get the job done and assume you will refactor that code soon.
Design your code not for deceiving goal of "maintenance", but for ease of future refactoring: write simply, document well, use automated tests (unit-tests rock), modularize code and couple components loosely -- so that when you modify one thing, the entire application does not fall down on you.
When somebody else has to touch your code, the first thing they want is to rewrite your "mess" anyway. Don't fight it -- make it easy and let them only rewrite a small part of the code that they need to deal with, without having to untangle entire monster. Design for refactoring.