Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 3, 2022 05:06 pm GMT

How to Build a Good API That Wont Embarrass You

Everyone and their puppy wants an API these days. APIs first gained popularity around 20 years ago. Roy Fielding introduced the term REST in his doctoral dissertation in the year 2000. It was the same year that Amazon, Salesforce and eBay introduced their APIs to developers around the world, forever changing the way that we build software.

Before REST, the principles in Roy Fieldings dissertation were known as the HTTP object model, and youll see why thats important soon.

As you read on, youll also see how to determine if your API is mature, what are the main qualities of a good API, and why you should focus on adaptability when building APIs.

The basics of RESTful architecture

REST stands for Representational State Transfer, and it has long been the holy grail of APIs for services, first defined by Roy Fielding in his dissertation. Its not the only way to build APIs, but its the kind of standard that even non-developers know about thanks to its popularity.

There are six key characteristics of RESTful software:

  1. Client-Server architecture
  2. Statelessness
  3. Cacheability
  4. Layered system
  5. Code on demand (optional)
  6. Uniform interface

But thats too theoretical for daily usage. We want something more actionable, and thats going to be the API maturity model.

The Richardson Maturity Model

Developed by Leonard Richardson, this model combines the principles of RESTful development into four easy-to-follow steps.
The Richardson Maturity Model
The higher you are in the model, the closer you get to the original idea of RESTful as defined by Roy Fielding.

Level 0: The swamp of POX

A level 0 API is a set of plain XML or JSON descriptions. In the introduction, I mentioned that before Fieldings dissertation, RESTful principles were known as the HTTP object model.

Thats because the HTTP protocol is the most important part of RESTful development. REST revolves around the idea of using as many inherent properties of HTTP as possible.

At level 0, you dont use any of that stuff. You just build your own protocol and use it as a proprietary layer. This architecture is known as Remote Procedure Call (RPC), and its good for remote procedures / commands.

You usually have one endpoint you can call upon to receive a bunch of XML data. One example of this is the SOAP protocol:
SOAP protocol
Another good example is the Slack API. It is a bit more diverse, it has several endpoints, but its still an RPC-style API. It exposes various functions of Slack without any added features in-between. The code below allows you to post a message to a specific channel.
Slack API
Even though its a level 0 API according to Richardsons model, it doesnt mean its bad. As long as its usable and properly serves the business needs, its a great API.

Level 1: Resources

To build a level 1 API, you need to find nouns in your system and expose them through different URLs, like in the example below.
Level 1: Resources
/api/books will take me to the general book directory. /api/profile will take me to the profile of the author of those booksif theres only one of them. To get the first specific instance of a resource, I add an ID (or another reference) to the URL.

I can also nest the resources in the URLs, and show that theyre organized in a hierarchy.

Going back to the Slack example, heres how it would look like as a level 1 API:
Level 1 API - Slack example
The URL changed; instead of /api/chat.postMessage, now we have /api/channels/general/messages.

The channel part of the information has been moved from the body to the URL. It literally says that using this API, you can expect a message to be posted to the general channel.

Level 2: HTTP verbs

A level 2 API leverages HTTP verbs to add more meaning and intention. There are quite a few of these verbs, Ill just use a fundamental subset: PUT / DELETE / GET / POST.

With these verbs, we expect different behaviors from URLs containing them:

  • POSTcreate new data
  • PUTupdate existing data
  • DELETEremove data
  • GETfind the data output of a specific id, fetch a resource (or an entire collection)

Or, using the previous /api/books example:

/api/books example
What does safe and idempotent mean?

A safe method is one that will never change data. REST recommends that GET should only fetch data, so its the only safe method in the above set. No matter how many times you call a REST-based GET method, it should never change anything in the database. But its not inherent in the verbits about how you implement it, so you need to make sure that this works. All other methods will change data in different ways, and cant be used at random. In REST, GET is both safe and idempotent.

An idempotent method is one that wont produce different results over many uses. DELETE should be idempotent according to RESTif you delete a resource once and then call DELETE for the same resource a second time, it shouldnt change anything. The resource should already be gone. POST is the only non-idempotent method in REST specifications, so you can POST the same resource several times and youll get duplicates.

Lets revisit the Slack example, and see what it would look like if we used HTTP verbs in it to do more operations.

Slack API verbs
We could use POST to send a message to the general channel. We could fetch messages from the general channel with GET. We could delete messages with a specific ID with DELETEwhich gets interesting because messages are not tied to specific channels, so I might want to design a separate API for removing messages. This example shows that its not always easy to design an API; there are plenty of options to choose and trade-offs to make.

Level 3: HATEOAS

Remember text-only computer games, without any graphics? You just had a lot of text with descriptions of where you are, and what you can do next. To progress, you had to type your choice. Thats kind of what HATEOAS is.!
Text game APIHATEOAS stands for Hypermedia as the Engine of Application State

When you have HATEOAS, whenever someone uses your API they can see other things they can do with it. HATEOAS answers the question, Where can I go from here?
hateoas example
But thats not all. HATEOAS can also model data relationships. We can have a resource, and we dont have authors nested in the URLbut we can post the links, so if someones interested in authors, they can go there and explore.

This is not as popular as other levels of the maturity model, but some developers use it. One example is Jira. Below is a chunk from their search API:
Jira API
They nest links to other resources you can explore, as well as a list of transitions for this issue. Their API is quite interesting because of the expand parameter at the top. It allows you to choose fields where you dont want links, and prefer the full content instead.

Another example of using HATEOAS is Artsy. Their API heavily relies on HATEOAS. They also use JSON Plus call specifications, which imposes a special convention of structuring links. Below is an example of pagination, one of the coolest examples of using HATEOAS.
Artsy hateoas
You can provide links to next, previous, first, last pages, as well as other pages you find necessary. This simplifies the consumption of an API, because you dont need to add the URL parsing logic to your client, or a way to append the page number. You just get the client ready to use already structured links.

What makes a good API

So much for Richardsons model, but thats not all that makes a good API. What are other important qualities?

Error/exception handling

One of the fundamental things I expect from an API that I consume is that there needs to be an obvious way to tell if theres an error or an exception. I need to know if my request was processed or not.

Lo and behold, HTTP also has an easy way to do that: HTTP Status Codes.

The basic rules governing status codes are:

  • 2xx is OK
  • 3xx means your princess is in another castlethe resource youre looking for is in another place
  • 4xx means the client did something wrong
  • 5xx means the server failed500 internal server errorAt the very least, your API should provide 4xx and 5xx status codes. 5xx are sometimes generated automatically. For example, the client sends something to the server, its an invalid request, the validation is flawed, the issue goes down the code and we have an exceptionit will return a 5xx status code.

If you want to commit to using specific status codes, youll find yourself wondering, Which code is best for this case? That question isnt always easy to answer.

I recommend you go to RFC which specifies these status codes, they give a wider explanation than other sources, and tell you when these codes are appropriate etc. Luckily, there are several resources online that will help you choose, like this HTTP status code guide from Mozilla.

Documentation

Great APIs have great documentation. The biggest problem with documentation is usually finding someone to update it as the API grows. One great option is self-updating documentation that isnt detached from the code.

For example, comments arent connected to the code. When the code changes, the comments stay the same and become obsolete. They can be worse than no comments at all, because after a while theyll be providing false information. Comments dont update automatically, so developers need to remember to maintain them alongside the code.

Self-updating documentation tools solve this problem. One popular tool for this is Swagger, a tool built around the OpenAPI specification which makes it easy to describe your API.
Swagger API
The cool part of Swagger is that its executable, so you can play around with the API and instantly see what it does and how it changes.

To add self-updating to Swagger, you need to use other plugins and tools. In Python there are plugins for most major frameworks. They generate descriptions of how API requests should be structured, and define what data comes in and what comes out.

What if you dont want Swagger, and prefer something simpler? A popular alternative is Slatea static API you can build and expose on your URL.
Slate API documentation
Something in-between thats also worth recommending is a combination of widdershins and api2html. Itll allow you to generate Slate-like docs from Swaggers definition.

Cacheability

Cacheability may not be a big deal in some systems. You might not have a lot of data that can be cached, everything changes all the time, or maybe you dont have a lot of traffic.

But in most cases, cacheability is crucial for good performance. Its relevant to RESTful APIs because the HTTP protocol has a lot to do with cache, for example HTTP headers allow you to control cache behaviour.

You might want to cache things on the client side, or in your application if you have a registry or value store to keep data. But HTTP allows you to get a good cache essentially for free, so if its possibledont walk away from a free lunch.
HTTP Cacheability
Also, since caching is part of the HTTP spec, a lot of things that participate in HTTP will know how to cache things: browsers, which support caching natively, as well as other intermediary servers between you and the client.

Evolutionary API design

The most important part of building APIs, and modern software in general, is adaptability. Without adaptability, development time slows down, and it becomes harder to ship features in a reasonable time, especially when you're facing deadlines.

Software architecture means different things in different contexts, but lets adopt this definition for now:

Software architecture: the act/art of dodging decisions that prevent change in the future.

With that in mind, when you design your software and have to choose between options with similar benefits, you should always choose the one thats more future-proof.

Good practices arent everything. Building the wrong thing in the right way is not what you want to do. Its better to adopt a growth mindset and accept the fact that change is inevitable, especially if your project is going to continue growing.

To make your APIs more adaptable, one of the key things to do is to keep your API layers thin. The real complexity should be shifted down.

APIs shouldnt dictate the implementation

Once you publish a public API, its done, its immutable, you cant touch it. But what can you do if you have no other choice but to commit to a weirdly designed API?

You should always look for ways to simplify your implementation. Sometimes controlling your APIs response format with a special HTTP header is a leaner solution compared to building another API and calling it v2.

APIs are just another layer of abstraction. They shouldnt dictate the implementation. There are several development patterns that you can apply in order to avoid this issue.

API gateway

This is a facade-like development pattern. If you break up a monolith into a bunch of microservices, and want to expose some functionalities to the world, you simply build an API gateway that acts like a facade.

It will provide a uniform interface for the different microservices (which may have different APIs, use different error formats, etc).

Backend for frontend

If you have to build one API to satisfy a bunch of different clients, it might be difficult. Decisions for one client will impact the functionality for others.

Backend for frontend saysif you have different clients that like different APIs, say mobile apps which like GraphQL, just build it for them.

This works only if your API is a layer of abstraction, and its thin. If its coupled to your database, or its too big, with too much logic, you wont be able to do this.

GraphQL vs. RESTful

Theres a lot of hype for GraphQL. Its kind of the new kid on the block, but it has already gathered a lot of fans. So much so, that some developers claim that it will dethrone REST.

Even though GraphQL is much newer compared to the RESTful specification, they share a lot of similarities. The biggest downside of GraphQL is cacheabilityit has to be implemented in the client or in the application. There are client-libraries out there that have caching capabilities built-in (like Apollo), but its still harder than using the almost-free cacheability provided by HTTP.

Technically, GraphQL is level 0 in terms of the Richardson model, but it has qualities of a good API. You might not be able to use several HTTP functionalities, but GraphQL is built to solve specific problems.

One killer use for GraphQL is aggregating different APIs, and exposing them as one GraphQL API.
GraphQL killer usage
GraphQL does wonders with underfetching and overfetching, which are issues where REST APIs can be difficult to manage. Both are related to performanceif you underfetch, youre not using API calls efficiently, so you have to make a lot of them. When you overfetch, your calls take result in a bigger data transfer than necessary, which is a waste of bandwidth.

The comparison of REST vs. GraphQL is a great segue into summarizing the most important qualities of a good API.
Features of good API
You need a clear representation for dataRESTful gives you that in the form of resources.

You need a way to show which operations are availableRESTful does that by combining resources with HTTP verbs.

There needs to be a way to confirm that theres an error/exceptionHTTP status codes do this, possibly with responses that explain them.

Its nice to have discoverability and possibility to navigatein RESTful, HATEOAS takes care of that.

Its important to have great documentationin this case executable, self-updating docs can take care of that, which goes beyond the RESTful spec.

Last but not leastgreat APIs should have cacheability, unless your specific case dictates that its not necessary.

The biggest difference between REST and GraphQL is the way they handle cacheability. When you build your API the REST way, you get HTTP cacheability essentially for free. If you choose GraphQL, you need to worry about adding a cache to your client or your application.

Further reading

This article was based on a recent presentation by Sebastian Buczyski. Check out his blog Breadcrumbs Collector and grab his ebook Implementing the Clean Architecture.

For more reading about APIs, check out Phillip Sturgeons blog or his great book called Build APIs You Wont Hate.


Original Link: https://dev.to/stx-next/how-to-build-a-good-api-that-wont-embarrass-you-5hi2

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To