Another thing I hate about Web application frameworks (by )

They have basically zero support for reusable components.

Right now, I'm writing an app that lets you claim phone numbers from a pool. It has an interface where you can see what numbers you already have, and a page you can go to to claim more numbers by doing a search, then clicking on a number you like to claim it.

This page is implemented by a server-side script (actually, it's a Rails controller, but that's an irrelevant detail at this level) that spits out a search form and a list of matching numbers. The form posts back to the same script; if you hit Search it re-runs the search and displays the new results; if you hit Grab it claims the selected number in your name, and replies with a redirect to the details page for that number.

But now I need to add to it so that new users, when they sign up, get to choose three numbers, which are stored slightly specially in the database, differently from numbers they subsequently claim.

Back when I was doing Java Swing GUI programming, this would be a cinch. I'd have implemented the claiming user interface as a JDialog subclass that displays the search form and search results, with a button to run a new search and repopulate the results, and a button to claim a number that does the database magic then closes the dialog.

Then to extend it to support the signup wizard, I'd have pulled the core of the JDialog out into a JComponent subclass that accepted a callback for what to do when a number is selected, and replace the JDialog with one that puts an instance of the component in with a callback that does the database magic and closes the dialog.

Then I'd be able to make my wizard invoke the same component, but with a callback that does the slightly different database magic and then moves the wizard to the next stage, either presenting a new instance of the component to select the number, or terminating the wizard when they're done.

This would not take long.

But done as a Web application? Oh, no. Each form posts certain named fields to a specified handler, which handles the form and then either spits out a redirect or a new page. And currently, my number grabber, when a correct form submission of the Grab button is detected, does the database magic and then redirects to an editing page for the new number.

Sadly, I can't pass a different "callback" into the controller to change what it does when a number is selected. With a continuation-based web framework I could do reuse of sequential sets of pages, which would be nice; I could write a function to let the user choose a number, which spits out a form with an embedded continuation then suspends until the form is submitted, after which it decides whether to redisplay the page (search button pressed) or to return the chosen number (grab button pressed). This function could be reused in the normal number grabbing system or in the signup process.

I can fake a similar effect without continuations by putting a switch statement in the number grabber script, at the point where a successful submission is detected; if mode = 1 then do this, otherwise do that. Then pass in a 'mode' parameter in the initial link to the page. Which is, of course, more or less what I did.

But continuations only let us to sequential composition of reusable sequences. It's no use if I decided I wanted to have two number choosers side by side on the one page, to pick two numbers at once. To do that, I'd need two sets of 'page state'. I'd need to be able to somehow prefix the form field names used by the two instances of the form, so they didn't clash, and route things appropriately on the server so that if I press the search button on one of the forms, that form's handled is told about it and performs the appropriate process while the other one (which is part of the same HTML form, even though a logically separate entity) should just accept the current state of the editable fields in the submission and redisplay the form with them as the initial state.

That's the sort of thing War Rocket Ajax does; it's a component-based application framework. Once a component is defined, each instance of it in a form is given a name, and the actual HTML form fields must use that name as a prefix, to avoid clashes. The component is responsible for managing its own state, so if the form is submitted via a button in another component, every other component on the page should 'come back' from the server exactly as the user saw them on the page he submitted.

Component instances are isolated from each other by the framework. However, War Rocket is currently just a prototype in PHP, with some limitations (as implemented, it can't handle dynamic forms, such as a table of rows built from a database with editable components in each row). But I know how to fix that, with a 'dynamic' wrapper component that is given a list of objects from somewhere, and row template to instantiate for each object in the list. It can put a list of the IDs of the objects in a hidden field, then create instances of the row template with a prefix made by appending the object ID to the name given to the dynamic component itself. Then when the form is submitted and the component initialised from the form submission rather than the database's current state, it uses the hidden field to reconstruct the row template component instances ready to receive the submission.

I hope to implement this in Scheme, when I get a moment, since Scheme will also allow me to use the continuation approach, where applicable...

But for now, I must soldier on with less imaginative tools!

3 Comments

  • By Ben, Sun 17th Jun 2007 @ 7:25 am

    Rails, which I believe you're using, has a couple of ways of supporting this. The first is 'components', which are a bit heavyweight and you're not encouraged to use them.

    The second is partials, little bits of templates you can include in more than one view in more than one controller.

    With the partials route, there's no explicit support for the business logic, but an acceptable pattern is to put the logic in ApplicationController (in a separate file of course), in a Module you include or a separate class you instantiate and use. All depending on the visibility you need of the other parts of the framework.

  • By alaric, Sun 17th Jun 2007 @ 10:35 pm

    Yeah, but look at what I was doing in the post - it's not much fun ripping out an existing part of the .rhtml, and the associated controller logic, and making it into a reusable component. Under Swing, it would be.

    What I'm really moaning about is that existing WAFs are very much oriented towards producing pages; under Swing (or, indeed, many other such toolkits) you'd be hard pressed not to do things in a component-like way.

    I want to make it so easy to throw together your own components that it's the logical thing to do. The system shouldn't provide controllers and views; just views that can use components, and an easy to use framework for creating components, so the natural way of making a special form page is to throw together a component for it, which is then instantly malleable and reusable. Or, at least, that turning a page (or part thereof) into a component is just a matter of extracing the desired bit of template, shoving it into a 'compound component definition' file along with a bit of metadata, and then referring to it by name wherever required.

  • By werutzb, Wed 8th Oct 2008 @ 1:04 am

    Hi!

    I want to improve my SQL knowledge. I red so many SQL books and would like to read more about SQL for my occupation as mysql database manager.

    What would you recommend?

    Thanks, Werutz

Other Links to this Post

RSS feed for comments on this post.

Leave a comment

WordPress Themes

Creative Commons Attribution-NonCommercial-ShareAlike 2.0 UK: England & Wales
Creative Commons Attribution-NonCommercial-ShareAlike 2.0 UK: England & Wales