Decomposition — How: The Method
Two Directions
There are two fundamental approaches, and experts use both — often on the same problem.
Top-Down: Start From the Goal
Begin with the end result and repeatedly ask: "What sub-problems does this require?"
Each answer becomes a new question. You keep asking until each piece is small enough to describe with a clear contract — precise inputs, precise outputs, and you can estimate the effort.
Quick example: "Build an online bookstore."
- What does a bookstore need? → Browsing, cart, checkout, admin
- What does browsing need? → Search, filter, sort, details page
- What does search need? → Accept query, match results, handle "no results"
Three levels. Each level more specific. Stop when the pieces feel tangible.
Bottom-Up: Start From What You Have
Begin with the pieces you know and ask: "What can I compose from these?"
This works when you have existing components, known constraints, or a technology platform with built-in capabilities.
Quick example: You have a database of books, an email service, and a payment API.
- Database → browsing and search features
- Email → order confirmations and notifications
- Payment API → checkout flow
- Combine all three → a basic bookstore
Bottom-up is powerful when building blocks constrain the design. If your payment API only supports credit cards, that fact shapes the checkout feature — you discover this from the bottom, not the top.
When to Use Which
| Situation | Approach |
|---|---|
| New project, blank slate | Top-down — start from what users need |
| Existing system, adding features | Bottom-up — start from what already exists |
| Unclear requirements | Top-down first to clarify scope, then bottom-up to ground it in reality |
| Well-understood problem | Either works; most engineers blend both naturally |
The Decomposition Tree
The primary artifact of decomposition is a tree — a hierarchy where each node is a piece of the problem and its children are its sub-pieces.
At every leaf of this tree, you should be able to:
- Write a contract (inputs, outputs, errors)
- Estimate the effort (small, medium, large)
- Identify dependencies (does this need something else built first?)
If you can't do all three, the piece isn't decomposed enough — keep breaking it down.
Finding Seams
A seam is a natural break point — a place where one concern ends and another begins. Recognizing seams makes decomposition faster and more accurate.
Data format changes
Wherever data changes shape, there's a seam. Raw input → validated input. Validated input → database record. Database record → display format.
Responsibility changes
Wherever "whose job is this?" changes, there's a seam. The user's browser collects input. The server validates it. The database stores it. Three responsibilities, three seams.
Time boundaries
Wherever something can happen "later" or "separately," there's a seam. The order is placed now. The shipping label is generated later. The daily summary runs overnight.
Audience changes
Wherever different users see different things, there's a seam. The customer sees their order. The admin sees all orders. The warehouse sees orders ready to ship.
Error handling boundaries
Wherever the response to failure changes, there's a seam. Search fails → show "no results." Payment fails → stop checkout. Email fails → log it and continue.
Dependency Mapping
Once you have a tree, identify what depends on what.
Three dependency rules:
- Things at the bottom should depend on nothing or on stable abstractions
- Things at the top can depend on things below
- Circular dependencies are a design error — if A needs B and B needs A, your decomposition is wrong
The dependency arrows tell you the build order: start with pieces that have no dependencies, then build what depends on them, then what depends on those.
Estimating From Decomposition
Once a problem is decomposed into leaves, you can estimate by creating a table:
| Leaf | Complexity | Dependencies | Priority |
|---|---|---|---|
| Each decomposed piece | Small/Medium/Large | What it needs | High/Medium/Low |
This table, derived entirely from decomposition, gives you a project plan — not a guess, but a structured breakdown where each piece is estimable and the order is logical.
The Decomposition Checklist
When you've finished decomposing, verify:
- Every leaf is concrete — you can write a contract for it
- Every leaf is small — you could explain it completely in 2-3 sentences
- No leaf has hidden complexity — if it feels big, it needs more decomposition
- Dependencies are explicit — you know what depends on what
- No circular dependencies — everything flows in one direction
- Nothing is missing — trace the user's journey start to finish; every step has a leaf
- Nothing overlaps — each responsibility appears exactly once
- Build order is clear — you know what to start with
What to Look For in the Examples
The following pages take three very different systems and decompose them completely. As you read:
- Watch how the tree grows — from a vague goal to concrete, estimable leaves
- Notice where seams appear — and which type of seam it is
- Compare the final tree depth — some systems are deeper than others
- Look at the dependency map — what must be built first?
- Notice the decisions — decomposition isn't mechanical; there are judgment calls about where to split