Hard to Misuse
Make interfaces easy to use correctly and hard to use incorrectly, so the design prevents mistakes instead of relying on the documentation.
Also known as: Easy to Use Correctly, Hard to Use Incorrectly, Hard to Misuse Interfaces, Rusty's API Design Manifesto, Misuse-Resistant APIs
Category: Principles
Tags: software-design, software-development, api-design, interfaces, developer-experience, usability, error-prevention, principles
Explanation
Scott Meyers called it possibly the most important design guideline of all: "Make interfaces easy to use correctly and hard to use incorrectly." He wrote about it in IEEE Software in 2004, and in Effective C++. Rusty Russell, a Linux kernel developer, turned the same idea into a scale of API quality known as Rusty's API Design Manifesto.
**The core idea**:
The interface should carry the burden of correct use. If an API can be called in a way that compiles, looks reasonable and does the wrong thing, someone WILL call it that way, sooner or later. Blaming that person fixes nothing; redesigning the interface does.
**Rusty Russell's scale (best to worst)**:
1. It's impossible to get wrong
2. The compiler or linker won't let you get it wrong
3. The compiler will warn if you get it wrong
4. The simplest use is the correct one
5. The name tells you how to use it
6. Do it right or it will always break at runtime
7. Follow common convention and you'll get it right
8. Read the documentation and you'll get it right
9. Read the implementation and you'll get it right
10. Read the correct mailing list thread and you'll get it right
The scale goes on into negative levels, where the obvious use is actually wrong. Your goal is to push every interface as high up that list as you can. Notice where "read the documentation" sits: level 8 out of 10.
**Techniques**:
- **Use precise types**: A `Duration` instead of a raw integer that could be seconds or milliseconds
- **Avoid parameter traps**: `copy(src, dst)` is easy to swap, and `setVisible(true, false)` tells you nothing. Named parameters or distinct types fix both
- **Make dangerous operations explicit**: `deleteAllUnsafe()` beats a `delete()` whose default wipes everything
- **Provide safe defaults**: The zero-configuration call should do the right thing
- **Manage resources automatically**: RAII, `using` or `try-with-resources` instead of manual cleanup
- **Fail loudly and early**: Reject misuse at compile time, or immediately at runtime
- **Stay consistent**: Similar operations get similar names, argument orders and behaviors
**Why it matters**:
An interface gets designed once, then used over and over by people who never saw the design discussion. A little extra effort to make misuse hard saves bugs, debugging sessions and security incidents for every one of them. This is the Pit of Success at the interface level: when misuse is hard, correct use becomes the natural path.
Related Concepts
← Back to all concepts