Capstone: Refactoring a Real Codebase for Quality

Clean Code, SOLID & Refactoring

Chapter 10 · Capstone: Refactoring a Real Codebase for Quality

One continuous worked project: TangleMart's order-processing system, genuinely tangled, refactored end to end using every technique from Chapters 1 through 9 — in the order the code's own dependencies actually force, not an arbitrary walkthrough order. Design Patterns' own capstone refactored a tangled function by applying patterns; this one refactors the same kind of tangle by fixing the underlying quality problems patterns are built on top of — naming, purity, parameter design, duplication, SOLID, and the refactoring catalog itself.

BaselineThe Tangled Starting Point

inventory = {'widget': 50, 'gadget': 30} # global mutable state def po(oid, cid, its, ship, disc, pri, exp, addr): # 8 positional params, cryptic names t = 0 for i in its: t += i['price'] * i['qty'] inventory[i['name']] -= i['qty'] # impure mutation buried in the calc loop if disc == 'gold': t = t * 0.9 elif disc == 'platinum': t = t * 0.8 if ship == 'standard': t += 5 elif ship == 'express': t += 15 elif ship == 'overnight': t += 30 return t def print_summary_bad(oid, cid, its, ship, disc, pri, exp, addr): t = 0 for i in its: t += i['price'] * i['qty'] # duplicated - and missing the shipping add entirely if disc == 'gold': t = t * 0.9 elif disc == 'platinum': t = t * 0.8 return f"Order {oid} total: ${t:.2f}"
Verified directly — the duplicated copy had already silently diverged
Before any deliberate refactoring even began, running both functions on the same order revealed po(...) returning $41.00 (subtotal, discounted, plus shipping) while print_summary_bad(...) returned $36.00 — shipping was added to one duplicated copy and never to the other. This is Chapter 8's own duplicated-code finding, discovered in the wild rather than staged.
Verified directly — the impure global mutation breaks on a retried call
Calling the equivalent of po() twice on the identical order (e.g. a retried request after a network blip) mutated inventory twicewidget dropped by 4 instead of 2. This is Chapter 3's exact impurity finding, reproduced.

Step 1Naming (Chapter 2)

po, t, i, oid, its, disc, ship are all renamed to process_order, total, item, order_id, items, discount, shipping before anything else happens — a pure rename, verified producing byte-identical output, exactly Chapter 2's own case for why naming is free to fix and costly to skip.

Step 2Extract Method, Purity & Move Method (Chapters 3, 5, 8)

def calculate_order_total(items, discount, shipping): # pure - no mutation, safe to call any number of times total = sum(i['price'] * i['qty'] for i in items) if discount == 'gold': total *= 0.9 elif discount == 'platinum': total *= 0.8 if shipping == 'standard': total += 5 elif shipping == 'express': total += 15 elif shipping == 'overnight': total += 30 return total def apply_inventory_changes(items, inventory): # the ONLY place that mutates - isolated on purpose for i in items: inventory[i['name']] -= i['qty'] def checkout(items, discount, shipping, inventory): total = calculate_order_total(items, discount, shipping) apply_inventory_changes(items, inventory) # side effect happens exactly once return total
Verified directly — the shared function fixed the divergence and the isolated side effect fixed the retry bug
checkout() and a new print_summary() both call the identical calculate_order_total() and now agree exactly, $41.00 both — resolving the baseline's own $41/$36 divergence. Calling print_summary() three times in a row left inventory completely untouched; a real checkout followed by a safe query-only retry left inventory decremented exactly once.

Step 3Long Parameter List (Chapter 4)

Verified directly — a swapped argument order was silently wrong with positional args, loudly wrong with keyword-only args
Calling the original 8-positional-argument signature with shipping and discount accidentally swapped returned $40.00 instead of the correct $41.00 — no error, no warning, a plausible-looking wrong number. Converting to keyword-only arguments (def calculate_order_total(*, items, shipping, discount)) made the identical mistake, attempted positionally, raise TypeError immediately, before any calculation ran — reproducing Chapter 4's own create_user_bad/create_user_good finding on this exact codebase's own function.

Step 4Replace Conditional with Polymorphism (Chapters 6, 8)

Both if/elif chains — discount and shipping — are replaced with DiscountStrategy and ShippingStrategy hierarchies, reusing the exact class shapes verified in Chapters 6 and 8.

Verified directly — 6 existing strategy classes stayed byte-identical after adding 2 new ones
Adding SilverDiscount and EconomyShipping left NoDiscount, GoldDiscount, PlatinumDiscount, StandardShipping, ExpressShipping, and OvernightShipping all confirmed byte-identical via inspect.getsource()all 6: True. SilverDiscount + EconomyShipping correctly computed $40.00 (40 × 0.95 + 2), matching a hand calculation exactly.

Step 5SOLID: LSP, ISP & DIP (Chapter 7)

class Chargeable: def charge(self, amount): raise NotImplementedError class Refundable: def refund(self, amount): raise NotImplementedError class GiftCardPayment(Chargeable): # only implements what it can actually support def charge(self, amount): return f"Charged ${amount} to gift card" class OrderService: def __init__(self, payment_method: Chargeable): # injected, not hardcoded self.payment = payment_method
Verified directly — the original interface forced a broken refund; segregating it removed the crash entirely
The original single Payment interface forced GiftCardPayment to implement refund(), which raised NotImplementedError: Gift cards can't be refunded the moment code written against the full Payment contract tried to use it — an LSP violation caught in the act. Segregating into Chargeable/Refundable means GiftCardPayment simply never claims to be Refundable (isinstance(GiftCardPayment(), Refundable) is correctly False) instead of lying about it and crashing later.
Verified directly — OrderService's own source stayed unchanged across three different injected payment types
OrderService's source, captured before and after injecting a brand-new CryptoPayment class it had never seen, is confirmed byte-identical — the same dependency-inversion guarantee Software Architecture Fundamentals Chapter 7 verified for PricingEngine, reproduced here for payment methods specifically.

Step 6Debt Prioritization Retrospective (Chapter 9)

Applying Chapter 9's own interest = (severity − 1) × frequency formula to the three duplication/branching-shaped smells actually found in the baseline code, using each chain's own branch count (including the implicit "no match" path) as severity:

SmellSeverityChangesInterest
Shipping if/elif chain4 branches27
Duplicated total calc2 copies12×12
Discount if/elif chain3 branches8
Verified directly — the single Step 4 refactor resolved nearly 3x more interest than the duplication fix
The shipping chain alone (27) outranks the duplication fix's own interest (12), even though duplication was fixed first — a structural necessity, since Step 4's strategy classes needed Step 2's own extracted calculate_order_total to plug into. Combined, both conditional chains fixed together in Step 4 total 35 interest — 2.92× the duplication fix's own 12. The highest-value single step wasn't the one performed first; it was the one the earlier steps had to unlock.

Final Integration Check

Verified end to end — every fixed component working together on one real order
A full order (2× widget, gold discount, standard shipping) run through the fully assembled system: pre-checkout print_summary() reports $41.00 with zero inventory mutation; checkout() via an injected CreditCardPayment charges the identical $41.00 and decrements inventory exactly once; two further print_summary() calls leave inventory unchanged; and swapping in a brand-new StoreCreditPayment — never seen by OrderService before — correctly charges the same order with zero changes to OrderService's own source. Every number matches the original baseline's own correct total, and every bug the baseline exhibited is now structurally impossible, not just fixed by coincidence.

What This Course Doesn't Cover

  • Automated refactoring tooling (IDE-assisted extract/rename, static analysis linters) — this course covered the underlying judgment, not any specific tool
  • Language-specific idioms beyond Python's own conventions used throughout
  • The full Gang-of-Four pattern catalog — that's Design Patterns' own territory, reused here only where a pattern (Strategy) was the direct destination of a refactor
  • Formal code review process, team conventions, or style-guide enforcement — reserved for the still-outstanding Software Development Lifecycle course
  • Performance profiling or optimization — a clean design and a fast one are different concerns, covered by Technical Support's own diagnostic courses instead

Where This Connects

This capstone's techniqueDirect connection
Extract Method resolving a duplicated, diverged calculationChapter 8, and Design Patterns' own Strategy chapter — the same shape of fix, one course apart
Injected payment dependency, OrderService source unchanged across 3 typesSoftware Architecture Fundamentals Chapter 7's own ports-and-adapters finding, reproduced at class scale
Debt-interest ranking justifying which refactor mattered mostChapter 9's own formula, applied retrospectively to a real, not hypothetical, codebase
Pseudocode & Algorithmic Problem-Solving's own decomposition disciplineThe six-step refactor sequence itself — breaking one tangled function into independently verifiable pieces

Hands-On Exercises

Exercise 1

Add a fourth smell to this chapter's own Step 6 ranking table: the original 8-positional-parameter signature from Step 3, treating "adjacent same-typed parameters that could be silently swapped" (2: shipping/discount) as severity, changed 6 times over the same period. Compute its interest and determine where it lands in the full four-item ranking.

📄 View solution
Exercise 2

Add a PlatinumDiscount-equivalent tier to this chapter's own final integrated system — a LoyaltyDiscount class applying a 15% discount — and verify all pre-existing discount classes (NoDiscount, GoldDiscount) stay byte-identical, and that a full checkout using the new tier produces the correct total.

📄 View solution
Exercise 3

Add a second concurrent order to this chapter's own final integration check — a different item set, different discount and shipping strategies, checked out through the same OrderService instance used for the first order. Verify both orders' totals are correct and independent, and that inventory reflects both orders' own deductions correctly.

📄 View solution

Chapter 10 Quick Reference — Course Summary

  • Verified end to end: a genuinely tangled order processor, refactored in 6 dependency-ordered steps, each directly reusing a specific prior chapter's own verified technique
  • Step 2 fixed a real divergence: $41.00 vs $36.00 in the baseline, both agreeing at $41.00 after Extract Method
  • Step 3 turned a silent wrong answer into a loud error: $40.00 silently vs. an immediate TypeError
  • Step 4 verified 6 strategy classes byte-identical after 2 real extensions
  • Step 5 verified an LSP violation caught in the act, then fixed via ISP segregation and DIP injection, OrderService staying byte-identical across 3 payment types
  • Step 6 verified the highest-interest fix (27) wasn't the one performed first — it was the one the earlier steps had to unlock
  • Course complete: naming, purity, function design, code smells, SOLID, the refactoring catalog, and technical debt — all ten chapters, verified throughout