What if webapps worked like pinball machines?

Currently web frameworks are all about the page. This is starting to change a little thanks to Ajax but mostly just towards the idea of page snippets. But why? “Pages” are a metaphor taken from books, but books are linear and the page serves to restrict the layout. Things like Yahoo Widgets have shown us that there’s no need for layout to be bound to the “page” metaphor and we’ve known for a long time now that webapps are rarely linear, and when they are people don’t like it. Essentially we’re writing glorified “choose your own adventure” games that still say “To open the door on the left go to page 65. To open the door on the right go to page 27. Rails, and it’s clones, even number the “Pages” like that. We need a new metaphor. What if, instead of writing frameworks that are all about serving and managing pages, we started to think of webapps more like pinball machines. There are 5 major parts in every modern pinball machine (other than the ball):

  1. The Flippers. You use these to force the ball in some direction You want, as opposed to the direction it wants.
  2. The Bumpers. Posts that actively push the ball off in another direction when hit.
  3. The Posts and Rubbers. These stick out of the Playfield with rubber that passively bounce the ball away.
  4. The Playfield. The board that defines the scope of the game.
  5. Gravity.

For this metaphor let’s imagine the ball represents the user and their session as they bounce around your site.

  • The Flippers forcefully redirect your users to do something you want, as opposed to what they wanted, and that generally appreciated. But sometimes you have to force them to do things like go to a login page. Of course, every time you have to use the flippers you risk loosing the ball down the outhole.
  • The Post annd Rubbers are simple no real processing required responses to a user’s actions. Maybe it’s a request for a css file. Maybe it’s a help page. Either way it’s an, essentially static, file or straight database read that provides the user with some information that alters their trajectory.
  • The Bumpers involve work, some active processing based on the data imparted by the user hitting it. They alter the user’s trajectory like a Post but also impart energy to the user as they send them off.
  • Gravity is like time. It’s what’s trying to get the ball to leave the playfield of your webapp.

In general you want to just let the user do whatever they want. The pinball machine doesn’t care about the where the ball just came from or where it’s going. Maybe it’ll keep a running log of the “Score” but in general it is only concerned with if the ball is on the Playfield or not. A bumper doesn’t care what other Bumper or Post the ball came from or where the ball is going after, although it will participate in recalculating the ball’s trajectory. They just sit around in their own stupid little world listening for input from balls.

The Ball…. The Ball is where the magic is. Since the ball represents our user we can assume it has a brain…even if they, like Pooh, they are “a bear of very little brain.” It knows where it’s been. It sees where it’s headed. And, it is actively trying to get a good score, or get off the Playfield. That point’s never been quite clear. Either way it’s the ball that changes it’s direction when affected by gravity. It’s the ball that is running around your site. It’s the ball that triggers the bumpers and it’s the ball that makes the game worth playing.

So what if we stopped focusing on pages (Bumpers / Posts) and started focusing on the Ball. What if the Bumpers and Posts were just listeners who knew nothing about each other. If you like technologies like Mule you could think of them as listeners on a queue. Or you could think of it as a publish subscribe model where they’re all listeners registered with the ball. Regardless of how i architect it why should my “Address” Bumper know anything about the “Company” Bumper. Why should it have to know that that’s where to force you next. What if you let the ball decide where it wants to go. Sure the Bumper will give it a push but maybe the ball just doesn’t have enough energy to care about going to the Company page/Bumper after filling out an Address. Maybe it’s feeling the influence of Gravity and just wants to get off the Playfield.

If everything on the Playfield is truly independent we add and remove them without concern for the effect on other ones because there isn’t any direct coupling. More Posts? No problem. Since Posts don’t know or care where you came from or are going it doesn’t matter if the Post that was there yesterday is still there or not. More balls? Again, no problem. Yes they might collide but that doesn’t affect the Posts or Bumpers, and interesting things happen when users interact with each other.

A friend said,

“I’m still a little unclear on how pages are tightly coupled to each other, and how the bumper idea fixes that.”

So let’s look at a concrete example. Lets imagine you were buying some stock. You place a buy order (the ball hits a Bumper). Now, it’s important to the user that they see an acknowledgment that the order was successfully placed but the Bumper / Controller that processed that form doesn’t and shouldn’t care if you see an acknowledgment or not. It’s done it’s job by processing your buy order. It’s the User that cares about that acknowledgement. Where you bounce off to is their concern not the Bumper’s (unless of course there was a problem). But a lot of frameworks actually make you put that routing information in there with the form processor (Ruby on Rails being a perfect example).

What if User A is an advanced user and should be shown some complex acknowldgement page but User B is a computer neophyte who should be shown something simple and to the point. Do you really think it’s appropriate for those routing decisions to be implemented in the controller that submits stock purchase orders? No, of course not. It should be handled in the object that actually cares about what’s displayed next; the User object. The Ball. The ball knows what kind of user it represents. It can decide. Sure it’ll take suggestions from the Bumper as hitting a bumper does affect a pinballs trajectory but the Bumper shouldn’t be tied to any of the other Bumpers / Pages.

Some frameworks like Struts handle this by having the controller send you to the success or error page and let a central point in the framework decide what that is, and while this is definitely better it’s still the wrong place. That’s like having the bumper ask

The Playfield where to send the Ball. It makes no sense. It is the combination of the spin, speed and initial direction of the ball, it’s angle of impact, and the force of the bumpers push plus a little bit of Gravity and other more negligable factors.

The Playfield itself plays almost no part in the equation. It’s almost entirely dependent upon the state of the ball. In a webapp it’s all about what the User wants not what the framework wants. So why would you have the framework that binds all the Posts and Bumpers to the playfield decide where the ball should go?

And before you ask… No, I’m not suggesting you actually ask the user if they want to see an acknowledgement to their buy order. Im suggesting that the Ball should act as their proxy. It should know, or at least be able to make an educated guess at, what the user will want to see after a given action based on where they came from and where they were headed.

In most cases this would be akin to the success page / error page routing table in Struts only moved to the User’s control. But, imagine what could happen if you wanted to get fancy. You could throw in some Bayesian filtering or other statistical analysis to watch how a user interacts with Posts and Bumpers. After a few times on your site it would know that they generally want to go from Post A straight to Bumper D.

In summary: Why are we using web frameworks to tell users where to go? Shouldn’t web frameworks be listening to where the user wants to go? And why should different pages and form processors in our webapps be tightly coupled?