This is the first of several posts that deal with legacy software in an OO context. In particular, I <eventually> describe an approach to replacement of legacy systems that is relatively low risk and fairly manageable. However, before going there I need to address some basic issues about legacy code and the techniques currently employed to deal with it.
Technically the term legacy code just refers to any applications or modules created by developers who are no longer with the organization. In practice, though, it is commonly used in a pejorative sense to describe code that is very expensive to maintain. This is important because, depending on whose data one looks at, the average software developer spends 50-80% of their time doing maintenance. In addition, various industry gurus argue that maintaining legacy code can require up to a couple of integer factors more effort than developing new applications from scratch. If those numbers are even remotely realistic, then legacy code represents a huge cost to the software industry in general and to those shops with significant legacy code.
Clearly the cost of maintenance is a complex issue and depends upon many factors. However, we can probably broadly classify legacy code in terms of the additional effort needed compared to original development:
Good (10-40%). This is code that is quite maintainable and employs modern technologies. Typically such code will not be very old and it is highly modularized at the subsystem or layer level. It will also have been constructed with disciplined design and programming practices. Perhaps most important, it will be carefully documented, including an up-to-date requirements specification. (The form of the documentation is much less important than its accuracy.) Usually well-formed OO applications live in this category but a very good procedural applications would also qualify. (It just takes a lot more developer discipline to produce a procedural application that provides the same degree modularization and decoupling that one gets "for free" in routine OO development.)
Fair (30-80%). Typically these are somewhat older systems created using reasonable programming practices and modularization but the documentation, particularly requirements, is out of date and the technologies (languages, methodologies, etc.) employed may be obsolete. These will also usually involve well-formed OO applications or good procedural applications in the original development that may be showing their age because of "architectural drift" due to continuing maintenance.
Average (60-120%). These are older applications using obsolete technologies that were developed with inconsistent programming practices and modularization. That is, there was inconsistent quality among the various developers or teams. (The inconsistency could be introduced into good original applications during ongoing maintenance) In addition, the documentation is quite spotty. These will usually be poorly-formed OO applications or good but inconsistent procedural applications. (Good because they originally employed SA/D properly but years of maintenance trashed the original design.)
Poor (100-180%). Here the original development was done with uniformly poor design techniques, programming practices, and modularization -- probably because it is old enough that the original developers did not know any better. Documentation is largely nonexistent and usually incorrect when present. It very likely employs obsolete technologies. This is the realm of bad OO applications, but more commonly the application will have been a procedural development. If procedural, the quality of the original SA/D was probably not very good.
Awful (150-??%). These are the true disasters that are virtually unmaintainable. The documentation, particularly the original requirements, is nonexistent and any comments embedded in the code are hopelessly out of date. Naming conventions, if they were systematic in the first place, are out of date and misleading. If the original development was in an OOPL, then it was done by developers who were applying procedural paradigms so that the OOPL was used solely for strong typing. Most likely the original development was procedural using ad hoc design and programming techniques.
The important thing to note here are that there are several distinct factors that contribute to creating legacy code with a high cost of maintenance: system design (large-scale modularity); software development practices (e.g., SA/D/P, OOA/D/P, etc.); up-to-date documentation, particularly of the current requirements; technologies employed; whether the original development was OO or procedural; and the amount of maintenance already done. By the time one is at average maintainability or worse, all of these factors are likely to be conspiring together to create the problem. In my opinion, once the software reaches the level of Average or worse, it is no longer viable and needs to be replaced. (The fact that I call this Average is a sad commentary on the current state of the software industry.)
Another important thing to note is the doing OO development is no guarantee of long-term maintainability. One can write bad OO applications just as easily as one can write bad procedural applications. All OO development brings to the table is that for a given developer skill level the probability of increasing the time until software becomes unmaintainable increases. That is, there are no Silver Bullets and every software shop needs to be vigilant about their development processes and needs to accept the fact that all applications eventually must be replaced. That is, every software shop needs to plan ahead for ongoing replacement before the costs of maintenance become prohibitive.
My point here is that a software shop that has its act together with produce software that is maintainable at the Good level as original development. The shop will then monitor the cost of maintenance so that it will know when the software degrades to Fair maintainability. At that point the shop will take proactive action for replacement while it is still reasonably modular. That will make the replacement vastly easier for reasons I will get to in subsequent posts.
Unfortunately most of the world's current software already ranks as Average or worse. That presents some big problems for the industry and I will be focused on those situations for the remainder of this blog category.