Module 3: Clean Code: Case Studies
These cases make readability observable through names, structure, tests, and review comments.
Case Study 1: Names That Hide Intent
Scenario: A function called process(data) takes customer records, removes inactive accounts, normalizes email addresses, and returns billing contacts. New learners cannot tell which part failed.
Source anchor: Google Python Style Guide.
Module concepts:
- intent-revealing names
- single responsibility
- small functions
- reviewability
Wrong Approach
Add comments above vague code while leaving the names unchanged.
Better Approach
Rename around intent: active_customers, normalize_email, billing_contacts. Split unrelated transformations and make each function's input/output clear.
Tradeoff Table
| Choice | Gain | Cost |
|---|---|---|
| Vague names | Fast typing | Slow reading |
| More precise names | Clear intent | Requires domain understanding |
| Comments only | Quick explanation | Can drift from code |
Failure Mode
A bug fix changes the wrong part of the workflow because the function name hides the real responsibility.
Required Artifact
Produce a before/after naming table with old name, problem, new name, and reason.
Project / Capstone Connection
Use the naming table in later code reviews so you can justify refactors with evidence instead of taste alone.
Case Study 2: Deeply Nested Validation
Scenario: A signup function has five nested if statements for email, password, age, terms acceptance, and invite code. Error handling is duplicated across branches.
Source anchor: Google Python Style Guide.
Module concepts:
- guard clauses
- control-flow clarity
- error messages
- focused tests
Wrong Approach
Indent more carefully and hope formatting makes the logic clear.
Better Approach
Use guard clauses for invalid inputs, return specific errors, and keep the success path visible. Add tests for each validation rule and one happy path.
Tradeoff Table
| Choice | Gain | Cost |
|---|---|---|
| Nested conditionals | Keeps one block | Hard to scan |
| Guard clauses | Clear failure paths | Multiple exits |
| Validation object | Reusable rules | More abstraction |
Failure Mode
An error message from the wrong branch confuses users and support.
Required Artifact
Write a validation decision table with input condition, expected error, and test name.
Project / Capstone Connection
Apply this table format to later API validation, CLI parsing, and form handling so correctness stays visible as systems grow.
Case Study 3: Test Names as Documentation
Scenario: A beginner test suite contains test1, test2, and test_error. When a test fails, nobody knows which behavior changed.
Source anchor: Google Python Style Guide.
Module concepts:
- readable tests
- behavior naming
- arrange-act-assert
- regression capture
Wrong Approach
Add more assertions to the same vague tests.
Better Approach
Name tests by behavior: rejects_password_shorter_than_minimum, normalizes_email_before_lookup. Structure each test so setup, action, and assertion are obvious.
Tradeoff Table
| Choice | Gain | Cost |
|---|---|---|
| Vague test names | Quick writing | Poor failure signal |
| Behavior names | Self-documenting | Longer names |
| One giant test | Less setup | Hard failure diagnosis |
Failure Mode
A regression is detected but not understood, so the fix is slow and risky.
Required Artifact
Rewrite five test names and add one sentence explaining the behavior each protects.
Project / Capstone Connection
Carry this test-naming standard into every later project so failing tests explain behavior regressions without needing the original author.
Source Map
| Source | Use it for |
|---|---|
| Google Python Style Guide | Readability, naming, and maintainability anchors. |