Design by Contract
A methodology where software components define precise, verifiable interface specifications: what they require (preconditions), what they guarantee (postconditions) and what stays true (invariants).
Also known as: DbC, Contract Programming, Programming by Contract, Design-by-Contract Programming
Category: Software Development
Tags: software-design, software-development, software-engineering, programming, interfaces, reliability, principles
Explanation
Every function call is a deal between two parties. The caller wants something done. The function needs certain things to be true to do it. Most of the time, that deal stays implicit and written down nowhere. That's exactly where bugs hide.
Design by Contract (DbC) makes the deal explicit. Bertrand Meyer introduced it in the 1980s with the Eiffel programming language, and described it in depth in Object-Oriented Software Construction (1988). Each component declares its preconditions (what it requires), its postconditions (what it guarantees) and its invariants (what stays true). Just like in a business contract, each party has obligations and gets benefits in return.
**The three parts**:
- **Preconditions**: What the caller must provide. If violated, the fault is the caller's
- **Postconditions**: What the component guarantees on return. If violated, the fault is the component's
- **Invariants**: Properties that remain true before and after every operation
**An example**:
A `withdraw(amount)` method on a bank account could declare:
- Precondition: `amount > 0` and `amount <= balance`
- Postcondition: `balance == old balance - amount`
- Invariant: `balance >= 0`
**Why it matters**:
Contracts make interfaces explicit. Debugging becomes straightforward: check the preconditions, then the postconditions. Blame is unambiguous. And components can be swapped if they satisfy the same contract, which is what the Liskov Substitution Principle in SOLID asks for.
And there's more... A component can trust its preconditions instead of defensively re-checking everything, so the code gets simpler. The contracts also double as precise documentation that a machine can verify.
**Design by Contract vs. Defensive Programming**:
Defensive programming checks for every possible bad input, everywhere. Design by Contract assigns responsibility instead: the caller ensures the preconditions, the callee ensures the postconditions. You avoid redundant checks, and a violation shows up as what it really is: a bug.
**In practice**:
Few mainstream languages support contracts natively. Eiffel, Ada/SPARK, D and Kotlin are the exceptions, and C++26 adds them too. Elsewhere, you approximate DbC with assertions, type systems, validation at the boundaries, property-based tests and schema libraries.
**In AI skills**:
AI skills lack formal type systems, but contract thinking still applies:
- **Preconditions**: "This skill requires a note path as argument and the osk-obsidian-cli context loader"
- **Postconditions**: "This skill outputs a markdown document with H1 title matching the filename"
- **Invariants**: "This skill never modifies files outside the target folder"
Making these explicit (e.g., in a dedicated Input/Output section of SKILL.md) enables substitution, composition and trust between skills that chain into each other. Today, most skill "contracts" are implicit. Formalizing them is the next step for skill ecosystems.
Related Concepts
← Back to all concepts