Use Continuations to Develop Complex Web Applications

An introductory article from IBM developerWorks on Cocoon, continuation-based (sometimes called "modal") web applications, and such.

If you've ever developed a non-trivial Web application, you know that development complexity is increased by the fact that Web browsers allow users to follow arbitrary navigation paths through the application. No matter where the user navigates, the onus is on you, the developer, to keep track of the possible interactions and ensure that your application works correctly. While the traditional MVC approach does allow you to handle these cases, there are other options available to help resolve application complexity. Developer and frequent developerWorks contributor Abhijit Belapurkar walks you through a continuations-based alternative that could simplify your Web application development efforts.

via comp.lang.scheme

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Functional model of web forms

I read the article and thought it rather missed the point. There are two main ways to write form-handling code. The commonly used version is to use a single state-object. However, it is typically better to associate a state-object with every state of the interaction and use side-effect free (or functional) code to write the state transformer.

In the article, continuations were really used as a way to encapsulate state in a rather clumsy way, it seemed to me, lacking transparency. Nor was there any mention of the role of side-effects which rather easily destroy the scheme.

Unfortunately, the single state approach gained dominance very early on in the history of the web with the metaphor of the "shopping cart". This reduced the forward/backward button to navigational transitions rather than state transitions. I recall the debates we had at HP Labs on this topic but the general view at that time was that the shopping cart metaphor was likely to dominate.

Navigation should not change state

This reduced the forward/backward button to navigational transitions rather than state transitions.

This is a very healthy reduction and very RESTful.

The best way to write applications is to keep all the state at the client. That way all communications with the server is static, and can be cached aggresively.

REST of limited usefulness

Keeping state at the client is the best way to write content-driven "applications", but any application that is mostly concerned with providing a service, rather than content, is less likely to be easily arRESTed.

REST assured

sjoerd_visscher wrote:

This is a very healthy reduction and very RESTful.

The best way to write applications is to keep all the state at the client.

In the REST context, it often needs to be made clear that the above comment refers to session state, rather than e.g. resource state. To relate that to the shopping cart example (and to my earlier comment about orders), there's really nothing fundamentally wrong with the idea of a shopping cart as a server-side resource — that's a decision which may be driven by application requirements.

REST design principles argue that server-side carts are less scalable, but they're not "wrong". Besides, Amazon seems scalable enough, server-side carts and all.

In that case, state is kept at the server, but it can be defined, and implemented, as resource state rather than session state.

(Note that the extant definitions of REST are fuzzy enough that this point may be arguable, but I stand ready to defend it using nothing but common sense. ;)

randallsquared wrote:

Keeping state at the client is the best way to write content-driven "applications", but any application that is mostly concerned with providing a service, rather than content, is less likely to be easily arRESTed.

I think this perception comes from the terminology ambiguity I've just described. I don't know what example you might have in mind, but there are usually reasonable ways to model services using REST. That's not to say there aren't often tradeoffs, of course, as with almost any design decision.

Shopping cart defense

Unfortunately, the single state approach gained dominance very early on in the history of the web with the metaphor of the "shopping cart". This reduced the forward/backward button to navigational transitions rather than state transitions.

People pick on shopping carts because they're a soft target. Try something more critical, like actual orders. After an order is placed, a common application requirement is that the back button should not unplace the order. How do you want to model this?

I'll conjecture that whatever reasonable answer you give, similar logic can be applied to shopping carts. "[Reducing] the forward/backward button to navigational transitions rather than state transition" is an inevitable requirement of even minimally complex applications.

Client state and bookmarking

If state is kept on the client in a continuation based webapp, how would bookmarking work? If the data is in a hidden field this isn't saved by the browser when a bookmark is made is it?

If it's held in a cookie the bookmark will work but then you're back to shared state and cloning browser windows becomes problematic.

Keeping state in the client has it's own set of problem I guess. Is there a 'right' solution that works in the presence of cloning, bookmarking, forward and back without server side state?

In the system I work on (using Sisc scheme) the continuations are serialized to a database. This is surprisingly quick. As the continuation is serialized it cannot be modified so forward/back do become state transitions. 'Shopping cart' type state is handled using the database or other resources. But again you have the server state issue and when to expire continuations.

Keeping state in the client h

Keeping state in the client has it's own set of problem I guess.

Especially if the state gets large and the client is on a dialup line.

where to store the continuation

Well storing the whole continuation on the client is only one option -- a more popular option is to store it on the server and give each continuation a unique identifier for the client to reference.

Cleaning up the continuations

Storing it on the server is the popular option and it's what I do. But then the problem becomes one of garbage collection. Given limited storage space you need to be able to expire and delete unused continuations. So some arbitary time limit is often imposed whereby continuations older than this time are deleted. This time limit can become an important and difficult parameter to tune.

That said I think continuation based web applications are a great idea. With quite a few in commercial use now I can say that for certain classes of applications they make development much easier and the problems like continuation cleanup etc are quite manageable.