4.5 Software Maintenance
What is Software Maintenance?
IEEE 1219 / ISO 14764 definition: "The modification of a software product after delivery to correct faults, improve performance or other attributes, or adapt the product to a modified environment."
The simplest definition: everything that happens to the software after it ships.
Maintenance is the longest and most expensive phase of the SDLC. Industry figures:
- 60–80% of total software cost goes into maintenance
- Average commercial system lives 7–15 years after first release
- Some legacy systems run 30+ years (COBOL banking, FORTRAN scientific)
Yet maintenance gets the least academic attention. The IPU paper corrects this — maintenance is a guaranteed exam topic.
---
Why software needs maintenance
A delivered system is not finished. It must keep up with:
- Bugs discovered in production — testing never finds all defects
- Changing requirements — business evolves
- Changing environments — OS upgrades, browser updates, library deprecations
- Performance demands — user base grows
- Security threats — new vulnerabilities, new attackers
- Regulatory changes — new laws, new compliance requirements
A system that doesn't evolve becomes obsolete — Manny Lehman's first law of software evolution: "A system must be continually adapted, or it becomes progressively less satisfactory."
---
Lehman's Laws of Software Evolution (1974, 8 laws — IPU sometimes asks)
| # | Law | Meaning |
|---|---|---|
| 1 | Continuing change | A system must be continually adapted to remain useful |
| 2 | Increasing complexity | Unless work is done to reduce it, complexity grows |
| 3 | Self-regulation | Evolution follows feedback-controlled patterns |
| 4 | Conservation of organisational stability | Average effort per release tends to stay constant |
| 5 | Conservation of familiarity | Average incremental growth per release is roughly constant |
| 6 | Continuing growth | Functional content must continually grow |
| 7 | Declining quality | Without maintenance, perceived quality drops |
| 8 | Feedback system | Process is a multi-loop feedback system |
The most-cited are #1 (continuing change), #2 (increasing complexity), and #7 (declining quality).
---
Types of Software Maintenance (Lientz & Swanson, 1980 — the IPU classic)
Four types. The IPU exam always expects these four with proportions.
1. Corrective Maintenance (~20%)
Purpose: Fix defects found after delivery.
| Trigger | Defect reports from users, monitoring alerts |
|---|---|
| Activity | Reproduce, locate, fix, regression test |
| Example | Fixing a crash that occurs only with empty input |
2. Adaptive Maintenance (~25%)
Purpose: Adapt the software to changes in its environment.
| Trigger | OS upgrade, hardware change, regulatory change |
|---|---|
| Activity | Modify code to remain compatible |
| Example | Updating a Java 8 application to run on Java 17; migrating to a new database version |
3. Perfective Maintenance (~50% — the largest)
Purpose: Improve the software — add features, improve performance, improve usability.
| Trigger | User feedback, performance issues, new requirements |
|---|---|
| Activity | Add features, optimise, refactor |
| Example | Adding mobile responsiveness; adding a new report; reducing page-load time |
Surprising fact: Half of all maintenance effort goes into new features on existing systems — not bug-fixing.
4. Preventive Maintenance (~4%)
Purpose: Make the software more maintainable for future changes — prevent future problems.
| Trigger | Technical debt, complexity accumulation |
|---|---|
| Activity | Refactor, restructure, update documentation, modernise dependencies |
| Example | Splitting a 5,000-line god-class; removing dead code; upgrading deprecated libraries |
---
Quick comparison
| Type | Reason | When triggered | Proportion |
|---|---|---|---|
| Corrective | Fix defects | After bug reports | ~20% |
| Adaptive | Adapt to environment | After external change | ~25% |
| Perfective | Improve / add features | User requests, performance | ~50% |
| Preventive | Reduce future maintenance cost | Internal decision | ~4% |
Exam tip: Memorise the proportions. "50% perfective, 25% adaptive, 21% corrective, 4% preventive" is the classic Lientz-Swanson figure.
---
The Maintenance Process
1. Modification Request (MR)
A formal request from a user or stakeholder. Fields: request ID, requester, description, priority, business justification.
2. Analysis
Understand the request, assess impact, estimate effort. Decide: accept, reject, or defer.
3. Change Design
Design the modification. Apply software-design principles (cohesion, coupling, minimal disruption).
4. Implementation
Modify code, configuration, documentation. Follow coding standards. Update tests.
5. System Test
Regression testing — confirm change works AND nothing else broke.
6. Acceptance Test
User confirms the change meets their request.
7. Delivery
Package, deploy, update documentation, notify users.
8. Closure
Update issue tracker, document lessons learned.
---
Maintenance Activities — Boehm's view
Boehm classifies maintenance work as:
| Activity | Description |
|---|---|
| Program understanding | Read code to figure out what it does |
| Localisation | Identify which modules to change |
| Impact analysis | Predict ripple effects of the change |
| Change implementation | Make the modification |
| Re-validation | Test that change works |
Program understanding is the single largest maintenance cost — often 50–60% of effort goes into reading and understanding code before any change is made. This is why documentation, naming, and structure matter so much.
---
Maintenance Tools & Techniques
| Category | Tool |
|---|---|
| Version control | Git, Bitbucket, SVN |
| Issue tracker | Jira, Bugzilla, GitHub Issues |
| Documentation | Confluence, ReadTheDocs, MkDocs |
| Static analysis | SonarQube, Checkstyle |
| Code search | grep, ripgrep, IDE go-to-definition |
| Reverse engineering | UML reverse engineering, doxygen |
| Refactoring | IDE refactoring tools (IntelliJ, Eclipse) |
| Regression testing | Automated test suite in CI |
| Monitoring / Observability | Datadog, New Relic, Grafana, ELK |
| Profiling | YourKit, JProfiler, py-spy |
---
Challenges of Maintenance
| Challenge | Detail |
|---|---|
| Maintainer is not the author | No first-hand knowledge of design decisions |
| Documentation is missing or stale | Common; investigate via code reading |
| Domain knowledge gap | Maintainers may lack business-domain expertise |
| Code complexity | Years of patches make code hard to read |
| Lack of regression tests | Risk that fixes break something else |
| Stakeholder pressure | Fix this NOW, no time to think |
| Technology obsolescence | Old languages, frameworks, hardware |
| Side effects | Changes ripple unpredictably |
Famous saying: "Legacy code is code without tests." — Michael Feathers (Working Effectively with Legacy Code, 2004).
---
Cost of Maintenance — why so high?
Several factors compound:
- Time pressure — fixes are urgent; shortcuts are taken
- Limited knowledge — maintainer must learn before changing
- Side effects — large systems have hidden coupling
- Lack of investment — preventive maintenance is the first thing cut from budgets
- Skill mismatch — best developers move to new projects; maintenance falls to juniors
The result: maintenance costs grow over time even though feature delivery slows down. The eventual outcome is either re-engineering or replacement.
---
Measuring Maintainability
| Metric | Description |
|---|---|
| MTTR (Mean Time To Repair) | Average time from bug report to fix |
| Defect backlog | Open issues at any time |
| Code churn | Lines changed per period |
| Cyclomatic complexity | High complexity → harder maintenance |
| Maintainability Index (MI) | Composite of Halstead, McCabe, LOC, comments |
| Technical debt | Estimated effort to bring code to clean state |
SonarQube reports many of these automatically.
---
Key Terms — Lesson 4.5
The terms below define the maintenance vocabulary every PYQ on SDLC's longest phase expects you to deploy fluently.
Software Maintenance — Per IEEE 1219 / ISO 14764, the modification of a software product after delivery to correct defects, improve performance, or adapt the product to a changed environment. Maintenance is the longest and most expensive phase of the SDLC — typically 60–80% of total lifecycle cost.
Lehman's Laws of Software Evolution — Manny Lehman's eight empirical laws (1974, refined through 1996) describing how large software systems change over time. The three most-cited: continuing change (a system must adapt or become obsolete), increasing complexity (entropy grows unless explicitly fought), and declining quality (without active maintenance, perceived quality drops).
Corrective Maintenance (~21%) — Maintenance to fix defects discovered after delivery — crashes, wrong outputs, performance failures. Triggered by bug reports from users or monitoring alerts. The activity most people think of when they hear "maintenance," but actually only about a fifth of total maintenance effort.
Adaptive Maintenance (~25%) — Maintenance to adapt the software to a changed environment — new operating system, new browser, deprecated library, changed regulation, hardware refresh. Triggered by external changes outside the team's control. Example: migrating a Java 8 application to Java 17, or updating PDF generation after the underlying library changes API.
Perfective Maintenance (~50%) — Maintenance to improve the software — add new features, improve performance, improve usability, refactor for clarity. The largest category of maintenance effort. Triggered by user feedback, business strategy, performance issues. Most "feature work" on shipped products is technically perfective maintenance.
Preventive Maintenance (~4%) — Maintenance to reduce future maintenance cost — refactor god-classes, modernise dependencies, update documentation, remove dead code. Triggered by internal decisions, not external events. Underfunded because nobody celebrates not having a bug, but quietly saves multiples of its cost downstream.
Lientz-Swanson Proportions — The classic 1980 study (and consequent IPU exam favourite) measuring maintenance effort distribution: ~21% corrective, ~25% adaptive, ~50% perfective, ~4% preventive. The single most-cited maintenance-economics statistic.
Modification Request (MR) / Change Request (CR) — The formal record of a requested change — ID, requester, description, business justification, priority. Each MR goes through analysis, design, implementation, testing, and closure. The MR is the unit of maintenance work.
Maintenance Process — The standard sequence for handling a modification request — Request → Analysis → Change Design → Implementation → System Test → Acceptance Test → Delivery → Closure. The maintenance process mirrors a mini-SDLC, applied to a single change.
Impact Analysis — The activity (often part of MR analysis) of predicting which other parts of the system the proposed change will affect. Impact analysis prevents the classic maintenance failure mode of "fix one bug, introduce three more." Tools: dependency analysis, regression test suite, traceability matrix.
Program Understanding (Boehm) — The activity of reading code to figure out what it does before changing it. The single largest maintenance cost — 50–60% of maintenance effort typically goes into program understanding. The strongest economic argument for clean code, good naming, and adequate documentation.
Localisation (Maintenance) — Identifying which modules need to change to satisfy the modification request. High coupling makes localisation hard; high cohesion makes it easy. Modern IDEs (find-usages, call-hierarchy, type-hierarchy) accelerate localisation dramatically.
Re-Validation — Testing performed after a maintenance change to confirm (a) the change works as specified and (b) nothing else has broken. Almost always involves running the automated regression suite.
Software Aging / Software Rot / Bit Rot — The metaphor for how software becomes harder to maintain over time even without source-code changes — its environment changes, its dependencies deprecate, its assumptions break. Bit rot is the consequence of Lehman's laws and is the underlying reason maintenance budgets grow.
Technical Debt (recap) — Ward Cunningham's metaphor for the future cost of suboptimal design decisions taken to meet a short-term need. Like financial debt, technical debt accrues interest in the form of increased maintenance cost. Repaid through preventive maintenance and refactoring.
Maintainability — The ease with which a software system can be modified to correct defects, adapt to environments, add features, or improve quality. Measured by metrics like MTTR, defect backlog, code churn, cyclomatic complexity, maintainability index, technical debt. ISO 25010 lists maintainability as one of its eight quality characteristics.
Maintainability Index (MI) — A composite metric combining Halstead Volume, McCabe Cyclomatic Complexity, LOC, and Comment Ratio to produce a single number (typically 0–100). MI > 65 is considered healthy; below 65 signals refactoring is needed. Tools like SonarQube compute MI automatically.
Legacy Code — Michael Feathers's working definition: "Code without tests" (from Working Effectively with Legacy Code, 2004). A more general definition: code that continues to deliver value but uses outdated technology, lacks documentation, or has long-departed authors. Most enterprise code is legacy by either definition.
Strangler Fig Pattern — Martin Fowler's pattern for incrementally replacing a legacy system with a new one. New functionality is built in the new system; legacy functions are gradually re-implemented; over time the new system "strangles" the legacy until it can be removed. Named after the strangler fig tree that grows around its host until the host dies. Used by Amazon, Etsy, Shopify in their famous monolith-to-microservices transitions.
Sunset / End-of-Life (EOL) — The formal retirement of a software product or version. Sunsetting strategies include phased migration (users move at their pace), parallel run (both systems run side-by-side during transition), strangler fig, and hard cutover (everyone switches on a date). Each has trade-offs in risk and customer experience.
Site Reliability Engineering (SRE) — Google's 2003 discipline that applies software-engineering practices to operations — software engineers run the systems they build, code-driven automation replaces manual ops, SLIs (Service Level Indicators) and SLOs (Service Level Objectives) quantify reliability, and error budgets govern how much risk new features can take. SRE has reshaped how modern teams think about maintenance.
DevOps — The cultural and technical movement that merges development and operations into a unified team and process — shared on-call, infrastructure-as-code, continuous deployment, blameless post-mortems. DevOps blurs the historical SDLC boundary between "development phase" and "maintenance phase."
MTTR (Mean Time To Repair / Recovery) — The average time taken to diagnose and fix a failure (or recover service). Lower is better. Modern DevOps culture often distinguishes MTTR (Repair) — fix the root cause — from MTTR (Recovery) — restore service, which may use a workaround.
Defect Backlog — The count of open, known defects in the issue tracker at any time. A growing defect backlog is the most visible warning sign that maintenance is falling behind feature work.
Code Churn (Maintenance Context) — The volume of code changes in a maintained system, often measured per sprint or per release. Microsoft Research famously correlated high churn with high future defect rates; modern static-analysis tools track churn as a risk signal.
Post-Mortem / Retrospective — A meeting after a production incident or release where the team reviews what happened, what went well, what failed, and what to change. Modern SRE culture emphasises blameless post-mortems — focusing on system improvements rather than individual blame.
---
Study deep
- Maintenance is the iceberg. First-year development cost is the visible 20% above water. The 80% below is the cost of maintaining the software over its lifetime. Design for maintainability from day one.
- The "first 90% / last 90%" rule. Cargill's law applies to maintenance too — feature additions take 10× longer than original estimates because of the existing system's complexity.
- Preventive maintenance is undervalued. Only 4% of effort goes here, but every rupee spent on preventive maintenance saves multiple rupees in future corrective and adaptive maintenance. The economics are clear; the politics are hard (no one celebrates not having a bug).
- DevOps + SRE rethink maintenance. Modern Site Reliability Engineering (Google, 2003) blurs the line between "development" and "operations" — code authors run their own code in production. This forces designs that are maintainable, observable and reliable from the start.
- The end of maintenance. Eventually every system reaches end-of-life — either retired or replaced. Sunsetting strategies: phased migration, parallel run, strangler fig pattern, hard cutover. Each has trade-offs.
PYQ pattern (very common): "Explain types of software maintenance with their proportions." — List the 4 types (corrective, adaptive, perfective, preventive); table with reason and approximate proportion (20-25-50-4); give one example per type.
PYQ pattern: "Describe the software maintenance process." — Diagram the 7 steps (request → analysis → design → implement → system test → acceptance → delivery); mention Boehm's program-understanding cost.