Encapsulate Composite With Builder

Destination
Symptom

A construction site the agent traces line-by-line across many intermediate variable assignments to reconstruct the tree's shape. Behavioural preservation on tree-shape edits requires loading the full construction span and following cross-variable references — the agent's carries the full wiring, and the of resolving each variable into its parent doubles for every level of nesting.

Goal

A construction site that reads as a tree literal the agent parses structurally in one pass. Edits to one subtree don't require loading the rest; the chain's indentation tells the agent which method calls operate on which node, and the holds the visual nesting that mirrors the structural nesting, dropping per edit.

Before the refactoring

// Client constructs the XML tree by wiring TagNodes manually.
const order = new TagNode('Order');
const customer = new TagNode('Customer');
customer.setAttribute('id', 'C-901');
order.addChild(customer);
const items = new TagNode('Items');
const item1 = new TagNode('Item');
item1.setAttribute('sku', '123');
item1.setAttribute('qty', '2');
items.addChild(item1);
const item2 = new TagNode('Item');
item2.setAttribute('sku', '456');
item2.setAttribute('qty', '1');
items.addChild(item2);
order.addChild(items);
const xml = order.toXML();

After the refactoring

// Client reads as an outline of the tree it builds.
const xml = new XMLBuilder('Order')
.addChild('Customer').addAttribute('id', 'C-901').end()
.addChild('Items')
.addChild('Item').addAttribute('sku', '123').addAttribute('qty', '2').end()
.addChild('Item').addAttribute('sku', '456').addAttribute('qty', '1').end()
.end()
.toXML();
Example source: Adapted from Joshua Kerievsky's XML-builder example in Refactoring to Patterns (Addison-Wesley, 2004), chapter 6. The Java original used a TagNode composite + XMLBuilder fluent API; this JavaScript translation keeps the same shape — TagNode for the composite, a chained builder for the construction grammar.
Pressure

Tree wiring across N intermediate variables × M tree nodes consumes context budget proportional to the tree's size. Renaming a variable risks breaking the wiring; the data flow is brittle in a way static analysis cannot fully catch. The agent's multiplies with N×M, and the wiring's dependence on identifier reuse escapes .

Tradeoff

A fluent chain is one large expression the agent must keep coherent — losing track of `.end()` placement silently produces a different tree shape. Long chains evade static analysis of intermediate states, and partial failures inside the chain are hard to attribute. The agent's rises when verifying that every node's parent and `.end()` align as intended.

Relief

The builder's method chain reads structurally; nested calls visually mirror nested nodes. Verifying a tree edit is a localized diff inside the chain rather than a cross-variable trace; the build is a single expression with one rooted result. The agent's per tree edit drops because intermediate variables disappear and the structural shape is the syntactic shape.

Trap

A builder that returns `this` everywhere becomes one massive expression; the agent's reasoning about partial-state failures degrades because there are no intermediate names to anchor on. Debugging requires re-reading the entire chain to localize where the failure happened, and the count rises per debugging pass.