The limits of MVC for APIs

(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: lawrence@krubner.com, or follow me on Twitter.

This article has some stupid points, but this is good:

A thick client does not want to maintain a vast list of static strings representing all the crazy URLs that it will have to call in a non standard API. As an API designer, you don’t want them doing this anyway, because hard-coded URLs and URL structures make it a real pain for you to change your API.

The AtomPub protocol, if you ignore its XMLiness, gets this right — The thick client just knows the root URL (which serves up a simple service document) and is aware of a bunch of relationship types (the ‘rel’ attribute on ‘link’ and ‘a’ tags) that it can follow as necessary. If a game client needs to access a list of players, it just goes to the root url, and follows the link with the rel property called ‘players’ (and probably remembers that link until the server says it has moved via 301 status code). JSON has no concept of links or rel, but this is still easy to imagine and implement, and while it’s a teeny bit of extra work up front, the standardization buys you the ability to start writing smarter HTTP/REST clients for your frontend that take care of much more for you automatically, so you can spend time on real business logic and actually do something more productive than fiddle with the javascript version of a routes.rb file.

(A really great API framework might generate some or all of these links on its own and automatically put them in the JSON documents. It’s pretty easy to imagine pagination links like next/back being generated automatically, or even links amoung resources in some cases, possibly based on some internally declared relationship.)

I think the most important point is that MVC frameworks like Rails are not setup to handle true HATEOAS:

The last constraint is incredibly simple, but nobody actually does it. It’s named Hypertext As The Engine Of Application State. I still haven’t decided how to pronounce the acronym, I always try to say “Hate ee ohs,” which sounds like a breakfast cereal. Anyway, let’s break this down. We’re using Hypertext, fine, that makes sense. But what’s it mean to be an engine? And application state?

It’s all about state transitions. It’s right there in the name: Representational State Transfer. Your application is just a big state machine.

Your APIs should do this. There should be a single endpoint for the resource, and all of the other actions you’d need to undertake should be able to be discovered by inspecting that resource. Here’s an example of what our Entry XML might look like if Rails handled HATEOAS:


1337
Steve Klabnik

When we GET a particular Entry, we discover where we can go next: we can make a new comment. It’s a discoverable action. The particular state we’re in shows what other states we can reach from here.

Now, when I said ‘nobody’ does this, what I meant was ‘for APIs.’ This is exactly how the Web works. Think about it. You start off on the homepage. That’s the only URL you have to know. From there, a bunch of links point you towards each state that you can reach from there. People would consider it ludicrous if they had to remember a dozen URLs to navigate a website, so why do we expect the consumers of our APIs to do so as well?

On a totally different track, we could say that stuff like Rails is not set up to handle new protocols like WebSockets, since WebSockets is all about getting away from HTTP. That is not a criticism of Rails, but if WebSockets suggests the future of the Internet is less about the Web, then stuff that is very much about the Web, like Rails, will suffer a relative decline, no matter how much it improves at its core mission.

Post external references

  1. 1
    http://caines.ca/blog/programming/the-sun-is-setting-on-rails-style-mvc-frameworks/
  2. 2
    http://timelessrepo.com/haters-gonna-hateoas
Source