The first two articles in this series discussed the importance of goals and consumers, two factors critical to...
designing APIs. Combined, these factors emphasize the importance of context for design. The context may influence the technologies involved or the scope of information exposed.
Once the context for the API has been established, it's time to get down to the details. This is broken into separate sections on read operations versus write operations because the majority of a service portfolio will be read operations, both in the number of operations exposed and in the number of invocations. The write functions should be minimal, preferably with only one way of making the update occur.
On the read side of things, flexibility must be kept in mind. As a developer, what comes to mind when you think about reading information? SQL. When looking at technologies for service invocations today, providing inquiry flexibility is largely left up to design. SOAP doesn't provide functional structure on its own, only the mechanisms to design a structure. REST, when applied using HTTP, at least relies on the HTTP verbs and URL structure, therefore GET and query parameters can be used. Although that provides some framework, there's still more design work to do.
Get going with nouns
Step one is to start with nouns. This applies whether you're using REST or SOAP, XML, or JSON. With REST, there will be the verb "GET." With SOAP, there will be an operation of the form "get XYZ." Don't worry about the verbs; focus on nouns and their structure. REST calls these nouns resources. SOAP, harkening back to when SOAP was an acronym, calls these nouns objects. For our purposes, this will be referred to as a resource model. A resource model needs to be designed that represents the information exposed by inquiry APIs. It's an information modeling exercise. This doesn't mean a logical database model can be picked up and run through a code generator, and the APIs that result exposed. A database may be optimized for other purposes, and there may be dynamically generated values. Most important, best practices of SOA should be followed and APIs used to present an appropriate abstraction layer.
The amount of information can be daunting, especially if you're looking at internal APIs. In their book, A Practical Guide to API Design, authors D. Keith Casey, Jr. and James Higginbotham provide guidance for using this resource model. They recommend a simple classification scheme for resources as either independent (can stand completely on their own), dependent (relevant only when they're in the context of another resource), or associative (information is needed to describe the relationship between two resources).
Once a resource model has been made, the next decision is how to expose the information model. A RESTful approach using HTTP GET with JSON responses is the most popular technique. However, the decisions don't end there. A call to an HTTP GET will return a single resource or a collection of resources. But if that resource has dependent resources, should they also be returned, or should there be a return link to them? What if the resource has a substantial number of attributes? Will the entire resource be populated? If not, how will consumers specify what information they want? Specifications like OData or JAX-RS can be considered for this, and it's also an area where one should look to tooling.
It's important to keep in mind that frameworks and tooling are not substitutes for design work. If so, there wouldn't be a need for articles and books on the subject. For the decisions about how little or much data to expose, think about the following:
How frequently will services be changed? If all data isn't exposed (at least internally) every time a consumer needs something that isn't accessible, a change in service will be necessary. It may be best to change inquiry services only when underlying data sources change, not when consumers change.
Are there performance implications associated with retrieving any portion of the data? For example, returning another column from a database typically won't impact performance. Performing a join with another table will have a more significant impact.
How much flexibility should consumers have? Allowing them to ask for exactly what they want versus choosing from some predefined collections has tradeoffs. Predefined collections are quicker to implement and provide a layer of protection from misbehaving consumers. The tradeoff, however, is that if predefined collections don't adequately cover the use cases, there will be a stream of change requests. If maximum flexibility is wanted, the implementation will be more complex, translating some form of query language into appropriate calls to data sources, and applying defensive programming to make sure the allowed flexibility doesn't put the stability and integrity of the data systems at risk.
Eighty percent of this article about designing APIs covers the inquiry side of things, which is justified, because 80% of APIs may be about supporting inquiries. The other 20% will cover APIs that allow a consumer to request that actions be taken. This is where things may get a bit controversial.
Don't forget verbs
In the world of HTTP verbs, besides GET, there are PUT, POST and DELETE. While it's true that most everything about information systems comes down to creating, reading, updating and deleting, those aren't the only verbs used to describe business processes. This really comes down to PUT and POST.
SOAP tunnels everything into a POST request for a reason: It's the most flexible. In a common e-commerce scenario, does anyone ever use the verbs POST, or update? No, there are verbs like buy, pay and checkout. Does this make this aspect of RESTful approaches bad? Certainly not. It simply means that to follow the rules to the letter, developers will need help to understand what needs to be PUT or POST to buy an item, ship a package or whatever the business may be. Aspects of REST, like having links to other resources, are still important and should be part of an API.
No matter how much time is spent understanding goals, knowing consumers and coming up with the perfect resource model, things will change. The last article in the series will cover versioning and provide detail on the additional role management tools can play when designing APIs.
About the author:
Todd Biske is an enterprise architect with a Fortune 50 company in the St. Louis metro area. He has had architecture experience in many different verticals, including healthcare, financial services, publishing and manufacturing, over the course of his 20-year career.
Find out if you have what it takes to design APIs