---
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
