Traditionally developed software does not age gracefully. In fact, on average, it only takes about five years for newly developed software to deteriorate to a state where it is no longer economically feasible to maintain it. I.e. the cost of adding new features is larger than the income that the new features would generate.
Why does this keep happening? The answer is that through the years, business people have learned that developers are lazy. When developers whine about impossible deadlines it is just a matter of telling them that it needs to get done, or else… and then they will do it.
Developers, on the other hand, have learned many powerful ways to “speed up” the development when presented with impossible deadlines that “have to” be met. They can skip making the code readable, skip the unit testing, skip refactoring, skip the load and security testing, skip the code review, skip the documentation, … In this way they can easily double the speed at which they produce crap.
Of course the drawback of these techniques is that they do not really produce usable software. So a lot of time will have to be spent on fixing trouble reports. Typically 15-60 times as much as it would have taken to build quality in from the start. Also, over time, the code base gets more and more messed up and harder to modify. Thus, development will get slower and slower.
Naturally a project like this will overrun its initial schedule & budget. After a few years it will no longer be possible to maintain the system and the company will be in serious trouble.
The way to make this madness stop is to shift to iterative, value-driven development. I.e. each release is split into a number of iterations. Each iteration a number of features of value to the users will be completely developed. The most important thing with this is to establish a “definition of done”, a detailed specification of what it takes for a specific feature to be considered as “done”. If the definition of done states that quality shall be built in from the start, it will no longer be possible to “speed up” development by reverting to produce crap instead of working software. Business people will not be able to tell developers to work faster anymore, so instead they will need to start selecting the features for each iteration/release that give the maximum return on the investment.
One interesting thing about that is that an average requirements specification contains 64% features of little or no use to customers. These features will never be selected for implementation when doing value-driven development and thus the project time may be cut in half.
Here are a few ideas on what to put into your definition of done:
- Code shall be covered by automatic units tests with at least 90% branch/condition coverage
- The design shall have been refactored to integrate the new features in the cleanest possible way
- There shall be no duplicate code
- Coding standards shall have been met
- The code shall be easy to read and understand
- Documentation required for future maintenance shall be done
- Cycliomatic complexity of the code shall be < 10
- Maximum levels of nested code (if statements etc) shall be 3
- The code passes some lint-type tool at some specified warning level
- All automatic tests have been run with a dynamic checking tool such as Purify
- The new feature shall be covered by automatic customer acceptance tests
- All non-functional requirements applicable to this feature shall be covered by automatic tests
- User documentation shall be done
- Release documentation shall be done
- The feature shall have been accepted by the customer
- The feature shall have been installed at the customer site
Pair programming is very useful to make it possible to maintain extreme dicipline like this under pressure. For the same reason, whenever possible, try to cover your definition of done with automatic tests. Some useful tools for this are BullsEye, Lint, Purify, CloneDetective, …
The list above is just a quick example. You will be able to add a lot more to your list, and yet most teams will not be able to meet the example list initially. But just get started with whatever you can manage today and keep working on it. With time you will be able to expand your definition of done so that there is really nothing left to do when the code is marked as done.
When you get to that point, you will always be operating at maximum speed since there will be no old baggage slowing you down. At this point, few of your competitors will be able to keep up with you. That is a good place to be…