It is still a sad reality that many software development projects are in bad conditions, and some might even be in a serious crisis. The reasons for this are manifold. Some projects, for example, are afflicted because of lousy project management. In other projects, the conditions and requirements are constantly changed, but the process does not support this high-dynamic environment. In some projects there are pure technical reasons: their code is of poor quality. That does not necessarily mean that the code is not working correctly. Its external quality, measured by the quality assurance department using blackbox, user, or acceptance tests, can be pretty high. It can pass the QA without complaints, and the test report says that they find nothing wrong. Also users of the software may be satisfied and happy, and its development has been completed on time and budget (… which is rare, I know).
Everything seems to be fine … really everything? Nevertheless, the internal quality of this code, which might work correctly, can be very poor. Often the code is difficult to understand and horrible to maintain and extend. Countless software units, like classes, or functions, are very large, some of them with thousands of lines of code. Too many dependencies between software units lead to unwanted side effects if something is changed. The software has no perceivable architecture. Its structure seems to be randomly originated and some developers speak about “historically grown software” or “architecture by accident.” Classes, functions, variables, and constants have bad and mysterious names, and the code is littered with lots of comments: some of them are outdated, just describe obvious things, or are plain wrong. Developers are afraid to change something or to extend the software because they know that it is rotten and fragile, and they know that unit test coverage is poor, if there are any unit tests at all. “Never touch a running system” is a statement that is frequently heard in such kinds of projects. The implementation of a new feature doesn’t need a few days until it is ready for deployment; it takes several weeks or even months.