2.1. Layered Software Architecture
A good web application should look like a trifle, shown in Figure 2-1.
Figure 2-1. A well-layered trifle (photo by minky sue: http://flickr.com/photos/kukeit/8295137)
Bear with me here, because it gets worse before it gets better. It's important to note that I mean English trifle and not Canadianthere is only one layer of each kind. This will become clear shortly. If you have no idea what trifle is, then this will still make sensejust remember it's a dessert with layers.
At the bottom of our trifle, we have the solid layer of sponge. Everything else sits on top of the sponge. It wouldn't be trifle without it. The sponge supports everything above it and forms the real inner core of the dessert. The sponge is big, solid, and reliable. Everything above it is transient and whimsical.
In web applications, persistent storage is the sponge. The storage might be manifested as files on disk or records in a database, but it represents our most important assetdata. Before we can access, manipulate, or display our data, it has to have a place to reside. The data we store underpins the rest of the application.
Sitting on top of the sponge is the all-important layer of jelly (Jell-O, to our North American readers). While every trifle has the same layer of spongean important foundation but essentially the same thing everywherethe personality of the trifle is defined by the jelly. Users/diners only interact/eat the sponge with the jelly. The jelly is the main distinguishing feature of our trifle's uniqueness and our sole access to the supporting sponge below. Together with the sponge, the jelly defines all that the trifle really is. Anything we add on top is about interaction and appearance.
In a web application, the jelly is represented by our business logic. The business logic defines what's different and unique about our application. The way we access and manipulate data defines the behavior of our system and the rules that govern it. The only way we access our data is through our business logic. If we added nothing but a persistent store and some business logic, we would still have the functioning soul of an applicationit's just that nobody would want to eat/use it. In days of old, business logic was written in C or COBOL (seriously). These days, only the big (where performance really matters) and the entrenched (where it's too painful to change) do it that way. It's perfectly acceptable to write business logic in your scripting language of choice (PHP, Perl, Python, Ruby, etc.) or the corporate-friendly alternative of Java.
So we have our supporting sponge and our personality jelly (perhaps with lumps of fruit, which have no sensible analogous component, but are useful ingredients in a trifle, nonetheless). We might have a dessert and we can certainly see the shape it's taking, but it's not yet a trifle. What we need now is custard. Custard covers the jelly and acts as the diners' interface to the layers beyond. The custard doesn't underpin the system; in fact, it can be swapped out when needed. True storyI once burnt custard horribly (burnt milk is really disgusting) but didn't realize how vile it was until I'd poured it over the jelly. Big mistake. But I was able to scrape if off and remake it, and the trifle was a success. It's essentially swappable.
In our web application, the custard represents ourpage and interaction logic. The jelly of the business logic determines how data is accessed, manipulated, and stored, but doesn't dictate which bits of data are displayed together, or the process for modifying that data. The page logic performs this duty, telling us what hoops our users will jump through to get stuff done. Our page and interaction logic is swappable, without changing what our application really does. If you build a set of APIs on top of our business logic layer (we'll be looking at how to do that in Chapter 12), then it's perfectly possible to have more than one layer of interaction logic on top of your business logic. The trifle analogy starts to fall down here (which was inevitable at some point), but imagine a trifle with a huge layer of sponge and jelly, on which several different areas have additional layers; the bottom layers can support multiple interactions on top of the immutable bottom foundation.
The keen observer and/or chef will notice that we don't yet have a full dessert. There's at least one more layer to go, andtwo in our analogy. On top of the custard comes the cream. You can't really have custard without cream; the two just belongtogether on a trifle. A trifle with just custard would be inaccessible to the casual diner. While the hardened chef/developer would recognize a trifle without cream, it just looks like a mess to the diner/user. We need some way to convey the message of the lower layers to our diners/users.
In our web application, the part of the cream is played by markup on the Web, GUI toolkits on the desktop, and XML in our APIs. The markup layer provides a way for people to access the lower layers and gives people the impression of what lies beneath. While it's true that the cream is not a trifle by itself, or even a very important structural part of a trifle as a whole, it serves a very important purpose: conveying the concept of the trifle to the casual observer. And so our markup is the samethe way we confer the data and the interaction concepts to the user. As a slight detour from our trifle, the browser or other user agent is then represented by the mouth and taste buds of our usersa device at the other end of the equation to turn our layers into meaning for the diner/user.
There's once thing left to make our trifle complete, other than the crockery (marketing) and diners (users). It would already work as is, containing all the needed parts. A developer might be happy enough to stop here, but the casual user cares more about presentation than perhaps he should. So on the top of our layered masterpiece goes garnish in the form of fruit, sprinkles, or whatever else takes your fancy. The one role this garnish performs, important as it is, is to make the lower layers look nice. Looking nice helps people understand the trifle and makes them more likely to want to eat some (assuming the garnish is well presentedit can also have the opposite effect).
Atop the masterpiece of code and engineering comes our metaphorical garnishpresentation. When talking about web pages, presentation is the domain of some parts of the markup, the CSS, and the graphics (and sometimes the scripty widgets, when they don't fall into the realm of markup). For API-based applications, this usually falls into the same realm, and for email, it doesn't necessarily exist (unless you're sending HTML email, in which case it resembles regular web pages).
So the point of all this? A good web application has many layers, each of which provides a discrete function. All of the layers together make up the application, but randomly combining them will get you a badly built application or a bowl of sugary foodstuffs. From the perspective of the developer/chef, the most important layers are at the bottom because they support and provide the basis for the ones above. From the perspective of the diner/user, the higher layers are the important part that set the dessert apart, with the lower layers being taken for granted, particularly the ones at the very bottom of the stack. And so it should be with web applications. In a moment, we'll look at how these layers can interact (we can't just rely on gravity, unfortunately; besides, we need a trifle that can withstand being tipped over), but first we'll look at some examples of what can go where.