5 exercises — Practice the vocabulary engineers use when discussing code smells, refactoring techniques, legacy migration patterns, and technical debt.
Core refactoring vocabulary clusters
Code smells: Long Method, Large Class, Primitive Obsession, Feature Envy, Dead Code, bit-rot
Refactoring moves: Extract Method, Rename, Move, Inline, Pull Up
Migration patterns: strangler fig, Branch by Abstraction, seam
Debt concepts: technical debt, debt quadrant, Boy Scout Rule
0 / 5 completed
1 / 5
A tech lead reviews a pull request and leaves this comment: "This method is 180 lines long and handles validation, pricing, discount logic, persistence, and email notification. It has seven parameters and three nested loops. This is a classic code smell — specifically a Long Method combined with Feature Envy."
Which statement best describes what a code smell is?
Code smell (Kent Beck / Martin Fowler): a surface indication that something might be wrong with the code's design. The code may run perfectly — a smell is not a bug. It signals structural problems that raise the cost of future changes.
Key smells from the passage: Long Method — a method doing too many things; fix with Extract Method. Feature Envy — a method that uses data from another class more than its own; fix with Move Method. Other common smells: Large Class (God Class) — violates Single Responsibility. Primitive Obsession — using raw strings/ints where a domain object would be clearer. Dead Code — unreachable code that should be removed. In a code review: "I'm not raising a bug here — it's a smell. The method still works, but it will get harder to change as requirements evolve."
2 / 5
Fill in the blank. A senior engineer explains each refactoring move to a junior: "When a method is too long, I use ___ to pull a cohesive block of code out into its own well-named method. When a name no longer reflects the intent, I use Rename. When a method belongs in a different class, I use Move. When a method in a subclass is also needed by sibling classes, I use Pull Up to move it to the superclass."
Which refactoring technique fills the blank?
Extract Method: take a section of code, give it a meaningful name, and move it into its own method. Replace the original fragment with a call. This is the most frequently applied refactoring.
The full catalogue from the passage: Rename — the cheapest, highest-value refactoring; improves readability immediately. Move — relocate a method or field to the class that uses it most (fixes Feature Envy). Pull Up — move shared behaviour from subclasses to the superclass (eliminates duplication). Inline — the inverse of Extract Method; use when a method's body is as clear as its name and the indirection adds no value. Rule of thumb: if you need a comment to explain a block of code, that block is a candidate for Extract Method — name it instead.
3 / 5
An architect explains a migration strategy in a design meeting: "We cannot rewrite the monolith in one go — it's too risky. Instead we'll use the strangler fig pattern. We place a proxy in front of both systems. New functionality goes straight to the new service. As we migrate each domain, we flip the routing. Eventually the monolith handles zero traffic and we decommission it. An alternative for library replacements is Branch by Abstraction: introduce an abstraction over the old library, implement the new one behind it, then switch atomically."
What does the strangler fig pattern primarily achieve?
Strangler fig pattern (Martin Fowler, 2004 — named after a tropical fig that grows around a host tree): incrementally replace a legacy system by routing traffic to a new implementation one domain at a time. The old system keeps running until its traffic reaches zero, at which point it can be safely decommissioned. Each migration step ships to production independently, giving continuous feedback and a rollback path.
Branch by Abstraction: create an abstraction (interface) over the component you want to replace, implement the new component behind it, then switch the implementation reference. Used for framework or library migrations within a single codebase. Seam (Michael Feathers): a point in code where you can change behaviour without modifying the code itself — e.g. an injection point, an interface boundary. Seams are what make both patterns possible.
4 / 5
Match the definition. An engineering manager introduces the concept to a new team member: "We track what Ward Cunningham called technical debt. It's not about messy code per se — it's an economic metaphor. Every shortcut taken creates a liability. The liability has a principal (cost to fix) and interest (ongoing slowdown). Cunningham's debt quadrant helps us categorise it: was the debt deliberate or inadvertent? Was it prudent or reckless?"
Which definition best matches Fowler's debt quadrant?
Technical debt quadrant (Martin Fowler): two axes — how the debt was created (Deliberate vs Inadvertent) and how damaging it is (Reckless vs Prudent).
Four quadrants: Deliberate + Prudent — "We must ship now; we'll deal with the consequences later." Conscious trade-off with a repayment plan. Deliberate + Reckless — "No time for design." Knowingly accrues debt with no plan. Inadvertent + Prudent — "Now we know what we should have done." Learning through building — healthy. Inadvertent + Reckless — "What is layering?" Pure ignorance; the most dangerous because the team doesn't know what they don't know. Related: bit-rot — the gradual degradation of software quality over time as the surrounding ecosystem (OS, libraries, frameworks) evolves while the code stays static. Not a deliberate decision — it simply accrues through inaction.
5 / 5
Fill in the blank. A senior engineer describes a cultural practice to an onboarding developer: "We follow the ___: every time you open a file, leave it slightly better than you found it. Rename an unclear variable. Extract a helper method. Delete a dead code path. It's not a refactoring sprint — it's continuous, low-risk improvement. Over months, the files we touch most become noticeably cleaner."
Which practice fills the blank?
Boy Scout Rule (Robert C. Martin — "Uncle Bob"): "Always leave the campground cleaner than you found it." Applied to software: each time you open a file, make one small improvement beyond your immediate task. No approval required; no refactoring sprint needed. The key properties: low risk per change (small scope, easy to review, easy to revert), compounding benefit (frequently touched code improves fastest), no dead code accumulates. What counts: renaming an unclear variable, extracting a named method, removing a dead code block, adding a missing edge-case test. Contrast with bit-rot — the Boy Scout Rule is the antidote; without it, code entropy naturally increases over time as surroundings change but the code does not.