LI

API Surface Design

Public API design, naming conventions, and developer experience patterns for libraries

Details

Language / Topic
_UUniversal
Category
Architecture

Rules

balanced
- Keep the public API surface minimal. Every exported symbol is a maintenance commitment — if in doubt, keep it private.
- Design APIs that are impossible to misuse: required parameters cannot be omitted, invalid states cannot be represented, types enforce constraints.
- Use consistent naming conventions across the entire API: if you use create() in one module, do not use make() or new() in another.
- Make the common case easy and the advanced case possible. The 80% use case should require minimal code; power users get escape hatches.
- Use the builder pattern or option objects for functions with more than 3 parameters. Positional arguments become unreadable and error-prone.
- Design for composability: functions that accept and return the same types can be chained and combined. Prefer data-in, data-out over complex object graphs.
- Provide sensible defaults for every option. Users should be productive with zero configuration — customization is opt-in.
- Return specific types, not generic ones. createUser() returns User, not Object/any. Specific types enable IDE autocomplete and catch errors at compile time.
- Use method overloading or union types to handle multiple input formats: accept both a string ID and a full object where it makes sense.
- Make side effects explicit. Functions that read data should not write data. Functions that modify state should have names that indicate mutation (save, delete, update).