I’m pretty confident the vast majority of developers have either used or are at least familiar with RESTful APIs. I have a love-hate relationship with them. On the one hand, I understand the rationale behind the architecture and agree with
all most of the constraints which has has driven me to create the most beautiful APIs you could imagine. However, there is a but - I always end up having to bastardise my design to satisfy a requirement that goes beyond traditional CRUD calls.
Here’s a few RESTful contracts that follow the usual trend of using the HTTP Method to indicate the operation around a resource:
# Create a new user /users POST # Find a specific user /users/:userId GET # Update a specific user /users/:userId PUT # Delete a specific user /users/:userId DELETE
Create, Read, Update, Delete. CRUD. But what if we want to Clone a user? Or Block/Unblock them? Yes, there are “RESTful” ways to do this, but they all suck IMO. Let’s take a closer look at some of the proposed solutions I’ve seen for cloning a user:
- Custom HTTP Method
- Special header as part of a PUT request
- Query string argument (pointing to the original resource) as part of a POST request
…but my particular favourite is creating a fake child resource to house the clones (e.g.
users/:userId/clones). Really? And all because we want to be RESTful!
My point is that you’ll spend unnecessary time trying to convert business rules into a CRUD pattern just for the sake of it. It reminds me when ASP.NET MVC 1.0 was released and everyone (including myself) was on the N-Tier bandwagon after reading about NerdDinner. We blindly abstracted an abstraction in the form of
IRepository<T> that gave us a warm feeling inside, only to realise that it was ultimately a waste of time (but that’s for another blog post).
Ensuring everyone speaks the same ubiqutous language is more crucial to the success of a project and this applies directly to the code along with any integration points that are exposed. The fact that there is only a finite number of HTTP Methods that don’t always align with the business domain contradicts that statement. If we could extend this list, I’d probably be writing a completely different blog post or nothing at all, but we can’t.
Luckily, I have the answer in the form of Verby APIs (Tweet me if you have a better name).
Verby APIs only use two of most common HTTP Methods;
GET for reading state and
POST for changing state which is similar to how websites (should) work. The URLs follow a simple convention that will be familiar to any RESTafarian:
# Create a new user /users/create POST # Find a specific user /users/:userId/find GET # Update a specific user /users/:userId/update POST # Delete a specific user /users/:userId/delete POST
Hopefully you’ll be able to see where the name comes from - every URL ends in a verb. Be creative, but it’s always good to have some common verbs to cover the basic (CRUD) operations;
UPDATE. In terms of the URL structure before the verb, it’s petty much RESTful with a parent resource followed by an identifier and any optional child resource. Simples.
You might be reading thinking this is an outrageous idea, but ask yourself why you’re so against it. I’d suggest telling me in the comments, but I haven’t got round to adding them yet 😉.
Verby APIs tie in really nicely with CQS (Command Query Separataion) but I’ll talk more about that in my next post.