This post originated from an RSS feed registered with Java Buzz
by Jon Tirsen.
Original Post: Software Rot
Feed Title: jutopia
Feed URL: http://sedoparking.com/search/registrar.php?domain=®istrar=sedopark
Feed Description: Ramblings on Java, AOP, TDD, agile and so on. some like it jutopic!
Cleaning day today at home. While running round the apartment with a vacuum cleaner I started thinking of one of the common phenomenon in our profession: software rot.
Anyone thats been maintaining or developing a larger system has experienced this; the system is slowly getting harder and harder to work in. Every bug fix or new feature takes longer and longer time to implement (and the results look uglier and uglier).
The difficult thing is that software rot happens slowly, theres no single event or single person that causes it. It will slowly creep onto you, and all of a sudden the system is dead. It's a slow, painful and horrible death.
In order to prevent it we must be aware of the forces that induce it. Heres an incomplete list of some of the things Ive experienced (most of these are composed and non-orthogonal, but Im not trying to write a scientific essay here):
Changes in requirements
The abstractions you previously designed your system around will no longer be appropriate and need to change. This will happen, be prepared
Duplication
Code should be the direct results of your (explicit or implicit) requirements. Every piece of requirement should have one and only one place where it is encoded. If not the different places will start competing and contradicting each other when requirements change.
Lack of refactoring
Refactoring, the process to continuously improve and adapt design, is one of the more powerful tools against software rot. Software that is not refactored when changing will lead to software rot.
Premature optimizations
Crisp clear, optimal design is the goal. Dont let anything distract your attention from this long-term course. Optimize until its good enough and never too early.
Technical constraints preventing refactoring
Use of inferior technology or architecture may prevent many refactorings. For example EJB doesnt support inheritance and Transaction Script doesnt support encapsulation.
Lack of knowledge and/or experience
The developers working on the system may not be experienced or trained sufficiently for the task. For example letting a couple of inexperienced VB programmers build the next ERP system for Ford worldwide may not be the smartest thing to do (even if you employ a couple of thousands of them).
Incomplete tests or manual tests
To get the courage to refactor we need to be able to ensure that system is still working afterwards. We cant go through a two week test-phase for each chopped up inheritance chain or each extracted method. We need to know if it works within minutes or preferably within seconds. (5 seconds is fine, 5 minutes is way too long.)
Most processes or methods are (more or less consciously) designed to prevent software rot. Most formal methods use extensive documentation of every component of the system to do this. I have personally never experienced this as preventing software rot in the field though, almost the contrary since it may hinder refactorings and puts the focus away from producing the best possible code. Some things that has helped me though (quite inspired from The Pragmatic Programmer):
Refactoring
This is actually pretty obvious: Okay, if we continuously make things better it wont get worse, right? Duh. So the trick here is how to do it effectively.
DRY
Dont Repeat Yourself. Simply dont tolerate duplication. Just say no. Its dangerous and will kill you. Slowly.
TDD
Test Driven Development promotes clean, clear and crisp design. It will also give you a test-suite of high-quality and high-coverage that will help you while doing your refactorings.
Pair Programming
Pair programming is the use of continuous code inspection. Somebodys always gonna sit next to you and force you to stick to the rules: Hey, you havent got a failing test for that yet. You need a space after that comma. Hmm I remember I wrote something that looked like that some time ago, maybe you should reuse it. If you rotate the pairs properly it will also promote communication and the flow of knowledge, information and experience within the project.
Dont live with broken windows
Dont just shrug your shoulders at code/design smells, duplication, ugly naming, wrong formatting, unused code and so on. Its your responsibility to fix anything you may encounter. If theres a bug in some part of the code thats kind of messy, clean up the mess before fixing the bug. Incidentally this will commonly fix the bug too, and hopefully not introduce too many new ones. Your tests should prevent the introduction of previously discovered ones though.
There's other forces in software development too and sometimes they contradict each other. (For example your boss insisting you to release on time with sufficient quality and functionality.) But make some of these practices an integrated part of your every day coding. For example don't tell your boss: "It's done know, but it needs some refactoring." Will he let you do that if you're on a tight schedule? Instead use for example TDD which promotes small doses of refactorings, say for every 5 lines of code you write. It's hard to avoid the need for a larger overhaul but it will be measured in days not months. In the end your boss will be content because you will keep producing functionality and quality at a high pace.