How maintainable is your code?
Most of the discussions dealing with software development methods and techniques appear to focus on the initial development of software: figuring out what is needed, building it and then delivering it to the customer. After delivery however, the work is rarely done. In fact, according to Thomas Pigoski in his book Practical Software Maintenance, up to 90% of the actual development effort of a piece of software takes place after it has been delivered, with two-thirds being a typical amount of development being done after delivery.
There are some fundamental differences between going from one iteration in development to the next during the initial development of a product and actually doing maintenance. The most important issue being that after a product has been delivered, making changes to it can potentially break something that is already being used in production. So suddenly you need to start thinking about creating a new interface instead of just modifying the original one, or modifying your parser to deal with multiple data formats instead of just changing it to work with only the latest extension.
But before I get too far ahead of myself, I’d like to discuss some of the typical quality attributes associated with software that are relevant to software maintenance: aspects of software that help the maintenance effort. These are different from quality attributes that customers care about, or that matter most during initial development. They are specific to having to modify an existing system where the original creator(s) may no longer be available. Although in research and practice papers a lot of different attributes are mentioned, the five defined by the IEEE in their software maintenance glossary are a good starting point:
-
Modularity — Whether or not the software’s functionality has been properly split up into different components. This is important for maintainers because it allows them to selectively replace or rework components without having to deal with the entire system all the time. Note though that there is more to it than just splitting stuff into physical components: the components themselves need to be properly abstracted, using interfaces and the least possible amount of assumptions about how other components work internally.
-
Consistency — Relevant on multiple levels. First of all, whether the same design and implementation approaches are used throughout the software. Maintaining a piece of software where some methods assume the caller frees up memory afterwards and some methods do it themselves is a large amount of memory leaks waiting to happen once people start modifying the system. Even when doing initial development, when you discover that an approach is suboptimal: either change it everywhere straight away (recommended) or keep using the suboptimal approach (after you determine it won’t hinder stability) and do the change completely afterwards as part of maintenance.
It’s also an issue in areas such as coding standards: different coding standards, tab settings, naming conventions, etc. are a headache to deal with afterwards because it makes the code much less readable even if the code itself is of high quality.
-
Simplicity and Concisiveness — These are very different things, but they can sometimes appear to be contradictory. Simplicity is basically the KISS principle: never complicate things beyond what is absolutely necessary to express the functionality in code. Concisiveness on the other hand means expressing functionality in the least amount of code. For example, regular expressions are usually concise but rarely simple, while large switch/case-statements are basically very simple but rarely concise.
To keep your code maintainable, it’s best to just create straight-forward solutions without worrying about too many possible variations of what your code should be doing. When you identify a piece of code where for instance you may need different algorithms to perform the same task, abstract the algorithm away using the Strategy pattern. Most design patterns are simple and concise (with the exception of the Visitor-pattern, which is neither :-))
-
Self-descriptiveness — Sometimes called understandability, in software maintenance this attribute deals with the amount of time it takes to get to grips with a piece of software in such a way that you feel comfortable modifying it. Code comments are useful here, although a good naming comvention is just as important, as well as having good high-level documentation along with a description of possible low-level choices that have been made during development. Unit-tests however often also add to the self-descriptiveness of a piece of software: having a couple of unit-tests for a class or method often illustrates wonderfully how it works. For me however, there is no substitute for a good description of what a class or method does, what it needs as input and what it provides as output.
I plan to write more on the subject of software maintenance, both generally and related to actual software projects. Since .NET has been around for quite a while now, so instead of creating .NET applications and maintaining C/C++/Java systems, maintenance is starting to become an issue in all environments!
Great post. Unfortunately, most of the software that has been written to date has not been written with the maintainability attributes you share in mind. For those cases, Phil Murphy of Forrester Research published an excellent piece on the subject yesterday, http://forrester.com/Research/Document/Excerpt/0,7211,40446,00.html. In it he points out that impact analysis tools and complexity tools can increase productivity of software maintenance activities by as much as 30% and 20% respectively. Either way, it is time to start paying attention to this issue. Ideally, at the outset as you suggest, but minimally, utilize best practices to minimize the maintenance burden when the software has already been written.
[…] Jeroen asks, How maintainable is your Code? He goes on to identify 4 attributes of well written code. […]
[…] Jeroen asks, How maintainable is your Code? He goes on to identify 4 attributes of well written code. […]