So... You want your code to be maintainable.
Posted by Uncle Bob on 06/24/2008
We know that maintenance is 90% of the software lifecycle, and 90% of the cost. We know that our systems need to be flexible, reusable, and maintainable. Indeed, that’s why we spend so much of our time trying to get the design and architecture just right. Because we all know that good design and architecture is the key to flexibility, reusability, and maintainability…right?
Of course. Good design and architecture is what makes software easy to change. Good design and architecture separates the things that change for one reason from the things that change for another reason (The Single Responsibility Principle). Good design allows us to add new features without changing a lot of old code (Open Closed Principle). Good design makes sure that high level policy does not depend on low level detail (Dependency Inversion Principle), etc. etc.
So how do we get good design? Well, that’s tricky. Oh it’s not too tricky to get a good design in place at first. The tricky part is to keep the design good. That’s the problem, you see. It’s not that the design starts out so bad (although sometimes…) rather it is that the design degrades over time as the system changes.
Systems change. Often they change in ways that thwart the original intent of the design. Unfortunately, changing the design to align to these changes is hard. So we wind up hacking the new features into the system and thwarting the design. And that’s how even the best designed systems rot.
So how do we keep the design from rotting? How do we make sure we can migrate the design as the system changes? Simple. Tests.
When you have a suite of tests that covers >90% of the code in the system, you are not afraid to make changes. Every time you make a little change you run those tests, and you know that you have not broken anything. This gives you the confidence to make the next change, and the next, and the next. It gives you the confidence to change the design!
Nothing makes a system more flexible than a suite of tests. Nothing. Good architecture and design are important; but the affect of a robust suite of tests is an order of magnitude greater. It’s so much greater because those tests enable you to improve the design.
This can’t be overstated. If you want your systems to be flexible, write tests. If you want your systems to be reusable, write tests. If you want your systems to be maintainable, write tests.
And write your tests using the Three Laws of TDD.
Comments
Peter Bonney about 10 hours later:
I agree that tests can provide a strong sense of security when making changes.
However, they can also have the converse effect, especially when the system is being maintained by programmers other than the original authors.
If tests need to be edited every time a simple “business as usual” change is made, there can be a strong temptation to ignore the broken tests. And soon, the test suite rots … and design calcifies.
Thus, comprehensive test coverage may not actually be optimal for future flexibility.
Sebastian Kübeck about 11 hours later:
@Uncle Bob
Great post! Really looking forward to read your new book!
@Peter
please read:
Ignoring broken tests is destroying business value. I recommend not to accept (and pay) for code chanegs from developers that break tests.
unclebob about 13 hours later:
If tests need to be edited every time a simple “business as usual” change is made, there can be a strong temptation to ignore the broken tests. And soon, the test suite rots … and design calcifies.
Ignoring broken tests is like ignoring high blood pressure, or severe chest pains, or the “maintenance needed” light on your car’s dashboard. It’s pretty damned foolish. A professional team does not tolerate broken tests.
Fragile tests are a symptom of a poor design. If your tests break a lot because of small changes, it’s time to change the design of the tests.
yachris about 13 hours later:
Peter—I’ve seen what you say as an excuse not to comment code, too: “Gee, someone someday is going to change the code and not the comments, and then it all goes to hell, and pretty soon it’s the END OF CIVILIZATION AS WE KNOW IT!!!1!”
In other words, don’t forget who’s writing - it’s Uncle Bob - he’s advocating an extreme position. The extreme he’s advocating is that people do The Right Thing™ continuously. And we all know that’s utter fantasy. At least where I work… sigh…
Joe about 17 hours later:
Actually, an extreme position is 100% coverage. 90% is the target in our environment, it is reasonable.
Brett L. Schuchert about 17 hours later:
Yachris,
The extreme he’s advocating is that people do The Right Thing™ continuously. And we all know that’s utter fantasy.
I hear this kind of logic a lot. It is OK if it is not used to do nothing about your situation. However, if you really believe this is the case, then get a new job.
I don’t know your situation or where you live but I do know there are plenty of IT jobs for the having in several of the big cities. If you do not like the environment and you really don’t think it’s possible to do things better where you work, you really have four options
Do nothing (maybe whine and complain, but not anything significant)
Try to change the environment
Change where you’re working
Be subversive and just do things well anyway.
I’ve seem many places where is it well neigh impossible to get things to change. But in those same environments projects are typically behind schedule, over budget and generally out of control. AND nobody ever seems to get in trouble for it.
It’s that second thing that makes doing work well possible. Simply do the things you think you should. Make sure the work you do is done well. Write tests for your code. You can and will be able to move faster than your colleagues … even the ones just slapping shit together and checking it in.
I’ve personally done this before I was a consultant and I’ve seen people do it. It is possible to take advantage of the chaos that exists in many organizations and simply do your job well.
Note I am not advocating over design or RDD (resume driven development). I am, however, advocating CYAD (cover your add development) where you cover your ass by writing well-written code, backed with tests so that when someones says “your code is broken”, you can either:
Discover a missing test, fix it and then not have to worry about that problem again.
Show them that in fact it is not broken and the problem is elsewhere.
Most place (not all) the bark is bigger than the bite. Deadlines, which simply cannot be missed, are regularly missed. “Getting in trouble” really means getting yelled at but not fired (and if the environment is really bad, getting fired might, in the long run, be a good thing).
Rich Sharpe 1 day later:
“The tricky part is to keep the design good”
Although I agree this is difficult a large part is Attitude! Both you and Scott Bain, in his book Emergent Design, discuss evolving the Professionalism of our industry. If a developer has the attitude of ‘every time I touch the code, I will make it a bit better’ then they are on the path to keep the design good.
Of course we do not live in a Utopia and some developers just want to hack code for the pay…and obviously ‘a bit better’ is subjective – but I think you get the point ;-)
tieTYT 3 days later:
Although I agree with the start (about design) and the finish (about tests), I don’t think tests enforce your design. They just check that your system works correctly. For example, I can have 90% test coverage and still make direct database calls in my view. This is bad design and good tests.