State in Web Applications

The prevailing strategy of writing web applications is to write server-side code that renders the interface in full. Dynamic interaction, when needed, is achieved by playing tricks with the DOM using frameworks like jQuery or Backbone, but the majority of interactions happen via following links and receiving pages from the server. I’ll call this the CGI way, and there’s certainly plenty of fun to be had using it. You’re afforded a nice programming language on the server side with a plethora of tools to make your life easier, with JavaScript and its unique strengths and weaknesses providing variety on the client side. If you look at an app like the old Basecamp, it’s clear that you can make quality products this way. Despite this, I feel the approach is deficient.

I believe the fundamental problem centers around state. At Atomic Object, we tend to have an allergy to state, and for good reason: as you keep more state, the complexity of your logic increases, the testability of your code decreases, and unforeseen interactions become more likely. Without keeping some state, however, it becomes harder or impossible to do practical things.

The problem with the CGI way is that the state of your application is bifurcated between client and server and exists in different places at different times. The server is responsible for building most or all of the interface, but must start fresh with each request using only persisted and request data. Objects are required to be short-lived to the point where it becomes a handicap. For a good example, think about the subtle problems with multiple ActiveRecord objects representing the same row in a table, or where inserting my_record.reload was the fix for a problem.

On the other side, the client takes its turn keeping track of the information required to make requests back to the server. A significant effort goes into passing this data back and forth, and as applications become more dynamic on the client side, so does the need to re-architect models for the client side. This duplication isn’t ideal and can be very frustrating.

A trend has been slowly emerging where newer frameworks such as Cappuccino and Ember.js are beginning to address this problem. Moving more responsibilities to the client and reducing the server to an API is an excellent idea, as it consolidates state on the client side and helps force your server API to be well-defined. I’m excited to see how this trend continues and what new frameworks appear in the future.