continuations

Abstracting

April 15, 2005 18:30:23.262

I'll be speaking on April 25th at the Vrije Universiteit in Brussels. Here's the abstract of my talk:

On the web, abstraction is a dirty word. The dominant paradigms and philosophies of web development -- CGI, Servlets, Server Pages, REST-- provide only a thin wrapper around the low-level details of HTTP, and encourage you to use the rough stones of the transport protocol as the direct building blocks of your application. Web developers by and large reject any further abstraction in the way that assembly hackers once rejected structured programming: it's too inflexible, uses too many resources, and above all, it doesn't let you see what's *really* going on. As a result, web applications suffer the same problems now that assembly language programs did years ago; they're fragile, verbose, difficult to maintain and ill-suited to reuse.

That's not to say that better abstractions aren't available. The Lisp and Scheme communities have been working on them for years. Paul Graham's ViaWeb pioneered the use of closures, not query parameters, to capture application state in each link. Christian Quiennec showed how to use first class continuations to invert the flow of control of HTTP and put the server back in the driver's seat. Macro packages like htmlgen bring HTML into the language itself, opening up much more than a template system can provide. Meanwhile, object-oriented packages like WebObjects have demonstrated how to decompose the web page into a tree of stateful, interacting objects, allowing a finer granularity of development.

Seaside combines these ideas and others with the rich development environment of Smalltalk to provide a stable, complete, and innovative web application platform. This talk will introduce Seaside, and will focus in particular on the ways in which these abstractions can be leveraged to enable reuse: how to use closures, continuations, and intelligent HTML generation to destroy the intra- and inter-page coupling that is holding web development back.

continuations

In Order of Importance?

April 14, 2005 19:13:28.369

The inimitable David Heinemeier Hansson points out that in a recent set of slides by Sam Ruby, Rails is the fourth item from the top on a list of things Worth Watching. What's item number three? Continuations.

Sam also brings us Continuations for Curmudgeons, an explanation of call/cc from the point of view of a C programmer. I've also often found that explaining continuations in terms of the possible machine (or virtual machine) implementation often gets the point across much easier than trying to explain the semantics. How do you capture a continuation? You save a copy of the current execution stack. How do you invoke it? You blow away the current stack and replace it with a fresh copy of the one you saved. How many times can you do this? As many as you like.

Just don't explain it that way around Scheme folk...

continuations

Like, Totally

April 14, 2005 15:40:11.887

Darren Hobbs writes:

Today I saw something in Seaside that gave me one of those 'Dude, that so totally rocks' moments.

There's an innocent toolbar option in Seaside called 'Toggle Halos' that switches on a visual representation of the components on a page, with some icons for each one. One of the icons looks like a spanner (US: wrench), and when clicked on, shows you the code for the component in your browser, and lets you edit it!

Oh yes. Welcome to really rapid application development.

Dude. That's what I like to hear.

Apart from the occasional quick fix to a live site, I don't tend to use that feature much for development, but what I use it for all the time is for getting my bearings in a complex codebase. When you're deep inside an application that someone else (like, say, yourself two years ago) wrote, there's nothing quite like being able to point at the screen and say "ok, now show me the code that renders that bit of the page".

(And in case anyone's wondering what halos look like, Ian Prince has a great reflexive screenshot here).

Update: Ian just posted a more detailed look at halos here

continuations

Briefly

March 29, 2005 16:50:45.747

You'll have to forgive another navel-gazing fluff post, but I thought this was interesting: I happened to read two separate blog postings today that mentioned Seaside even though they were mainly talking about web frameworks in other languages. One was from Ian Bicking, talking about Rails and Python; another was from Dion Almaer, surveying Java frameworks. I flatter myself that this is evidence that Seaside (along with related frameworks like Wee) is slowly moving from being simply a wacky out-of-the-mainstream way of building web apps to being the canonical wacky out-of-the-mainstream way of building web apps. Here's Ian:

Rails ... doesn't have any novel ideas. I'm not trying to talk it down, that's just the reality of what Rails is -- it's not Seaside or Wee (and if it was it wouldn't be so popular anyway).
More novel than popular; I can live with that.

continuations

OOPSLA

November 7, 2004 14:31:44.603

I wasn't able to make it to OOPSLA this year (ironic, since it was in my home town of Vancouver). But there was apparently a successful Seaside BOF, and I just came across this flattering reference to it: Nat Pryce writes

Wow!

Seaside makes writing web apps startlingly simple and straightforward. In comparison, web app frameworks in the Java world, such as JSP or Struts, and even Ruby on Rails look like dinosaurs.

Thanks, Nat.

He then makes a great point about the relative philosophies of Java and Smalltalk at a language level, and how that affects the APIs built on top of them:

Seaside is able to present such a simple API because it takes advantage of "esoteric" features of its implementation language/platform, Smalltalk, such as continuations and closures. Java, in comparison to Smalltalk, is designed on the assumption that programmers using the Java language are not skilled enough use such language features without making a mess of things, and so the language should only contain simple features to avoid confusing our poor little heads. Paradoxically, the result is that Java APIs are overly complex, and our poor little heads get confused anyway. Seaside is a good demonstration that powerful, if complex, language features make the job of everyday programming easier, not harder, by letting API designers create elegant abstractions that hide the complexity of the problem domain and technical solution.

continuations

Lakeshore

October 28, 2004 17:42:32.656

Wow. In the comments to my previous entry, Leslie Hensley points me to Lakeshore, a Seaside clone in Java. Them memes, they sure do like spreading...

Leslie, I assume you don't support the back button?

continuations

Wee

October 28, 2004 12:50:15.622

I've been helping Mike Neumann with his new Wee web framework, by explaining Seaside's solutions to the various problems he's coming across. I think I can count Mike among my oldest fans, because years ago he wrote a chapter in a Ruby book about using IOWA, my first attempt at a Seaside-style (or, as I thought of it then, WebObjects-style) web framework. I've learned a lot since then, and it's been great fun bringing Mike up to speed on my latest thoughts on the problem of web development - especially since he seems to agree with most of them ;).

The result is interesting on a couple levels: first, it's a reimplementation in Ruby of many of the core concepts of Seaside, but without (as far as I know) Mike looking at a single line of Seaside code - it's all just been email conversations at the design level. This is in stark contrast with Borges, which started out as a line-by-line translation of the Seaside codebase into Ruby, and I have to confess that I think Mike's is the better approach. It's been a nice chance for me to think about the various "tricks" (patterns?) that make up the framework, and how to generalize them to other languages and other implementation constraints. I've always meant to write those up, and this may be the trigger to start me on doing that. Given my record with regular posts to this blog so far, however, I shouldn't be too optimistic...

The second way in which Wee is interesting is that it doesn't use continuations. Mike wanted to be able to serialize the session state, and although Ruby does support call/cc, it can't marshal continuations, so Wee doesn't use them. Given that continuations are the aspect of Seaside that I spend, by far, the most time talking about, it's very interesting to be reminded of everything else that's going on by seeing a framework that leaves them out and yet is still instantly recognizable as Seaside-influenced.

continuations

Archiving "Arms Race"

May 28, 2004 16:00:04.564

Ian Prince has been doing a great job of collecting links to notes and slides from my "Winning the Application Server Arms Race" keynote at Smalltalk Solutions. Each successive link he's posted has had more detail and less commentary; the latest set of notes, from Niall Ross, are especially complete.

To round off the collection, here's an unedited audio recording in MP3 format (low quality, so it's only 13MB or so). Thanks to Michael Lucas-Smith for making the recording and sending it to me.

I'm not sure how useful it is to listen to a talk that you can't see, but it's there if you want it.

Two notes on the recording: it begins with Alan Knight introducing me, and the "A" in my name is pronounced closer to "Ah" than the way he says it; and no, I wasn't aware that I said "you know" every three seconds until listening to the recording myself.

continuations

Simple Sequences II

May 20, 2004 16:00:52.252

Bob Baxley has a nice article on common structures in web applications over at Boxes and Arrows. He claims that

...taken together, hubs, wizards, and guides comprise the full universe of task flows applicable to web applications and form the basis of all web-based processes and transactions.
This diagram from the article should make the three structures pretty clear:

One of the points I was trying to make in my previous post was this: most people seem to grok that Seaside is useful for "wizards", and maybe even for "guides". What I'd like people to realize, however, is that Seaside is also extremely adept (maybe even more adept) at hubs. Continuations aren't just the arrows, they're also the lines - the spokes in the hub. The beauty of Seaside is that you get complete separation of all the box-and-circle bits of those diagrams from all the line-and-arrow bits. That lets you move the little red circles around, and reuse them, much more effectively.

Well, I know what I mean.

continuations

Simple Sequences

May 20, 2004 15:59:41.036

David Naseby writes

This little exercise has proven to me the value of continuations in writing sequential web apps. This just leaves the question that I haven't yet asked... how useful are sequential web apps? How often does one string together forms in a set sequence? The archetypal example is credit card payment - there is a set series of forms one generally must pass through, from basket checkout to payment process, and Borges'’ #isolate function comes in handy here. But nothing else springs immediately to mind. Perhaps I'm just too accustomed to bunging too much onto a single form to work around this issue, when I should be thinking more linearly. Or perhaps I've been conditioned into thinking of a more user-driven, event-driven style, rather than an imposed, console-like, application driven process.
David, I'll let you in on a secret: most Seaside apps aren't long sequences of forms. They're event driven, like anything else, and although every once in a while one of those events will trigger a lengthy business process like paying for shopping cart items or booking an airline ticket, for the most part the events are short: show a page of info or a form or two and then back to where you started. Even though, in Seaside, your session could look like a continuous piece of code from start to finish, the truth is that most of that continuum is spent spinning in an event loop, with only brief though frequent forays into sequential logic. It's the same model every UI toolkit uses: user events trigger callbacks which give the application temporary control, but once it's popped up a dialog box or two it falls right back into the event loop.

So why, then, do I blather on about continuations and control flow all the time? Because it turns out that even for those very brief event handlers - even when all they do is show a single page and return - the continuation model is hugely beneficial. Let's take a login link as a simple example. The user is on the home page, they click "login", that triggers an event (in Seaside's case, through a block that's been registered as a callback), and the event shows the login form. Simple enough to do with any old plain-jane web framework, and no continuations in sight - right?

The question is, once the user has succesfully filled in and submitted their credentials, what happens next? Well, next we want to show the home page, since that's where the user was when they clicked login. So can't we just write the login page so that the "submit" event shows the home page if the login was succesful?

Well, hang on. What if this app lets them browse a bit, maybe read but not write, before logging in? There might be a "login" link on every page of the application. So we can't hard code the main page - we're gonna need to tell the login page where it's supposed to go once the user has logged in, so that they get back to the right place. How do we do that?

And, gosh, we do seem to write login pages a lot - what if we wanted to reuse the same one for multiple different apps? Well, we'd probably need to tell it even more, then: not just where to go, but what to do (for this app, do we store the current user in the session? In a cookie? What flags do we need to set based on which user it is?). How do we do that?

It's looking like this simple login page, if we want to reuse it within our application or across several, is going to either become a complex parameterized beast or acquire a couple of dozen nearly identical subclasses. But there's actually a good word for the "where to go and what to do next" parameters that it needs: that's this page's "continuation". And so perhaps it shouldn't be surprising that using a "real", first-class continuation for this simplifies things greatly.

To be concrete: in Seaside, that login page wouldn't have parameters, it would have a return value - some object representing the user or username that had logged in. The login event wouldn't just show the login page, it would "call" it: show it and then wait for, after some further events are triggered on the login page itself, a value to be returned. Only then, and after some processing of the return value, does the login event handler end, at which point the home page (or wherever we started) would be shown again and the event loop continued. So although this was a sequence of only one page, it was a full sequence: to the login page and back again, rather than the GOTO of simply showing a page and stopping there:

login
    |user|
    user := self call: (LoginPage new authenticateAgainst: myAuthDB).
    user
        ifNil: ["login was cancelled"]
        ifNotNil: [self setFlagsForUser: user].
There's a similar example that Paul Graham gives when talking about ViaWeb, which is a color picker. In his store builder, there were many places on many forms where the user needed to pick a color. Rather than ask for a hex value or have a menu of available colors, he had a link that would take them to a full-page color picker; when they had the one they wanted, they'd be returned to the form they started at and the appropriate color value would be set. This is another instance of a page needing to know both "where to go and what to do" - it needs to return to the right form, and it needs to put the chosen color in the right place (were we choosing the foreground text color or the background?). In Seaside, that would again be a simple call and answer:
chooseForegroundColor
    |color|
    color := self call: ColorPicker new.
    myText foregroundColor: color.

Next (36 total)