Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Ajax Patterns And Best Practices (2006)

.pdf
Скачиваний:
39
Добавлен:
17.08.2013
Размер:
15.94 Mб
Скачать

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

199

Figure 7-2. Example data-gathering web application1

The HTML form has an editing problem, and two factors are largely responsible: bad userinterface design, and not knowing how to deal with HTML forms. In contrast, Figure 7-3 illustrates how HTML can be organized to be both visually attractive and data-entry effective.

In Figure 7-3, Slashdot presents a very simple user interface that has a single-line text field for the subject and a generous text area for the comments. This is a good example of how to write a data-gathering application. However, there is a catch in that a well-organized HTML form takes a larger amount of screen real estate.

1.For those wondering, I sent a message to the Zurich regional government indicating how a pet collar that has GPS and cellphone capabilities could be used to control dogs such as pit bulls without resorting to drastic measures. This is a concern in Europe (also in other places such as the US) as fighting dogs have been responsible for many child deaths and critical injuries.

200

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

Figure 7-3. A properly formatted text box

This leads us to the question of whether it is even possible to write a compact and effective HTML form. And if it is not possible, does this mean web applications are ill-suited for data gathering and better suited for navigation? The answer lies in a change in thinking, where HTML offers capabilities that are beyond the reach of other technologies. Traditional user interfaces generally have predefined windows and dialog boxes, and are very static in nature (not dynamic). A traditional user interface application does not generate user interface elements dynamically from a few pieces of information. Traditional user interfaces are a “what you see is what you get” type of programming environment. Dynamic HTML, on the other hand, makes it possible to define the user interface as the application is being executed. It is possible to do the same sort of thing with traditional programming environments, but the effort required is not insignificant.

Static user interfaces are the result of creating a component that is a single block manipulated by a programming language. Figure 7-4 illustrates such a component, which is a combo box used to specify and purchase a plane ticket.

Figure 7-4 shows a combo box that when clicked will expose a list of available times that a person wants to fly. The combo box displays all available hours and is large enough to accommodate a large number of times with the least amount of scrolling required. The combo box is functional and represents the data in a format that JavaScript and a server application can easily process. Some developers consider this sort of user interface as being developer-convenient but user-inconvenient.

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

201

Figure 7-4. Simple example of anchored state

From a user interface perspective, the combo box is not optimal, but it is what we would use because of traditional programming habits. Another approach would be to create little sun and moon clocks and let the user click on the time. Creating the clocks would enable the user to make a choice more quickly and could even let the user specify quarter-hours. The combo box in Figure 7-4 cannot specify anything other than the hourly choices.

Another approach would be to use two separate components to select a value. Each component would represent a “best-of-breed” representation. For the time, the static representation could be a text box indicating the preferred time. The second component would present a user-friendly way to select the time. Such an example of using two separate components already exists today in the form of a calendar, as illustrated in Figure 7-5.

Figure 7-5. Using two components to determine a single state

Figure 7-5 shows a text box, representing the machine-friendly component, which contains an example of how the date should be formatted. The date-formatting specification is mm/dd/yy. The date formatting is cryptic, not obvious in the least, yet most of us seem to know what it means. The formatting is an example of incredible user idiosyncrasies that most of us accept because they are machine-friendly. The second component is user-friendly and is the larger calendar window. When the user selects a day in a month, the user-friendly component updates

202

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

the contents of the machine-friendly component. The user does not have to understand the formatting; the date could even be formatted in seconds since 1970.

Most of us appreciate the two components as a single component called the calendar component, which is an example of the Representation Morphing pattern. The important message is that a calendar at its basic level has two best-of-breed representations (user friendly and machine friendly), where the model (date) is transferred from one representation to the other.

The calendar component is trivial and may lead you to wonder what the difference is between components and the Representation Morphing pattern. The answer is defined as follows:

Traditional components are programmed so that the state of the component is determined at the component’s runtime.

Traditional components are hardwired together, not allowing for any flexibility when transferring the model from one representation to another.

Traditional components have their model transferred by using external access mechanisms and consider the internals private.

In a nutshell, when implementing the Representation Morphing pattern, you are defining a structure in which the model, view, and controller are part of the representation.

The motivation for using the Representation Morphing pattern is as follows:

To enable a programming model where the model, view, and controller are self-contained and can be saved and loaded. This makes it possible to create work spaces that a developer can save.

To enable the flexible combination of representations so that a best-of-breed approach can be used when manipulating data. A simple example is the ability to transform an HTML form so that people who are blind or nearly blind can view content that suits their needs.

To enable the definition of states that can be used in workflow applications without having to wire together an extensive number of objects.

The idea is to enable a programming model where the model, view, and controller can interact among themselves. A user of the model has the choice of manipulating the model directly or using helper functions, but the model is not hidden from the user of the representation. The idea of letting a script access the internal workings of a component does violate objectoriented programming. But the aim of the Representation Morphing pattern is not to abstract, but to standardize the model that makes up the component. In object-oriented programming techniques, the internal state is abstracted so that it can change without having to change the code of the user. With the Representation Morphing pattern, the intention is to keep the model constant and have the representation change.

Applicability

Technically speaking, the Representation Morphing pattern is used whenever data is transformed from one representation to another. This is useful when developing data-gathering

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

203

applications that require two different representations for viewing the data and editing the data. In the “Implementation” section, the transformation of editing and viewing the data is illustrated.

A very appropriate example of where the Representation Morphing pattern is used is in a wiki-type application. A wiki is a web-based application used to manage documents that can be viewed and edited by individuals. A wiki is an ideal example of an application that has a common state but multiple distinct representations (editing, versioning, commenting, and viewing).

The Representation Morphing pattern is also very applicable in a navigation scenario, when navigated state should be presented by using different representations. A common navigation situation is the conversion of an HTML page into another HTML page that is printer-friendly.

With the Representation Morphing pattern, it is possible to send a representation to the server side for further processing. Such an approach gets around the limitations of HTML forms, allowing more complicated structures to be sent. The advantage of sending a representation directly to the server is that the client has to do no processing. A client can take advantage of the Content Chunking or Persistent Communications pattern without implementing extensive serialization routines.

The Representation Morphing pattern would be inappropriate if the data-gathering application were a generate and forget type of application. In a generate and forget application, somebody submits data that is sliced and diced into another state. After the state is transformed, implementing the Representation Morphing pattern becomes more complicated. The complication is the result of potentially losing a state that a representation needs. For example, imagine building a web application that adds two numbers. If the server side uses the two numbers to generate another number and then returns the generated number only, information is lost. The representation that generated the numbers needs the added numbers when generating its view.

Associated Patterns

The Representation Morphing pattern relies on blocks of content that can be either state or representation related. The blocks of content can be either sent or received, and therefore this pattern makes use of the Content Chunking pattern. When the content is received by using the Content Chunking pattern, the Permutations pattern does apply. The Representation Morphing pattern is a form of the Permutations pattern intended for the client side.

A more accurate description is that the Representation pattern imitates the Permutation pattern, except the Representation pattern has no URL. The URL is the model in the representation. The Representation Morphing pattern is used when the State Navigation pattern is implemented. The purpose of the Representation Morphing pattern is to define the state that is managed by the State Navigation pattern.

Architecture

Technically, the Representation Morphing pattern is used to define some representation that has some state that can be transferred to another representation, and back again with the state intact. The “Architecture” and “Implementation” sections will move away from the model-view- controller analogy because the analogy is good for presenting an initial impression of what the

204

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

Representation Morphing pattern does, but bad for explaining the nitty-gritty details. These nitty-gritty details, when critically considered, illustrate that there are some fundamental differences between the Representation Morphing pattern and the Model View Controller architecture.

Basic Theory

The architecture of the Representation Morphing pattern considers the state as the basis of the representation. The representation relies on the state, but not the state on the representation. This means that two representations can contain the same state but display the state differently. The state within a representation will be identical in literal terms. Figure 7-6 illustrates how this might work and provides a closer look at the calendar and its underlying HTML structure.

Figure 7-6. Transformed state between text box and window

In Figure 7-6, the common state is represented by the attributes value and date. The format of each attribute is identical; only the attribute identifier is not. What you want to avoid is the deciphering of the state into its base components, which for a date is month, day, and year. Deciphering state means that an external script accessing the state needs to understand how the state is deciphered. One could argue that because the calendar uses two different attribute identifiers, a state has already been deciphered. However, the point of the modified identifier was to illustrate that the Representation morphing pattern probably needs a bit of flexibility with respect to state identification, but not state value. Of course the ideal solution is to have 100 percent identical state identification across representations, but that is not always possible.

Having identical state values across representations makes it possible to apply transformations across representations without the loss of information. The moment state has to be deciphered, you are risking losing information. This is not to say that a representation cannot

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

205

decipher the state. The point of the Representation Morphing pattern is to enable individual representations to decipher the state to something that is useful for their context. Additionally, embedding the state in the representation itself ensures that state is not lost when it exists temporarily in the context of an executing JavaScript document.

Why the Pattern Is Not an HTML Component

Considering the basic theory of the Representation Morphing pattern, you might question how the pattern is different from a component. The purpose of the component and the pattern are identical in that they provide multiple representations of the data.

Previously I discussed traditional components. Now, after having explained a bit of the pattern’s architecture, I will define the attributes of the Representation Morphing pattern implementation:

The representation and state are combined as a single piece of content.

The “guts” of the component are exposed and can be manipulated by other representations.

Transferring the representation means transferring a work space that is self-contained and allows for a later reinstantiation.

A representation can be combined with other representations that evolve over time, and can create new pieces of functionality that the developers of the web application had not previously considered.

The logic associated with the representation is used to manipulate state, and not keep state (for example, a JavaScript variable instance is not used to keep state).

In a nutshell, the big difference between most user interface–based components is that when the component is instantiated, it has no state. However, when a representation that implements the Representation Morphing pattern is instantiated, there is a state. The result is that potentially two instantiations of functionally identical representations will contain two entirely different states.

What the Representation Morphing pattern implements is one of the concepts made possible with dynamic programming. The entire architecture of the Representation Morphing pattern rests on the capabilities of dynamic languages and the Dynamic HTML object model. Dynamic languages2 are known to some people as scripting languages. What makes a dynamic language unique is its ability to define, add, or delete functions, modules, or class types during the execution of the language and to have the ability to persist those changes as a work space for later execution. Languages such as Java and C# cannot do that, or at least not as simply as dynamic languages.

Consider the following example, which illustrates how a dynamic language operates:

function createTypeAndProperty() { var obj = new Object(); obj.prop = 12345;

return obj;

}

2. http://en.wikipedia.org/wiki/Dynamic_language

206

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

In the function createTypeAndProperty, the variable obj references the type Object, which has a minimal number of properties and methods. Dynamically, the property prop is assigned a value of 12345. There is no definition of prop in the Object type, but a dynamic language allows this arbitrary assignment. Had this example been coded using either Java or C#, there would be compilation problems due to the incomplete definitions. The dynamic assignment of the property is part of the basic design of a dynamic language. The result is that a dynamic language can assign properties that represent methods or data members on an as-needed basis. Putting this into the context of the pattern, it means that properties can be assigned to already-existing HTML elements. When implementing the Representation Morphing pattern, a dynamic language is needed because the state changes dynamically, including the type of state stored.

It also requires developers to stop coding using static programming techniques. Consider the following source code that illustrates two JavaScript functions; one uses static programming techniques, and the other uses dynamic programming techniques:

var value;

function AssignStatic() {

value = document.getElementById( "form-element").value;

}

function AssignDynamic() {

document.getElementById( "div-variable").innerHTML = document.getElementById( "form-element").value;

}

Let’s say both functions are used to process a state that is entered in an HTML form element. The function AssignStatic transfers the state from the HTML form element to the variable value. The function AssignDynamic also transfers the state, but transfers the value to the div HTML element div-variable.

The ramification of storing the state directly in the representation is that you can transfer content by transferring the representation. From a traditional client perspective, it is as if somebody entered some text in a text box that is stored in another user interface element, and not the executing program. The representation is self-sufficient, and when it is transferred, the representation still continues to function—albeit with a few gotchas that will be explained in the “Implementation” section. It is not possible to transfer the contents of an HTML chunk without first explicitly transferring the state of the running JavaScript to some other content chunk.

Defining Blocks of State

Designing the Representation Morphing pattern requires defining blocks of state that are associated with a representation. A representation is a content chunk akin to that defined by the Content Chunking pattern. Figure 7-7 shows an initial HTML form that will be used to illustrate how an HTML form is converted into a number of content chunks representative of the Representation Morphing pattern.

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

207

Figure 7-7. Example HTML form3

Figure 7-7 shows an HTML form with HTML form elements such as a text box, combo box, and the likes. The HTML form is used to enter some data, and is a classical example of a form that is machine-friendly, but in many aspects user unfriendly. The following points illustrate the user unfriendliness of the HTML form:

What happens if you are older than 65? The Age combo box has a maximum of 65, which has been cited as the keyhole problem by Scott Meyers.4

What happens if your naming pattern does not fit into the classical model of first name and last name? Many cultures on this planet have other naming conventions.

What happens if the country does not have a state or a zip code?

What happens if the phone number does not fit into the classical area code and seven digits? Where does the extension fit in?

Why must the Comments text box have fixed rows and columns that always seem to be too narrow for anything but the simplest of information?

Why must the Browser(s) list box contain elements that can be viewed only if the scroll bar is used?

Why must abbreviations (such as WA for the state) be used that not everybody may understand?

Why are the text boxes in the HTML form not wide enough?

3.The source of the HTML is http://demo.xoad.org/examples/forms/, which uses the XOAD toolkit.

4.http://www.aristeia.com/

208

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

The HTML form can be used to display the data, but when the data is edited a different representation should be used. Of course you could argue, why use an HTML form in the first place if a different representation is going to be used to edit the content? Even though that point is correct, most people today have HTML forms and it makes more sense to discuss how HTML forms and the Representation Morphing pattern can interact with each other. To convert the HTML form to use the Representation Morphing pattern, individual states have to be defined, as illustrated in Figure 7-8.

Figure 7-8. Example HTML form converted into three state blocks

Figure 7-8 shows three blocks of state. These blocks were defined based on the way that the elements were grouped. After all, if you group something, you have created an association between the grouped elements. However, it is not necessary to create one state per grouping, and there could be multiple groupings per state. The idea is to define a block of representation that contains a state. For this explanation, the focus is on Block 1 in Figure 7-8. Block 1 is a representation that contains a state made up of five pieces of information. Those five pieces of information make up the model that will be extracted and injected into different representations.

HTML form elements are useful for gathering data but hinder the user’s comprehension of the data because the data’s layout tends to be irregular. To improve the user’s comprehension when viewing data, a better approach would be to use HTML without the form elements.

Figure 7-9 illustrates what the state of Block 1 would look like without using HTML forms. Figure 7-9, which presents a new representation of Figure 7-8, is more compact and easier

to read at a glance. The representation is user friendly for reading purposes. The state in Figure 7-9 is contained within a series of span HTML tags. Each individual span tag has an identifier similar to the identifier in Figure 7-8. The state of Figure 7-9 is also the representation, as illustrated by the following HTML:

<td><span id="first-name">Bill</span>,

<span id="last-name">Gates</span><br />

...

</td>