Prioritize usability, scalability and evolvability in API design
To work effectively, a Web API must display a range of specific software qualities. In this lesson, we outline what we call the “USE Paradigm” – a principle of API design, which states that interface designers should prioritize three particularly important software qualities: usability, scalability and evolvability.
The software qualities that any given API should display will depend, to a certain extent, on the API’s unique context. Nevertheless, in our work with API providers, we have found that the most successful interfaces tend to be highly usable, scalable and evolvable – to the extent that these three qualities can reasonably be considered hallmarks of superior API design.
The USE Paradigm states that, by focusing on designing a Web API that exhibits these three qualities, you can create an interface that offers a better experience both for the developers who build client apps against your API and the end users who consume these apps, while also extending the longevity of these apps.
USABILITY The Design of Everyday Things, a book by cognitive scientist and usability engineer Donald Norman, describes the way people interact with things in the world as an execution-evaluation loop. First, they execute an action, then they evaluate whether the action achieved the effect they were seeking. Then they execute a follow-up action, evaluate that and so on.
So, as developers try to determine how they can use your API, they take actions to achieve a result and then evaluate how successful each action was. They are continuously making usability judgments and assessing how usable your interface is. By keeping this in mind, you will get a sense of how you can improve the usability of your API.
Design for usability When you design your interface, you need to take into consideration: who your target developers are, what they are interested in doing and what skill level they have. But how do you actually tell whether you are addressing these factors effectively in order to create an interface that is truly usable?
This challenge is best approached in three stages:
- An early focus on users and tasks
- Empirical measurement
- Iterative design
From the very beginning of the API design process, it is crucial that you make every decision with a clear focus on your users and the tasks they need to accomplish. If you begin with this in mind, you will find it easier to ensure that, throughout the design process, you remain focused on making it easy for them to accomplish those tasks.
Along the way, you should empirically measure the actual usability of your API by testing how developers interact with it. In the same way you might test a user interface, you can ask developers to perform a task and then measure the number of mistakes they make, how many API calls they make and how many steps they have to go through to finally accomplish the task.
As you receive feedback from these empirical measurements, you should be prepared to enter a process of iterative design. Based on your findings, you can address problem areas and then repeat the execution-evaluation cycle of testing and redesigning as you gather additional feedback on each new iteration of your API.
To get a broader perspective on the usability of your interface, you can test it on a variety of different developer communities – ranging from experienced programmers who have knowledge of sophisticated languages and compiling tools, to eager college students building their first mobile apps.
SCALABILITY A well-designed API will be able to effectively handle a growing workload over time. Scalability should be addressed early in the API development process. If you wait until later to address scalability, you may have to throw hardware at the problem (e.g. by adding more memory or disk power), which will inevitably be less effective than dealing with it at the design stage.
Scale out, not up Scaling up by adding memory, processor power etc. – making the same machine bigger – is easier but less effective. Scaling out by adding more machines requires greater upfront coordination but is more reliable. Virtualization and cloud technologies should be factored into your design from the beginning to enable the quick addition of more machines if necessary.
Take advantage of DevOps practices to support scaling By integrating software development and operations, DevOps has taught us that virtualizing infrastructure and making it more flexible enables scalability. DevOps makes it cheaper and easier not only to add more machines but also to deploy code – in other words, scaling out not just your hardware but your deployment as well.
With the process of deployment simplified, you can deploy APIs multiple times, enabling the iterative design process discussed above. Companies that are the most successful at scaling out do so not only with their hardware or their software design but also with their human resources and processes.
EVOLVABILITY As well as being able to grow and handle extra load over time, your API should be able to evolve and adapt to changing circumstances. The most successful companies make their systems adaptive by designing in the ability to extend in order to quickly react to new developer needs and possibilities as and when they emerge, without breaking existing client apps.
To be extendable, an API must adhere to the following rules:
- Existing elements cannot be removed
- The meaning/processing of existing elements cannot be changed
- New elements must be optional
Removing or even changing existing elements of your API will negatively impact – or even break – the functioning of existing apps that leverage those elements. Similarly, any new elements you add must be optional. Requiring developers to use new elements will create a strong risk of breaking existing apps.
Choose extending over versioning whenever possible It is still common to introduce a new version of an API every time additional functionality is introduced. However, the most successful API providers choose to extend their existing APIs – incrementally adding optional new functionality without removing or altering existing elements. This allows them to evolve their interfaces without breaking anyone’s app.
By contrast, versioning APIs without breaking anything requires a “forking” approach where multiple unrelated versions must be supported. This creates a less-than-ideal developer experience and is also more difficult and costly to maintain. Therefore, versioning should be avoided whenever possible and only used as a last resort (e.g. if there is a security breach).