skip to content

Specifications are traditionally described as having three uses: validation, selection, and construction-to-order. What does 'construction-to-order' mean, and how does it differ from just validating an object after it's built?

level: middleimportance: should knowfreq 45%

answer

  1. validate existing, select from many, construct new
  2. factory reads spec params
  3. correct by construction vs build-then-check
  4. least common of the three uses

basics

~20 s

Validation checks an object after it exists. Construction-to-order uses the same rule before building, to describe exactly what a new object should look like so a factory can build one that already satisfies the rule, instead of building something and then rejecting it.

solid answer

~40 s

The three classic uses (from Evans/Fowler) are: validation - checking an existing object satisfies a rule; selection - filtering a collection (in memory or via query) for objects that satisfy a rule; and construction-to-order - handing the specification to a builder/factory so it constructs a new object guaranteed to satisfy the rule from the start, rather than building blindly and validating afterward. Construction-to-order matters when building a valid instance is expensive or when you want "correct by construction" rather than "build then check," e.g., a factory that reads the specification's required attribute ranges to generate a new object directly within valid bounds instead of retrying random values until one passes validation.

go deeper

for a junior

Should be able to distinguish, at a high level, checking an existing object versus filtering a list versus building a new one to match a rule, even if 'construction-to-order' isn't a term they know by name.

for a middle

Should name and describe all three classic uses and give a plausible example of each, including a rough construction-to-order scenario.

for a senior

Should explain why construction-to-order requires exposing the specification's structured parameters (breaking pure black-box encapsulation) and identify when it's worth the extra design cost versus a plain factory method.

for a principal

Should recognize construction-to-order as a rarer, domain-specific need (generative/combinatorial construction) and be able to judge in review whether a team is reaching for it unnecessarily versus genuinely needing it for expensive or rare-valid-candidate construction.

## The three roles one specification plays Eric Evans, in the original Specification pattern write-up (later expanded by Martin Fowler), identifies three distinct roles a single specification object can play, all backed by the same `isSatisfiedBy` predicate but consumed differently depending on the caller's intent. 1. **The first, validation**, is the most familiar: given an already-existing candidate object, ask whether it currently satisfies the rule — `orderSpec.isSatisfiedBy(existingOrder)`. 2. **The second, selection**, uses the specification to filter a collection down to matching members, either in memory (`orders.filter(spec::isSatisfiedBy)`) or, more powerfully, translated into a query executed by a repository so the filtering happens in the database rather than after loading every row into memory. 3. **The third and least obvious, construction-to-order**, inverts the direction of use entirely: instead of checking an object that already exists, you hand the specification *to a factory or builder* as an input, and the factory reads the specification's parameters to construct a brand-new object that is guaranteed to satisfy it from the moment it exists, rather than being built first and checked second. ## What construction-to-order looks like Concretely, imagine a specification like `LoanEligibilitySpecification(minIncome, maxDebtRatio)` used for validation against existing applicants. Construction-to-order would use the *same* specification object, but instead pass it to a `TestDataFactory` that reads `minIncome` and `maxDebtRatio` off the specification and generates a synthetic applicant whose income and debt ratio are deliberately set within those bounds — producing an object that is correct by construction, with zero chance of generating an invalid one and then discarding it. Another common real scenario: a scheduling system where a `MeetingSlotSpecification` (business hours, no existing conflicts, room capacity >= N attendees) is normally used to validate a proposed slot, but a "find me a valid slot" feature instead hands that same specification to a slot-generator that walks the calendar and constructs a `TimeSlot` object it knows in advance will satisfy the specification, rather than generating arbitrary slots and validating each one after the fact. ## Why it earns its own name Why does this distinction matter enough to name separately? Because build-then-check and build-to-satisfy have very different cost profiles when construction is expensive, random, or combinatorially large. - If constructing a candidate object is **cheap** (a plain in-memory object with a few fields), build-then-validate-then-discard-on-failure is perfectly fine and often simpler to implement — you just call the constructor and check the result. - But if construction involves **expensive** work — hitting a database, calling an external allocation API, running a simulation — repeatedly building throwaway candidates until one happens to satisfy the specification is wasteful and can even be infeasible if valid candidates are rare (imagine randomly generating credit applicants until one happens to qualify for a loan — the acceptance rate could be near zero). Construction-to-order pushes the specification's constraints *into* the generation logic itself, so the factory only ever produces valid objects. ## The trade-off: encapsulation The trade-off is that construction-to-order requires the factory to actually understand and use the specification's internal parameters, not just its opaque `isSatisfiedBy` predicate — which means the specification can no longer be a fully black-box boolean function; the factory needs structured access to its bounds/thresholds. This partially breaks encapsulation: a specification designed purely for validation (an opaque `isSatisfiedBy` closure) often can't be reused for construction-to-order without redesigning it to expose its parameters in a structured, factory-consumable way. Teams that only ever need validation and selection frequently skip implementing construction-to-order entirely, and that's a reasonable choice — it's the least commonly needed of the three uses in ordinary CRUD-style business applications, and shows up more often in domains involving generative or combinatorial construction: - test-data generation; - constraint-based scheduling; - procedural content generation; - configuration solvers that need to synthesize an object meeting a set of constraints rather than merely check one against them. ## The over-reach to watch for A failure mode worth flagging: teams sometimes reach for construction-to-order where a much simpler default-plus-override builder would do, adding a layer of specification-driven generation to a case where a straightforward parameterized factory method (`Applicant.qualifying(minIncome, maxDebtRatio)`) is more direct — construction-to-order earns its complexity when the constraints are the same constraints already validated elsewhere and you want a single specification object as the sole source of truth for both checking and generating, not as a way to avoid writing a normal constructor.

  • Why can't every validation specification automatically be reused for construction-to-order?
    A validation specification is often just an opaque `isSatisfiedBy(candidate)` predicate - a black box that returns true/false. Construction-to-order needs a factory to read the specification's internal parameters (thresholds, ranges) to generate a matching object, so the specification has to expose structured data, not just a boolean function, which is a different, more invasive design than pure validation needs.
  • When would build-then-validate-then-retry be preferable to construction-to-order?
    When constructing a candidate is cheap and the space of valid candidates is large relative to the space of all candidates - e.g., generating a random small positive integer is trivial and most attempts succeed. Construction-to-order earns its complexity specifically when construction is expensive or valid candidates are rare, making random build-and-discard wasteful or infeasible.
  • Give a realistic example outside test-data generation where construction-to-order is used.
    A constraint-based scheduling system building a meeting slot: rather than generating arbitrary time slots and validating each against business-hours/no-conflict/capacity rules, the slot-finder consumes the specification's constraints directly to walk only the valid region of the calendar and construct a slot guaranteed to satisfy them, which is far cheaper than generate-and-check when the calendar is large and open slots are sparse.

Validation is a bouncer checking IDs at the door of people who already showed up. Selection is scanning the whole guest list for everyone who matches a rule. Construction-to-order is handing the rule to event planning so they invite exactly the right people in the first place, instead of inviting randomly and turning people away.

saying these in an interview costs you the question

  • Only knows validation and can't name selection or construction-to-order at all
  • Thinks construction-to-order just means calling the constructor and then validating
  • Believes the same opaque isSatisfiedBy closure works unchanged for construction without any redesign
  • Can't explain why build-then-validate-then-discard becomes expensive at scale
  • Applies construction-to-order to a trivial case where a plain factory method would be simpler

context