Daniel Watrous on Software Engineering

A Collection of Software Problems and Solutions

Posts tagged restful

Software Engineering

Design principles for REST APIs

I have recently had to work with a few REST APIs that exhibited some poor design choices that I had previously assumed would be obvious. Since they may not be obvious to everyone, I wanted to highlight them.

Idempotent operations

When an operation is idempotent that means that an end state will be identical regardless of how many times the operation is executed. If the end state is dependent on the number of times an operation is executed, then it is not idempotent.

Why is this important?

REST interfaces should assume unreliable networks (which isn’t hard). A consumer of a REST API may issue the same call multiple times if a call fails, or times out or for any other reason. An idempotent operation ensures that the end result of a system is identical in cases where an operation is called multiple times.

The most common violation of this in REST APIs is a call to create a record using a POST. I do agree that in some cases it is unavoidable, but there are many instances where a PUT would be a good replacement. PUT semantics simply make the server representation of a resource match what is sent in. When a POST is unavoidable, it may be possible to add some throttle or comparison function in the API that monitors for replays and either drops them or flags them as potential duplicates.

Authentication

Authentication is a critical element of any application. Fortunately there are some well established standards which also make your application more interoperable, such as oAuth. Unfortunately, many developers tend to roll their own authentication code, which can be a resource drain and present security risks.

What is this important?

Security is a big deal and has a huge potential impact on business for better or for worse. More and more businesses are getting hacked, which comes with a huge cost to both businesses and consumers.

Accepted standards are more likely to be secure. It is also more likely that there is an existing implementation that can be dropped in to your application.

Personal Information

Personally Identifiable Information (PII), such as username, email, user ID, address, phone, etc. should NEVER be included in a URI. Not only does this muddy the concept that a URI identifies a resource (since a userid in the URI would make it appear to be many resources, one for each userid), but it also compromises personal information. Any necessary personal information should be transmitted in the HEADERS or BODY of the request, not in the URI.

What is this important?

In REST, it’s important to make sure that a given URI identifies one resource, whether that resource is identified as a single item or a collection of items. It must also be reproducible. When personal information is included in a URI, the resource correlation is lost.

Proxy and cache servers often use the URI as the cache key to facilitate lookups. Most web servers also include full URIs in log files. For these reasons, any personal information that is included in the URI may end up persistently stored on any number of systems, including the local browser.

Response Codes

HTTP response codes are standard. Unfortunately many REST APIs make poor use of the standard. Some lump nearly all response states into just one or two response codes, like 500 and 404. Others deviate from the standard and create their own response codes. I’m not going to argue that the available response codes are sufficient for every case. What I will argue is that there is more value in terms of interoperability and adoption when a REST API conforms to existing response codes.

What is this important?

REST APIs are designed to accommodate integration with other systems and applications. Developers of those systems and applications are more likely to be familiar with the standards. It may even be that they are using a library that only accommodates standard response codes (possibly omitting 418 I’m a teapot). Sticking with standard response codes makes integration more straight forward.

Software Engineering

WordPress plugin licensing: API and class diagram

In the first article in this series, I sketched out some of the basic design ideas for the wordpress plugin licensing system.

The next step is to come up with some more concrete details about how the application will work, what information it will manage and what the interfaces will look like when accessing it. I really like using the UML as I flesh out a design. In particular I find the class diagram and activity diagram useful.

I frequently make use of stereotypes to extend the meaning of my classes. I’m not sure if this is exactly how the UML was intended to be used, but it’s really helpful. At times I also use simple tables, hand drawings, etc. if it helps capture an important point.

Here are the first design documents showing the classes I have in mind for the application and the RESTful API that will provide access to them.

Classes and API

Design choices

My initial design included normalized classes for Licensee, Product and LicenseTemplate. This would prevent duplication of licensee data across multiple licenses and would facilitate reporting by liensee and product. I also had APICall associated with AdministratorAccount since each API call could correspond to various objects in the system.

As I fleshed out the API, a few drawbacks came to mind regarding the normalization I mentioned above. First was the additional complexity in managing all of the normalized classes and associating parent and child objects. Since I am not targeting an RDBMS, the traditional SQL joins and other query approaches don’t benefit me with properly normalized design. I can make the application much more performant and simple by keeping everything in a single SiteLicenses container as shown.

Next design steps

You can see from the diagram above that I haven’t begun assigning responsibilities yet. However, it’s easy to see already where some of the key responsibilities, like isPremiumAccount(), getSiteLicenses(), revokeLicense(), getAPICallsMinutes(Integer minutesBack), etc. will end up.