Developing maintainable software

By Steve Crouch.

Why it's important and how to do it...

WomanAndLaptop.jpgSoftware always needs new features or bug fixes. Maintainable software is easy to extend and fix, which encourages the software's uptake and use. The Software Sustainability Institute can advise you on the design and development of maintainable software that will benefit both you and your users.

Why write this guide?

We wrote this guide to give an overview of a subject that we think is important to software sustainability.

What is maintainable software?

Maintainable software allows you to quickly and easily:

  • Fix a bug
  • Add new features
  • Improve usability
  • Increase performance
  • Make a fix that prevents a bug from occurring in future
  • Make changes to support new environments operating systems or tools
  • Make it easier for others to maintain the software

More formally, the IEEE Standard Glossary of Software Engineering Terminology defines maintainability as:

"The ease with which a software system or component can be modified to correct faults, improve performance or other attributes, or adapt to a changed environment."

The maintainability of software depends on a few different factors. In general, it must be easy to understand the software (how it works, what it does, and why it does it the way it does), easy to find what needs to be change, easy to make changes and easy to check that the changes have not introduced any bugs.

Why is maintainability desirable?

Today, you have the skills and knowledge to understand and make changes to your software, but what about next week, or six months from now?

What if a developer leaves your team (or they are ill), and you need to take over their code? What if you need to get a new developer up to speed with your software? What if you have to suspend your project whilst you get more funding, and then need to recall all the information about the software a year later?

In all these cases, you or your developers, will find themselves wading through code trying to figure out how it all fits together. This isn't fun, and it wastes valuable time that could be used to write new functionality. Maintainable software is software that is easy to understand. It is code that can be understood by someone new - or someone that hasn't seen it in a while - with a minimum of effort.

Open-source software

You may be developing open-source software with the intent that it will live on after your project completes. It could be important to you that your software is adopted and used by other projects as this may help you get future funding. It can make your software more attractive to potential users if they have the confidence that they can fix bugs that arise or add new features they need, that the evolution of the software is not dependant upon the lifetime of your project.

If you release maintainable open source software during your project's lifetime then you might get other developers fixing bugs or making extensions that you don't have time to do. If they contribute these back to you, or make them freely available, this can be viewed as free effort for your project. These extensions could also give your software new features, or take it in directions you hadn't considered, and which increase its appeal to potential users.

Disposable software

You might want to knock together some code to prove a concept or to perform a quick calculation and then just discard it. But can you be sure you'll never want to use it again? Maybe a few months from now you'll realise you need it after all, or you'll have a colleague say "I wish I had a..." and realise you've already made one. A small investment in the maintainability of your code makes it easier to pick up after a break, and can provide you with an insurance policy should your disposable software turn out to be more useful than you thought.

The reasons for,  and the cost of, neglecting maintainability

When resources are tight, it's easy to focus on the bare minimum needed to get the software to do what it's meant to do and leave less pressing tasks, such as documentation, testing, and refactoring, until the end of the project. The plan is to complete these tasks when time permits, and time rarely permits!

You can save time, in the short term, by not commenting code, not refactoring to make it more readable, not addressing compiler warnings, leaving aside tests, skipping documentation and not recording why something was implemented in a specific way. These actions all incur technical debt and - just like financial debt - it's a debt that gathers interest over time. Technical debt is paid off in the cost of maintenance. Software that is written without maintainability in mind requires about four times as much effort to maintain than it did to develop. For this reason, many applications are replaced simply because the overhead to modify them becomes prohibitive.

Help is at hand! Developing maintainable software helps reduce technical debt. By thinking ahead and investing now you reduce the impact of changes in the future.

How to develop maintainable software

Developing maintainable software is like picnicking. Once you're finished, leave your spot as you would like to find it yourself. There are a number of principles, approaches and techniques that can help you develop maintainable software. Many of these are generally applicable to writing good software:

  • Design for maintainability from the outset
  • Iterative development and regular reviews improve quality - see the section below
  • Readable code is easy to understand
  • Refactor code to improves its understandability
  • Relevant documentation helps developers understand the software
  • Automated builds make the code easy to compile
  • Automated tests make it easy to validate changes
  • Continuous integration makes the code easier to build and test
  • Version control helps keep code, tests and documentation up to date and synchronised
  • Change the way you work to make maintainability a key goal

Prevention is better (and cheaper) than cure: get others to review your code

There are a couple of very useful preventative techniques you can consider which can greatly reduce the cost of maintenance.

Firstly, there is code review, also known as peer reviews or code inspection. This is done prior to to any testing activity and involves developers reviewing code line by line to find errors. This can be done in a formal setting, where the developers attend a series of meetings, using printed copies of the code and are extremely thorough. Alternatively, it can be done in a more lightweight, informal manner which if done properly can be just as effective. This involves the original developer of the code walking through it and explaining the goals of each part of the code to another developer (perhaps more than one) and the reasoning behind its implementation. In this way, it can be done as part of the normal development process. The great news is that it has been known for a long time that code reviews can remove up to 90% of errors in checked code before the first test is run[1], and it is cheaper to fix errors at this stage than further down the line.

Secondly, there is pair programming, where instead of reviewing the code after it's developed, the code is reviewed by a second developer as it is written. The driver writes the code while the observer or navigator reviews each line of code as it's typed in, and the two switch roles frequently. This allows the observer to consider the high-level goals of the code itself, its strategic direction: such as how it fits in with the rest of the code, improvements and importantly future maintenance. With an observer 'safety net' the driver simply has to then consider the tactical aspects of completing the coding task. Pair programming also means both participants won't be distracted by Facebook or e-mail, and can learn handy hints and tips off each other to improve their skills!

Code reviews and pair programming, whilst valuable, require a great deal of concentration and rigor. Because of this it's been found, at least for code reviews, that the first hour of the first code review matter most[2]. So when should you use either of these techniques? A good approach to get the most benefit is to employ them for critical portions of critical code, which may be relatively complex and prone to error, and where errors have the highest impact on successful function.

The other big advantages to these approaches is that they increase the knowledge of the code base across a developer team, and can also prove a valuable 'code induction' experience for new developers just joining a project (pair programming in particular can be great for this, with the newcomer acting as observer). This can greatly help to mitigate the risk of key developers leaving the project with all the knowhow!

A maintainability checklist

Answering the following questions will help you judge the maintainability of your software:

  • Can I find the code that is related to a specific problem or change?
  • Can I understand the code? Can I explain the rationale behind it to someone else?
  • Is it easy to change the code? Is it easy for me to determine what I need to change as a consequence? Are the number and magnitude of such knock-on changes small?
  • Can I quickly verify a change (preferably in isolation)?
  • Can I make a change with only a low risk of breaking existing features?
  • If I do break something, is it quick and easy to detect and diagnose the problem?

Now ask the questions again but, this time, adopt the perspectives of someone else in your team and someone who is completely new to your software.

Further Reading

The Importance of Maintainable Software”, B. Vandegriend
How to Create Maintainable Software”, B. Vandegriend
Creating a Maintainable Software Ecosystem”, J. Miller
"Using Pair Programming Practices in Code Inspections", M. Heusser

References

[1] "Design and Code inspections to reduce errors in program development", M. Fagan, IBM SYstems Journal 15(3), pp 182-211 (1976)
[2] "Best Kept Secrets of Peer Code Review", smartbearsoftware.com, ISBN 1599160676 (2006)