loading...
Cover image for Software Maintenance, Understanding the 4 Types

Software Maintenance, Understanding the 4 Types

lpasqualis profile image Lorenzo Pasqualis Originally published at coderhood.com ・7 min read

This post was first published in its entirety on CoderHood as Software Maintenance, Understanding the 4 Types. CoderHood is a blog dedicated to the human dimension of software engineering.


Software systems are a collection of bits recorded on a storage device. It might seem that once a software application works, as long as the hardware it runs on is functional, it should just keep working for eternity. So, why is "software maintenance" even a thing? There is no physical wear and tear, and there are no materials that can rot or rust away. Software systems are not affected by the atmosphere, pollution, the weather, and there isn't anything that can physically break. However, this argumentation doesn't take into consideration an essential aspect: the context.

While software applications do not have moving parts that are subject to physical wear and tear, they most often have dependencies with their working environment. With very few exceptions, as the working environment inevitably changes, the assumptions the application was built upon crumble. Eventually, the app stops working or loses its value.

Examples of Context Changes

Let me give you a few examples of context changes that can cause a software system to lose its value or break:

  • A website that allows users to log-in using Google authentication stops working when Google changes its authentication protocol. (External dependencies change)
  • A weather prediction software system becomes outdated when the implemented mathematical weather models become outdated. (State-of-the-art knowledge change)
  • The navigation software of a car becomes obsolete when more recent navigation software products released by competitors are significantly better. (Market expectation change)
  • The software that manages bank accounts in a financial institution must be updated when the hardware it runs on breaks, and compatible hardware is no longer available. (Hardware change)
  • An application stops working when any one of the used third party libraries requires an update to a new version that is not backward compatible. (Software dependency change)
  • An application needs to be modified to comply with new laws and regulations. (Compliance change)
  • An application needs to be fixed because the definition of leap year changed. (External concepts and definitions change)
  • An application needs to integrate with a new and popular third-party system. (Market environment change)
  • Traffic is increasing on a website, and the website software needs to be rearchitected to be able to scale to the new traffic levels. (Usage patterns change)

So, in principle, it is true that software applications don't withstand physical wear and tear. However, non-physical processes cause software applications to age and expire if they are not rigorously maintained.

The Different Types of Software Maintenance

Maintenance of software systems comes in four different flavors: adaptive, corrective, perfective and preventive. Please, note that I did not make up these names. If I did, I would have chosen something different. For example, I find the term "perfective" to be cringy, but I am going to stick with it for compatibility with the standard industry jargon.

A maintenance action is always a software change, but its classification depends on the reasons that triggered it. Let's take a deep dive in the four types of maintenance, and how to recognize them.

Corrective Software Maintenance

A corrective maintenance action is a software change that you make because:

  1. there is an acute issue that prevents the software to work as expected
  2. the problem is actively affecting users, or you suspect that it is.

For example, if you release a software system and your users ran into a bug, a corrective maintenance action is required to fix it. Note that, if the users were never affected by the bug and you resolve it before anybody noticed it, the maintenance action is preventive or adaptive. However, if even one single user might have been affected, then fixing the problem is a corrective maintenance action.

If you spend the majority of the time dealing with corrective maintenance tasks, your engineering team is running in firefighting mode. Pay attention to that situation, as something might be wrong with your testing practices, your ability to anticipate problems, seniority and skill level of your team, the quality of your code or your engineering capacity.

Adaptive Software Maintenance

Adaptive maintenance is something you do when you change a software system because:

  1. you have definite information that the landscape in which your software operates is changing (i.e., market, technology, laws, etc.)
  2. you have a good understanding of the direction and timeline of the landscape change
  3. your customers will be affected at some predictable point in the future, or they are affected now but have trivial and inexpensive workarounds

For example, let's say that you are running a website and you discover that it is not compatible with a new version of Safari that was pre-released by Apple in developer-only beta. Based on historical patterns, you know that Apple will release the incompatible version of Safari in the next few months. If you address the problem before the new version of Safari goes mainstream, then you are performing an adaptive maintenance task. That's because:

  1. Safari is changing
  2. you have a good guess on when it will be released
  3. your customers are not using the developer version of Safari; if they are, they are probably aware of the risks and can switch to the generally available release.

If you wait for the new version of Safari to become generally available to the public, and your customers run into issues, then you have to take a corrective maintenance action. Knowingly delaying adaptive maintenance until it becomes necessary to perform corrective maintenance is costly and should always be avoided.

A very famous example of massive worldwide adaptive maintenance rush was caused by the "Y2K bug" in the late 1990s. The calendar year was guaranteed to change from 1999 to 2000 on 1/1/2000. Many software systems were clearly not ready for it, but customers of those systems were not affected yet. At exactly midnight on January 1st, 2000, any software maker who did not invest in the adaptive maintenance work to fix the Y2K flow was now dealing with a corrective maintenance emergency.

Perfective Software Maintenance

You perform perfective maintenance when you change a software system because you decide to improve its value by improving something that is already working. Perfective maintenance includes things like speed optimizations, UI and usability improvements, etc. Perfective maintenance is often, but not always, initiated by customer feedback. Well-run software organizations listen carefully to their customers and invest in perfective maintenance tasks until just before they hit a point of diminishing returns.

Preventive Software Maintenance

Preventive maintenance is a software change you make to avoid potential (but not guaranteed) future issues.

The difference between adaptive and preventive maintenance can be fuzzy at times. In general, preventive maintenance is not bound to a trend that is sure to occur due to changing contextual conditions; instead, it is linked to an event that might or might not happen in the future. For example, if you are concerned about traffic spikes due to unforeseen and unpredictable future circumstances, and you decide to reinforce your software to deal with it, you are performing preventive maintenance. On the other hand, if your traffic growth patterns are somewhat predictable, and you have a good idea when your systems will start having scalability issues, any change you make to avoid those issues is adaptive maintenance.

Mindmap of the Key Concepts

Why is this important?

Every time that you make changes to a software system, it is essential to identify the type of maintenance that you are performing. Keeping track of it gives excellent insights into your engineering practices. For example, the percentage of time that you spend in each of the four maintenance types gives you an idea of the maturity and skill level of your software engineering organization. It can also give you an idea of the maturity level of your product and codebase.

How much time your engineering team should spend on each of the four types of maintenance depends on many factors. For example, immediately after a release, you should not be surprised to see a spike in corrective maintenance work. Despite your best attempts to release bug-free code, issues always crop up after a release. There are no hard and fast rules, but there are general considerations and principles to keep in mind.

  • Software systems age. Maintenance is part of a software system cost of ownership. You can somewhat keep it under control, but you cannot avoid it.
  • As your software systems become bigger and more sophisticated, or as your customer base grows, the amount of maintenance required increases proportionally (but not linearly). Without growth (AKA, more people), engineering teams that keep adding new features to a software system, or supporting a growing customer base, sooner or later end up spending 100% of their time on maintenance tasks. I call that the "zero-growth" stage, and it is not a good place to be. How quickly you'll get there depends on many factors.
  • Investing in preventive maintenance is like taking a bet. To win you have to bet and be right more often than you are wrong.
  • Do not let issues go from "potential" to "predictable" to "acute." Most corrective maintenance tasks are very costly because they affect your brand. You can usually avoid them with less expensive adaptive or predictive maintenance work if you pay attention. Take bets, move quickly, don't ignore clear signals.
  • If you are not working on any adaptive or preventive maintenance task, you are probably not paying attention to the context in which your software operates.
  • There is a point of diminishing returns in perfective maintenance tasks. You can polish an apple only so much before it becomes a futile exercise.
  • There are always going to be parts of a software system that you prefer not to touch. That is not necessarily a bad thing; however, you should watch out for how much time you spend working around problems in those areas.
  • Sometimes it is not immediately obvious how to categorize maintenance work as it seems to fall into multiple buckets. That's ok. Take your best shot. The more you do it, the easier it gets.

If you enjoyed this article, keep in touch!

Posted on by:

lpasqualis profile

Lorenzo Pasqualis

@lpasqualis

I started writing software in 1984. Over the years I worked with many languages, technologies, and tools. I have been in leadership positions since the early 2000s, and in executive roles since 2014.

Discussion

markdown guide
 

Great post. I'd say preventive and perfective maintenance have overlapping goals. I'd bucket refactoring under both. You refactor to make future changes easier. That's adaptive but also perfective since it improves the software in some way. And it is preventive because it makes it easier to perform future changes without introducing new bugs.

How you categorize your changes is less important than being conscious of where you are spending your time. As you say, when you spend a lot of time firefighting you need to step back and figure out if there's a better course of action.

It's easy to get stuck doing a lot of maintenance without seeing the bigger picture. The fate of most succesfull software is that eventually the accumulated engineering effort is mostly spent on maintenance. Some studies I read in the early 2000s suggested that most big IT projects see upwards of 60% of their budgets eaten up by maintenance. This is a sobering thought if you are doing a greenfield project (which is fun).

My view is that maintenance problems pile up and become an obstacle to necessary adaptive maintenance. When certain changes become hard or impossible, this can result in software being decommissioned. That too is a common problem with many software projects. Many projects do not survive their first birthday.

This also means that if you know you are working on something that only has short term relevance, maybe over-engineering it in an attempt to perfect it is not the right way. Quick and dirty is not long term sustainable but it can get your results quickly.

 

Looks like what I call "technical debt" is federated in those buckets.

I distinguish between internal technical debt, versus external technical debt.

Internal technical debt is "we took some shortcut so we could ship, but as a result the code in that area is a mess... if we're going to keep this code going forward we HAVE to address it at some point in time". Hmmm, Predictive: cost of not doing?

External technical debt are things like "The OS changed on us, Windows now requires XPS for printing, and macOS deprecated all the FSSpec and FSRef APIs in 10.8" or "C++17 is out, and most of our code is still C++98". Hmmm, Adaptive: triggers - changing landscape?

 

Great to see you writing again! Adding this to my reading list to read over lunch. :)

 

Thank you! Yes, I did take a writing break, but I am planning on starting my writing routine again. I definitely missed the dev.to community. I also realized that writing is like coding, and you do get rusty. I'll need to shake some rust off my keyboard :)

 

Another great article Lorenzo. You have a way of putting the abstract into concrete understandable terms. That ability is very much appreciates. Looking forward to the next one!

 

Thank you, David! You just made my day :)

 

Welcome back! Great explanation :)