13.5. Fat ClientBrowserSide, Decoupled, DHTML, Fast, Responsive, Rich, Thick Figure 13-11. Fat Client13.5.1. Developer StoryDave's new mortgage application is very quick as it avoids server calls wherever possible. After some benchmarking, he discovered that optimized JavaScript is actually fast enough to run the financial algorithms in the browser, so that users now receive almost immediate feedback as they tweak parameters. 13.5.2. ProblemHow can you architect the system to feel truly rich and interactive? 13.5.3. Forces
13.5.4. SolutionCreate a responsive Ajax App by performing remote calls only when there is no way to achieve the same effect in the browser. Whereas the server is traditionally the realm of more complex processing, this pattern suggests harnessing the browser for all it's worth. In the extreme case, it means running just about everything inside the browser, but that's not the main message here. The main message is to reconsider the traditional server-centric view of web architecture; for developers to be more conscious about decisions on matters regarding where the various components live. Placing more logic inside the browser gives you the opportunity to make the application more responsive. Web apps usually have several layers:
The user interface is what the user sees and interacts with. The application logic concerns the dialogue between the user and the computer, the flow of information back and forthfor example, given a particular user action, what should the computer do next? The business logic concerns knowledge about the domain and the web site owner's practices and policies. The data access layer concerns reading and writing data to a persistent store. External system communication is also necessary in many enterprise systems, where outside systems play the role of information sources and sinks. Conventional web apps concentrate UI code in the browser, using a mix of HTML and CSS, with some JavaScript used to perform a few basic UI tricks like placing keyboard focus or showing some animation or offering a dynamic menu. Everything else is usually managed on the server. This pattern reconsiders the balance by suggesting that some applications are better served pushing application and business logic into the browser (Figure 13-12). Figure 13-12. Responsibilities of a Fat ClientWith application logic in the browser, an inversion of control occurs in which the browser now controls the flow of activity. When the user performs some action, it is the browser that decides how to respond, and it calls the server only if necessary, and for very specific services. The advice to hold business logic in the browser is anathema to most literature on serious web site development and should not be taken lightly. Business logic in the browser has numerous problems:
Are any of these showstoppers? Let's look at how we can cope with each of these problems:
None of this says that programming in JavaScript is more productive than programming in Java or C# or Ruby. In most cases, it isn't and never will be. Serious JavaScript programming is nonetheless a very real proposition. Professional software development involves choosing the language that fits the task at hand. Given the many benefits of browser-side coding, there are at least some circumstances that make JavaScript the language of choice for implementation of business and application logic. 13.5.5. Decisions13.5.5.1. How will business and application logic be implemented in the browser?Conventional applications use JavaScript for a little decoration. Even when a lot of JavaScript is used, it's often packed into tightly scoped library routines, to perform little tricks like validating a form's fields match regular expressions or popping up a calendar. These are just little detours on the well-travelled road between browser and server. In contrast, a Fat Client responds to many events itself, delegating to the server only if and when it deems necessary. All this implies a very different usage of JavaScript, and there are some techniques that can help. It's beyond the scope of this chapter to cover them in detail, but here are a few pointers:
13.5.6. Real-World Examples13.5.6.1. NumSumNumSum (http://numsum.com) is an Ajax spreadsheet that provides all the basic spreadsheet functionality in JavaScript: insertion and deletion of rows and columns; various formulas; the ability of a user to enter values into any cell; text-formatting (bold, italic, or underlining); text-justification; and embedded links and images. The basic spreadsheet is implemented as a table. Table cells aren't actually editable, so the script needs to simulate an editable table. An event handler ensures that a cell becomes active when the user clicks on it, and that cell is then morphed to reflect subsequent user input. 13.5.6.2. GmailGmail (http://gmail.com), like several of its competitors, presents a rich, Ajax interface to a mail system. Conventional web mail offerings rely heavily on form submissions and page reloadsa new page must be opened each time the user wants to start composing an email, finish composing an email, or open up an email message. With Gmail, the list of emails is always present and regularly refreshed. Partial edits are periodically saved as well. All of these activities are handled within the browser using a combination of Display Manipulation (Chapter 5) and Web Remoting (Chapter 6). 13.5.6.3. DHTML LemmingsDHTML Lemmings (http://www.oldgames.dk/freeflashgames/arcadegames/playlemmings.php) shows how much can be achieved with some clever JavaScript hacking (Figure 13-13). It's a full-featured implementation of the Lemmings PC game utilizing a Richer Plugin only for soundthe entire game runs on DHTML, DOM, and CSS. The gameplay consists of a static image for the current level, with Sprites used to render the lemmings and other objects in the game. There is a periodic timer continuously checking the current state of each object, and DOM manipulation of the objects' properties is used to render their states at any time. Figure 13-13. DHTML Lemmings13.5.6.4. JS/UIX shellJS/UIX shell (http://www.masswerk.at/jsuix/) is a demo of an in-browser Unix shell (Figure 13-14). In its current form, it's a demo only. But it's capable of all the basic operating systems commands and even includes a vi editor! The approach stands in contrast to browser-side terminal emulators, which are thin applications that pass characters back and forth. With appropriate server-side integration, the application could be made into a functional multiuser application. Command line remains the mode of choice for many power users, and this demo shows how an Ajax Fat Client can achieve it. Figure 13-14. JS/UIX shell13.5.7. Code Example: AjaxPatterns Basic WikiThe Wiki Demo (http://ajaxify.com/run/wiki) is based on Fat Client principles, though its functionality is fairly limited. All of the interaction and rendering occurs locally. The only interaction with the server is a periodic synchronization event, when the following occurs:
There's a timer to ensure synchronization occurs after five seconds of inactivity: var syncTimer = null; function startPeriodicSync( ) { stopPeriodicSync( ); syncTimer = setInterval(synchronise, 5000); } function stopPeriodicSync( ) { clearInterval(syncTimer); } The timer starts on page load and is suspended each time the user begins to modify some text: window.onload = function( ) { synchronise( ); startPeriodicSync( ); } function onMessageFocus(event) { ... stopPeriodicSync( ); } function onMessageBlur(event) { ... startPeriodicSync( ); } The script also contains a variable to accumulate pending messages whenever the user changes something: var pendingMessages = new Array( ); ... function onMessageBlur(event) { ... if (message.value != initialMessageContent) { pendingMessages[message.id] = true; ... } The synchronization event builds up some XML to post to the server, based on the pendingMessages array that has been accumulated. If no changes are pending, it simply requests the current server state. If there are changes pending, it posts those changes as an XML message. Either way, the server will respond with an XML specification of its current state. function synchronise( ) { var messageTags = ""; for (messageId in pendingMessages) { var initialServerMessage = $(messageId).serverMessage; messageTags += "<message>"; messageTags += "<id>" + messageId + "</id>"; messageTags += "<lastAuthor>" + $("authorIdSpec").value + "</lastAuthor>"; messageTags += "<ranking>" + initialServerMessage.ranking + "</ranking>"; messageTags += "<content>" + escape($(messageId).value) + "</content>"; messageTags += "</message>"; $(messageId).style.backgroundColor = "#cccccc"; } var changesOccurred = (messageTags!=""); if (!changesOccurred) { ajaxCaller.getXML("content.php?messages", onMessagesLoaded); return; } var changeSpec = "<messages>" + messageTags + "</messages>"; ajaxCaller.postBody ("content.php", null, onMessagesLoaded, true, null, "text/xml", changeSpec); pendingMessages = new Array( ); } The main application logic is virtually orthogonal to server synchronization. The only concession is the accumulation of pending messages, to save uploading the entire browser state each time. The timer and the synchronization process know about the core wiki logic, but the core wiki knows nothing about them and can therefore be developed independently. It's easy to imagine how the wiki could evolve into something with much richer browser-side features, like formatted text and draggable messages and so on. 13.5.8. Alternatives13.5.8.1. Thin clientA thin client contains only basic JavaScript and frequently refers back to the server for user interaction. This is likely to remain the dominant style for Ajax Apps and is useful in the following circumstances:
13.5.8.2. Desktop clientA desktop client runs as a standard application in the user's operating system, and connects to one or more servers using HTTP or any other protocol. Compared to a Fat Client, a desktop client can be richer and faster. However, the benefits of a web-enabled application are lost as a result. You can compensate for some of these benefits:
In some contexts, a desktop client represents the best of both worlds: a rich client backed by a powerful server. In other situations, a Fat Client based on Ajax principles is a more appropriate sweet spot: a powerful server, a rich-enough client, and easy access through any modern web browser. 13.5.9. Related Patterns13.5.9.1. Periodic RefreshPeriodic Refresh (Chapter 10) is a relatively unobtrusive way for the client state to be enriched with any new server-side information. 13.5.9.2. Submission ThrottlingSubmission Throttling (Chapter 10) is a relatively unobtrusive way for the server to be notified of any significant changes that have occurred in the browser. 13.5.9.3. WidgetsIf the user is going to spend a long time in the browser, the various widgets (Chapter 14) should be adopted to improve the experience. 13.5.9.4. On-Demand JavaScriptSince Fat Clients tend to contain bulkier scripts, On-Demand JavaScript (Chapter 6) is useful for managing them. 13.5.9.5. Drag-And-DropDrag-And-Drop (Chapter 15) is familiar to many desktop users and helps to make a large application feel more natural. Whereas more conventional web clients rely on form-style interaction, Fat Clients can feel more rich if they support Drag-And-Drop. 13.5.9.6. Host-Proof HostingWhere a Fat Client is seen as a replacement for a desktop equivalent, Host-Proof Hosting (Chapter 17) might be considered to avoid compromising on the superior security a localized solution sometimes offers. 13.5.10. MetaphorAgile development methodologies such as Scrum aim for an "inversion-of-control." Workers (like the Fat Client) are empowered to plan their own activities, and management's role (the Server) is to offer whatever services workers request in order to conduct those activities. 13.5.11. Want to Know More?
|