Day 22 / 25 Clean Code, Refactoring & Code Review 0/0 exercises Exercises ↓

AmouAI Hub/Courses/Programming Fundamentals/Day 22

Week 5 · Craft, Comparison & Capstone · Day 22

Clean Code, Refactoring & Code Review

Readability as a feature. A deliberately ugly 200-line program, refactored live, plus the Git and review workflow around it.

Study time
4 hours
Reading
Focus
smells · moves · review

By the end of today you can

  1. Name eight code smells on sight
  2. Apply the refactoring moves that fix each one
  3. Refactor in small steps with tests green the whole way
  4. Write a commit message a stranger could act on
  5. Open a pull request that is pleasant to review
  6. Give review feedback that is specific and kind
  7. Receive review feedback without taking it personally

Today's videos

Watch each video, then work the matching sections below. Watching alone will not do it.

22A
Smells & Refactoring Moves (120 min)
Eight smells on sight · the move that fixes each · a comment explaining what is a function name in disguise · one move, run the tests, commit · when not to refactor.
22B
The 200-Line Refactor, Live (120 min)
A deliberately ugly program taken apart in committed steps · branches and git add -p · commit messages that say why · a pull request worth reviewing · giving and receiving feedback.

1Code smells

Not bugs. Signals.

A smell is not a rule violation — it is something that is usually a symptom of a deeper problem. The value is in noticing, not in obeying.

SmellLooks likeUsually fixed by
Long functionOver ~30 lines, or needs section commentsExtract function
Long parameter list5+ parametersIntroduce an object
Duplicated codeThe same shape twiceExtract function
Magic number* 0.15 with no nameExtract constant
Deep nestingFour levels of indentGuard clauses, extract
Comment explaining what# add 1 to totalRename, then delete the comment
Feature envyA method mostly using another object's dataMove the method
Primitive obsessionstr for money, tuple for a pointMake a small class
The smell that outranks the rest

**A comment that explains what the code does is a function name in disguise.** Take the lines the comment covers, extract them into a function, and name the function what the comment said. The comment disappears and the code improves. This is Day 6's "name an idea" arriving as a mechanical procedure.

Count what changed: single-letter names got meanings, 0.15 and 0.08 became named constants, three levels of nesting collapsed into a filter, i[1] and i[2] became o.amount and o.is_active, and the rate decision moved into its own named function. The behaviour is identical.

2The refactoring moves

Small, named, reversible.

MoveWhat you doWhen
Extract functionLift a block into a named functionThe block needs a comment
Inline functionReplace a call with its bodyThe name adds nothing
RenameChange a name to say what it meansYou hesitated while reading it
Extract constantReplace a literal with a named valueA magic number appears
Introduce parameter objectGroup parameters into a classFive+ parameters, or they travel together
Replace conditional with polymorphismOne class per branchA type-checking if-chain
Guard clauseReturn early on the awkward caseDeep nesting
The discipline that makes this safe

One move, run the tests, commit. Not five moves and a hopeful run. If the tests go red after a single small move, you know exactly what caused it and git checkout costs you thirty seconds. This is the same binary-search instinct from Day 5 and the same diff rule from Day 6.

Refactoring requires tests. Otherwise it is just editing.

Without a test suite you cannot tell restructuring from breaking. That is why Day 15 and Day 21 came first — and it is why "we will add tests later" so often means "we will stop being able to change this safely".

When not to refactor

  • While adding a feature. Do one, commit, then do the other. A diff that mixes them cannot be reviewed.
  • Code nobody touches. Ugly and stable beats clean and freshly broken.
  • Without tests, unless you write characterisation tests first.
  • On a deadline, unless the mess is what is slowing you down — which it often is.

3Git and review

The part of programming that is about other people.

terminal
git switch -c refactor/extract-tax-rate   # a branch per change

git add -p                                # stage in pieces, review as you go
git commit -m "Extract rate_for() from total_tax"

git push -u origin refactor/extract-tax-rate

Commit messages

The rule for the body

The diff already shows what changed. Your message exists to record why — the thing that is otherwise lost forever. Same principle as comments on Day 5.

Reviewing

Instead ofWrite
"This is wrong.""This returns None when items is empty — should it raise instead?"
"Bad naming.""d took me a moment. discount_rate?"
"Why did you do this?""What was the reason for the second loop? I might be missing something."
"Add tests.""Could we add a test for the empty case? That is the one I would break."
Two rules that make review work

As the reviewer: review the code, never the person. Say what you observed and what you would prefer, and ask rather than assert when you might be wrong. As the author: your code is not you. A reviewer finding a bug has done you a favour that would otherwise have been done by a user. The correct response to good feedback is "good catch", not a defence.

A pull request worth reviewing

  • Small. 400 lines is a real review; 4,000 is a rubber stamp.
  • One concern. Refactor or feature, never both.
  • Green. Tests pass before you ask anyone to look.
  • Described. What, why, and how you tested it.
  • Self-reviewed. Read your own diff first — you will find something every time.

>_Python playground

A real Python interpreter running inside your browser. Nothing is installed, nothing is uploaded, nothing can break.

scratch.pypython not loaded
Values for input(), comma separated →
Output appears here. The first run takes a few seconds while Python loads.

Exercise set

Checked automatically the moment you submit. Work top to bottom — each one assumes the last. Your answers are saved in this browser.

All Warm-up Core Challenge Reset day

Day 23 — Comparative Case Study + Capstone Kickoff

One application, built twice — and the capstone design document.

Continue →