1. What is legacy code?
1.1. Definitions.
1.2. Value in legacy code.
1.3. Legacy code as a business problem.
1.4. The human cost of legacy code.
1.5. Legacy code can be beneficial for our career.
2. Technical debt prioritization.
2.1. Technical debt.
--- 2.1.1. Original metaphor, inclusive definition and classifications.
--- 2.1.2. Costs: principal, recurring interest and accrued interest.
--- 2.1.3. Technical debt lifeline.
2.2. Prioritization.
--- 2.2.1. Continuous inspection.
--- 2.2.2. Technical debt contingency.
--- 2.2.3. Code behavioral analysis.
--- 2.2.4. Hotspots analysis.
--- 2.2.5. Product Hurricane Maps.
--- 2.2.6. Change Coupling and implicit dependencies analysis.
--- 2.2.7. Sum of Coupling (SoC) analysis.
--- 2.2.8. Combining analyses: Hotspots, Change Coupling and SoC.
3. Evolving legacy code: techniques.
3.1. Value in legacy code: behaviour.
3.2. Types of changes.
3.3. Protecting behaviour.
3.4. Cover & Modify.
3.5. Testability problems <=> Poor design.
4. Introducing tests in untestable code.
4.1. Problematic dependencies.
4.2. Dependency-breaking techniques.
--- 4.2.1. Reasons.
--- 4.2.2. Seam model.
--- 4.2.3. Object seams.
--- 4.2.4. Basic techniques.
--- 4.2.5. Techniques for static dependencies and Singletons.
--- 4.2.6. Shortcuts.
5. Testing strategies in legacy code.
5.1. Types of tests.
5.2. Advantages and disadvantages of each type of test.
5.3. Test distribution: goals, trade-offs and alternatives.
5.4. Testing pyramid in legacy code?
5.5. Proposed strategy.
6. Characterization tests.
6.1. Characterizing legacy code.
6.2. Structural Testing.
--- 6.2.1. Using coverage tools.
--- 6.2.2. Heuristics and criteria for selecting relevant inputs.
--- 6.2.3. Coverage criteria.
--- 6.2.4. Boundary value analysis.
6.3. Mutation Testing: concept, tools and practical use.
7. Finding testing points.
7.1. Analysing the propagation of the effects of a change.
7.2. Points from which to test.
--- 7.2.1. Interception points.
--- 7.2.2. Pinch points.
7.3. Distance from which to test and test scope.
8. Other ways of characterizing legacy code.
8.1. Golden Master + Sampling.
8.2. Approval Testing.
--- 8.2.1. Combinatorics & Approval Testing.
9. Relationship between lack of cohesion and testability.
9.1. Analysis of different cases.
--- 9.1.1. Cohesive code.
--- 9.1.2. Lack of cohesion due to divergent change (hotspots).
--- 9.1.3. Lack of cohesion due to shotgun surgery (change coupling).
10. Making changes: TDD in legacy code.
11. Making changes: shortcuts when there is no time to cover and modify.
11.1. Sprouting.
11.2. Wrapping.
12. Incremental rewrites.
12.1. Why incremental rewrites?
12.2. Branch By Abstraction.
12.3. Strangler Fig Application.
12.4. Testing rewrites in production with experiments.
13. Refactoring legacy code.
13.1. Refactoring flows.
13.2. Goals and strategies.
13.3. Refactoring strategies according to DDD subdomains.
13.4. Refactorings that improve testability and productivity.
--- 13.4.1. Separating infrastructure from business logic.
--- 13.4.2. Improving cohesion.
14. Introducing DDD in legacy code.
14.1. Motivation.
14.2. Useful patterns.
--- 14.2.1. Bubble Context.
--- 14.2.2. Autonomous Bubble.
--- 14.2.3. Exposing legacy assets as services.
15. Refactoring techniques for hotspots.
15.1. How does a hotspot form?
15.2. Heuristics for identifying responsibilities.
15.3. How to split a hotspot into more cohesive classes?
--- 15.3.1. Approach in Working Effectively with Legacy Code.
--- 15.3.2. Splinter Pattern.
--- 15.3.3. Approach in Object-Oriented Reengineering Patterns.
16. Object orientation to improve legacy code.
16.1. Applying design patterns to simplify legacy code.
--- 16.1.1. Cross-cutting concerns.
--- 16.1.2. Separating the main task from associated secondary tasks.
--- 16.1.3. Byzantine business rules.
--- 16.1.4. Conditional code.
--- 16.1.5. Procedural substitutes for polymorphism.
--- 16.1.6. Suitable interfaces for stable legacy code.
16.2. Code smells that harm or inhibit object orientation.
17. Refactoring techniques for inheritance-based seams.
17.1. Moving an inheritance-based seam to a delegate.
17.2. Introducing dependency injection.
18. Course closure: navigation maps.
18.1. Overview: topics explored and yet to explore.
18.2. Changing perspectives on legacy code.