O'Reilly logo

Ajax Design Patterns by Michael Mahemoff

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Chapter 3. Ajax Design: Principles and Patterns

AJAX DOES A LOT FOR WEB USABILITY, HAS ALREADY DELIVERED SOME STUNNING APPLICATIONS, AND IS clearly the “in” thing at this time. But it’s no magic bullet. Careful design is always required, and it must be tailored to the technology at hand. By monitoring the state of Ajax applications, we continue to learn about what works and what doesn’t, and about how developers are succeeding in their design trade-offs. This chapter explains these lessons at a high level and introduces the patterns, which discuss them in depth.

Desirable Attributes of Ajax Applications

Ajax is about improving user experience and delivering value to the organizations that own and use web applications. Here, we’ll look at the key attributes of an ideal Ajax application. Reality dictates that you’ll never get the best of all worlds, so you’ll have to make trade-offs based on how important you consider each attribute. The Ajax Patterns are intended to help you deal with these trade-offs.

Usability

Ajax applications should be as intuitive, productive, and fun to use as possible.

Developer productivity

Development should be as efficient as possible, with a clean, maintainable code base.

Efficiency

Ajax applications should consume minimal bandwidth and server resources.

Reliability

Ajax applications should provide accurate information and preserve the integrity of data.

Privacy

While user-generated data can and should be used to improve the user experience, users’ privacy should also be respected, and users should be aware of when and how their data is used.

Accessibility

Ajax applications should work for users with particular disabilities and of different ages and cultural backgrounds.

Compatibility

As an extension to accessibility, Ajax applications should work on a wide range of browser applications, hardware devices, and operating systems.

Designing for Ajax

By studying existing Ajax applications, as well as any relevant precursors, it’s been possible to distill a number of important design principles for Ajax, which are shown in this section. The thinking behind the principles was a big influence on the pattern discovery process, and knowing them will help to apply the patterns.

We’ll begin by looking at principles of user-centered design, followed by those of software design. Of course, you can never fully separate those concerns, and they’re often in conflict with each other. Dealing with those conflicts is really a key concern of the patterns. Incidentally, it’s worth checking out a good online resource that takes the opposite perspective: Ajax Mistakes (http://swik.net/Ajax/Ajax+Mistakes) is a long list of Ajax mistakes and gotchas, as well as anti-patterns originally authored by Alex Bosworth and now maintained on a wiki.

Usability Principles

Follow web standards

Try hard enough, and you can do some very confusing things with Ajax, even more so as rich graphics become commonplace. Rather than reinventing the Web as we know it, use Ajax to build a “better Web,” an enhanced layer over what’s already there. Respect the conventions that users are already familiar with.

The browser is not a desktop

Further to the previous principle, Ajax is a richer brand of the traditional web site rather than a webified brand of the traditional desktop. True, desktop widgets like sliders are migrating towards Ajax, but only when they make sense in a web context and often in a modified form. We’re also seeing application categories like word processors head online as well, but again, the best products will be those that fit in with the Web rather than blindly replicating the desktop experience.

If it’s different, make it really different

Subtle differences confuse people. If you’ve decided it makes sense to diverge from a standard or a common idiom, ensure your design is distinct enough to avoid confusion.

Provide affordances

Affordances (http://en.wikipedia.org/wiki/Affordance) are as important as ever in Ajax. You may have a fancy new drag-and-drop technique for updating a form, but will the user even know it’s possible? Visual design, dynamic icons, and status areas all help here.

Smooth, continuous interaction

Avoid the start-stop rhythm of conventional web apps. Full page refreshes are a distraction and a time-waster. If used at all, they should be reserved for significant, infrequent activities such as navigating to a conceptually new place or submitting a large form.

Customization

Application preferences haven’t been very important on the Web. Why bother personalizing background colors for a shopping site you use once a month, especially if it means sitting through a tedious sequence of form submissions? But for some web applications, the user might be spending eight hours a day working with them, and customization suddenly feels a whole lot more useful. With Ajax driving the customization process, it’s a lot easier too.

Make it fun

Ajax makes the Web a lot more fun than it used to be. Techniques like visual effects, drag-and-drop, and periodic updates are sometimes labelled “gimmicks” or “eye candy,” as if users don’t actually enjoy those things. Applied with care and ideally, user testing, they can definitely add real value, even in “serious” applications.

Software Design Principles

Embrace JavaScript

Thanks mostly to the interest in Ajax, JavaScript (http://www.crockford.com/javascript/javascript.html) is no longer seen as a basketcase language to be avoided at all costs. It can actually be surprisingly powerful (cut the sniggering already!), provided that developers are willing to study the idioms, patterns, and idiosyncrasies.

Accept workarounds where necessary

Because Ajax is firmly based on standard browser facilities, there’s simply no getting around the many constraints imposed by modern browsers. If you seek the benefits of a rich web application that will run immediately on any modern browser, and you consider usability to be critical, then you can only use whatever hacks are necessary. You might well lament that Ajax development is inherently troublesome and pine for a cleaner way to get the job done (I know I do). But the point is that you don’t get a lot of say in what the vast majority of the world is already using, and will continue to use in the next few years. Maybe web development will be neater one day, but here in the present, the land of reality, it’s advisable to deal with the technology at hand and work around—or exploit—whatever cheap tricks are available if they ultimately enable useful functionality that would otherwise be unachievable.

Tame asynchrony

The browser-server communication of an Ajax App is asynchronous by nature. This leads to several risks: users might not be told that a call has failed or timed out; calls might be processed in a nonatomic manner; or the browser might forget why a call was made by the time its response has arrived. As explained in several patterns, there are techniques available to monitor and control calls so that these situations don’t arise.

Develop for compatibility

Where JavaScript programming still has issues is in portability. At a syntax level, JavaScript is reasonably consistent across browsers, as the ECMA standardization process (an effort to define JavaScript standards; see http://en.wikipedia.org/wiki/ECMAScript) has generally been respected by all the major browser makers. However, it’s still a moving target, so older browsers of any variety simply won’t support some features. Moreover, the DOM remains a serious portability concern. Despite gradual improvements over the years, there remain many subtle differences, and we’re set for more divergence in the future. Developing for compatibility means being explicit about which versions are targeted, using portable libraries where available, and architecting so that portability concerns are isolated from core logic.

Reduce bandwidth

If there’s frequent network activity, you’ll want to think carefully about the size of the messages being passed back and forth.

Deal with latency

When people talk about “how fast” their connection is, they’re usually discussing throughput rate; e.g., “a 4 megabit connection.” That’s great for downloading large content, but what about interactivity? Latency—basically the time for a bit to travel between browser and server—is usually more important than throughput rate (http://richui.blogspot.com/2005/09/ajax-reducing-latency-with-cdn.html). In web apps where the server may be halfway across the world, you can’t reasonably respond to each keystroke or mouse movement due to latency overheads. The challenge is to make the application feel responsive while reducing the frequency of interactions. Techniques like Submission Throttling and Predictive Fetch make the trade-off by decreasing frequency but increasing the amount of data sent each time.

Partition into multiple tiers

As in any web architecture, Ajax applications should use multiple tiers to help separate concerns. This advice is commonly misinterpreted as implying “keep the presentation simple,” a mistake that unfortunately leads to pathetically barren user interfaces. Don’t be afraid to create rich, intelligent user interfaces with JavaScript; just be sure to develop for compatibility and ensure your business logic is separate from your presentation logic. In addition, practice “unobtrusive JavaScript” and “unobtrusive CSS.” That is, keep your initial HTML page clean by referencing external JavaScript and CSS files; no embedded JavaScript or CSS. JavaScript and CSS should be kept apart too; where possible, the script should change an element’s display by switching its CSS class rather than micromanaging style information directly.

Go easy on the browser

Unfortunately, your Ajax App will probably end up being one of many things running in the client machine. This is exacerbated by the fact that JavaScript is pretty slow anyway, meaning that you have to exercise restraint in how much happens in the browser.

Practice graceful degradation

Where a browser doesn’t support advanced features, Ajax applications should gracefully fall back to use whatever is possible. In an ideal world, the same functionality would still be available, albeit with less bells and whistles. But even if you need to sacrifice functionality—and you often will—it should be done in a graceful manner. (Think “polite error messages” and not “complicated stacktraces.”)

Ajax Patterns Overview

The Ajax Patterns show how people have used the design principles effectively in real-world Ajax applications. It might seem funny that we can have so many patterns about Ajax, a term that was coined only a few months before work on these patterns began. However, the ideas are not new; there were many Ajax features on the Web before the term came about to describe them. The healthy Net economy has helped a lot too, with hundreds of new sites now using Ajax, along with powerful tools (RSS, Technorati, Google, and wikis) to locate them as soon as they’re available.

With over 60 patterns, it’s useful to classify the patterns hierarchically. At a high level, the book is divided into four parts, each corresponding to a different focus area—Foundational Technology, Programming, Functionality and Usability, and Development. Beyond that, each part is divided into several chapters, where each chapter includes related patterns. For instance, Foundational Technology Patterns (Part II), includes Web Remoting (Chapter 6), which includes several patterns for web remoting. Here’s a summary of each part:

Foundational Technology patterns (11 patterns)

The foundational technologies are the building blocks that differentiate Ajax from conventional approaches, and this section explains typical usage.

Programming patterns (23 patterns)

These are the features of architecture and code that serve the software design principles listed previously. These include, among other things, design of web services; managing information flow between browser and server; populating the DOM when a response arrives; and optimizing performance.

Functionality and Usability patterns (28 patterns)

These are the things that matter to users, including widgets and interaction techniques; structuring and maintaining what’s on the page; visual effects; and functionality that Ajax makes possible.

Development patterns (8 patterns)

These are process patterns advising on best practices for development, as opposed to all the previous patterns, which are “things” that live inside an Ajax application. The practices are about diagnosing problems and running tests.

Figure 3-1 shows where the four parts sit in the context of an Ajax application. Most patterns—those in the first three parts—are about the product, while the remaining part, Development patterns, is about the process. Of the product-oriented patterns, the Foundational Technologies explain how to use the crude web technologies such as XMLHttpRequest and the DOM. At a medium level are the Programming patterns, guiding on strategies to use these technologies. At a high level are the Functionality and Usability patterns. Overall, the Foundational Technology patterns are at the core of the Ajax Patterns language; the remaining three parts all build on these, and are fairly independent from one other.

Ajax Patterns: four parts
Figure 3-1. Ajax Patterns: four parts

On the inside covers of this book, you’ll find an alphabetically ordered reference of all the patterns, providing summaries and page numbers. The introduction to each part of the book and to each chapter also contains some summary information.

In addition, the following pages contain pattern maps for each of the four high-level groups—Foundational Technologies, Programming, Functionality and Usability, and Development. The diagrams in Figures 3-2 through 3-5 follow these conventions.

Foundational Technology patterns
Figure 3-2. Foundational Technology patterns
Programming patterns
Figure 3-3. Programming patterns
Functionality and Usability patterns
Figure 3-4. Functionality and Usability patterns
Development patterns
Figure 3-5. Development patterns
́

Pattern

̂

Pattern group

̃

Foundational Technology pattern group

̄

Pattern A “leads” to Pattern B

̅

Patterns A and B solve a similar problem, but in different ways

Anatomy of a Pattern

All of the patterns follow the same basic format, though certain fields are left out where appropriate. This section explains the meaning of each section.

Evidence

How much real-world evidence exists for the pattern, on a 3-point scale and presented graphically? It’s a rather subjective estimate, but use the following icons as a guide:

Suggests the idea is purely speculative

Suggests there’s at least a proof-of-concept or an early usage

⊙⊙

Suggests there’s a few established examples

⊙⊙⊙

Suggests the pattern is in widespread usage

Tags

Tags—or keywords —help people locate the pattern and get a sense of its focus.

In a Blink

This is a sketch to set the scene for the pattern.

Goal Story, Developer Story

A story is a typical scenario to explain how the pattern is used or what the benefit will be to end users. This pattern has been implemented. Each story is based on a “persona”—a fictitious person (http://www.evolt.org/article/Practical_Persona_Creation/4090/56111/)—to make the story more realistic. (And quite frankly, talking about specific people lets me say “he” and “she” instead of obfuscating the text with gender-neutral language!)

A small cast of personae is used throughout the patterns. Their names are mnemonic in that they reflect the personae’s roles. It’s cheesy, but it will hopefully help you remember what these people do without having to refer back here.

The stories in Foundational Technology Patterns (Part II) and Functionality and Usability Patterns (Part IV) are all “Goal Stories”; they illustrate how users interact with a system once the pattern has been implemented. Here are the personae used in all the Goal Stories:

Bill

A Bill-paying citizen with a wife, 2.4 kids, and a dog named after a contemporary sitcom character.

Doc

A Doctor with geeky tendencies.

Frank

A Factory Floor Manager, often stressing about machine safety and worker productivity.

Pam

A Project Manager for a perpetually overdue IT project.

Reta

A Retailer of high-class fashions.

Sasha

A Socialite with plenty of time for social bookmarking, social blogging, and social tagging.

Stuart

A Student with plenty of time for music and other hobbies not related in any way to his studies.

Tracy

A fast-paced financial Trader, dealing in any asset type where there’s a buck to be made.

Then there are the stories in Development Patterns (Part V), which show how a Developer uses a particular pattern. These are present in all the “Programming” and “Development” patterns, reflecting the nature of those sections. There are two aptly named developers who appear throughout these stories:

Dave

A senior Developer, skilled in the various Ajax-related technologies.

Devi

A senior Developer, also skilled in the various Ajax-related technologies.

Problem

The problem that is being addressed.

Forces

The forces that arise in addressing the problem.

Solution

A brief solution statement (the first sentence of the section), followed by an elaboration of the technique.

Decisions

Each decision is posed as a question. The decisions are not a FAQ section to help clarify the solution—such material would belong in the solution itself. Instead, they are “reusable decisions”—that is, decisions that will often arise once you decide to incorporate this pattern. There is no precise answer given, because each decision must be made pragmatically. The description can only guide you in making the decision, first and foremost by flagging that the decision is there to be made. And beyond that, by alerting you to the variables involved and the consequences of going in one direction or the other.

Real-World Examples

Real-world examples of the pattern at work. Where real-world evidence is lacking, proof-of-concepts and libraries are used instead. Some examples may not be strictly Ajaxian but are included to illustrate a particular point.

Code Example: Refactoring Illustration

A code example and walkthrough.

Where the system is an Ajax Patterns demo rather than an external application, it’s usually a “Refactoring Illustration” because an earlier version is being refactored according to the given pattern. This is explained further at the end of this chapter. Note that Martin Fowler originally defined “refactoring” as a code change without any user-observable behavior change. I am using the broader definition, now in common industry parlance, of a small, incremental improvement, which may well be externally visible.

Alternatives

Other patterns that solve the same problem in a different way. These are often, but not always, Ajax Patterns documented elsewhere in this book.

Related Patterns

Other Ajax Patterns that are somehow related to this pattern, other than the alternative patterns that would have appeared in the previous section. Usually, this means the Related Pattern is a possible follow-up pattern. It may also mean the patterns are somehow similar; e.g., they rely on the same technology.

Metaphor

A metaphor to help remember the pattern. Some people will find this annoying (and should therefore skip over) and others might find it a helpful way to firm up their understanding of the pattern and help remember it later on.

Want to Know More?

Links to any original references and other useful material.

Acknowledgments

Most patterns in the collection were not just speculations, but were discovered from what others were actually doing. As well as the examples above and the initial Acknowledgments section, this section is a place where people can be acknowledged for their contributions.

Ajax Patterns Demos

The Ajax Patterns Demos appear in many patterns as Refactoring Illustrations and also in the Solution section. They’re all online at http://ajaxify.com/run/, and it would be worth trying them out. In addition, the full code base can be downloaded from that location; its installation is explained in the Appendix B. It includes the demos as well as completed code for Chapter 2. Note the demos have been tested on Firefox 1.5 and IE6, though most of them work on comparable browsers as well.

The server-side code is all PHP, but most of it is fairly trivial, so it should be fairly easy for all programmers to comprehend. PHP was chosen as it’s quite easy for anyone to set up, on any platform. Also, the language itself is fairly “generic” in that anyone with web development experience should have no difficulty following the code.

The demos are organized around a refactoring theme. For most of the examples, there is an initial, “embryonic,” Ajaxian application. Then, several parallel refactorings are applied to the same demo, each in a separate subdirectory. And each of these refactorings may have a further refactoring applied, contained in a deeper subdirectory. A tree structure emerges on the site, with each application having evolved in different ways.

For example, look at the evolution of Finite Cache Sum Demo (http://www.ajaxify.com/run/sum/xml/cached/expiry/), which has the path /sum/xml/cached/expiry/.

/sum/

First, there is the basic demo at /sum/. Enter some numbers and the server responds with a sum. As a basic Ajaxian application—with no form submission involved—there are some foundational technologies illustrated here, but that’s about it.

/sum/xml/

Next, the sum is refactored to receive results in XML form, as a demo is done for the XML Message pattern. The “xml” prefix on the URL tells you its lineage.

/sum/xml/cache

One benefit of the new XML form is its convenience for caching, so a further evolution is a basic cache. This is a refactoring illustration for the Browser-Side Cache pattern.

/sum/xml/cache/expiry

Finally, the cache undergoes further improvement. This time, a concession to the laws of physics is made, and the cache is now of finite size. Unused elements expire. So here’s a further refactoring illustration for Browser-Side Cache.

Conclusions

This chapter has covered how people are designing for Ajax and introduced the Ajax Patterns. The pattern language (just like Ajax itself) isn’t a magic bullet, but a tool intended to improve your mastery of Ajax web development. You can use it as a reference for “quick-fix” problem solving, but you probably gain more if you also treat it as an educational resource to learn more about the recurring problems and solutions in Ajax. The remainder of this book constitutes the patterns themselves, divided into four parts according to their area of concern—Foundational Technologies, Programming, Functionality and Usability, and Development.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required