A1.02 · Pragmatic, revisited · dive 2
The unit is a contract
A routine's obligations stated as three clauses — a precondition in, a postcondition out, an invariant throughout. For an agent that triple is not a nicety; it is the specification itself.
A contract is the smallest precise statement a Claude agent can implement against and you can accept against without reading every line of the diff. Pick the input on the right and watch the three clauses light: where the contract holds, the work is acceptable; where it breaks, the named clause is the verdict.
The contract, evaluated live · choose the input
What Design by Contract says
Design by Contract — Meyer's principle, born in Eiffel — specifies a routine by three obligations. A precondition the caller must meet for the routine to run; a postcondition the routine guarantees in return; and an invariant that holds before and after every call, on every path. State those three, and the routine is specified — not described, specified.
The agent-era reading is sharper than the original. The contract is the acceptance criterion. A diff that satisfies the contract is acceptable; one that does not is rejected by the named clause it broke. That verdict is reachable at the boundary — from the contract alone — so you do not re-read the implementation to render it. An agent need not handle the impossible: if the precondition is unmet, the routine refuses, and the case is out of scope by construction.
- precondition
- The caller's obligation — what must hold for the routine to run. Unmet, the routine refuses, and the agent need not handle the impossible.
- postcondition
- The routine's guarantee — what is true of the result when the precondition held. This is what you accept against.
- invariant
- A property true before and after every call, on every path — never broken in between.
- Design by Contract
- Specifying a unit by those three clauses (Meyer, Eiffel). Agent-era: the contract is the acceptance criterion — satisfied is acceptable, broken is rejected by name.
The triple does double duty: it is precise enough for an agent to implement against, and precise enough for a human to accept against. One statement, both ends of the boundary.
The contract is the gate
Once a unit has a contract, acceptance stops being a reading exercise and becomes an evaluation. You do not re-read the agent's diff line by line to decide whether to take it; you check the diff against the contract. Each clause is a gate the work passes or fails, and the verdict carries the reason: the first clause that does not hold names exactly why the work is rejected.
Model an agent's submitted output below. The slider is the produced id's length — the contract requires exactly 14. The two toggles are the other guarantees: does the id decode back to the type, and is it unique within a node-millisecond. The contract accepts only when every clause holds; otherwise it rejects, and names the first failing clause.
The acceptance gate · would the contract take this diff?
Acceptance moves to the boundary: the contract decides, clause by clause, and the first one that fails is the reason — a verdict you reach without re-reading the implementation.
One contract on the Portal
Take one unit on the Portal — the learning platform this course builds — and write its contract.
The branded id has exactly three clauses. Precondition: the namespace is a known type
(:user, :event, :lesson).
Postcondition: the result is a 14-character TSK…-prefixed id
that decode/1 maps back to that type. Invariant: ids are unique and
monotonic within a node-millisecond — never two the same.
This is exactly the contract that made “generate one id” an acceptable thin slice back in A1.01.3: the slice carried its own acceptance. The contract names what to build and what to check, so the unit is the same precise thing whether an agent implements it or you accept it.
# The branded-id contract, stated as three clauses. # PRE : the namespace is a known type (:user | :event | :lesson) id = Portal.ID.generate(:user) # => "USR0NbAb1xcFCy" # POST : 14-char TSK… id that decodes back to that type assert byte_size(id) == 14 assert Portal.ID.decode(id).type == :user # INV : unique & monotonic within a node-millisecond — never two the same next = Portal.ID.generate(:user) refute next == id assert Portal.ID.decode(next).timestamp >= Portal.ID.decode(id).timestamp
A diff that keeps every assertion green satisfies the contract and is acceptable; one that breaks an assertion is rejected by the clause it broke — a length that is not 14, a type that does not round-trip, a collision within the node-millisecond. The verdict is the failing clause, not a re-read of the routine.
The principle
A routine's obligations are stated as a precondition, a postcondition, and an invariant — the smallest precise statement of the unit.
On the Portal
The id contract — known namespace in, 14-char decoding id out, unique within a node-ms — is the slice's acceptance: what an agent builds and what you accept against.
The contract is the unit of specification and the unit of acceptance at once — what lets a human accept an agent's work at the boundary instead of line by line.
Recap — the spec is a triple
A unit handed to an agent needs a contract: a precondition the caller meets, a postcondition the routine guarantees, an invariant that always holds. That triple is precise enough to implement against and precise enough to accept against, which is what moves acceptance from re-reading the diff to checking it against the named clauses. Knowledge has a home; a unit has a contract — two of three re-weighted principles down.
Next in A1.02: A1.02.3 · Orthogonality and blast radius — how a change to one unit ripples (or does not) into the rest, and why keeping units independent bounds what an agent's diff can break.
References
Primary sources for Design by Contract, and where the principle connects in the course.
Sources
- Meyer, B. — Object-Oriented Software Construction — Design by Contract and the pre/post/invariant triple, as realised in Eiffel.
- Hunt & Thomas — The Pragmatic Programmer — the “Design by Contract” topic: stating a routine's obligations as the specification.
Related in this course
- A1.02 · Pragmatic Programming, revisited — the module hub.
- A1.02.1 · The single source of truth — the previous dive: every fact has one home.
- A1.02.3 · Orthogonality and blast radius — the next dive.
- A1.01.3 · Thin slices — the slice that carried its own acceptance: this same id contract.
- A1 · Why an agile agent workflow