Design Smells and Refactoring Patterns in OOP Python¶
Page Maps¶
graph LR
family["Python Programming"]
program["Python Object-Oriented Programming"]
section["Resources Failures Safe Evolution"]
page["Design Smells and Refactoring Patterns in OOP Python"]
capstone["Capstone evidence"]
family --> program --> section --> page
page -.applies in.-> capstone
flowchart LR
orient["Orient on the page map"] --> read["Read the main claim and examples"]
read --> inspect["Inspect the related code, proof, or capstone surface"]
inspect --> verify["Run or review the verification path"]
verify --> apply["Apply the idea back to the module and capstone"]
Read the first diagram as a placement map: this page is one concept inside its parent module, not a detached essay, and the capstone is the pressure test for whether the idea holds. Read the second diagram as the working rhythm for the page: name the problem, study the example, identify the boundary, then carry one review question forward.
Purpose¶
Build a shared vocabulary for recognizing and fixing design problems.
This core catalogs common smells and pairs them with refactoring moves that we have already developed across Modules 1–5.
1. Smells: What to Look For¶
Common OOP Python smells:
- God object: one class knows/does everything.
- Feature envy: one method manipulates another object’s data heavily.
- Anemic domain: domain objects are data bags; logic lives in services.
- Primitive obsession: raw
str/int/floatcarry domain meaning (M02C14). - Boolean flags / state soup: many flags represent lifecycle (M03C28).
- Tangled dependencies: circular imports, infrastructure inside domain (M04C39).
- Hidden side effects: properties that do I/O (M03C22).
- Leaky resources: missing cleanup boundaries (M05C41–M05C43).
2. Refactoring Moves (Patterns You Can Apply)¶
High-leverage moves:
- Introduce semantic types (Module 2).
- Introduce aggregate roots for invariants (M04C31–M04C32).
- Introduce typestate to eliminate illegal states (M03C28–M03C29).
- Extract strategies for variation points (M04C37).
- Introduce ports/adapters (Module 2 + M04C38).
- Introduce UoW for commit boundaries (M05C42).
- Introduce facades to protect public API (M05C46).
3. How to Refactor Safely¶
Correct refactoring rules:
- Preserve behavior: tests must stay green.
- Work in thin slices: introduce new shape alongside old, migrate, delete old.
- Move one responsibility at a time.
- Add tests at the seam when you can’t test internals directly.
This course’s refactor cores (M02C20, M03C30, M04C40, M05C50) model this workflow.
4. Teaching Lens: Smell → Failure Mode → Refactor¶
For education, always connect:
- smell: “optional fields everywhere”
- failure mode: “invalid active rules slip into evaluation”
- refactor: “typestate + domain invariants”
This helps you see design as cause-and-effect, not taste.
Practical Guidelines¶
- Use smells as diagnostic tools, not as insults.
- Always connect a smell to a concrete failure mode and a concrete refactor.
- Refactor under tests; add tests at boundaries if needed.
- Prefer small, composable objects over clever inheritance and flag soup.
Exercises for Mastery¶
- Pick one smell in your codebase. Write the failure mode it can cause. Apply one refactor move and show the diff.
- Identify one variation point implemented with conditionals. Replace with a strategy.
- Create a “smell checklist” for code reviews in your project (5 items max).