Well, OK, it’s actually a story about hotels and software architecture. But, like anything worth doing, it starts with two breakfasts. (You all know about second breakfast, right?)
The first was the breakfast I ate on my ninth birthday, cooked by my dad on the banks of the Chobe river in Botswana. We were on a camping trip, at a remote spot in the middle of nowhere – no roads, no phones, no shops, no electricity - so to cook this particular breakfast, my folks had brought eggs, bacon, sausages, bread, butter, cooking oil – you name it, they had it, along with a gas-powered fridge to keep it all fresh, and a big tank of water to wash up afterwards, and a gas stove to cook it on, and matches to light the stove, and countless other necessities that were all written down on a big long list taped to the inside of Dad’s camping trailer. This single breakfast, like every meal we’d eat out out there in the bush, involved weeks of planning, preparation, equipment, checklists – did we have enough food? Would it stay fresh long enough? Had we brought enough gas bottles to run the fridge and still have enough left to cook with? Was it safe to wash up with boiled river-water or did we need to use bottled stuff? When it’s just you and your tent in the middle of nowhere, you have to cover every single detail – and if you pack two weeks worth of bacon and then wake up one day and fancy porridge, you’re screwed. It’s bacon or nothing.
The second breakfast was eaten on the 44th floor of a Manhattan hotel, sometime in 2004. Organising this breakfast involved picking up a phone and saying to Steph in room service "Hey, can you send up some pancakes and coffee?” and then going back to sleep until someone knocked at the door with – you guessed it - pancakes and coffee. Planning involved? Zero. Which was just as well; as I’d discovered the previous night, New York does a pretty good line in cocktails as well, and if I’d needed to plan anything whatsoever that morning, I’d probably have given up and gone hungry.
So, let’s compare the two scenarios. In both cases, someone’s making a request for breakfast, and someone is then responding to that request – ask for breakfast, wait a while, get breakfast. Simple. Thing is, you can clearly see that for my dad, responding to this particular request involves an awful lot of work, whereas Steph probably doesn’t even need to stand up. And the irony is that for all his hard work and planning, the only thing Dad can actually respond with is bacon and eggs, whereas Steph – who probably can’t even cook – can do bacon, eggs, orange juice, pastries, espresso, fresh fruit and even those famous silver-dollar pancakes covered in sugar. And martinis. And probably arrange a shoe-shine, a haircut, a massage and get your tux dry-cleaned while she’s about it.
If you’re only here to hear about breakfast, you can leave now; it’s about to get a bit geeky. Still here? Cool, OK, here we go.
If you’ve built web applications for any length of time, at some point in your career you probably wrote something like an ASP page that connects to a database, reads some files, sends an e-mail or two, updates a database, does some validation, resizes an image, saves it to disk, generates a bunch of HTML and returns it to the client – all in one file. It’s OK, you can admit it; we’re all friends here. For quite a long time, I wrote most web apps this way. At the time it all seemed terribly clever, and if you stuck at it long enough, you normally ended up with something that did the job, paid the bills and kept the client reasonably happy. Problem is, this is normally the client who thinks he has millions of potential customers, but actually the load on his Web 1.0 B2B portal is him, his business partner, and about four guys in Russia who they persuaded to sign up. The wonderful thing about scaling issues is that when you get them in your software, it normally means your business is doing OK. Assuming, of course, you have a business model in the first place…
Anyway. Point is, trying to apply this everything-in-one-page approach in any large-scale app is like using my dad’s catering strategy to make breakfast for 1,200 people. Last time I looked, the only people who set off into the middle of nowhere with fifty tons of bacon and eggs were the Army - and whatever your thoughts on the armed forces, I’m sure you’ll agree that if we’re trying to learn about minimalist efficiency and cost-effectiveness, we’re probably better off looking elsewhere.
So, how does Steph arrange a couple of hundred breakfasts a day using just a phone – and what can we learn from her about designing scalable web apps?
What’s happening is that Steph’s acting as a front controller in a service-oriented architecture. The front controller’s job is to grab the incoming request, call whichever services are necessary to fulfil that request, and tell them what to do with the result.
Steph has a single responsibility – she converts customer requests (imagine Peter from Family Guy ordering breakfast: “yeah, uh, do you have, like… ah… hang on… er… like, pancakes? With syrup? And some tea? No, wait, coffee… no, tea… no coffee. Yeah. Coffee. Did I get pancakes?”) into short, snappy, precise kitchen orders (“Mikey, two pancakes, two coffee for forty-four-oh-seven”). Mikey is the breakfast chef, and he’s just one of the services that Steph can delegate to. Someone orders a martini, she can delegate to Raoul, the bartender service. Someone orders a shoeshine, she can delegate to Chip the shoe-shine guy.
Like Steph, Mikey has a single responsibility. He turns short, snappy kitchen orders into plates full of food, and he does it quickly. He doesn’t buy the ingredients, he doesn’t serve the food – he delegates those responsibilities to other services. Like Tony, the delivery service, who turns up at 4am every day with a truck full of fresh supplies. Or Chet, the bellhop service, who takes the plates, puts them on one of those funny little trolley-tables with some cutlery, and takes them up to 4407 where I’m waiting for my breakfast.
Hotels can teach us a lot about scaling, because they’re good at it – they’ve been in the hotel business a lot longer than we’ve been in the software business, after all.
Make Your Controllers Delegate Heavy Lifting to Services
Think about a typical hotel; there’s probably only four or five points of customer interaction – say the front desk, the concierge, the room service desk, and the bar. There’s probably only one or two people at each desk, but because they’re working as part of a service-oriented architecture, they can fulfil a huge number of incredibly diverse requests, whilst keeping their own responsibilities simple, well-defined and manageable. Think of your controllers like the customer service desks in a hotel – clean, friendly, and completely dependent on supporting services to actually get anything done. That’s how it should be.
Cache Whatever You Can (Within Reason)
For a hotel, this is the early-morning deliveries of food, booze, fresh linen, theater tickets – stuff that you’re probably going to need sometime today, and you don’t want clients sat around waiting whilst you have to run out and fetch it. For web apps, this means setting up local caches of images, persistent data, resource files. But don’t go crazy. Just like hotels don’t order a ten-year supply of lamb chops, you’ll need to consider how much space your cache consumes, and how long it’ll stay fresh before you need to reload it.
Acknowledge Now; Deliver Later
The room-service desk doesn’t stay on the line yakking with you until your pancakes arrive. They tell you it’ll be twenty minutes, and then hang up so they can take the next call – if they didn’t, they’d need fifty room service operators instead of one. You can use asynchronous processing, message queues and Ajax callbacks to achieve the same thing in web applications – when you get a request that’s going to take a while, respond immediately saying it’ll take a while, and let your users get on with something else whilst it’s processing. And be careful with the Refresh button. If I call down to see where my pancakes have got to, it doesn’t mean I want to order more pancakes; I’m just chasing up the first batch.