Advanced Software Development

Chapter 13
Software Evolution and Digital Modernization

Bachelors Program in Computer Science Engineering
Advanced Software Development   •   Bachelor

Software Evolution and Digital Modernization

Introduction and Context

Software rarely remains unchanged after its first release. Business rules change, users expect new capabilities, regulations evolve, platforms become obsolete, and security threats increase. Consequently, software engineering is not only the construction of new systems; it is also the disciplined evolution of systems that already provide value.

Software evolution concerns the controlled modification of software throughout its operational life. Digital modernization is the broader organizational and technical effort to improve legacy capabilities, delivery practices, data, infrastructure, and customer experiences through contemporary technologies and operating models. Modernization is therefore not synonymous with replacing old code with fashionable technology. Its purpose is to improve business outcomes while controlling operational, financial, and transition risks.

A central challenge is that older systems often contain valuable, poorly documented knowledge. They may be reliable, deeply integrated, and essential to daily operations, yet difficult to change. Effective engineers must balance continuity and change: preserving useful behavior while reducing cost, risk, and delay.

Learning Objectives

After completing this chapter, a student should be able to:

  1. Distinguish corrective, adaptive, perfective, and preventive maintenance.
  2. Explain refactoring, program comprehension, technical debt, and legacy-system risk.
  3. Select suitable modernization strategies, including replacement, rehosting, replatforming, rewriting, and strangler architectures.
  4. Design a practical modernization roadmap using dependency, value, risk, and readiness information.
  5. Evaluate modernization outcomes using technical, operational, financial, and organizational measures.
  6. Identify governance, ethical, security, privacy, and continuity issues in legacy transformation.

1. The Nature of Software Evolution

Software evolution is the sequence of changes by which a system adapts to new requirements, environments, defects, and quality expectations. It differs from a one-time development project because the existing system, its users, data, interfaces, and operational history constrain every change.

A useful classification of maintenance is:

TypePurposeExample
CorrectiveRemove defects discovered in operationFix an incorrect tax calculation
AdaptiveAdjust to environmental changeSupport a new operating system or regulation
PerfectiveImprove functionality, performance, or usabilityAdd search filters or reduce response time
PreventiveReduce future failure or change costModularize a tightly coupled component

These categories may overlap. Replacing an insecure library can be adaptive, corrective, and preventive at the same time. The classification helps organizations understand why maintenance work is necessary rather than treating all changes as unplanned expense.

Evolution as Feedback

Operational software generates feedback through incidents, telemetry, support requests, security findings, user behavior, and business results. A mature evolution process converts this feedback into prioritized work. A simplified cycle is:

  1. Observe system and business outcomes.
  2. Analyze causes, dependencies, and risks.
  3. Select a change with explicit acceptance criteria.
  4. Implement and verify the change.
  5. Release safely, monitor outcomes, and update system knowledge.

This cycle is strengthened by version control, automated testing, continuous integration, observability, code review, configuration management, and reversible deployment techniques.

2. Program Comprehension

Program comprehension is the process of building a reliable mental and documentary model of an existing system. It is often the first major activity in maintenance because the original design documents may be incomplete or obsolete.

Comprehension Questions

An engineer should investigate:

  • What business capability does the system provide?
  • Which inputs, outputs, data stores, and external interfaces exist?
  • Which components are frequently changed or frequently failing?
  • What assumptions are embedded in code, schemas, batch schedules, and configuration?
  • Which behaviors are contractual, even if undocumented?
  • What are the security, privacy, availability, and regulatory constraints?

Sources of Evidence

No single source is sufficient. Useful evidence includes source code, build files, database schemas, deployment manifests, logs, traces, test suites, incident reports, user interviews, architecture diagrams, API specifications, and version-control history. Executable behavior is especially important: a document may claim that a process works one way while production behavior reveals another.

Static and Dynamic Techniques

Static analysis examines artifacts without executing the program. Examples include dependency analysis, call-graph construction, control-flow inspection, clone detection, complexity measurement, and vulnerability scanning. Dynamic analysis observes execution through logs, tracing, profiling, test instrumentation, and production telemetry.

A practical comprehension process is:

  1. Define the business capability and system boundary.
  2. Establish a safe, reproducible build and execution environment.
  3. Inventory modules, data stores, interfaces, jobs, and external dependencies.
  4. Run representative tests or workflows.
  5. Compare documented architecture with observed dependencies.
  6. Record uncertainty, assumptions, and high-risk unknowns.
  7. Create a living architecture and decision record.

The goal is not to understand every line before making progress. The goal is to understand enough to make a safe, testable decision and then improve understanding iteratively.

3. Technical Debt and Maintainability

Technical debt is the future cost or risk created when a design or implementation shortcut provides short-term benefit but increases later change effort, defects, or operational exposure. The metaphor is useful only when debt is made visible and managed; not every old component is debt, and not every new component is healthy.

Common forms include:

  • Code debt: duplication, unclear names, excessive complexity, and weak tests.
  • Architecture debt: inappropriate boundaries, cyclic dependencies, and shared mutable state.
  • Data debt: inconsistent schemas, duplicate records, undocumented meanings, and poor lineage.
  • Infrastructure debt: unsupported platforms, manual deployment, and obsolete runtime dependencies.
  • Knowledge debt: loss of expertise and undocumented operational procedures.
  • Security debt: unpatched libraries, weak identity controls, and obsolete cryptography.

A simple prioritization model can estimate expected annual loss from a debt item:

Expected Loss = p × I

Here, p is the estimated probability of an adverse event during the chosen period, and I is its impact in consistent units such as currency, downtime hours, or risk score. The model assumes that probability and impact estimates are meaningful and that the same period and unit are used. It is a decision aid, not a precise prediction. A debt item with low probability but catastrophic impact may require treatment even when its expected value is modest.

A broader prioritization score may combine value, urgency, risk reduction, and effort. For example, an organization may rank items using a documented weighted scoring method:

Priority Score = (wv V + wr R + wu U) ÷ E

where V is business value, R is risk reduction, U is urgency, E is estimated effort, and the w terms are agreed non-negative weights. All scores must be normalized before combining them, and the result should support discussion rather than replace professional judgment.

Managing Debt Responsibly

Debt should have an owner, a reason, a review date, and a repayment or containment plan. Teams should distinguish intentional debt, incurred consciously for a time-limited purpose, from accidental debt, created through inadequate design or process. Debt registers are useful when linked to measurable consequences such as change lead time, incident frequency, deployment failure, vulnerability exposure, or support cost.

4. Refactoring

Refactoring is a behavior-preserving transformation of the internal structure of software. “Behavior-preserving” means that, for the specified observable behavior and under stated assumptions, the transformation does not intentionally change externally visible results. Refactoring is not the same as rewriting, redesigning a business process, or adding a feature.

Typical refactorings include:

  • Extracting a method or class.
  • Renaming a misleading identifier.
  • Replacing duplicated logic with a well-defined abstraction.
  • Introducing a seam around an external dependency.
  • Encapsulating a data structure.
  • Splitting a large module along a stable responsibility boundary.
  • Replacing implicit configuration with explicit configuration.

Safe refactoring depends on feedback. A typical workflow is:

  1. State the intended invariant and scope.
  2. Add or improve characterization tests.
  3. Make one small structural change.
  4. Compile, run tests, inspect static checks, and review the diff.
  5. Commit a coherent change.
  6. Repeat while monitoring runtime behavior.

Characterization tests capture current behavior, including behavior that may be accidental. They are valuable in legacy systems, but engineers must decide whether captured behavior is actually a requirement. Tests should therefore be supplemented by domain review.

Refactoring has limits. It cannot by itself solve an unsuitable business process, incompatible data model, unsupported platform, or fundamentally wrong architecture. Large-scale refactoring also creates transition risk if it is performed without deployment discipline and observability.

5. Legacy Systems

A legacy system is an existing system that an organization depends on, especially one that is difficult or costly to change using current practices. “Legacy” does not necessarily mean defective. A decades-old system may be highly reliable, while a new system may already be fragile.

Legacy risk can be assessed across several dimensions:

DimensionQuestions
Business criticalityWhat services fail if this system is unavailable?
ChangeabilityHow difficult is a safe modification?
Technology viabilityAre platforms, tools, and skills still available?
Security and complianceAre vulnerabilities, privacy, or audit obligations unmanaged?
OperabilityCan the system be monitored, recovered, and capacity-planned?
Knowledge concentrationDoes only one person understand essential behavior?
Data and integrationHow many systems depend on its interfaces or records?

A system may be retained, contained, renewed, replaced, or retired. The correct choice depends on evidence rather than age alone.

6. Modernization Strategies and Migration Patterns

Modernization is a portfolio of strategies. Common choices are summarized below.

StrategyDescriptionStrengthMain risk
RetainContinue operating with limited changeLow immediate disruptionRisks and costs may accumulate
RehostMove largely unchanged to new infrastructureFast infrastructure transitionOld design problems remain
ReplatformMake limited changes to use a new runtime or managed serviceModerate improvementHidden compatibility issues
RefactorImprove internal structure without changing purposeBetter maintainabilityRequires tests and domain knowledge
Re-architectChange major structural qualities or boundariesEnables scalability and resilienceHigh complexity and transition risk
RewriteBuild a replacement from scratchPotentially clean designLost behavior and long delivery time
ReplaceAdopt a packaged or external productMay reduce custom maintenanceFit, migration, and vendor risks
RetireRemove unused capabilityEliminates cost and exposureHidden dependencies may be missed

The Strangler Architecture

A strangler architecture gradually replaces parts of a legacy system. A routing or façade layer directs selected capabilities to new services while remaining capabilities continue to use the legacy system. Over time, the new implementation expands and the old implementation contracts until it can be retired.

The pattern generally involves:

  1. Establishing an observable boundary around the legacy system.
  2. Selecting a capability with manageable scope and clear ownership.
  3. Creating an anti-corruption layer or façade that translates models and protocols.
  4. Implementing the capability in the target architecture.
  5. Routing appropriate traffic to the new path.
  6. Comparing results, monitoring failures, and expanding gradually.
  7. Migrating or reconciling data and removing the old path only after evidence supports retirement.

The anti-corruption layer prevents legacy concepts from contaminating the new model. It may translate field names, status codes, authentication conventions, error semantics, and transaction behavior. However, it adds temporary complexity and must itself have a retirement plan.

Other useful patterns include parallel running, branch by abstraction, database replication, event interception, and the strangler façade. Dual writes require particular caution because partial failure can create inconsistent records. Idempotency, reconciliation, audit trails, and carefully defined ownership are essential.

7. Building a Modernization Roadmap

A modernization roadmap converts an architectural aspiration into sequenced, fundable, and governable work.

Step 1: Establish the Case for Change

Document business objectives such as faster product delivery, regulatory compliance, lower outage risk, improved customer experience, or reduced operating cost. Avoid beginning with a technology slogan. A cloud migration, for example, is not automatically modernization if it merely relocates an unmanageable system.

Step 2: Baseline the Current State

Inventory applications, interfaces, data stores, infrastructure, skills, contracts, costs, incidents, recovery objectives, and compliance obligations. Record uncertainty explicitly. Unknown dependencies are a major source of migration failure.

Step 3: Segment the Portfolio

Classify systems by business value, technical health, change frequency, and risk. A simple four-quadrant view is useful:

  • High value, healthy technology: evolve incrementally.
  • High value, unhealthy technology: modernize with strong risk controls.
  • Low value, healthy technology: retain until a business trigger appears.
  • Low value, unhealthy technology: retire or replace quickly, after dependency checks.

Step 4: Select a Pilot

Choose a capability with meaningful value, bounded scope, observable outcomes, and manageable dependencies. A pilot should test architectural assumptions and delivery methods, not merely demonstrate a new tool.

Step 5: Define the Transition Architecture

Specify coexistence boundaries, routing, identity, data ownership, synchronization, failure behavior, rollback, monitoring, and decommissioning criteria. Transition architecture is often more important than the final-state diagram because both old and new systems must operate safely during migration.

Step 6: Sequence the Work

Sequence enabling capabilities first where necessary: automated tests, deployment pipelines, identity integration, observability, data quality controls, and operational runbooks. Deliver vertical slices of business value rather than isolated technical layers whenever possible.

Step 7: Measure and Govern

Useful measures include deployment frequency, lead time for changes, change failure rate, mean time to restore, vulnerability age, availability, response time, cost per transaction, defect escape rate, and user outcome measures. Metrics must be interpreted together. Increasing deployment frequency while increasing severe incidents is not modernization success.

A roadmap should contain decision gates such as: proceed, pause for risk reduction, change strategy, or retire. Governance should include architecture review, security and privacy review, data stewardship, financial controls, and operational readiness.

8. Worked Example: Prioritizing a Modernization Increment

Suppose a team is considering three initiatives. Scores are normalized from 1 to 5. The organization assigns equal weights to value, risk reduction, and urgency. Effort is measured in team-months.

InitiativeVRUE
Replace unsupported payment library3552
Extract customer notification service4334
Rebuild reporting portal5128

Using the stated score:

Priority Score = (V + R + U) ÷ E

The scores are:

  • Payment library: (3 + 5 + 5) ÷ 2 = 6.5
  • Notification service: (4 + 3 + 3) ÷ 4 = 2.5
  • Reporting portal: (5 + 1 + 2) ÷ 8 = 1.0

The payment-library initiative ranks first because it combines high urgency and risk reduction with limited effort. This does not prove that it must be done first: a regulatory deadline, dependency constraint, or lack of testing could alter the decision. The example demonstrates transparent reasoning rather than mechanical prioritization.

9. Illustrative Case Study: Modernizing a University Enrollment Platform

Background

A fictional university operates a twenty-year-old enrollment platform. It handles course registration, fees, prerequisites, and student records. The system is reliable during ordinary periods but becomes difficult to change before each academic term. Its database is shared with reporting applications, and several undocumented batch jobs run overnight.

Problem

Students experience slow registration during peak demand. Developers avoid changes because a modification to prerequisite logic once caused incorrect registration decisions. Only two experienced staff members understand the batch schedules. The platform also uses an unsupported application server.

Analysis

The university first mapped business capabilities, interfaces, batch jobs, data ownership, and peak-load behavior. It found that course search and registration were coupled in the user interface, while fee calculation and student-record updates depended on shared database tables. Logs were incomplete, so the team introduced correlation identifiers and centralized error monitoring before changing critical behavior.

The analysis distinguished three risks:

  1. Operational risk: peak registration overload and weak recovery evidence.
  2. Change risk: undocumented dependencies and insufficient regression tests.
  3. Technology risk: unsupported middleware and scarce specialist knowledge.

Approach

The university selected a strangler strategy rather than an immediate rewrite. It first created a façade for course search, which had relatively clear boundaries and high student value. The new search service used a read-optimized index populated from controlled data feeds; it did not initially become the authoritative source for enrollment.

Next, the team created characterization tests for prerequisite decisions and formalized domain rules with registrar staff. A branch-by-abstraction technique allowed the old and new implementations to be selected through configuration. A small percentage of requests were routed to the new path, and results were compared without changing authoritative records.

The team then modernized registration in vertical slices. Data ownership was explicitly assigned: the enrollment component owned registration status, while the student-record system owned official identity information. Reconciliation reports detected mismatches. Deployment runbooks, rollback procedures, dashboards, and on-call training were required before each expansion.

Outcome

After two academic cycles, course search had moved to the new platform, peak search load no longer overloaded the enrollment application, and the university had documented the previously hidden batch dependencies. Registration logic remained in controlled coexistence while further evidence was collected. The old application server was replaced only after tests and operational monitoring demonstrated compatibility.

The university did not claim success merely because new services existed. It measured response time during peak periods, registration error rates, recovery exercises, change lead time, and user complaints. It retained the legacy system where replacement risk exceeded current benefit.

Learning Points

  • Understanding behavior preceded architectural change.
  • Observability and tests were modernization enablers, not afterthoughts.
  • Data ownership prevented uncontrolled dual writes.
  • A bounded pilot produced evidence for later decisions.
  • Retirement criteria were defined before expanding the replacement.
  • Modernization preserved valuable reliability while reducing change risk.

10. Challenges, Limitations, and Professional Judgment

The Rewrite Fallacy

A rewrite can remove accumulated complexity, but it also discards undocumented behavior, operational lessons, and edge-case handling. Rewrites often underestimate integration, data migration, testing, and parallel-run costs. They are justified when the existing architecture cannot support required outcomes and a safe incremental path is unavailable—not simply because the code is old.

Migration and Data Risk

Data migration involves semantics, quality, history, identifiers, privacy, reconciliation, and rollback. A technically successful transfer may still be wrong if meanings change or records are silently omitted. Migration plans should include profiling, validation rules, sampling, reconciliation totals, access controls, audit evidence, and an explicit authority for resolving discrepancies.

Organizational Constraints

Modernization changes roles and may expose knowledge gaps. Engineers, operations staff, security specialists, domain experts, and users should participate early. Training and succession planning reduce dependence on individual experts. Teams should avoid blaming staff for inherited debt; governance and incentives often created the conditions in which debt accumulated.

Ethical, Security, and Regulatory Issues

Modernization must preserve confidentiality, integrity, availability, accessibility, and accountability. Data minimization and purpose limitation remain important when moving information to new platforms. Sensitive data should be classified, encrypted appropriately, access-controlled, logged, and retained only as required.

AI-assisted code generation may accelerate modernization, but generated code can reproduce defects, insecure patterns, licensing conflicts, or misunderstood business rules. Human review, dependency scanning, tests, provenance records, and restrictions on confidential source code are necessary. AI tools should support comprehension and productivity, not replace accountability for decisions affecting people or regulated records.

Accessibility must be evaluated in modernized interfaces, and automated decisions should be explainable and contestable where they affect students, employees, customers, or citizens. Contracts with cloud and software vendors should address portability, service levels, incident notification, data location, exit assistance, and deletion.

11. Best Practices

  1. Start with business capability and measurable outcomes.
  2. Treat production behavior and domain expertise as evidence.
  3. Establish tests, observability, version control, and reproducible builds early.
  4. Make technical debt visible, owned, prioritized, and reviewable.
  5. Prefer small, reversible, vertically valuable increments.
  6. Define data ownership and reconciliation before coexistence.
  7. Use anti-corruption layers to protect new domain models.
  8. Design rollback and failure handling before deployment.
  9. Include security, privacy, accessibility, and compliance from the beginning.
  10. Define retirement criteria; temporary compatibility layers should not become permanent accidental architecture.
  11. Measure technical and user outcomes together.
  12. Preserve institutional knowledge through documentation, pairing, and runbooks.

Contemporary Developments

Modernization increasingly combines cloud-native deployment, platform engineering, automated delivery, observability, event-driven integration, and infrastructure as code. These practices can improve repeatability and scalability, but they also create new operational complexity and costs. Containerization does not automatically produce good architecture, and microservices may increase distributed-systems failure modes, testing burden, and observability requirements.

Software bills of materials, automated vulnerability management, zero-trust security practices, and stronger supply-chain controls are becoming central to modernization. At the same time, organizations are reconsidering uncontrolled cloud expansion through FinOps, workload portability, and energy-efficiency analysis. The strategic question remains constant: which change improves outcomes enough to justify its technical, organizational, and environmental cost?

Chapter Summary

Software evolution is the disciplined adaptation of operational software, while digital modernization aligns technology, data, delivery, and organizational capability with current business needs. Maintenance may be corrective, adaptive, perfective, or preventive. Program comprehension combines static evidence, dynamic observation, documentation, and domain knowledge to reveal actual behavior and dependencies.

Technical debt represents future cost or risk created by shortcuts and must be made visible, owned, and prioritized. Refactoring improves internal structure while preserving specified behavior, but it cannot solve every architectural or business problem. Legacy systems should be evaluated by criticality, changeability, technology viability, security, operations, knowledge concentration, and data integration—not age alone.

Modernization strategies include retaining, rehosting, replatforming, refactoring, re-architecting, rewriting, replacing, and retiring. Strangler architectures enable gradual replacement through boundaries, routing, translation, observability, and controlled data ownership. A strong roadmap begins with outcomes, baselines the current state, selects evidence-producing pilots, defines transition architecture, sequences enabling work, and measures both technical and user results. Successful modernization is incremental, governed, secure, measurable, and attentive to the value already embedded in existing systems.

Key Terms

Adaptive maintenance: Modification required because the operating environment, platform, or external rules have changed.

Anti-corruption layer: A translation boundary that prevents legacy models or protocols from contaminating a new design.

Characterization test: A test that records observed current behavior of an existing system.

Digital modernization: Strategic improvement of technology, data, processes, and delivery capabilities to achieve contemporary outcomes.

Legacy system: An operational system that an organization depends on and that may be difficult or costly to change.

Maintenance: Post-release modification to correct, adapt, improve, or protect software.

Modernization roadmap: A sequenced plan connecting current-state evidence, target outcomes, transition steps, and governance.

Observability: The ability to infer internal system condition from outputs such as logs, metrics, and traces.

Perfective maintenance: Modification that improves capability, performance, usability, or other desirable qualities.

Preventive maintenance: Modification intended to reduce future defects, risk, or change cost.

Program comprehension: The process of understanding an existing program’s behavior, structure, dependencies, and purpose.

Refactoring: Behavior-preserving restructuring of software’s internal design.

Rehosting: Moving software to a new infrastructure environment with little or no code change.

Replatforming: Adapting software to use a different runtime or managed platform while preserving its main purpose.

Replacement: Substituting an existing system with a packaged or newly acquired product.

Strangler architecture: Incremental replacement in which new implementations gradually take over capabilities from a legacy system.

Technical debt: Future cost or risk created by shortcuts in design, implementation, process, or knowledge.

Transition architecture: The temporary architecture that enables old and new systems to coexist safely during modernization.

Review Questions

5 Short Answer Questions

  1. What distinguishes adaptive maintenance from perfective maintenance?
  2. Why are characterization tests useful when modifying legacy software?
  3. Define technical debt and give two examples.
  4. What is the purpose of an anti-corruption layer?
  5. Why should modernization roadmaps include retirement criteria?

5 Long Answer Questions

  1. Explain how static analysis, dynamic analysis, documentation, and domain expertise contribute to program comprehension.
  2. Compare refactoring, replatforming, rewriting, and replacement, including a risk associated with each.
  3. Describe the stages of a strangler architecture migration and explain the role of routing and data ownership.
  4. Design a modernization roadmap for a business-critical legacy application with poor documentation and unsupported infrastructure.
  5. Discuss how security, privacy, accessibility, and organizational knowledge should influence modernization decisions.

3 Analytical / Application Questions

  1. An organization wants to rewrite a reliable but difficult-to-change billing system. Analyze the conditions under which rewriting is justified and propose a safer alternative if those conditions are absent.
  2. Given several modernization initiatives with different values, risks, urgencies, and efforts, construct a transparent prioritization method and explain its limitations.
  3. Design a coexistence and rollback plan for migrating one capability from a legacy system while both systems handle production traffic.

Multiple Choice Questions with Answers

Question 1

Which maintenance type primarily responds to a change in the operating environment?

A. Corrective maintenance

B. Adaptive maintenance

C. Perfective maintenance

D. Preventive maintenance

Correct Answer: B. Adaptive maintenance

Question 2

What is the main purpose of a characterization test in a legacy system?

A. To replace all business requirements

B. To record observed existing behavior

C. To measure developer productivity

D. To eliminate the need for code review

Correct Answer: B. To record observed existing behavior

Question 3

Which statement best describes refactoring?

A. Replacing a system with a packaged product

B. Moving software to new hardware without code changes

C. Changing internal structure while preserving specified behavior

D. Adding a new business capability without testing

Correct Answer: C. Changing internal structure while preserving specified behavior

Question 4

In a strangler architecture, what normally directs selected requests to the new implementation?

A. A routing or façade layer

B. A compiler optimizer

C. A database backup

D. A static code formatter

Correct Answer: A. A routing or façade layer

Question 5

What is a principal danger of uncontrolled dual writes during migration?

A. Improved data lineage

B. Inconsistent records after partial failure

C. Reduced need for reconciliation

D. Automatic rollback of all transactions

Correct Answer: B. Inconsistent records after partial failure

Question 6

Using Expected Loss = p × I, what is the expected loss when probability is 0.2 and impact is 50,000 currency units?

A. 2,500 currency units

B. 10,000 currency units

C. 25,000 currency units

D. 250,000 currency units

Correct Answer: B. 10,000 currency units

Question 7

Which strategy moves software to new infrastructure with little or no code change?

A. Rehosting

B. Rewriting

C. Retiring

D. Re-architecting

Correct Answer: A. Rehosting

Question 8

Why is an anti-corruption layer used in modernization?

A. To prevent all integration between systems

B. To translate legacy concepts and protect the new model

C. To remove the need for data ownership

D. To guarantee zero downtime

Correct Answer: B. To translate legacy concepts and protect the new model

Question 9

Which item is most important when assessing whether a legacy system should be modernized?

A. Its age alone

B. The programming language alone

C. Business criticality, risk, changeability, and dependencies

D. The number of developers who prefer a new language

Correct Answer: C. Business criticality, risk, changeability, and dependencies

Question 10

Which result would provide the strongest evidence that a modernization initiative is successful?

A. A new technology stack exists

B. The system has more microservices

C. Technical and user outcomes improve without unacceptable risk

D. All legacy code is deleted immediately

Correct Answer: C. Technical and user outcomes improve without unacceptable risk

Advanced Software Development
Chapter 13 of 15