Much discussion on rich-client user interfaces and Ajax focuses on the client. Yet, the most fundamental design decision for a rich-client application involves the interaction between client and server, with potentially far-reaching impact on an application's overall architecture.
A popular episode in the Life of the Caesars, Suetonius' account of Rome's first twelve emperors, describes how Julius Caesar vacillated before deciding to cross with his army the river Rubicon on his way to call the senate at Ravenna to account:
Coming up with his troops on the banks of the Rubicon, which was the boundary of his province, he halted for a while, and, revolving in his mind the importance of the step he was on the point of taking, he turned to those about him, and said: "We may still retreat; but if we pass this little bridge, nothing is left for us but to fight it out in arms... Let us go whither the omens of the Gods and the iniquity of our enemies call us. The die is now cast."
The decision to cross the Rubicon was momentous because Roman law forbade a general returning from wars to cross the river with his troops. Passing the Rubicon meant that Caesar openly challenged existing tradition, and would either have to prevail in his self-declared role as leader, or perish. Crossing the Rubicon has ever since come to mean a point of no return, a momentous decision that would change everything.
Perhaps the least thing enterprise architects desire is to have to cross a point of no return. Indeed, a wise path to managing technology and design risk leads through the terrain of reversible decisions: Making small, reversible changes to a system minimizes the risk that any one of those changes do not work out. By keeping your options open, you can substitute one technology for another, should the initial choice prove ineffective.
Yet, there is also risk in avoiding the decisions that involve big, fundamental changes to a system. Major redesigns of a database schema, picking a new programming language, and even choosing an enterprise framework, are often such fundamental decisions that switching to alternatives down the road, or backing out of such decisions, is seldom practical, no matter how agile the design or the development process. Still, if such decisions are called upon by pressing present needs, not making, or postponing, them could prove more disastrous over the long haul than incurring the risk of a practically irreversible decision.
Is the choice of providing a rich-client user interface to an application such a big, irreversible decision?
At first blush, it doesn't seem to be the case: You could just add small pieces of interactivity to an existing user interface, requiring little, if any, architectural or systemic changes. If anything, enriching a user-interface in this manner could exemplify small, reversible changes.
Progressive enhancement can seldom just be bolted onto an existing set of HTML pages: Like security, effectively implementing progressive enhancement requires a systemic approach. Thus, the decision to provide even progressively enabled rich-client elements in the UI would require system-level, architectural support. That, in turn, suggests that properly implementing a rich-client user experience is a more involved decision. But is it an all-encompassing choice from which to back out is costly and impractical?
Several frameworks attempt to alleviate the unease that come with making big decisions. Frameworks such as JSF make the question of rich client-centric architecture moot, mainly by making that decision for us. Providing a component design with client and server-side elements, turns the development process into one of defining and working with components, and letting the JSF framework and associated libraries take care of the rich-client user experience. To a lesser extent, Rails makes similar decisions for a developer, as it provides code generators for the popular Prototype and script.aculo.us Ajax libraries.
Yet, I suggest that many developers choose JSF, and even to a lesser extent Rails, too, precisely for these frameworks' ability to provide high levels of rich-client user experience. It is the availability of Ajax-ready JSF components that may compel a developer to choose JSF as an architectural framework in the first place; and the ease with which to get started with Prototype or script.aculo.us through the framework are important motivators for working with Rails. In this manner, the desire of provide a rich-client user experience does lead to the big, hard-to-reverse decision of choosing a framework.
Another category of rich-client frameworks, however, do not depend on any specific server-side technology. The most notable ones are Flex and the significant client-side Ajax libraries, such as Dojo. It is perfectly possible to enrich an existing Web application with Flex components without making any changes to server-side code. But beyond the most trivial visual filigree, working with Flex in that manner quickly proves ineffective.
In contrast to JSF and Rails, where UI rendering for the most part takes place on the server, in the latter category of rich-client tools, rendering takes place entirely on the client. Once the client renders such UI components, the components almost always expect some kind of data from the server. In effect, the server first simply delivers the components to the client and, in a second pass, provides the components with their expected data. In a variation on this theme, it also possible to incorporate the data along with the components, embedded in the HTML as XML or JSON elements. Still, the principle is the same: The server-side framework primarily concerns itself with emitting data, and not with rendering the UI. One could argue that the primarily data-centric, as opposed to rendering-centric, task of the server a key hallmark of an Ajax-oriented architecture.
I found that offering such an Ajax-centric server-side infrastructure is a major architectural decision. First, the interface to the server becomes HTTP (in the case of REST) or SOAP, and not a business-specific API written in a programming language. The deeper the HTTP or REST abstraction runs, the more sweeping the architectural decisions that provide for the rich user interface. For instance, submitting data via an Ajax POST should return HTTP response codes, not human-language error messages. It becomes the client's task to interpret those response codes and to translate them to the user.
With two parallel code-bases to maintain, it would be hard to claim that investment into the rich-client user experience is small and easily reversible. Once you go down that path, the die is cast, and you'd better have the wherewithal to stick with that design decision and to manage that architecture's inherent risks.
The main risk, interestingly, may lie on the server, rather than on the client. Flex, for instance, is a so well-designed and mature that a developer with little Flex experience can create fairly complex user interfaces with it. But developing an elegant REST or SOAP/RPC interface on the server requires a lot of experience without which such projects may not succeed. In the absence of such expertise, what is likely to emerge is a hybrid of traditional, server-side rendering of HTML, with methods sprinkled here and there on server-side components to service the needs of the rich-client Flex and Ajax components.
The result may not be a clean, coherent design and architecture. Inasmuch as I like Flex and some of the Ajax UI toolkits, JSF and Rails at least provide some sensible, but not always correct, defaults in binding between client and server-side components, reducing somewhat the risk of major design errors on the server.
In conclusion, providing a rich-client interface is likely to be a big architectural decision. If you have already crossed the metaphorical rich-client Rubicon in your projects, to what degree did that decision impact your overall architecture? If you are standing on the banks, considering the decision, what worries you the most?
In my experience it wasn't really a Rubicon but rather, like climbing a hill: you elevate little by little until you realize you are in a different zone now -- the landscape and the plants are a bit different and it's harder to breathe :-)
I cannot say I've seen those server-side risks yet. In a well designed application server side talking to the rich client would be probably a thin layer around the business logic and it is just a job of Web Services infrastructure (REST/SOAP/JSON) to expose it as transparently as possible.
The main burden was still the client side, to get these JS's working properly and support all the target browsers. Dunno about Flex, it may be easier.
What bothers me on most Ajax examples I see, is the tight coupling between Client, Server and database logic. Especially java approaches like GWT more or less mandate that the client and database follow the Server code, and try to abstract them so that you can do no finetuning in client or specific SQL (like stored procedures instead of server java code).
Instead of traditional MVC I would like clean interfaces between client and server and between server and database: client and server: REST. server and database: something like iBatis but allowing to specialize for different databases in XML.
If the interfaces are clean then you should be able to switch one component (say a dojo based turbogrid replaced by an extjs one) without any changes to the server. Same for database: replace mysql (and business logic in server code) for oracle (with business logic in PL/SQL).
So if I have an existing Oracle database with stored procedures etc, how do I put a nice rich client frontend to manage the data and add a server in between to do webservices and REST etc... WITHOUT redesiging the (Oracle) backend and WITHOUT being tied to an Ajax technology that me well be not around in 2 years.
The frameworks to do this are not yet in place though. I suspect that anything written today will be very ugly legacy code in two years time.