Week 13 Lesson
Refactoring, Code Smells, and Technical Debt
Improve design without changing external behavior.
Learning Objectives
- Identify common code smells.
- Plan safe refactoring steps.
- Explain technical debt without drama.
- Use tests and small commits to reduce refactor risk.
Lecture Notes
Refactoring means improving internal structure without changing external behavior. It is not rewriting from scratch. It is not adding features. It is disciplined cleanup that keeps the program working while making future work easier. Good refactoring is usually done in small safe steps.
Code smells are warning signs. A long method may be fine once, but it often hides multiple responsibilities. A god class knows too much and does too much. Shotgun surgery means one small feature requires tiny edits across many files. Feature envy means a method seems more interested in another object’s data than its own.
Technical debt is the future cost of today’s shortcuts. Not all debt is irresponsible. Sometimes teams take debt intentionally to meet a deadline or learn quickly. The danger is pretending debt does not exist. Honest teams track debt, explain its impact, and pay it down when the cost of carrying it becomes too high.
Safe refactoring depends on feedback. Tests are the strongest feedback, but careful manual checks, small commits, and code reviews also help. A useful refactor process is: lock behavior with tests, make one structural change, run tests, commit, repeat. Large secret rewrites often fail because they change too many things at once.
Students should learn to refactor toward better names, smaller functions, clearer boundaries, and explicit dependencies. The goal is not aesthetic perfection. The goal is to reduce risk and make the next change easier.
Worked Example: Extracting a method to reveal intent
function printInvoice(order: Order) {
let total = 0;
for (const item of order.items) {
total += item.price * item.qty;
}
if (order.customer.type === 'student') {
total = total * 0.9;
}
console.log('Invoice total: ' + total);
}function calculateSubtotal(order: Order): number {
return order.items.reduce((sum, item) => sum + item.price * item.qty, 0);
}
function applyCustomerDiscount(total: number, customer: Customer): number {
return customer.type === 'student' ? total * 0.9 : total;
}
function printInvoice(order: Order) {
const subtotal = calculateSubtotal(order);
const total = applyCustomerDiscount(subtotal, order.customer);
console.log('Invoice total: ' + total);
}Lab: Refactor Safely
Scenario: You receive a working but messy invoice system.
Steps
- Write or identify expected behavior.
- Find at least five code smells.
- Choose one smell to refactor first.
- Make small changes and verify behavior after each step.
- Write a technical debt note.
Deliverables
- Code smell list
- Refactored code
- Test/check evidence
- Technical debt note
Assignment
Write a refactoring plan for your capstone. Include what you would fix first and why.
Discussion Prompts
- When is rewriting better than refactoring?
- How can technical debt be intentional?
- What makes a refactor risky?
Week 13 Quiz
Use these as quick checks after the lesson.
Question 1
Refactoring means:
Question 2
A code smell is:
Question 3
Shotgun surgery means:
Question 4
Technical debt is:
Question 5
Safe refactoring usually uses:
Student Notes
Saved in this browser only.