Re: Model-driven Views

Hi Olli,

Thanks very much for taking time to read & digest our design.

I'm going to use this thread to start a FAQ on our project site. Some
of these questions have answers that deserve more detail than is wise
to put in an email =-).

On Wed, Apr 27, 2011 at 8:33 AM, Olli Pettay <Olli.Pettay@helsinki.fi> wrote:
> HI Rafael,
>
>
> few random comments, or mainly just random questions :)
>
> On 04/23/2011 03:35 AM, Rafael Weinstein wrote:
>>
>> Myself and a few other chromium folks have been working on a design
>> for a formalized separation between View and Model in the browser,
>> with needs of web applications being the primary motivator.
>>
>> Our ideas are implemented as an experimental Javascript library:
>> https://code.google.com/p/mdv/ and the basic design is described here:
>> http://mdv.googlecode.com/svn/trunk/docs/design_intro.html. It's not
>> complete and there are things we're not happy with, but it's
>> self-consistent enough that you can start to imagine what a full
>> design might look like.
>>
>> We hope to get others interested in collecting requirements/use cases
>> and fleshing out a good solution.
>
> Would be good to know what are the use cases you had in mind.

I'm never sure if I'm using the term "use case" correctly =-).

Our primary motivator is the needs of web applications, but if we can
create a good solution for more static cases in the process it'll be
that much more a win.

By "collecting use cases" I was thinking more about specific patterns
that emerge in composing views for applications. One very common
example is master/detail.

>
>
>>
>> We're starting the discussion here because a few people in this group
>> from whom we got early feedback felt that it would be most appropriate
>> place and, further, that this work bears some relation to XBL.
>
> Not sure why this had some relation with XBL. Unless you are
> planning to put the template based DOM nodes to anonymous DOM.

I'm creating a FAQ question for this. Will reply again when its ready.

>
>
>>
>> What do you think?
>>
>
> - Is this something you'd like to be implemented in the browsers,

Yes.

>  and if yes, why? What would be the reasons to not just use script
>  libraries (like your prototype).

FAQ item also coming for this.

>  If the have-to-change-HTML-parser like parts could be removed,
>  this all feels like something for JS + Proxy objects, just like what
>  you've done in the prototype.
>
> - Is there a reason why you have chosen to create yet another
>  datastorage like object (although your Model is just a kind of
>  proxy)? Couldn't you reuse for example IndexedDB?
>  XUL Templates can be bound to sqlite, XML and RDF.

The goal isn't to create a storage mechanism, its to free the
application from directly manipulating the DOM and allow it to operate
on its data. To *say* what it wants to happen to the UI rather than to
do it. If JS objects were directly observable, that would be ideal --
but it seems unlikely that runtime implementors will take the perf
hit.

Allowing bindings to IndexedDB is a cool idea. We should explore that
more. In general, there are a number of things we should consider for
sourcing data.

>
> - Model looks in many ways like JS-fied and simplified XForms
>  model/instance. Have you investigated if there are important use cases
>  which XForms can handle (because it has more powerful binding
>  mechanism) but MDV can't? Are there plans to extend

I've read the XForms spec, but I don't feel qualified to comment on
use cases that it can better handle. It sounds like you might...? ;-)

>  the "Path language", or ideas how it could be extended? (XForms has
>  extensions to XPath)
>  In general I'm not too happy to see yet another
>  selector/path language. Would be great if some existing one could
>  be reused. Sure, some parts of the proposed language look quite a bit
>  like JSON, but there are other parts which are something very
>  different.

The goal wasn't to create a path/selector language. The basic idea is
simple JSON dot-notation. The funny syntax you see (../, ./, /) is our
solution to three patterns that come up frequently in templating:

-You're in an iteration, but you need a value which is "just above
your head" (e.g.
http://mdv.googlecode.com/svn/trunk/capabilities/path_reference_ancestor.html)

-You're down deep in a object graph rendering you're output, but you
need a global value. An example might be composing a URL for an
application which is versioned. You need to grab a "global" static
path and combine it with some local state (e.g. userId). (e.g.
https://code.google.com/p/mdv/source/browse/trunk/capabilities/path_reference_root.html)

-Needing to refer to *this* value. This happens all the time. (e.g.
http://mdv.googlecode.com/svn/trunk/capabilities/path_reference_this.html)

We considered several other options and couldn't come up with a better
idea. Suggestions very welcome here (and everywhere, in fact).

In general, we're not at all wedded to naming or syntax. Its the
semantics were after.

>
> - It is not quite clear to me how the Model-as-a-proxy works.
>  What if the raw object has getters or setters, how does the Model
>  work in that case? (Calling a getter or setter may do any kinds of
>  changes to the raw object, and/or to the model)

This is an aspect of the design that we're not settled with.

Initially we proxy-wrapped all function arguments and the |this|
object for function calls, but that creates problems if the
implementation of a domain object asks questions about object identity
(such as array.indexOf).

After some discussion we decided that a clean place to draw the line
was on the "outside" of objects. I.e. its up to the object to
externalize observability for mutations they make on themselves.
There's a clean way to do it, it just needs to be explicit.

This is one thing that dirty-checking has going for it relative to the
proxy pattern.

>
> - How does Model.get handle objects which have circular references?
>  How does the Path language work in that case?

I'm aware that we're going to need to face cycles WRT:
-Mutation notifications
-Bindings

We talked about it some and figured that there were only a few options
and we'd delay picking one until the more central aspects of the
design were widely agreed upon.

I'm not aware that Model.get or the Path language need to deal with
cycles. I'm probably just being dense. Can you give me an example?

Also, Model maintains a weakmap of proxiedObject->modelObject. Paths
are finite length (just strings). If a cycle exists in a path as
traversed from a reference object, the Model will happily follow it.
Multiple model objects will *not* be created for the same "raw"
object.

>
> - How does the observing mechanism handle the case when there are
>  several observers for the same property and the first one which gets
>  notified updates the relevant property (and then sets some flag to
>  itself to not handle following updates to prevents notification
>  loops).  What values are notified to other callbacks?

Our general idea with notification callbacks is that
-Only one callback should be on the stack at a time (generally, async semantics)
-All pending callbacks for a mutation are cancelled if the relevant
property is further mutated (they'll get back in line again for the
new mutation).
-Callbacks will only fire if the value has actually changed *from the
observers POV* *at the time the callback is to be invoked*.

This means that observers are not notified of all mutations. A
property could travel through multiple states before an observer hears
about it. If the value is returned to the observer's
"lastObservedValue", the observer isn't called back.

This behavior is described (somewhat badly) for Model.observe(), but
we recently decided to make Model.observeObject() callbacks behave the
same way (and its not implemented yet in the prototype or updated in
the doc).

>
> - Nit, why are you using document.querySelector('#example') in the
>  examples. The good old document.getElementById("example") should be
>  faster ;)

Fixed. =-).

>
> - "Child nodes are not considered to be a part of the DOM. During
>  parsing, they are lifted out..." Huh, you really want to alter HTML
>  parsing?
>
> - "If a template element is created via script, any children are
>   removed and attached to the instancePrototype when the template
>   element is attached to a document." What if the template is already
>   in DOM when the new child elements are added.
>   It sounds *very* strange to add new special cases to DOM Core
>   methods.
>
> - What kind of property is instancePrototype? NodeList?
>
> - What does this mean
>  "Any instances of a template must exist as a sequence of nextSiblings
>  following the template element itself, with each instance being
>  terminated by a HTMLTemplateInstanceElement."
>  I couldn't see any <templateinstance> elements in the examples.
>
> - At which point and how are the instances created? How are

The general idea is that all work that needs to be done in response to
data mutations will be done "after the current script event exits".

>  mutation events handled? (Unfortunately we do need to care about
>  mutation events still some time before there is a replacement.)

Not sure. Do you have ideas here? The closest precedent is innerHTML
which seems to fire sync mutations for each node created =-(.

I think this came up when we talked to Hixie, and he said that we
should just expect that mutation events will become async. I may be
imagining this, though.


>
>
> -Olli
>
>
>

Received on Thursday, 28 April 2011 01:47:03 UTC