design
Design
Design interfaces that are hard to misuse, easy to extend, and stable under change. Applies to API contracts, module boundaries, config schemas, and any surface where components interact.
Principles
Contract first
Define the interface before implementing it. The schema is the contract — implementation follows.
Hyrum's Law
All observable behaviors of your system will be depended on by somebody, regardless of what you promise in the contract. Every public behavior becomes a de facto commitment. Be deliberate about what you expose.
Prefer addition over modification
Extend interfaces by adding optional fields rather than changing existing ones. Changing a field's type or removing it breaks consumers silently. Adding is safe; modifying is not.
When different behaviors carry different intent, prefer separate variants or schemas over a single shared shape with conditionally meaningful fields.
Validate at boundaries
Trust internal code. Validate at system boundaries — API payloads, config files, external inputs. Don't scatter validation deep inside the call stack.
Predictable naming
Follow established project conventions consistently. When no convention exists, prefer explicit and descriptive over terse and clever.
Workflow
- Identify the boundary. What calls this? What does it return? Who else might consume it?
- Define the schema. Schema first, types inferred. Include descriptions for non-obvious fields.
- Design for the common case. Make the default behavior correct. Require explicit opt-in for unusual behavior.
- Review for misuse. Can a caller get into a bad state by passing valid-looking but wrong data? Add discriminants or branded types where confusion is likely.
- Check extensibility. Can this be extended without modifying existing consumers?
See also
sddfor source-backed API and framework decisionsarchitecturefor boundary and dependency integrityreferences/security-checklist.mdfor trust-boundary validation
Red flags
- Interfaces that require callers to know implementation details
- Fields that mean different things depending on context
- Breaking changes disguised as bug fixes
- Validation scattered through the call stack instead of at the boundary
More from cniska/skills
tdd
Drive implementation with red-green-refactor. Use when building features or fixing bugs test-first.
12review
Run all review skills against the current branch diff. Use when reviewing a feature branch before merge.
10plan
Design a feature or behavior change through dialogue. Use when asked to plan, scope, design, or break down work before coding.
10explore
Explore a task or design through systematic questions until reaching shared understanding. Use before implementing complex or ambiguous work.
10issue
Create a GitHub issue from a short description. Use when filing a bug, feature request, or task.
10pr
Create a pull request with review and verify. Use when the branch is ready to merge.
10