DecompositionGENERALSIMPLIFIEDILLUSTRATIVE

Recognising a Bad Decomposition

Layer-only, too wide, too deep, a single child, vague names: the five shapes a decomposition takes when it has stopped being about the problem. Each is visible in the tree's outline before any code is written.

The moveWorked exampleNext questions

The situation, the reflex, and why it stalls

Every lesson starts where being stuck starts: someone has a problem, and the first move that comes to mind feels like progress.

The question

A decomposition can look complete and be useless. What are the shapes that give a bad one away, and what does each one mean you skipped?

The situation

You are reviewing a colleague's plan for the store. It has a tree. The tree has twenty-three top-level children, one of which is "Backend", which has one child, "API", which has one child, "Endpoints". You know something is wrong and cannot say what.

The reflex

Judge it by coverage. Does every requirement appear somewhere in the tree? If so, approve it; the decomposition is "complete". Coverage is countable and arguing about shape feels like taste.

Why it stalls

Coverage is satisfied by any tree that mentions every word in the requirements, including a flat list of the requirements. It cannot distinguish a decomposition from a table of contents.

What the reflex produces — and fails to produce
  • Coverage is satisfied by any tree that mentions every word in the requirements, including a flat list of the requirements. It cannot distinguish a decomposition from a table of contents.
  • The shape defects are exactly the ones coverage cannot see: a layer-only tree covers everything and orders nothing; a too-wide tree covers everything and prioritises nothing; a chain of single children covers one thing three times.
  • The plan is approved, work begins along the tree, and the defects surface as scheduling problems — everything seems to be first, or nothing can start — which get blamed on estimation.
ProblemUnderstandRequirementsConstraintsUnknownsDecompositionSmallest StepModelExperimentObserveDebugLearnIterate

The move

Precisely enough to apply it to a problem you have never seen — not a slogan.

  • Read the tree's shape before its content. Five shapes mean five different skipped steps. *Layer-only* children (Frontend, Backend, Database) mean the capabilities were never listed. *Too wide* — a root with a dozen or more children — means grouping was skipped; the children are requirements, not capabilities. *Too deep* — leaves five or six levels down — means splitting continued past the point where the leaf was buildable. *A single child* means a node was renamed, not split; the level adds nothing. *Vague names* — "Misc", "Core", "Handle errors" — mean an unknown was filed as a heading.
  • For each defect, do the skipped step rather than rearranging the tree. Layer-only: list the actors' actions and regroup. Too wide: ask which children are the same actor doing related things, and group. Too deep: find the highest level at which every leaf is buildable and prune below it. Single child: collapse the chain. Vague: sharpen into a question or delete.
  • Then apply the leaf test: every leaf must have an observation (What Makes a Good Subproblem). A tree with a good shape and untestable leaves is still a heading list, just a well-arranged one.

Five shapes, five skipped steps

The table is the whole diagnostic. Read a tree's outline, match the shape, and the "cause" column tells you which part of decomposition never happened. The response is always to do that part, not to reshape the tree by hand.

What a bad decomposition looks like
TriggerSymptomCauseResponse
Children are Frontend / Backend / DatabaseEvery child contains the whole product; nothing can be finished aloneCapabilities were never listed — the solution was split instead of the problemList actor actions, regroup by capability; let layers appear inside each
Root has a dozen or more childrenEverything is first; no order of work emergesGrouping was skipped — the children are requirements pasted inGroup by actor and related action; each group is a capability
Leaves five or six levels deepLeaves are trivial; the tree is bigger than the code will beSplitting continued past the buildable levelFind the highest level where every leaf is buildable and prune below it
A node with exactly one child, sometimes chainedThe same thing named three times at three depthsA node was renamed rather than splitCollapse the chain to one node
Names like Misc, Core, Handle errors, Edge casesNobody can say when the node is doneAn unknown was filed as a headingSharpen into a question or a failure leaf under a real capability, or delete

Before and after

The colleague's chain, and what it became. The "after" is shorter, and everything the "before" mentioned is still there — inside a capability, with an observation.

Backend → API → Endpoints, repaired
Before
Backend → API → Endpoints → (list of every endpoint the store will ever have). Three levels that add nothing, and a flat list at the bottom that is the whole product again.
After
No Backend node. Each capability — Browse, Add to cart, Check out — owns the endpoints it needs as part of its leaves: "add with a quantity" implies an endpoint, and its test is in the customer's words.

An endpoint is how a capability is reached, not a piece of the problem; putting endpoints under capabilities makes each one testable by what it lets the customer do, while a list of endpoints is testable only by whether it responds.

The repaired tree

After the three repairs, the top level is capabilities, "Edge cases" has dissolved into failure leaves under the capabilities they belong to, and the deepest leaf sits at the third level. This is the tree the review should have been arguing about.

The colleague's tree, after repair (two branches shown)
E-commerce platform — V1
  • Cart
    • Add with a quantitytestable After adding quantity two, the cart shows that product with quantity two.
    • Adding more than stock is refusedwas "Edge cases"; now it lives where it appliestestable Adding a quantity above the product's stock is rejected with a message naming the product.
    • Change quantity, removetestable After changing to three then removing, the cart no longer holds the product.
  • Checkout
    • Create the ordertestable Exactly one order exists with the cart's lines and captured prices.
    • A declined payment leaves the order unpaidwas "Edge cases"testable After a test-mode decline, the order is unpaid, the customer sees a reason, and a retry does not create a second order.

The other five branches follow the same pattern. Nothing from the original twenty-three requirements was lost; each now has a parent that says what it is for.

How to do it

Most important first.

  • Count the root's children. A handful is normal; a dozen is a smell; twenty means the requirements were pasted in.
  • Find the deepest leaf and count its depth. Past three or four levels, ask whether the leaf's grandparent was already buildable.
  • Look for any node with exactly one child and ask what the extra level is for. Almost always, nothing.
  • Search the tree for Frontend, Backend, Database, API, Misc, Core, Other, Errors. Each hit is a step that was skipped, not a piece of the problem.
  • Check that siblings differ in what they do, not only in name. "Order creation" and "Creating orders" as siblings is one problem twice.

Worked on a concrete problem

The move has to produce something. This is what it produced.

  • The colleague's tree, diagnosed: twenty-three top-level children — too wide; the requirements were listed, not grouped. Among them "Backend → API → Endpoints" — a chain of single children, and layer-only at that. "Edge cases" as a top-level child — vague. Three defects, three skipped steps: group by capability, delete the layer chain and let layers appear inside capabilities, and turn "Edge cases" into failure leaves under the capabilities they belong to (Failure Path Second).
  • After repair: seven children — Catalog, Cart, Checkout, Orders, Payments, Inventory, Admin — each with two to four leaves, deepest leaf at level three. "Edge cases" became "a declined payment leaves the order unpaid" under Checkout and "adding more than stock is refused" under Cart. Every requirement from the original twenty-three is still present; it is now somewhere that says when it is done.
  • A too-deep case from the same review: Cart → Cart items → Cart item quantity → Increment quantity → Validate increment. The leaf "validate increment" is real, but its great-grandparent "cart items" was already buildable: add, change quantity, remove, each with an observation. Pruned to that level; the validation became the observation on "change quantity" rather than a node of its own.

How you know it worked

What now exists that did not before, and what question you can now ask.

  • You can name the defect in a bad tree in one word, and the skipped step in one sentence.
  • The repaired tree is smaller, not bigger, and every original requirement can still be found in it.
  • The review conversation is about the problem — "is checkout one capability or two?" — rather than about the diagram.

The questions you can now ask

The field this whole domain exists for. After this lesson, these are the questions to put to an unfamiliar problem.

Next questions
  • ?Which of the five shapes does this tree have, and which step does that say was skipped?
  • ?Is this node a real split of its parent, or the parent renamed?
  • ?Can every requirement in the original list still be found in the repaired tree — and now with a place that says when it is done?

What can go wrong

How the move itself fails
  • Enforcing shape rules as rules. A root with a dozen children can be right for a genuinely broad product; a five-level tree can be right for a genuinely intricate capability. The shapes are symptoms to investigate, not violations to fix.
  • Repairing by rearranging: moving nodes until the counts look good, without doing the skipped step. The tree then has a healthy shape and the same absence of capabilities.
  • Reviewing shape and forgetting leaves. A perfectly shaped tree of headings is still a tree of headings.
What the move costs
  • Shape review finds structural problems fast and misses content problems entirely; a tree can be perfectly shaped and about the wrong product.
  • Telling a colleague their tree has a defect named "too wide" is easy; explaining that the fix is to do the grouping they skipped is a longer, more useful, less comfortable conversation.
Misreads
  • "Never have more than a few children." The number is a smell, not a rule. Diagnose why it is wide; a broad product with many genuinely distinct capabilities is allowed to be wide.
  • "A single child is always wrong." It is always a level that adds nothing *now*; occasionally it is a placeholder for siblings known to be coming. Then say so in the node's note rather than leaving a mystery.

Where this applies

Problem-solving advice is stated as universal far more often than it is. These labels say what each method is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.

  • GENERALThe five shapes are properties of any tree and indicate the same skipped steps regardless of what is being decomposed; only what counts as "too wide" or "too deep" moves with the size of the problem.
  • SIMPLIFIEDReal trees mix defects — a layer-only child that is also a single-child chain — and the repair order matters less than doing each skipped step; the five-way split is a teaching cut through one continuous judgment.
  • ILLUSTRATIVEThe colleague, the twenty-three children and the five-level cart chain are invented to show each shape clearly; real reviews find subtler versions.

Where the depth lives

This domain asks the question and hands the answer off by name.