Sunday, August 01, 2004
Thin vs Rich, and The Smart Client Pendulum
When Adam Bosworth moved to Google recently, Dare wondered if they weren't finally working on sorting out the Thin vs Rich vs Smart client thing once and for all.
Adam was quite vocal on this last year, for example describing how he wished he could properly browse offline (even though what he describes sounds much like a service providing a hierarchy of RSS feeds).
Adam just posted a follow up that lends some credence to Dare's theory...
I find the whole debate quite timely. One of the challenges we face at work (and I'm sure we're not alone) is balancing the whole thin vs rich thing. For years the pendulum was firmly in the "thin" camp, but last year it swung and much of the new thinking is going into the "rich" camp, being WinForms.
Thin works great for transactional pages, where information comes back (or you fill in some form) then click to perform an action, then another unit of work is delivered and so on. But it falls down on two fronts:
At the thin end, Using an ActiveX for state persistence. By deploying an ActiveX that does client-side state persistence, you can get a rich interactivity model that follows you from page to page without having to marshall a lot of state back and forth from client to server. You then access your client state directly using JavaScript at the client.
Next up, Using an ActiveX as a server conduit. By deploying an ActiveX that acts as a conduit to your server, you modify your server interactivity to channel through this conduit (say to a web service). Now if you write your conduit appropriately, its not hard to disconnect your web client and run it interactively from cache. This model should work with Java components too.
Moving up, Run your Rich Client as an ActiveX. Here you get all the benefits of a rich client (it is a rich client!), but you host in the browser and let the browser take care of downloading new version of the hosted control if it changes. This model works great, but has some issues, notably the browser won't pull down your dependencies, so you'd better not have any! I've seen workarounds for this, notably Mercury Interactive's TestDirector. TestDirector has a stub ActiveX that functions much like the ClickOnce feature of Whidbey, where the stub pulls down a manifest that tells it what other components it needs to load. It compares what it already has in its cache, downloads any next bits, then fires up what is a highly complex application, inside the browser. This model doesn't work in Java because of the Java sandbox.
Moving beyond the browser, .NET supports Web-based WinForm execution. In this model, you run a WinForms app from a url, and it brings down the components it needs and runs on the client. In this model, .NET takes care of the deployment issues (up to a point - that point being it only does what it sees through the assembly manifest - it won't install Oracle drivers if your client needs them). The biggest downside of this model is that you are constrained by .NET's trust model and specifically Code Access Security, so you can't just go writing to the disk or adding to the Windows registry.
So what do I think the answer is? The model I think works best is the one that TestDirector uses. From one perspective you might also consider it the same model that Windows Updates uses. A stub component is installed (which doesn't change all that often, so the user doesn't keep seeing the Authenticode permissions dialog). This component then gets a list of bits it needs, compares with what it already has, and pulls down what it needs. Of course, there are problems with this model too. What if the client never restarts the stub? How then can you get new components to them? TestDirector seems to solve this by using an RPC channel to talk to its server component, which allows it to break the client out of its happy bubble and restart (though obviously you'd wait until the middle of the night to do such a thing).
Still, all things considered, this seems to be the best of all worlds. As Windows Update has shown, you can have the stub run .msi installs to get whatever drivers and local evilness you need to install and not bother the user with any of it except a progress dialog while the stub does its thing.
As there's always new techology and new ideas, this will be a pendulum that keeps on swinging. I'm hedging my bets for now with Xanadu (ours, not Ted Nelson's), where I can write an app that has zero lines of UI code (only UI metadata that describes the controls you want and their behavior) and can be run as thin (DHTML) client or a rich (WinForm) client with no visible difference to the client. Allow the server to build a manifest from Xanadu's code components and metadata (easy to do, as Xanadu's XML parser supports document discovery) and use a stub to pull it all down, and you've got a pretty compelling rich client solution. The good thing about Xanadu with this approach is that if it doesn't work out and we need to go back to a thin client, there's little or no work to make it happen, as Xanadu can render DHTML just as well, and all we lose is the ability to run the client disconnected.
Post a Comment
Adam was quite vocal on this last year, for example describing how he wished he could properly browse offline (even though what he describes sounds much like a service providing a hierarchy of RSS feeds).
Adam just posted a follow up that lends some credence to Dare's theory...
I find the whole debate quite timely. One of the challenges we face at work (and I'm sure we're not alone) is balancing the whole thin vs rich thing. For years the pendulum was firmly in the "thin" camp, but last year it swung and much of the new thinking is going into the "rich" camp, being WinForms.
Thin works great for transactional pages, where information comes back (or you fill in some form) then click to perform an action, then another unit of work is delivered and so on. But it falls down on two fronts:
- You can't use the model in a disconnected form (out of the box)
- You can't (or it would be too hard) do complex ui interactions. For example, building fuzzy logic in to guide your workflow based on what you type as you type it... not fun to do in JavaScript/DHTML)
- Deployment (especially on-demand, or on-change deployment) will kill you
- Supporting all the different combinations of client system configurations and troubleshooting client issues is a b*tch
At the thin end, Using an ActiveX for state persistence. By deploying an ActiveX that does client-side state persistence, you can get a rich interactivity model that follows you from page to page without having to marshall a lot of state back and forth from client to server. You then access your client state directly using JavaScript at the client.
Next up, Using an ActiveX as a server conduit. By deploying an ActiveX that acts as a conduit to your server, you modify your server interactivity to channel through this conduit (say to a web service). Now if you write your conduit appropriately, its not hard to disconnect your web client and run it interactively from cache. This model should work with Java components too.
Moving up, Run your Rich Client as an ActiveX. Here you get all the benefits of a rich client (it is a rich client!), but you host in the browser and let the browser take care of downloading new version of the hosted control if it changes. This model works great, but has some issues, notably the browser won't pull down your dependencies, so you'd better not have any! I've seen workarounds for this, notably Mercury Interactive's TestDirector. TestDirector has a stub ActiveX that functions much like the ClickOnce feature of Whidbey, where the stub pulls down a manifest that tells it what other components it needs to load. It compares what it already has in its cache, downloads any next bits, then fires up what is a highly complex application, inside the browser. This model doesn't work in Java because of the Java sandbox.
Moving beyond the browser, .NET supports Web-based WinForm execution. In this model, you run a WinForms app from a url, and it brings down the components it needs and runs on the client. In this model, .NET takes care of the deployment issues (up to a point - that point being it only does what it sees through the assembly manifest - it won't install Oracle drivers if your client needs them). The biggest downside of this model is that you are constrained by .NET's trust model and specifically Code Access Security, so you can't just go writing to the disk or adding to the Windows registry.
So what do I think the answer is? The model I think works best is the one that TestDirector uses. From one perspective you might also consider it the same model that Windows Updates uses. A stub component is installed (which doesn't change all that often, so the user doesn't keep seeing the Authenticode permissions dialog). This component then gets a list of bits it needs, compares with what it already has, and pulls down what it needs. Of course, there are problems with this model too. What if the client never restarts the stub? How then can you get new components to them? TestDirector seems to solve this by using an RPC channel to talk to its server component, which allows it to break the client out of its happy bubble and restart (though obviously you'd wait until the middle of the night to do such a thing).
Still, all things considered, this seems to be the best of all worlds. As Windows Update has shown, you can have the stub run .msi installs to get whatever drivers and local evilness you need to install and not bother the user with any of it except a progress dialog while the stub does its thing.
As there's always new techology and new ideas, this will be a pendulum that keeps on swinging. I'm hedging my bets for now with Xanadu (ours, not Ted Nelson's), where I can write an app that has zero lines of UI code (only UI metadata that describes the controls you want and their behavior) and can be run as thin (DHTML) client or a rich (WinForm) client with no visible difference to the client. Allow the server to build a manifest from Xanadu's code components and metadata (easy to do, as Xanadu's XML parser supports document discovery) and use a stub to pull it all down, and you've got a pretty compelling rich client solution. The good thing about Xanadu with this approach is that if it doesn't work out and we need to go back to a thin client, there's little or no work to make it happen, as Xanadu can render DHTML just as well, and all we lose is the ability to run the client disconnected.



