Re: [PrototypeRoot]

On Mon, Jun 22, 2009 at 4:49 PM, Ian Hickson<ian@hixie.ch> wrote:
> On Sun, 21 Jun 2009, Garrett Smith wrote:
>> On Sat, Jun 20, 2009 at 12:43 AM, Ian Hickson<ian@hixie.ch> wrote:
>> > On Sat, 20 Jun 2009, Garrett Smith wrote:
>> >>
>> >> I still want to know: Why would a program want to know the object's
>> >> [[Class]]?
>> >
>> > It shouldn't, but [[Class]]es are exposed by ECMAScript objects in
>> > their toString() method and thus if we want to ensure universally
>> > consistent behaviour we have to define this.
>>
>> No, that is all untrue.
>
> Which part is untrue?
>

1) The [[Class]] property is not exposed in the object's toString.
[[Class]] is exposed in Object.prototype.toString. This is very easy
to demonstrate.
2) The decision to define this is a choice. That choice as being (part
of) a conclusion to the argument: How to define universally consistent
behavior.

It is possible to define "universally consistent" as having toString
to be a callable object for host objects and allowing for enough
wiggle room for things to not break at every possible change (change =
browsers, versions, code contexts). It is not necessary to define any
sort of prototype chain (e.g. which toString shadows which other
toString).  That lacks good design sense.

> I said three things:
>
>  - A program shouldn't want to know an object's [[Class]]
>  - [[Class]] is exposed by ECMAScript in an object's toString() method
>  - If we want to ensure universal behaviour we have to define this
>
> You seem to agree with the second point, as you say:
>
>> The [[Class]] property is exposed in Object.prototype.toString.
>
> You presumably agree with the first point since you were asking for a
> reason and implying there wasn't one.
>

I haven't actually seen a good reason.

> Do you disagree that we need to define things to get universal behaviour?
>

No. Do you disagree that design ought to be flexible and extensible?

Is universal behavior necessary though? There are many things that
browsers will do.  Browser vendors can and do innovate proprietary
useful features. Sometimes its bad. Okay, often it is bad. As a whole,
if done right, implementations can innovate new ideas. It does not all
need to come from HTML 5.

>
>> Ensuring universally consistent behavior would require that *all
>> browsers* behave exactly the same.
>
> Right, that's the goal.
>

That is easy:
var objString = Object.prototype.toString.call( hostObj );
Assert.isTypeOf( objString, "string" );

It is more complicated than what we have today (nothing), but adds a
little stability to the way objects behave. It says that a string can
be obtained from an object. That is not guaranteed today.

A program that makes assertions on that string's *value* would be
locking itself in to what the API is today. This limits future APIs by
locking them in to what web pages use.  Authors should not be
discouraged from using toString(), but programs that make decisions
based on the value it returns would be considered unsafe.

>
>> MSIE does not behave that way today and versions of other browsers may
>> vary, too.
>
> Indeed, that's the problem we are trying to fix.
>
>

It is not a problem.

The proposed change cannot address all possible host objects or other
host interfaces. I can't address browsers that do not currently behave
that way. On those counts alone, it would be unadvisable for a program
to utilize the [[Class]] for anything other than an error message.

Probably by the time you are "done" with fixing it, there will be new
interfaces being completed and these interfaces will also need to be
woven in.

The change you are eliciting seems well-intentioned, but serves only
to encourage authors to use strategies that are not advisable.

>> To ensure safer, more reliable behavior, define the [[Class]] property
>> as being a string value. That way, it would be guaranteed that
>> Object.prototype.toString.call( any_object ); would result in string
>> value being produced, and an error would not occur.
>
> As far as I can tell, everyone agrees that [[Class]] should be a string.
>
>
>> The value of that string should be implementation-dependent.
>
> That would not lead to a well-defined universal behaviour.
>

It would most lead to a well-defined universal behavior. It would
define the [[Class]] as being a string value, and so a program could
reasonable expect that:-

Object.prototype.toString.call( anotherObject )

- would return a string value and would not throw errors. That is is
not a lot expect, but as a testing requirement, it might help prevent
bugs.

>
>> This makes the feature flexible, extensible, and provides the
>> aforementioned benefits of interfaces over classes (e.g. mixin style
>> behavior with implementation-specific host objects).
>
> It seems that the [[Class]] value has nothing to do with the flexibility,
> extensibility, and mixin style behaviour of objects.
>
>
>> Providing a suggestion to implementors as to what that value might be
>> would be harmless.
>
> And mostly useless, if they ignore it; if they don't, it might as well be
> a requirement.
>

Is this (yet another) feature intended to punish Microsoft?

>
>> Mandating the *value* of that [[Class]] property creates a brittle,
>> fragile API.
>
> It creates a well-defined, consistent and predictable API. This is
> desireable.
>

It creates a brittle API. This is not desirable. Code that relies on
that feature is as brittle as that feature itself.

Strings are not a substitute for capability checks. The [[Class]] in
particular has very little potential to return information about what
an object can do. It would be a very risky design decision to make
inferences solely on the [[Class]] value.

>
>> Authors will utilize the specification to write code to that value to
>> create code that is as brittle and fragile as the API it uses and works
>> in fewer implementations, including browsers that are in widespread use
>> today.
>
> I think it is woefully optimistic to expect any significant number of
> authors to read the specification.
>

It is woefully optimistic to expect every author who does read the
specification to disregard it. I've noticed that some knowledgeable
web developers have, but not out of ignorance.


>
>> >> Even if a program could know the [[Class]], what's to say it won't
>> >> change in the future?
>> >
>> > The specs we write.
>>
>> No, the specifications do change.
>
> The specifications we write are the ones that are to say that it won't
> change. If the specifications say it changes, then it changes. My point is
> that it is up to the specifications we write to make this not change.
>

That is the heart of the problem. "It won't change". You need to nail
down what can change. [[Class]] is one of those things that has and is
changing, as we've seen HTMLFormControls change.

>
>> The introduction of "HTMLFormControls" collection, for example, was a
>> new one. There is a possibility of a "StaticNodeList" or "HTMLLinks"
>> collection in the future. The interfaces implemented by an object vary
>> between implementations and evolve over time.
>
> So long as we converge on a stable and well-implemented platform, early
> changes are not a problem.
>

What is early?

Extensible design doesn't have a due date; it is never done. Things
change over time.

>
>> >> Given a particular object, can that object's [[Class]] property
>> >> change in the future? If it there is an object that exists, say, some
>> >> sort of HTMLCollection, and it becomes desirable to make more
>> >> specific behavior, say "HTMLFormControlsCollection", what would the
>> >> code that expects the object's class to be HTMLCollection need to do
>> >> to continue working in multiple versions of multiple browsers?
>> >
>> > We would have to test to see if any pages rely on it; if they do, we'd
>> > have to make sure we don't change the [[Class]] somehow.
>>
>> That sounds like a brittle feature.
>
> It is no more or less brittle than anything else in the Web platform as
> far as I can tell. Any API could change; it is our responsibility to make
> sure that we don't change APIs that pages rely on.
>
>

It is not really necessary to find something on the web platform that
is less brittle. It would be akin to any appeal to popularity/appeal
to common practice -- hey, I see brittle design everywhere and things
are working, so it must be OK. I could probably use the same thinking
to justify using pesticides on food or other things that might seem
insignificantly bad.

Interface-based design is one of the things that is not brittle.
Interface-based design helps facilitate flexible design. New
properties can be added to the interface. New interfaces can be
created.

The proliferation of things that are wrong, even if commonplace, does
not in any way justify making more things that are wrong.

Trying to specify [[Class]] for each host object makes the web more
brittle. It is bad for the web because it encourages authors to rely
on that feature.

>> An object's [[Class]] feature should ideally provide specific, detailed
>> information, and should be used *only* in debugging. Never rely on it.
>
> It would be wonderful if that were the case.
>

Then why encourage it?

>
>> >> Given all these reasons, it would still seem like a bad idea to
>> >> program to an object's [[Class]]. Instead, the interface should be
>> >> programmed tot using feature detection.
>> >
>> > Yup.
>>
>> OK. Strings are not a substitute for capability checks. The [[Class]] in
>> particular has very little potential to return information about what an
>> object can do. It would be a very risky design decision to make
>> inferences solely on the [[Class]] value.
>
> Yup.
>

There you go.

>
>> We seem to be eye to eye on that much but I think the API design has
>> gone too far.
>
> What API design?
>

The design of specifying [[Class]]. The return value of arbitrary host
objects' toString is great for debugging, but should never be relied
upon.

>
>> Defining the value of the [[Class]] encourages that value to be used in
>> code.
>
> In practice, people are encouraged to use these features regardless of
> whether the specifications exist or not.

Nobody who knows what he is doing should be encouraging checking the
[[Class]] to make runtime decisions.

Some web developers look to HTML 5 as the future of web development.
For them, encouragement might seem to be coming from you to use
[[Class]]; e.g. "Oh, it says here in the spec that I can do ..." and
then go on to make a mistake. The contractor might then find his
program to appear to satisfy requirments in a few browsers and
conclude that the job was done.

Type checking is both a symptom of complicated design strategies and a
cause of complications.

For example, people use
> document.all even though it hasn't previously been specified, and they
> used it when only one browser supported it. Meanwhile there are plenty of
> specs that exist and are implemented that describe features that are used
> only in small amounts (relatively speaking). So I think it is clear that
> your statement here doesn't hold.
>
>
>> That is bad! Programmers who rely on that value will not rightly blame
>> themselves for their design mistakes. Instead, they will look
>> externally, read the standard, and blame the implementations that don't
>> do what their perfectly standards-compliant program expects
>
> If we define a value and everyone implements it, then they will not blame
> anyone, for their code will work. I would rather do that than try to find
> a way to make them blame someone else.
>

[[Class]], as you would like it to be, is not implemented that way in
major browsers today. Given feature X of interface I, There will
always be more browsers that implement X on I than browsers that
implement X on I AND have the [[Class]] matching your proposal. A
better strategy to check for support of X would be a feature or
capability test.

The idea of redesigning an API that is based on interfaces,
retrofitting the object to have a [[Class]] property adds some value
for debugging, but adds a lot of complexity. The downside is that it
the existence of the spec, and the wider prevalence of its
implementation encourages authors to do that.

When you say "their code will work", what would it be doing, other
than printing out debug strings?

It would be interesting to see you post your API design ideas on comp.object.

Regards,

Garrett

> --
> Ian Hickson               U+1047E                )\._.,--....,'``.    fL
> http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
> Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
>

Received on Friday, 7 August 2009 00:57:11 UTC