A constructor takes many positional arguments, several of which are optional and most of which are easy to swap by accident. Call sites pass null or 0 as placeholders for arguments that don't apply, and reviewers cannot tell from the call site which argument means what. The reader's comprehension cost rises at every call site.
The agent reads a multi-parameter constructor call and consults the constructor signature (often elsewhere in the codebase) to know which positional slot means what. Editing the call site requires keeping positional alignment correct on every parameter change. The agent's retrieval cost for the signature compounds across every reading, and the context-window load doubles for what reads as one construction.
A step-by-step construction surface where each step is named after what it sets, optional inputs are explicit, and the moment of 'now build it' is a separate, terminal call. The product is immutable once built; partial construction states never leak, supporting separation of concerns between assembly and use.
Self-describing construction the agent reads top-to-bottom without cross-file lookup. Each chained method names what it sets; the build() terminator marks the point where the product is verified. The agent's context window holds the call chain and the builder definition; the reasoning step count drops because positional alignment is no longer a verification axis.
Before the pattern
const request = new HttpRequest('GET','/api/users/42',{ 'Accept': 'application/json', 'Authorization': 'Bearer xyz' },null,30000,3,true);
After the pattern
const request = new HttpRequestBuilder('GET', '/api/users/42').accept('application/json').bearer('xyz').timeoutMs(30000).retries(3).followRedirects(true).build();class HttpRequestBuilder {constructor(method, url) {this.spec = { method, url, headers: {}, body: null, timeoutMs: 0, retries: 0, followRedirects: false };}accept(mediaType) { this.spec.headers['Accept'] = mediaType; return this; }bearer(token) { this.spec.headers['Authorization'] = `Bearer ${token}`; return this; }body(value) { this.spec.body = value; return this; }timeoutMs(ms) { this.spec.timeoutMs = ms; return this; }retries(count) { this.spec.retries = count; return this; }followRedirects(flag) { this.spec.followRedirects = flag; return this; }build() { return new HttpRequest(this.spec); }}
Adding a new optional input to the constructor breaks every existing call site and forces each to add a placeholder for the new slot. Default values drift between languages, frameworks, and developer assumptions; the constructor signature stops describing what a valid request looks like. The team's verification cost compounds across every call site updated for a new optional input.
Positional argument lists are the worst-case input shape for context budget — the agent holds the parameter order in context while reading every call. Mis-aligned arguments produce type-compatible bugs that escape type-checker visibility, exactly the bug class that demands the most verification effort. The agent's verification-surface cost multiplies with parameter count.
The builder is a second object the reader navigates to understand what a fully-constructed product contains. Fluent chains hide the build step's complexity behind method-chaining syntax that some teammates find unidiomatic; debugging a misconfigured builder requires stepping through every chained call. The team's maintenance cost reshapes across two objects rather than one.
The builder's chainable method set is a second surface the agent reads alongside the product itself; tests cover construction paths separately from product behaviour, so the agent traces any regression through two surfaces instead of one. The agent's completeness-check cost rises during the migration itself as every existing constructor call must be confirmed to route through the builder.
Call sites read as a sequence of named decisions; new optional inputs are additive without breaking existing callers; the immutable product is constructed once and never mutated thereafter. Code review reads top-to-bottom in domain terms, not positional argument terms. The team's enhancement cost drops because adding an input is one builder method, not N call-site updates.
Call-site edits become append-or-remove single-line operations on the chain. The build() step is a structural commit the agent relies on as the moment of validation; partial-construction bugs surface as builder-test failures rather than runtime mysteries scattered across consumers of the product. The agent's token cost per call-site edit drops to one chained method.
Builders that allow .build() to be called from any state — including states where required inputs were skipped — defeat the immutability win and replace one bug class (positional confusion) with another (silently-incomplete construction). A builder without 'build() validates the full spec' is a fluent setter chain, not the pattern; the cure adds accidental complexity without delivering structural guarantees.
Inconsistent builder discipline — some builders enforce required-input checks at build(), others tolerate missing inputs and produce half-built products with default sentinels — forces the agent to verify enforcement on every new builder it encounters. The pattern stops being a structural promise and becomes a per-class convention to look up, raising retrieval cost on every read.