Most design techniques for maintainability are well known: Reducing coupling, cohesion, and complexity, intelligent use of design patterns where appropriate, code comments, and so on. These techniques are not unique to object orientation, though we still believe that objects facilitate their implementation. However, today's software is largely ruled by systems that are hard to maintain. In my opinion, the interesting question therefore is, why don't we build maintainable software, though we basically know how to do it?
I can see three main causes for this phenomenon:
Lets analyze these three in some more detail
Maintainability is hard to measure.Whether software is hard to maintain or not usually is a very subjective view and there are no broadly accepted metrics for maintainability. An experienced architect can tell whether software is hard to maintain or not, but proving bad maintenance before the maintenance has started is a very hard job.
Therefore maintainability is hard to communicate to non-software managers. If you ask an executive for more money or a few additional months for a redesign, she would most probably ask why you didn't do the design right from the beginning. Redesign is considered being crisis management, rather than an investment into the future. Given the choice, almost all project stakeholders would prefer faster time-to-market or additional features over "technological fiddling" to improve something you can't even measure.
Architects tend to consider this shortsighted, because it speeds up the short-termed development on the expense of long-term maintenance costs. Seen from a management perspective, the world looks slightly different. The delivery date may decide the fate of the complete organization or at least of the project and additional features are definitely easier to sell than better maintenance.What we have here is a classic example of conflicting forces: Time-to-market versus features versus maintainability. You can improve one at the expense of the other only. Time-to-market and features are easy to measure, maintainability isn't. Hence the project looks better if you have put effort on the first two rather than on the latter. If looking good is a matter of project survival - like it is most times - every sensible project manager would promote fast delivery and additional features in this situation.
I don't want to promote metrics here. Rather I believe that one solution to this problem tries to vary the focus of the project over time and emphasize every force when its time has come. I'll return to this approach later.
This doesn't address the programming experience of the programmers. Especially organizations that run software for more than a decade have a body of extremely experienced programmers that form an invaluable resource. Instead I think that maintenance problems may stem from a lack of experience in maintaining your own software. In many cases it takes several months, if not years, between writing a piece of software and the next time when you have to maintain it. Most programmers have forgotten the details of their code during this time, so there is no difference between your own code and code written by somebody else. Even worse, you don't have the intimate knowledge anymore you need to correct maintenance problems. Therefore you can't correct the problems you might have found if you still had the original knowledge. In any case you don't have a chance to reflect measures that would increase maintainability and implement them.
The problem becomes even worse, if contract programmers or other organizations have written the software and vanished after delivery. These programmers often are not even aware of maintenance problems.
Just demanding professional education to teach maintenance is not enough. Rather it seems to be sensible to organize the project in a way that every project member has a chance to do maintenance, to reflect it and to adapt his way of work to the lessons he has learned.
"We write code, not novels" was the answer I got once to my asking for better comments. Many programmers consider code quality as a problem of the QA department. Maybe this comes from attempts to introduce quality assurance top-down by management order rather than seeding a profound understanding of what quality is good for. Productivity still is measured in lines of code per day, although good code is significantly shorter than bad code usually. Increasing the quality of working code is considered work without business value and thus futile.
Many teams wish they could start all over again after they have finished a project and avoid all the mistakes they know of. Surely, the result would show a significantly increased maintainability. But no sensible manager would spend the money on an experiment like that if the original system at least somehow fulfills its requirements. If it doesn't, the same team usually doesn't get a second chance.
Considering these forces, an incremental process can form a reasonable balance. The idea is to deliver a part of the project every three or four months or even more often (Extreme Programming tries to deliver every three weeks). Before you deliver you concentrate on the delivery deadline and on the features. You don't forget maintainability but you accept some stenches on your design in order to deliver on time - just as you do in every other project. After you have delivered you have the time to do a short redesign period of two to three weeks. this allows you to repair almost all design flaws you know about. This short redesign period is nothing your manager worries about. You can do it in parallel with starting the analysis of the next increment, so someone in the project always makes progress in terms of new features. After the cleanup period is done, the focus shifts to new features and the deadline again. Hence all of the forces get their attention at their time.
When you follow this strategy, the project enters the maintenance phase after the delivery of the first increment. This implies that the developers have to maintain their own code nearly from the beginning of the project. If you facilitate them to reflect their problems they have the chance to learn from their own and their colleagues' mistakes and thus produce more maintainable code. Mutual code reviews or Pair Programming are techniques to facilitate the reflection and help the programmers to develop a better understanding of the importance of quality code. The investment comes in small portions here - incorporating the changes of a code review is somewhere between a day and a week. This is what most managers are willing to invest.
Of course incremental development is no silver bullet. It doesn't guarantee maintainable software. Still I believe it gives the project manager a better chance to balance the forces right. However, you have to be aware of some difficulties. The reflection process need discipline in the team and an egoless attitude towards the own code. Finally, incremental development is a cultural change in the team and you have to be careful not to make it a cultural shock.
To participate in this workshop please read the Call for Participation