Re: Component Models and Encapsulation (was Re: Component Model: Landing Experimental Shadow DOM API in WebKit)

On Thu, Jun 30, 2011 at 1:32 PM, Maciej Stachowiak <mjs@apple.com> wrote:
>
> On Jun 30, 2011, at 1:03 PM, Dimitri Glazkov wrote:
>
>> Maciej, as promised on #whatwg, here's a more thorough review of your
>> proposal. I am in agreement in the first parts of your email, so I am
>> going to skip those.
>>
>>> =3D=3D Are there other limitations created by the lack of encapsulation=
? =3D=3D
>>>
>>> My understanding is yes, there are some serious limitations:
>>>
>>> (1) It won't be possible (according to Dmitri) to attach a binding to a=
n object that has a native shadow DOM in the implementation (e.g. form cont=
rols). That's because there can only be one shadow root, and form controls =
have already used it internally and made it private. This seems like a huge=
 limitation. The ability to attach bindings/components to form elements is =
potentially a huge win - authors can use the correct semantic element inste=
ad of div soup, but still have the total control over look and feel from a =
custom script-based implementation.
>>>
>>> (2) Attaching more than one binding with this approach is a huge hazard=
. You'll either inadvertently blow away the previous, or won't be able to a=
ttach more than one, or if your coding is sloppy, may end up mangling both =
of them.
>>>
>>> I think these two limitations are intrinsic to the approach, not incide=
ntal.
>>
>> I would like to frame this problem as "multiple-vs-single shadow tree
>> per element".
>>
>> Encapsulation is achievable with single shadow tree per element by
>> removing access via webkitShadow. You can discover whether a tree
>> exists (by the fact that an exception is thrown when you attempt to
>> set webkitShadow), but that's hardly breaking encapsulation.
>>
>> The issues you've described above are indeed real -- if you view
>> adding new behavior to elements a process of "binding", that is
>> something added to existing elements, possibly more than once. If we
>> decide that this the correct way to view attaching behavior, we
>> definitely need to fix this.
>>
>> I attempted to articulate a different view here
>> http://lists.w3.org/Archives/Public/public-webapps/2011JanMar/0941.html.
>> Here, adding new behavior to elements means creating a sub-class of an
>> element. This should be a very familiar programming concept, probably
>> more understood than the decorator or mixin-like "binding" approach.
>
> How would your "subclass" idea resolve the two problems above?

In the case of extending elements with native shadow DOM, you have to
use composition or have something like <inherited>, where you nest
native shadow tree in your own.

In the case case of attaching multiple bindings -- you just can't.
That's the difference between inheritance and mixins :)

>
>>
>> For the key use case of UI widgets, sub-classing is very natural. I
>> take a div, and sub-class it into a hovercard
>> (http://blog.twitter.com/2010/02/flying-around-with-hovercards.html).
>> I rarely bind a hovercard behavior to some random element -- not just
>> because I typically don't need to, but also because I expect a certain
>> behavior from the base element from which to build on. Binding a
>> hovercard to an element that doesn't display its children (like img or
>> input) is useless, since I want to append child nodes to display that
>> user info.
>>
>> I could then make superhovercard by extending the hovercard. The
>> single shadow DOM tree works perfectly in this case, because you
>> either:
>> 1) inherit the tree of the subclass and add behavior;
>> 2) override it.
>>
>> In cases where you truly need a decorator, use composition. Once we
>> have the basics going, we may contemplate concepts like <inherited>
>> (http://dev.w3.org/2006/xbl2/#the-inherited-element) to make
>> sub-classing more convenient.
>>
>> Sub-classing as a programming model is well-understood, and easy to gras=
p.
>>
>> On the other hand, the decorators are less known and certainly carry
>> hidden pains. How do you resolve API conflicts (two bindings have two
>> properties/functions by the same name)? As a developer, how do you
>> ensure a stable order of bindings (bindings competing for the z-index
>> and depending on the order of they are initialized, for example)?
>
> I think decorators have valid use cases. For example, let's say I want to=
 make a component that extracts microformat or microdata marked up content =
from an element and present hover UI to allow handy access to it. For examp=
le, it could extract addresses and offer map links. I would want this to wo=
rk on any element, even if the element already has an active behavior imple=
mented by a component. I should not have to "subclass" every type of elemen=
t I may want to apply this to. It's especially problematic if you have to "=
subclass" even different kinds of built in elements. Do I need separate sub=
classes for div, span, address, section p, and whatever other kind of eleme=
nt I imagine this applying to? That doesn't seem so great.
>
> You are correct that figuring out how multiple bindings work is tricky. B=
ut even if we choose not to do it, making components truly encapsulated doe=
s not make it any harder to have a one-binding-only model with no inheritan=
ce.
>
>
>>> Notice that this scheme is not significantly more complex to use, spec =
or implement than the shadow/shadowHost proposal. And it provides a number =
of advantages:
>>>
>>> A) True encapsulation is possible, indeed it is the easy default path. =
The component provider has to go out of its way to deliberately break encap=
sulation, though of course it can if it wants to.
>>
>> Yup.
>>
>>> B) Binding is atomic - the shadow root is not built up incrementally so=
 you can't have a half-built binding.
>>
>> I am not sure what's the danger here. Are you trying to protect the
>> author from displaying the shadow subtree while it's still being
>> built?
>
> My experience with API design is: it's better to design APIs so that it's=
 not possible to use them wrong. It's better not to

I think you fell off the bike here, but I think I understand where you
were going :)

>
>>
>>> C) Has a natural extension to allowing more than one binding on an elem=
ent, having a stacking behavior like XBL.
>>
>> Given discussion above, I don't see this as an advantage.
>>
>>> D) Can readily support custom components bound to form controls, with e=
ither semantics of stacking on top of the native binding or replacing it.
>>
>> This is where override and compose approaches work well for
>> inheritance-based approach.
>>
>>> E) Avoids use of the jargon-ish, mysterious and potentially confusing t=
erm "shadow" in favor of "binding" and "component" which are much more clea=
r IMO.
>>
>> I agree that "shadow" is jargon-ish. I would love to have a better
>> name for it that's not scary. I like "component" terminology!
>>
>>> F) The code to build up the DOM for the binding with raw DOM calls only=
 has to run once. After that it just gets cloned, which is likely faster th=
an creating a whole fresh one with raw DOM calls.
>>
>> Right. This is good stuff.
>>
>>> G) Naturally extensible to other ways of creating components, perhaps o=
n a declarative template a la XBL2.
>>
>> Ditto.
>>
>> Overall, aside from multiple trees and the use of bindings rather than
>> object inheritance, I like this API. Without those two, it's exactly a
>> superset of the my proposal, minus webkitShadow. I am a huge fan of
>> being able to produce a Component object that acts like a DOM object.
>>
>> To make further progress, I would like to concentrate on resolving
>> these two issues:
>>
>> 1) should we use object inheritance (one shadow subtree) or mixins
>> (multiple shadow subtrees)?
>
> I think it's possible to partially table this issue. If mixing are requir=
ed, then raw access to the shadow tree is not viable. But using inheritance=
 / single binding is possible with either proposal.

I think that changes a lot of nomenclature though, right? You don't
have "bindings" with inheritance. It's just you or your sub-class.
Also, element.bindComponent doesn't make much sense if you can only
inherit the relationship.

>
>> 2) do we need webkitShadow or similar accessor to shadow subtree(s)?
>
> This question is a helpful one. I haven't seen any reason articulated for=
 why such an accessor is required. The fact that it's not present in other =
similar technologies seems like proof that it is not required.

Yes, I will work on use cases. Though this concept is certainly
present in other technologies. Just take a look at Silverlight and its
LogicalTreeHelper
(http://msdn.microsoft.com/en-us/library/ms753391.aspx).

>
>
>>
>> I think these are all resolved by supplying use cases and rationale. Rig=
ht?
>
> If so, I think we need a real list of use cases to be addressed. The one =
provided seems to bear no relationship to your original proposal (though I =
believe my rough sketch satisfies more of them as-is and is more obviously =
extensible to satisfying more of them).

Did you mean the hovercard? I bet I can write a pretty simple bit of
code that would usefully consume the API from my proposal.

>
> Regards,
> Maciej
>
>

Received on Thursday, 30 June 2011 21:08:16 UTC