The Sun is setting on rails style MVC Frameworks

Lately I’ve been thinking a lot about the impact of the move to a thick client architecture for web applications, and I’m becoming more and more certain that this means that Rails-style MVC frameworks on the server-side are going to end up being phased out in favour of leaner and meaner frameworks that better address the new needs of thick-client architecture.

There are a few major reasons for this:

The server is no place for view logic

The devices available for running a web app are vastly different from when these web frameworks first sprung up. The slide towards thicker / richer clients has been proceeding on pace with increases in processing power since the Web 2.0 days. It’s much simpler to handle views and view logic in only one place, and that place is slowly moving away from the server side. MVC has always been a strained pattern for a server-side, non-gui application and it is been a confusing and complicated trade-off to have the backend generating front-end logic. Front-end frameworks like backbone.js, as well as advances in web technologies like HTML5’s history.pushState are now making server-free views a realistic quality of cutting-edge front-ends. Rendering on the client-side also gives us the opportunity to create responsive designs based on device capability rather than having the server try to somehow figure out what the capabilities are without actually running on that device.

The kinks aren’t all the way out yet, but I do think the trend is clear.

Server-side Templating and .to_json are both underpowered and overpowered for the actual requirements of JSON APIs

There’s no need for templating on the serverside (or view helpers, or any view-related cruft) to generate simple JSON documents, but there are a tonne of problems left unsolved when we fail to see that generating a JSON API is more than just a serialization problem.

How should dates look? (RFC3339 / ISO8601 of course!). What should the JSON error document look like when you provide a 400 and want to tell the client why? How should links to other resources in the API look? How does a collection look? How does pagination look?

These aren’t just serialization concerns, and they have nothing to do with templating.

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.)

In a resource-oriented API, the router need not be concerned with the http methods that are or are not allowed for the resource. That’s the concern of the resource and the resource alone. When the router tries to manage that, you get the unnecessary verbosity of a route for every method supported by the resource, and you get the app incorrectly throwing 404s instead of 405s when a method is not supported. This probably means that ‘controllers’ need to go away in favor of ‘resources’, and routes can be vastly simplified, if not completely derived/inferred by the framework. Because we keep thinking in this conventional MVC style though, we miss the possibility and potential of vastly more simple applications that actually do a lot more more for us.

The Application Developer shouldn’t have to Deal with these Details

There’s no reason for us to all separately think about these problems and solve them in a million different ways every time we’re confronted with them. Aside from the years of wasted time this involves, we’ve also got a bunch of non-standard and sub-standard APIs to interact with, so all the client code needs to be custom as well and nothing is reusable. This is why being RESTful is not just academic and this is why being concerned with the details is not pedantic.

As I said earlier, AtomPub gets a lot of this right. A lighter-weight JSON equivalent would be a huge improvement to what people are doing today, because the conventions would mean that the framework can take care of most of these API details that we reimplement ad nauseum — or worse, not at all. It also means that frontends can start to abstract away more of the HTTP details as well. This is already starting to happen in the new frontend MVC frameworks but in almost every case, the HTTP end of things still needs to be handled in a custom way for every API endpoint. There is still way too much work left to the application developer, and we’re silly to continue to do it over and over without coming up with a better abstraction.

CouchApps and WebMachine are just starting to touch on this style of architecture. Backend-as-a-service platforms like Parse certainly understand how far this simple architecture can go, but ultimately there’s a huge need for a framework that can create more complex RESTful APIs (in a language that’s more general purpose and “blue collar” than Erlang).

Rails-style MVC frameworks are both too much, and not enough at the same time. It really is time for a new framework to support this new architecture.