11---
22title : Working Effectively with Legacy Code
3- subtitle : Chapter 6 – I Need to Make a Change. What Can I Do?
3+ subtitle : Chapter 6 - I Dont Have Much Time and I Have to Change It
44...
55
66# Pre-work
77
88- Book : *Working Effectively with Legacy Code* by Michael Feathers
9- - Focus : Chapter 6 change techniques
10- - Optional : <https://michaelfeathers.silvrback.com/the-sprout-method>
11-
12- # Chapters
13-
14- :: : columns
15-
16- ::: : column
17-
18- | Chapter | Time |
19- | ---------------------------| -------- |
20- | Warmup | 00:00:00 |
21- | Sprout Method | 00:05:00 |
22- | Sprout Class | 00:15:00 |
23- | Wrap Method | 00:25:00 |
24-
25- ::: :
26-
27- ::: : column
28-
29- | Chapter | Time |
30- | ---------------------------| -------- |
31- | Wrap Class | 00:35:00 |
32- | Strategy Comparison | 00:45:00 |
33- | Summary & Q&A | 00:55:00 |
34-
35- ::: :
36-
37- :: :
9+ - Focus : Chapter 6: I Dont Have Much Time and I Have to Change It
3810
3911# Timetable
4012
41- | Activity | Time |
42- | ----------------------------| ------ |
43- | Warmup & Goals | 5 min |
44- | Sprout Method & Class | 20 min |
45- | Wrap Method & Class | 20 min |
46- | Compare & Discuss | 5 min |
47- | Summary & Q&A | 10 min |
13+ | Activity | Time |
14+ |-----------------------|--------|
15+ | Greetings, Warmup | 5 min |
16+ | Sprout Method & Class | 15 min |
17+ | Exercise 1 | 15 min |
18+ | Wrap Method & Class | 15 min |
19+ | Exercise 2 | 15 min |
20+ | Summary | 10 min |
21+ | Closing | 5 min |
4822
4923# Warmup
5024
@@ -62,37 +36,87 @@ Use this to establish mental models and prepare learners to explore change-based
6236- Call the new method from existing one
6337- No edits to original logic
6438
65- # # Example
39+ # Legacy Code Example
6640
6741` ` ` python
68- def charge(customer):
69- return new_charge_logic(customer)
42+ class VehicleLogger:
43+ def log_trip(self, vehicle_type, distance_km, fuel_used_liters):
44+ print(f"Trip: {distance_km} km")
45+ if vehicle_type == "gasoline":
46+ efficiency = distance_km / fuel_used_liters
47+ print(f"Fuel efficiency: {efficiency:.2f} km/l")
48+ elif vehicle_type == "electric":
49+ efficiency = distance_km / fuel_used_liters # misuse of field
50+ print(f"Energy efficiency: {efficiency:.2f} km/kWh")
51+ ` ` `
7052
71- def new_charge_logic(customer):
72- # New behavior
73- return 42
53+ # Improved Code Example
54+
55+ ` ` ` python
56+ class VehicleLogger:
57+ def log_trip(self, vehicle_type, distance_km, fuel_or_energy_used):
58+ print(f"Trip: {distance_km} km")
59+ self._log_efficiency(vehicle_type, distance_km, fuel_or_energy_used)
60+
61+ def _log_efficiency(self, vehicle_type, distance_km, amount_used):
62+ if vehicle_type == "gasoline":
63+ efficiency = distance_km / amount_used
64+ print(f"Fuel efficiency: {efficiency:.2f} km/l")
65+ elif vehicle_type == "electric":
66+ efficiency = distance_km / amount_used
67+ print(f"Energy efficiency: {efficiency:.2f} km/kWh")
7468` ` `
69+ \note{
70+ Benefits :
71+ Isolated new behavior (_log_efficiency) → easier to test
72+ Minimal change to existing method → reduced risk
73+ Future changes (e.g., hybrid logic) can be added safely to the new method
74+ }
7575
7676# Sprout Class
7777
7878- Create a new class for new behavior
7979- Keeps old logic intact
8080- Ideal for complex changes needing state
8181
82- # # Example
82+ # Legacy code Example
8383
8484` ` ` python
85- def calculate_invoice(cust) :
86- return InvoiceCalculator(cust).run()
87-
88- class InvoiceCalculator :
89- def __init__(self, customer):
90- self.customer = customer
91- def run(self) :
92- # New logic here
93- pass
85+ class VehicleLogger :
86+ def log_trip(self, vehicle_type, distance_km, fuel_used_liters):
87+ print(f"Trip: {distance_km} km")
88+ if vehicle_type == "gasoline" :
89+ efficiency = distance_km / fuel_used_liters
90+ print(f"Fuel efficiency: {efficiency:.2f} km/l")
91+ elif vehicle_type == "electric" :
92+ efficiency = distance_km / fuel_used_liters
93+ print(f"Energy efficiency: {efficiency:.2f} km/kWh")
9494` ` `
9595
96+ # Improved code Example
97+
98+ ` ` ` python
99+ class VehicleLogger:
100+ def log_trip(self, vehicle_type, distance_km, fuel_or_energy_used):
101+ print(f"Trip: {distance_km} km")
102+ if vehicle_type == "electric":
103+ EVLogger().log_efficiency(distance_km, fuel_or_energy_used)
104+ elif vehicle_type == "gasoline":
105+ efficiency = distance_km / fuel_or_energy_used
106+ print(f"Fuel efficiency: {efficiency:.2f} km/l")
107+
108+ class EVLogger:
109+ def log_efficiency(self, distance_km, energy_kwh):
110+ efficiency = distance_km / energy_kwh
111+ print(f"Energy efficiency: {efficiency:.2f} km/kWh")
112+ ` ` `
113+ \note{
114+ Benefits :
115+ New behavior is isolated in EVLogger
116+ We avoid changing or bloating the legacy method with EV-specific logic
117+ EVLogger is easy to test independently
118+ }
119+
96120# Wrap Method
97121
98122- Create a method that wraps (delegates to) the old method
@@ -173,8 +197,8 @@ public:
173197};
174198
175199int main() {
176- std::unique_ptr<Coffee> coffee = std::make_unique<Coffee>();
177- MilkDecorator decoratedCoffee (std::move(coffee));
200+ auto coffee = std::make_unique<Coffee>();
201+ MilkDecorator decorated_coffee (std::move(coffee));
178202 decoratedCoffee.cost();
179203}
180204` ` `
0 commit comments