Think Twice, Write Once: Notes on Rich Hickey's "Design in Practice"

In the popular imagination, the software engineer is a romantic hero who sits down at a glowing screen, cracks their knuckles, and immediately starts typing lines of code at a furious pace. They don't think; they just build.

In the real world, this is a recipe for building a system that runs beautifully, passes its tests, and solves entirely the wrong problem.

Rich Hickey’s talks have long been a guide for developers trying to escape this trap. He is famous for advocating "hammock time"—the practice of stepping away from the keyboard, closing your eyes, and actually thinking about the problem before writing a single line of code.

Hickey’s talk, Design in Practice, is a masterclass in how to formalize this process. It is the practical companion to his philosophical talks, offering a concrete structure for recording design decisions without drowning in corporate bureaucracy. It also serves as a beautiful elaboration on Architecture Decision Records (ADRs), a concept first popularized by Mike Nygard's 2011 post, which I still reference regularly.

Here are my key takeaways and reflections on the talk.

Why Design? (Or: The Cognitive Savings Account)

If you ask the average developer why they don't write design documents, they'll tell you they don't have time. They need to ship features.

But design isn't about satisfying auditors or writing massive Word documents that no one reads. Design is a cognitive savings account. The goals of formalizing design are intensely practical:

The Power of the Socratic Method

Hickey emphasizes that design is essentially a Socratic dialogue with yourself. It requires detaching your ego from your ideas. The goal isn't to prove your favorite solution is right; it's to discover the objective truth of the system.

He suggests framing your progress around four fundamental questions:

  1. Where are you at? (Your current state and constraints).
  2. Where are you going? (The target objective).
  3. What do you know? (Your facts and assumptions).
  4. What do you need to know? (Your unknowns and research spikes).

By continuously asking these questions, you engage in reflective inquiry—being aware of your own cognitive state.

Part of this discipline is linguistic precision. If two developers use the same word to mean different things, design fails. Hickey recommends compiling a glossary early in the process. Force yourself to define your terms. If you can't explain what a term means in two sentences, you don't understand it yet.

The 6-Phase Lifecycle of Design

To turn these philosophical ideas into practice, Hickey breaks the software design and development process into six distinct, sequential phases:

graph TD
    A[1. Describe] --> B[2. Diagnose]
    B --> C[3. Delimit]
    C --> D[4. Direction]
    D --> E[5. Design]
    E --> F[6. Dev]
    E -.->|Backtrack if needed| C

1. Describe (The What)

Write down the situation as you hear it. Focus entirely on describing symptoms, not solutions. How big is the problem? What is the business impact? If a database is slow, don't say "we need Redis." Say "queries on the user table are taking 800ms, delaying checkout."

2. Diagnose (The Why)

Accumulate hypotheses. There is never just one reason for a bug or bottleneck. List them all and use the scientific method to test them one by one. Prove your hypotheses with data, not vibes.

3. Delimit (The Scope)

If you do steps 1 and 2 correctly, you will discover that you are facing a Hydra of multiple, interconnected problems. You cannot solve them all. Delimiting means drawing a hard boundary around the single problem you are going to solve right now.

4. Direction (The Strategy)

List high-level approaches and evaluate their trade-offs. Hickey suggests putting these in a decision matrix: columns are your approaches, and rows are your criteria (e.g., development time, operational cost, legal compliance). This is where bad ideas go to die, cheaply and quickly, before they cost a single line of code.

5. Design (The Tactics)

Once you have chosen a direction, map out the implementation path. Choose your libraries, database schemas, and API contracts. If you discover during this phase that your assumptions were wrong, backtrack. It is infinitely cheaper to rewrite a design document than to refactor a production database.

6. Dev (The Execution)

Actually write the code. If you did phases 1 through 5 correctly, this should be the easiest, most mechanical part of the entire process. You aren't guessing or exploring; you are simply executing a well-defined blueprint.

The Takeaway

Writing code is fun. Thinking is hard.

But as software systems grow in complexity, the developers who succeed are not the ones who type the fastest. They are the ones who know how to sit in the hammock, ask the right questions, and write their decisions down.

For more details, check out the video of the talk or read the full transcript.

Published: 2023-08-17

Tagged: talk clojure design richhickey