Dieter Rams’ Design Principles
|
Core Principles Good API design
|
Good Design Makes a Product Useful – A good product must have utility and always balance form with function. |
Before all other considerations, firstly your API has to do something useful. I like to say, an API is just a messenger. Don’t shoot the messenger if the real problem you have is that you haven’t yet built some useful services the world needs to be served over an API. Then to make that service useful, the API needs to offer the right granularity, call sequencing and inputs/outputs that at least minimally enables the solutions your customer will want to build.
If you’re having difficulty getting customers to integrate your API (or any new product), usefulness is the assumption you really need to validate first – before assuming any other aesthetic re-working will solve your problems.
|
Good Design Is Innovative – The possibilities for innovation are not, by any means, exhausted. Technological development is always offering new opportunities for innovative design. Innovative design always develops in tandem with innovative technology, and design can never be an end in itself |
Great SaaS APIs unlock your customer’s ability to innovate, by being really good at one thing, so they don’t have to be. Innovation is cumulative, and engineering advances through useful layers of abstraction. Every good API a little giant for others to stand upon. Innovation also means differentiation, and avoiding commoditization. If there are many others already like it, what new value are you creating?
Conversely, good APIs are not led by Resume-Driven-Development. Be careful of the occasional impulse to leap upon new fashionable platform/language/frameworks etc as and end in itself.
|
Good Design Is Aesthetic – The aesthetic quality of a product is integral to its usefulness because products are used every day and have an effect on people and their well-being.. |
An aesthetic API picks a clear, readable, self-documenting style and is consistent. An elegant software design avoids ugly quirks or hacks to be effective.
A good API will steer (and not arbitrarily restrict) API users from making good design choices in their implementations. Aesthetic, UX tested reference apps or implementations can go a long way to set a bar or exceptions and help implementers make good choices. All of which will ultimately best improve changes success with end users and adoption.
If all else fails, just make sure your developer-docs site has a cool chill-wave vibe and renders well when viewed in ‘dark mode’.
|
Good Design Makes a Product Understandable – Good design leverages affordances, it can make the product clearly express its function by making use of the user’s intuition. |
Good APIs are well documented. Starting with having accessible (preferably public) documentation. And that the API’s behavior actually matches what’s in the documentation and the examples (Sounds obvious, but surprisingly hard in practice to maintain). Good APIs themselves should be self describing as reasonably possible. Sure, ‘naming things’ is known as one of the Hard Problems in computer science. Nonetheless, endpoints, methods, parameters, and returned results should strive to use intuitive names that convey their purpose and functionality.
Following familiar conventions (like standard REST and JSON) makes APIS understandable and reduces the learning burden on developers. Consistency is Key across your API products, rather than forcing developers to relearn different idiomatic patterns arbitrarily. Next best practices are having language-specific examples, ‘recipes’ for different solutions, SDKs if applicable, mock/sample apps to demo and test capabilities.
|
Good Design Is Unobtrusive – Neutral, allows user expression. |
One of the main reasons we build APIs as abstraction layers to our backends is to give flexibility to the front end implementation. A non-leaky abstraction is unobtrusive. A good API doesn’t force awkward or unnecessarily restrictive design choices for the front end. Good APIs can be opinionated about proper useage, Minimizing foot-guns and generally making it harder to use the API poorly. The art though is an inevitable tension between designing an API that is broad enough to support many use cases but exposes excessive complexity, data and surface area than is strictly needed for any one use case. Vs trying and failing to create a perfectly scoped API that becomes too narrow or restrictive to support some important but newly discovered use case.
What I love best, is to design a clean set of versatile primitives. Each service simple on their own, but composable and flexible to serve diverse customer segments, usecases and solution types.
|
Good Design Is Honest – Truthful about product capability. |
The Principle of Least Surprise:Â Software should behave in a way that is least surprising or astonishing to its users. In terms of capabilities and performance, this means that a system should accurately represent what it can and cannot do, and how well it performs.Â
Be up front about Beta vs GA readiness of your service. You’d be surprised how much less concerned your customers are about absolute levels of uptime, performance, bugs vs what they experience relative to the initial expectations you set.
|
Good Design Is Long-Lasting – Avoids being outdated quickly. It avoids being fashionable and therefore never appears antiquated. |
Extensible and Maintainable – Designing and launching some new feature is like the exciting ‘kitten’ phase of software ownership. But remember, the real cost is that, that you could now be on the hook for feeding and changing the litter box on this once-cute feature for years more to come. Software must always be maintained, patched and supported. And you need to build with that in mind. Similar to durability, Throw-away work and tech debt happen, but try to be intentional vs accidental about it. You often end up living with those choices longer that originally imagined.
Don’t break your Customers – Allow your customers’ investments in your service to be as durable as reasonably possible. Good APIs should be extensible without breaking or requiring onerous re-integration and re-testing by existing users. New features should be optional rather than required, and existing users should see forced version updates rarely as possible. (protip: But maybe also include some contractual sticks/carrots to keep your customers from forcing you to support legacy versions beyond all reason 🙂
|
Good Design Is Thorough – Care in every detail. |
Robustness Principle or Postel’s Law: “Be conservative in what you send, be liberal in what you accept”. This means an API or data system should strive to be as accepting as possible of the input data it receives (while still ensuring security), and follow standards strictly when sending data or communicating outward.
Errors and Exception Handling Matters: Sweat these details in the requirements. Your API should provide meaningful error messages that help developers understand what went wrong when a request fails. A lazy API spec focuses only the happy path, leaving other paths as ambiguous or undefined. |
Good Design Is Environmentally Friendly – Conserves resources, does not deliberately or incidentally externalize costs and harms. |
Literally environmentally friendly – not wasteful in use of resources, including memory, CPU cycles, and bandwidth. Both benefiting infrastructure costs of scaling and direct environmental impact of energy use.
Mindful of the Compliance, Security, Privacy Environment -Â For example, a mindful API doesn’t ask for, nor return any private data not strictly needed for the usecase, and adequately protects any private data that is.
The digital, social and economic environment – a responsible API designer would not single-mindedly help drive-up online clicks and engagement, but while also incidentally undermining western liberal democracies in the process. Â
|
Good Design Is as Little Design as Possible – Purity & simplicity. |
The ideal API asks for only what it needs, and returns only exactly what is needful
Similarly, a nice API is not overly chatty, requiring more round trips (each round trip adds more latency, more resources, more things to code and debug) than should be necessary.
Of course, easier said than done. Rare to get the above perfectly right on the first release of an API spec, nor is it even reasonable (or desirable) to necessarily predict all future use cases for your web service. Nonetheless, ‘as simple as possible, but no simpler’ is an important ideal. Versatility and flexibility are also valuable, but I always like to think of anything that drives complexity, as a budget to spend carefully and to continually re-evaluate.
Generally, the less complexity you need to effectively get a job done, also creates less surface area you’ll have later for bugs, exploits and maintainability. The less complexity debt you assume now, the faster you’ll be able to iterate and innovate on your product in the future
|