--- source: "hyperthrive_dev" date: "2026-03-13" tags: [research, oo-principles, 99-bottles, tdd, software-design, process, shameless-green, open-closed, refactoring] --- # 99 Bottles OOP — Full Software Design Process Map A complete map of the software design lifecycle described in *99 Bottles of OOP* by Sandi Metz and Katrina Owen. Documented during a session exploring how to better encode OO principles into AI coding conventions. ## Overview The process is an infinite loop with four distinct phases: initial development, a waiting period, a refactoring loop triggered by new requirements, and implementation. The key insight is that refactoring and feature addition are deliberately separated. ## Phase 1: Initial Development (Shameless Green) Goal: get to working, understandable, thoroughly tested code as fast as possible. Do NOT invent requirements or speculate about the future. 1. Sketch a high-level public API for the problem 2. Write the first test targeting the simplest, most thoroughly understood piece of that API 3. Red → Green (write only enough simple code to pass) 4. Write the next test proving existing code is incomplete 5. Write the simplest, most concrete code to pass — tolerate duplication 6. Repeat horizontally until all variations are handled 7. Stop. You have reached Shameless Green: easy to understand, fully tested, fulfills current requirements Shameless Green optimizes for understandability, not changeability. If the code never changes, you stop here. ## Phase 2: The Waiting Period Do nothing proactively. Wait for a new requirement. Two voluntary exceptions: - **Exception A (Purify Tests):** Clarify test names, remove echoes of implementation details, ensure every class has its own unit test - **Exception B (Aesthetic Improvements):** Fix Law of Demeter violations, remove hard-coded class names, push object creation to the edges Do NOT build abstractions speculatively. Save time and money. ## Phase 3: The Refactoring Loop (Open/Closed Principle) Triggered when a new requirement arrives. Separate refactoring from feature addition. **Decision gate:** 1. Is the code "open" to the new requirement? (Can you implement it by adding code, not modifying existing code?) - YES → go to Phase 4 - NO → continue 2. Do you know how to make it open? - YES → refactor → return to step 1 - NO → continue 3. Identify the best-understood code smell and remove it using a mechanical recipe: - Need to unearth an abstraction → **Flocking Rules** - Conditionals supplying behavior → **Replace Conditional with Polymorphism** - Need to choose which polymorphic class to use → **Factory** - Objects tightly coupled → **Dependency Inversion** (push object creation to edges, inject dependencies) 4. Enforce contracts: check LSP (objects return trustworthy types) and LoD (no chaining collaborator messages) 5. Return to step 1 ## Phase 4: Implementation Code is open. Make the change — usually as simple as creating a new polymorphic class and registering it in the factory. Then loop back to Phase 2. ## Code Smells and Mechanical Recipes **Switch Statement / Conditionals supplying behavior** → Replace Conditional with Polymorphism (or State/Strategy) **Primitive Obsession** → Extract Class (give the primitive a domain object) **Duplicated Code** → Extract to a single method; apply Flocking Rules to find the abstraction **Large Class** → Extract Class (divide responsibilities) **Data Clump** → Extract Class or consolidating method **Law of Demeter Violation** (chained sends: `a.b.c`) → Delegation / message forwarding, or redesign from the sender's point of view **LSP Violation** (returns unexpected types) → Perform type conversion inside the method **Temporary Variable** (used only once) → Inline Temp **Blank Line within a method** → SRP violation; separate responsibilities ## The Flocking Rules (Unearthing Abstractions) Apply mechanically when you don't understand the abstraction yet: 1. Select the things that are most alike 2. Find the smallest difference between them 3. Make the simplest change that removes that difference Apply in four microscopic steps: (a) parse the new code, (b) parse and execute it, (c) parse, execute, and use its result, (d) delete unused code. Make one line change at a time. Run tests after every change. Undo immediately on failure. ## Replace Conditional with Polymorphism (Recipe) 1. Create a subclass for the value you switch on 2. Copy one switching method into the subclass; keep only the true branch 3. Create a factory if none exists; register the subclass 4. In the superclass, remove everything but the false branch 5. Repeat for all switching methods 6. Iterate until a subclass exists for every switched value ## The Ultimate Goal Build applications out of trustworthy, loosely-coupled, polymorphic objects that can survive an unknown future. The programming aesthetic: fall in love with polymorphism. ## See Also - [[AI Coding Conventions Organization — External Research Synthesis]] — how practitioners encode process and principles into AI context - [[OO Principles Plugin Concept — Design Recommendations]] — how to build an AI plugin based on this lifecycle