[Seaside] Component tree vs. DOM tree

Sebastian Sastre ssastre at seaswork.com
Tue Mar 11 14:01:26 UTC 2008


Michael,

	thanks a lot for posting your experience so clearly. It makes me think
about valuable things on this regard.

	I'm curious about the back button alternative solution you mention. Did
you still provide the user of the back button feature with that approach?

	cheers,

Sebastian 


 

> -----Mensaje original-----
> De: seaside-bounces at lists.squeakfoundation.org 
> [mailto:seaside-bounces at lists.squeakfoundation.org] En nombre 
> de Michael Lucas-Smith
> Enviado el: Martes, 11 de Marzo de 2008 09:56
> Para: Seaside - general discussion
> Asunto: Re: [Seaside] Component tree vs. DOM tree
> 
> Andreas Tönne wrote:
> > Sophie,
> >
> > if you unify components and brushes to get a true model of 
> the client side
> > (how do you really keep this model in sync with the client 
> side if you use
> > DOM manipulating JavaScript?)
> It's a different conceptual model to the norm, that's for 
> sure. What you 
> do is think of the web browser as a smart client that is like a 
> Smalltalk image, except that its UI model is hard coded to this 'DOM' 
> and 'CSS' stuff but it can run code in its own bizarre 
> language called 
> 'javascript'.
> 
> Over the last several years we've seen an uptake in peoples 
> willingness 
> to use this 'javascript' language in more sophisticated ways to take 
> advantage of advances in the web browsers capabilities. 
> Firefox 3b4 for 
> example has sped up Javascript execution significantly in an 
> effort to 
> promote this esoteric platform as a unified smart client.
> 
> There are numerous other attempts at smart clients out there 
> too, from 
> Microsoft and Adobe and various other players too. Mozilla even have 
> their own attempt at a smart platform beyond the standards 
> with XUL... 
> but at the end of the day, the industry seems generally 
> uninterested in 
> non-standards compliant smart clients.. so we have XML and CSS and 
> Javascript as our drivers.
> 
> This has even been reflected in Mozilla's Prism effort, to provide a 
> client side launcher for websites to pretend that the web 
> browser isn't 
> a virtual machine in itself such that individual websites look like 
> independently running network requiring applications. Good on 
> them I say.
> 
> But with this change of mindset comes a change in how you write and 
> drive your server application code. You have to think of the 
> web browser 
> as something you command as a widget environment instead of a 
> publishing 
> environment - that is a radical change to current web development 
> philosophy.
> 
> When you make a <div> element and put it on the client, you 
> should think 
> of that <div> element as a widget that has a configurable display 
> routine (css) and customizable interaction logic 
> (javascript). So this 
> comes back to your question of how do you keep the client 
> side in sync 
> with the server side?
> 
> In a good client-server model, the messaging protocol will 
> allow you to 
> have transparent object references. They generally do this by 
> assigning 
> each object an id that they can refer to the object by on the remote 
> side. So the approach becomes pretty simple.. when you make 
> an element 
> on the server side, you give it an id - the client will honor that id 
> and you now have a common base of reference.
> 
> When you want to update the 'widget' on the client side, you 
> can refer 
> to it by its id. Often with Ajax, you will have client side code that 
> will make a specific request to the server and update a 
> specific id on 
> the client side. The server has no control over what will be 
> updated on 
> the client side except by virtue of having first emitted the 
> code that 
> will later do the update. This is a little limited - so one 
> of the first 
> things we did was to stop emitting xml from the server and 
> instead emit 
> javascript.
> 
> The javascript can then update as many widgets on the client 
> side as it 
> wants. The second step we did was to make this transparent. 
> Since each 
> widget on the server side had the same properties as the 
> client side, we 
> could simply modify ourselves on the server side and create a set of 
> commands we wanted to perform on the client side to keep it 
> in the same 
> state as the server.
> 
> Anytime a piece of information changes on the client side that the 
> server should know about, such as an event, we would emit a 
> message back 
> to the server and let it update itself transparently too. 
> However, when 
> you start getting more advanced you find that there are several nodes 
> and events and things that happen on the client side that the server 
> doesn't want or need to know about.
> 
> An example of this is a link widget that will do hover in/out to 
> simulate css's :hover because IE6 can't do it. This is a slightly 
> redundant example but it scales up to complex widgets that do tables, 
> sorting, column reordering etc.
> 
> So while you have a consistent view of most of the client on 
> the server 
> side, you don't know all of what the client is doing - you just know 
> about the things you made and control.
> >  then this opens the question:
> > - who is maintaining the application state and interaction logic?
> >   
> It's a combination of the server and the client. The client 
> is the one 
> who actually does the interaction, but it's the server who makes the 
> decisions. For example, if you have an autocomplete widget, when they 
> type in to the input box, the input is sent to the server. 
> The server, 
> in response, creates the drop down div and fills it with 
> stuff and that 
> is emitted back to the client as javascript to run. At the same time, 
> the server may have done other things, like turned you text red by 
> changing some styling, or updating a clock ticking away in 
> the corner of 
> the screen.. or updated a details pane to reflect the most 
> likely match 
> of the autocompleter..
> 
> Who knows, the sky is the limit because you can treat these 
> widgets like 
> you would regular GUI widgets. You hook up to them with events on the 
> server side and you can manipulate your server side DOM tree 
> in as many 
> ways as you want between the time a Request comes in and the Response 
> goes out. All the changes are queued up and replayed in order. We got 
> sophisticated and even know how to compress that list as we queued up 
> the commands so that we weren't doing redundant stuff.. this 
> was just an 
> optimization that wasn't actually required.
> > UI and application state are not necessarily identical and 
> you do not want
> > to keep your whole state in the DOM tree (this would mean 
> your application
> > becomes too much dependent on a particular tree). An 
> application state (in
> > VisualWorks it is the ApplicationModel, bad name) is the necessary
> > abstraction from a particular presentation. So by joining 
> components and
> > brushes, you have to introduce a new concept to replace the 
> now missing
> > other half of WAComponent.
> >   
> It's the same concept, .. though I was disagree that this 
> concept has to 
> be a separate tree. In fact, there's very little difference 
> between an 
> ApplicationModel and a CompositePart to use VisualWorks terminology. 
> Both are reusable - except that you have to jump through more 
> hurdles to 
> reuse an ApplicationModel than a CompositePart.
> 
> But yes, you end up creating a bunch of widgets and you hook 
> up to their 
> events which were fired to you from the client side. In response, you 
> tell the widgets and parts and things to do stuff and ... 
> their changes 
> go back to the client. The 'ApplicationModel' concept is 
> really just a 
> composite widget subclass, such that it can modify itself.
> 
> A common application model type widget was one that contained a 
> 'contents' slot that would be updated based on what the 
> current contents 
> wanted to do. For example, moving from workflow to workflow was done, 
> underneath the guys, like so:
> 
> call: aComponent
>  self topComponent push: aComponent
> 
> A number of things would happen here. For one, our application model 
> would keep a stack of the components so you could 'pop' again 
> afterwards 
> when the component did #answer(:). Another thing that would 
> happen is if 
> that aComponent you pushed ono could represent its current state as a 
> unique URL, it would also tell the web browser to update the 
> URL using 
> javascript too.. that allows bookmarkability and entry point 
> definition. 
> There's a lot more to that trick though.
> 
> The key point though is that a URL change is under the control of the 
> server... it never happens without explicit coding along the lines of:
> 
> window location: '.....'
> 
> This also means that in terms of continuations, which allow 
> the user to 
> hit the back button, you do not need them. The only URLs you 
> will ever 
> emit are ones that can be reproduced correctly from the URL 
> parameters 
> and name. Any action you take modifies the page in place, so no URL 
> change happens there either - which means there is no Back operation 
> when you're making manipulations. It's an interesting 
> alternate way to 
> solve the Back button problem that doesn't require 
> continuations. This 
> was the primary reason we made this technology - because VisualAge 
> Smalltalk didn't have continuations and we wanted the power 
> of Seaside 
> on VA :)
> 
> One thing I've always admired about Seaside is its ability to 
> serve more 
> than one conceptual model of how to be a webserver. I'd hate 
> for that to 
> disappear. When we implemented this stuff we tied ourselves 
> closely to 
> Mootools to reduce the cost of writing javascript and smalltalk code 
> that communicated to each other. In fact, if the Smalltalk 
> code sent a 
> message to the javascript code, it would json the arguments 
> and emit the 
> javascript call to the client immediately, get a response and turn it 
> back in to smalltalk objects. Vice versa, the Javascript code 
> could call 
> back to the server (obviously) using ajax and likewise also 
> get a response.
> 
> Another thing we did was embrace the Comet pattern - our 
> framework was 
> called CometWeb. In hindsight, this was overkill. The idea of 
> the Comet 
> pattern was that the server could make updates to the client 
> without the 
> client first needing to do some sort of action. There were only a 
> handful of places this was useful:
> a) Chat/IM
> b) Updating screen as results came back from a database query in the 
> background
> c) Clock
> 
> > I think splitting up the responsibilities of WAComponent 
> would not be too
> > bad for the clarity of the design. But a more elaborate 
> design of components
> > seems not to be too popular :-)
> >
> > Where did you see that quote from Michael?
> >   
> It's on the list somewhere.. it might have been on 
> seaside-dev instead 
> but I don't think it was. The reason why we didn't want the two trees 
> was because when you break it down, one of the trees is redundant. If 
> you need to know about the widget and have events hooked up 
> to it - you 
> can't throw it away. You also want its id. If you say, fine, that's a 
> WAComponent.. then you no longer need the brushes, because it 
> will have 
> to render itself out as javascript as a change regardless. The 
> unification is a natural refactoring when you go down this path.
> 
> The obvious problem here is that you're catouring specifically to the 
> pattern of treating the web browser as a smart client that you can 
> converse with in a sane way. This is *not* always true. For 
> example, if 
> you want to emit json or xml or rss or atom.. there are no 
> callbacks.. 
> there is no need to keep id's or state on the server, it's a one shot 
> path. In this kind of world, the brush idiom makes more sense.
> 
> In the end, we had two separate frameworks - one for emitting 
> tree like 
> things, such as json and xml.. and our CometWeb framework which would 
> use it to produce static pages, emails, rss feeds, json/xml 
> dumps, atom 
> search result feeds and the initial pages that a user gets when they 
> make their first request on an entry point. In short, the 
> emitter/brush 
> framework was 'low level' to the CometWeb framework.
> 
> I'm quite happy to talk about this more... I hadn't really 
> brought it up 
> before for a couple of reasons:
> 
> a) I'd not want to remake it, dividing the community with yet another 
> web framework is insane and requires redoing all the 
> fantastic leg work 
> that has already been done with Seaside to make a name for itself
> 
> b) Wizard owned the IP, but they have since died a tragic death and 
> while I could have talked about it and rewritten it, out of 
> respect that 
> they might have gone somewhere with the technology, I decided not to 
> talk about it.
> 
> c) I'm totally committed to Seaside, wherever its lead developers and 
> community want to take it. I really love this technology 
> which is one of 
> the reasons I work on it at Cincom.
> 
> So I guess my perspective is this - if this sounds like the sort of 
> direction that might be useful for Seaside 2.10 or 3.0, fair 
> enough. I'd 
> like to see that. If it's not, then fair enough too, I'm not too 
> worried. Seaside is well ahead of the game wrt to web 
> technology already 
> and will be for years and years to come.
> 
> Cheers,
> Michael
> > Andreas
> >
> >
> > Am 10.03.2008 18:48 Uhr schrieb "itsme213" unter 
> <itsme213 at hotmail.com>:
> >
> >   
> >> Seaside currently keeps a server-side component tree. Each 
> component will
> >> typically render a sub-tree of the browser-side DOM tree.
> >>
> >> What would be the disadvantage of maintaining a unified 
> server-side DOM
> >> tree, where some (but not all) nodes would correspond to 
> full-blown Seaside
> >> components? I think Michael Lucas-Smith had mentioned this
> >>
> >> "you tend to want only one tree to represent your UI state 
> on the server,
> >> not two - instead of having WAComponent and WABrush 
> separated, we combined
> >> the two so that each widget was an element which was also 
> represented on the
> >> client side as a DOM node."
> >>
> >> Thanks - Sophie
> >>
> >>
> >>
> >> _______________________________________________
> >> seaside mailing list
> >> seaside at lists.squeakfoundation.org
> >> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> >>     
> >
> >   
> 
> _______________________________________________
> seaside mailing list
> seaside at lists.squeakfoundation.org
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside



More information about the seaside mailing list