Friday, January 20, 2012

Single page web apps and REST

I was inspired by the Trello tech stack blog post. I've been talking and writing about something similar during the last year or so but never blogged about it. I agree on most of the points made in the post but they could -- and should -- go even further.

Traditionally, web applications are burdened with the spaghetti of too many technologies. The application logic is fragmented over many technologies: HTML/templates, JavaScript and a server side language. This kind of fragmentation makes it very difficult to maintain a consistent code base and to apply proven software patterns like information hiding and responsibility assignment. Web frameworks alleviate  problems to some extent but they don't take away the underlying problems. In the end, it's up to the developer to try and maintain the codebase and the responsibilities of different components. On the other hand these frameworks make things even worse because developers become dependent on their features and start using them blindly, maybe even without complete understanding of what goes on behind the scenes. The code they produce and the skillset they end up with is very difficult to reuse.

We have all been there; we start with a clean design, we set up our MVC model as provided by the framework. We implement the application logic on the server and the view becomes more or less a static web page that is presented to the user. Then we realize that our application is too slow and too error prone. Too many page reloads and too many milliseconds there is a blank screen before a new page comes up. Now starts the optimization; we start adding adding stuff into HTML templates for more convenient rendering and especially we start adding JavaScript to make pages more dynamic. Now we have a web application that is implemented in HTML templates, Java and, JavaScript. Moreover, the client and the server are very tightly coupled and any kind of reusability is seriously compromised.

This is not good.

Highly interactive web applications should be written more like the Trello application; do full MVC on the client side and build an API on the server that the client app consumes directly. Key point here is that you should completely decouple the client and the server. Implement the client as a single page web application that you can either host on a server or wrap it as an application that can be distributed in one (or several) of the web stores. The server on the other hand should be implemented in terms of REST. We are already dealing with HTTP so it makes sense to make best use of it. Another thing that speaks for using REST is its clear separation of responsibilities between the client and the server: the application is responsible for maintaining its state and the server is responsible for maintaining the state of the resources it exposes. There's no more guesswork like "should I implement this functionality in JavaScript, HTML templates or on the server?". You implement the application as much as possible in the client and use the server API only when necessary. 

Compared to the traditional way of implementing web applications this approach brings with it many advantages (these points are discussed in further detail in my paper presented at USENIX WebApps '11, slides):
  • Reusable service interface: the server API becomes reusable. You can use it from another application (possible a mobile app) or you can publish it for others to use.
  • Reusable client application: if you need the application in another environment, you can build the same REST API on top of that system and be able to use the same client application.
  • Responsibilities are easier to assign and enforce: REST sets a strict fence between the client and the server. This makes things like data validation, error handling and localization more explicit and easier to implement. Or should I say, more difficult to mess up.
  • Easier development model: the application logic is not fragmented over different technologies. The client and the server can be developed and especially tested individually and they both have their own internal design and architecture. Implementation of the client application becomes more like implementing a traditional desktop application.
  • Better user experience: the application is not reloaded all the time, so it's snappier. Moreover, the network traffic is minimized because only the payload data is transferred. After the initial page load (bootstrapping), no more CSS, HTML or JavaScript is transferred.

If you looked at the Trello tech stack, you can see that they did half of what I just explained. They have the single page web app with full MVC and they have the server API too. Only thing missing is the REST API. Actually, it just so happens that they are now also building the REST API but it's a different one. What I would like to see is them eating their own dog food and use the API directly from the web application. For some reason this seems to be fairly common these days: many web applications (that even have an API to begin with) have one API for their own use and another API for 3rd party access. If this is due to the fact that they don't want to allow 3rd party access to all of the same resources they have themselves, they should just implement proper authorization scheme. But that's another topic.

We have successfully utilized this approach on several of our (closed source / private) products so far. Not only have we been able to reuse the REST API but also the applications. We have implemented the same API on top of another system to be able to use some of the same applications in that setting. Compared to what we were doing before (traditional model 2 web applications) we have seen a serious boost in productivity and reusability.

No comments:

Post a Comment