MooTools: An Objective Look

T

Thomas 'PointedEars' Lahn

dhtml said:
What design patterns in Mootools were criticized?

I am not here to reiterate this discussion for you.
Take the pageX/Y properties. Problems in Firefox were that it did not
include scroll. An experimental monkey patch:-

MouseEvent.prototype.__defineGetter__('pageX', function() {
return this.clientX + window.pageXOffset;
});
MouseEvent.prototype.__defineGetter__('pageY', function() {
return this.clientY + window.pageYOffset;
});

If the monkey patch worked, it could be later incorporated into a real
patch.

Nobody in their right mind would write or test *Gecko* patches like so.
You will have to come up with something more convincing.
Many DOM properties have a |readonly| flag. This flag can map to
ECMAScript {ReadOnly} attribute. However, there is nothing that maps to
ECMAScript {DontEnum} attribute. This is not defined for any dom
objects,

That might sound highly sophisticated to some, but is utter nonsense altogether.

The ECMAScript `ReadOnly' attribute of properties applies for native objects
only because only those objects MUST implement the internal [[Put]] method
as specified where [[CanPut]] is called and the ReadOnly property becomes
relevant in the first place. In fact, it can be readily observed that
assigning to a property which is "readonly" per the IDL or the
implementation, reverts back in some implementations to its previous value
instead of just not being modified, and that the assignment can result in a
runtime error, which is also not specified at all in ECMAScript. (We have
discussed this ad nauseam here.)

The ECMAScript `DontEnum' attribute of properties does not apply to
properties of host objects per Specification, however it can be readily
observed that some properties of host objects do not occur in a for..in
iteration. (We have discussed this ad nauseam here as well.)
and so it is entirely dependent on the implementation.

We have a property of a host object here that is deliberately exposed by the
implementor, and it refers to a native object. It provides an efficient
means to add new default properties and new methods to a certain class of
related host objects. Not to use it and use another, less efficient
approach instead, is foolish.
The Host object might have a property with the same name hidden away
somewhere else on the object or its prototype chain. It might have a
getter defined on that object itself.

It would not, else the object the property refers to would either be made
non-augmentable (which is possible with host objects only) or the property
would not be publicly exposed by the implementation at all.
If('
Pardon?


The design issue...
Pardon?

I don't have costly iteration in my scripts and I never augment
Element.prototype. It is a solution to a problem that does not exist.

To a problem that *you* do not have. At least one OP had this problem
already, and I can imagine situations where this feature comes in handy.
"Big ball of mud" is packaging of everything together. ["snipped ball of
mud" "explanation"]

Sounds like a big ball of mud altogether.
I see no good reason why not to make use of such a useful DOM
feature if it is available. (In fact, I think it has the capacity to
become a DOM standard.)

It is becoming a DOM standard (WEB IDL). [...]
URL?
An element object reference, and the greater efficiency in this case
would seem to be self-evident.

As always, the bargain is runtime efficiency vs. memory efficiency.

Comparing:-

// 1.
Element.prototype.getX = function() { };
// 2.
function getX(el) { }

Where is the memory efficiency in #1?

If getX() is empty, none.
Function getX (2) would not have to be resolved off the host object's
prototype chain.

True, but if getX() was not empty, you would need to pass the element as an
argument, check the argument type, determine which class of element object
was being referred to with the passed value aso.
Element.prototype.getX would have to be resolved up the prototype chain.

We have discussed the efficiency of the prototype chain already.
The prototype chain in this particular case could not be shorter:

Element instance --> Element.prototype --> Node.prototype
--> Object.prototype --> null

The expected loss in runtime efficiency by using it is thus negligible.
That said, this is a border case. One would seldom want to augment
Element.prototype.
Given a host object Element, Element.prototype does not have to be a
native object.

True, but it is a native object in the relevant implementations.
Consider a case of a hypothetical user-defined property |x| on
Element.prototype, Element.prototype.x. When resolving an identifier |x|
on an img object, img.x, the |x| property would be not be resolved on
Element.prototype. Instead, it would more likely be found in
HTMLImageElement.prototype, or on the object itself. The |x| property
might be implemented as a getter or it might be implemented as a property.

Node
|
Element {x:Function(user-def} EventTarget
| |
HTMLElement {style::ElementCSSInlineStyle}
|
HTMLImageElement { getter x::uint }
|
img

[...]

You are constantly ignoring the fact that e.g. HTMLImageElement.prototype
could be augmented as well, and the benefit that could bring. You must do
so because otherwise you would hurt the pointless argument which says that
using host object's prototypes is a bad idea per se.


PointedEars
 
D

dhtml

Thomas said:
I am not here to reiterate this discussion for you.

Discussion of design patterns did not occur, at least not on this
thread. (or you have a different interpretation of what was discussed,
or a different definition of 'design pattern').

It isn't clear what you mean by 'criticism of design patterns'. So I
asked, and, you wanted to play a silly game.

I'm done with having a discussion with you. It is neither entertaining
nor educational.

Garrett
 
A

Andrew Poulos

dhtml said:
Discussion of design patterns did not occur, at least not on this
thread. (or you have a different interpretation of what was discussed,
or a different definition of 'design pattern').

It isn't clear what you mean by 'criticism of design patterns'. So I
asked, and, you wanted to play a silly game.

I'm done with having a discussion with you. It is neither entertaining
nor educational.

PointedEars replied with many other, in my opinion, valid points but you
have snipped them (chosen to ignore them). Why is that? I was hoping to
learn about more about MooTools.

Andrew Poulos
 
T

Thomas 'PointedEars' Lahn

dhtml said:
Discussion of design patterns did not occur, at least not on this
thread. (or you have a different interpretation of what was discussed,
or a different definition of 'design pattern').

It isn't clear what you mean by 'criticism of design patterns'. So I
asked, and, you wanted to play a silly game.

Replacing built-in methods and augmentation of prototype objects of host
objects were the design patterns I have been commenting on in this thread,
the latter quite at length, as you could have noticed.
I'm done with having a discussion with you. It is neither entertaining
nor educational.

If one chooses to be completely ignorant about the points raised in favor of
using one of the aforementioned design patterns, that is the impression one
must get.


PointedEars
 
D

dhtml

Thomas said:
Replacing built-in methods and augmentation of prototype objects of host
objects were the design patterns I have been commenting on in this thread,
the latter quite at length, as you could have noticed.

I did notice that.

It sounds like you are naming of two new patterns:
'replacing built-in methods'
'augmentation of prototype objects of host objects'

Are those your design patterns?

Those are more like javascript programming techniques. There may be
not-yet-defined design patterns (possibly structural), but they have not
yet been identified.

A design pattern is a reusable solution to a problem in a context.

Garrett
 
T

Thomas 'PointedEars' Lahn

dhtml said:
I did notice that.

It sounds like you are naming of two new patterns:
'replacing built-in methods'
'augmentation of prototype objects of host objects'

I beg your pardon -- "*it* *sounds* *like*"?
Are those your design patterns?

Are you able to read?
Those are more like javascript programming techniques. There may be
not-yet-defined design patterns (possibly structural), but they have not
yet been identified.

A design pattern is a reusable solution to a problem in a context.

And these "programming techniques" are not such solutions? Think again.
The meaning of the term "design pattern" is not limited to those named by
the Group of Four.


PointedEars
 
T

Thomas 'PointedEars' Lahn

dhtml said:
I did notice that.

It sounds like you are naming of two new patterns: 'replacing built-in
methods' 'augmentation of prototype objects of host objects'

I beg your pardon -- "*it* *sounds* *like*"?
Are those your design patterns?

Are you able to read?
Those are more like javascript programming techniques. There may be
not-yet-defined design patterns (possibly structural), but they have not
yet been identified.

A design pattern is a reusable solution to a problem in a context.

And these "programming techniques" are not such solutions? Think again.
JFYI, the meaning of the term "design pattern" is not limited to those named
by the Gang of Four.


PointedEars
 
D

dhtml

Thomas said:
I beg your pardon -- "*it* *sounds* *like*"?

You're not making yourself clear enough. Are these the names of your
patterns:-

'replacing built-in methods'
'augmentation of prototype objects of host objects'

- or it something else?

I've never heard talk of those as patterns.

To me, I see this coding construct as an AOP cross cut alternative to a
Decorator (structural).
Are you able to read?


And these "programming techniques" are not such solutions? Think again.
JFYI, the meaning of the term "design pattern" is not limited to those named

A common pattern has a name. This allows the pattern to communicated
with other developers.

What is the intent of the pattern (what problem is it supposed to solve?)

What is the motivation (scenario of a problem that can be solved by the
pattern)?

What is the applicability (context where this pattern can be used)?

For example, a partially filled-in template:-

Name:
Modify Base [Prototype] (Structural)

Intent:
The host object lacks a certain behavior that is needed.

Motivation/Scenario:
[...]

Structure:
SomeObjectPrototype -> newProperty
|
[...]
|
SomeObjectInstance

Applicability:
Use when desired to have that behavior on all objects of that type.

Collaboration:

Implementation:

Consequences:

Related Patterns:
Decorator

The "motivation/scenario" is crucial.

An OO Design Pattern should follow basic OO principles like programming
to an interface, not an implementation; encapsulating the parts that
vary; and favoring object composition over class inheritance.

Modifying the Foreign [Host] Object's Prototype is the exact opposite.
It relies on inheritance, does not use composition. It favors modifying
the implementation (not programming to an interface). The foreign object
doesn't do what is desired, so try to force it to. It does this at the
risk of the Host object allowing the modification and not shadowing the
property, in all environments, for all versions, and versions in the
future.

A pattern's usage is dictated by goals and constraints. So if this is a
pattern, we could look at the goals, usage, and constraints in Mootools.
From the homepage: "Mootools allows you to write powerful, flexible,
and cross-browser code". The pattern (if it is to called a pattern)
doesn't work in IE. It wouldn't seem to be a good choice for
"cross-browser code". So if the goal is to allow developers to write
"cross-browser code", and this is a pattern, then it seems
misappropriated for the goal.

The intent is nearly identical to a Decorator. This code technique (your
pattern) might be considered an AOP crosscut, but then the concern would
have to be identified. It would be hard to identify modular concerns
based on anything in the code or code comments. Let's take a look...

Mootools has a document.head. The document.head points to the head
element of the html document that the script is loaded in. Like other
elements, Mootools gives document.head the following methods (I kid you
not, these are the actual names): destroy, dispose, eliminate, erase,
grabBottom... -- sounds very heavy metal -- up until the "grabBottom"
method. Then there is toQueryString. Funny names, but what concern are
they related to? It doesn't seem very modular. It looks like a case of
"frameworkitis"[1].

Garrett

[1]http://www.artima.com/lejava/articles/reuse3.html
 
T

Thomas 'PointedEars' Lahn

dhtml said:
Thomas said:
I beg your pardon -- "*it* *sounds* *like*"?

You're not making yourself clear enough. Are these the names of your
patterns:- [...]

I have already said what I regarded as the design patterns I referred to.
That you are obviously unable to read is your problem alone.
'replacing built-in methods'
'augmentation of prototype objects of host objects'

- or it something else?
No.

I've never heard talk of those as patterns.

Your problem.

Obviously not. Question retracted.
A common pattern has a name. This allows the pattern to communicated
with other developers.

I gave it a name.
What is the intent of the pattern (what problem is it supposed to solve?)

What is the motivation (scenario of a problem that can be solved by the
pattern)?

What is the applicability (context where this pattern can be used)?

For example, a partially filled-in template:-
[...]

See, you *almost* got it. In time, you might actually get it.


PointedEars
 
D

dhtml

Thomas said:
dhtml said:
Thomas said:
dhtml wrote:
Thomas 'PointedEars' Lahn wrote:
dhtml wrote:
Thomas 'PointedEars' Lahn wrote:
dhtml wrote:
Thomas 'PointedEars' Lahn wrote:
dhtml wrote:
Thomas 'PointedEars' Lahn wrote:
David Mark wrote:
dhtml wrote:
David Mark wrote:
MooTools: An Objective Look
I was not arguing about the (doubtful) code quality of MooTools
here but about the -- I think -- inappropriate *general*
criticism of some of the design patterns it employs.
What design patterns in Mootools were criticized?
I am not here to reiterate this discussion for you.
Discussion of design patterns did not occur, at least not on this
thread. (or you have a different interpretation of what was
discussed, or a different definition of 'design pattern').

It isn't clear what you mean by 'criticism of design patterns'. So I
asked, and, you wanted to play a silly game.
Replacing built-in methods and augmentation of prototype objects of ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
host objects were the design patterns I have been commenting on in this ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
thread, the latter quite at length, as you could have noticed.
I did notice that.

It sounds like you are naming of two new patterns: 'replacing built-in
methods' 'augmentation of prototype objects of host objects'
I beg your pardon -- "*it* *sounds* *like*"?
You're not making yourself clear enough. Are these the names of your
patterns:- [...]

I have already said what I regarded as the design patterns I referred to.
That you are obviously unable to read is your problem alone.
'replacing built-in methods'
'augmentation of prototype objects of host objects'

- or it something else?
No.

I've never heard talk of those as patterns.

Your problem.

Obviously not. Question retracted.
A common pattern has a name. This allows the pattern to communicated
with other developers.

I gave it a name.
What is the intent of the pattern (what problem is it supposed to solve?)

What is the motivation (scenario of a problem that can be solved by the
pattern)?

What is the applicability (context where this pattern can be used)?

For example, a partially filled-in template:-
[...]

See, you *almost* got it. In time, you might actually get it.


PointedEars

I am helping to argue the case that what you were describing might be
patterns. I gave a pattern template to fill in, described how to fill it
in, and filled in a few parts myself.

You have confirmed now that the two descriptions of javascript
techniques are the respective names for your patterns.

The template I provided remains to be filled out.

I suggest you start working on the template.

Garrett
 
D

dhtml

Andrew said:
PointedEars replied with many other, in my opinion, valid points but you
have snipped them (chosen to ignore them). Why is that? I was hoping to
learn about more about MooTools.

Because when I ask:
| What design patterns in Mootools were criticized?

I get the reply:
| I am not here to reiterate this discussion for you.

PointedEars was the first to mention the term 'design patterns' in this
thread. I asked him to be specific; his reply does not answer, yet seems
to show what appears to be a superior attitude.

Another Ears quote:
| That might sound highly sophisticated to some, but
| is utter nonsense altogether.

Ears will say that something 'doesn't make sense' or is 'utter nonsense'
when he does not understand it himself. You'll never hear him say, for
example, "I'm not sure what you mean by that."

And if you back up to see what he responded to, I wrote:-

| Many DOM properties have a |readonly| flag. This flag can map to
| ECMAScript {ReadOnly} attribute. However, there is nothing that maps
| to ECMAScript {DontEnum} attribute. This is not defined for any dom
| objects.

We can see in a DOM spec, take DOM 2, for example, that the Node
interface, among others, has a |readonly| "nodeName" property[1].

http://www.w3.org/TR/DOM-Level-2-Core/idl-definitions.html#idl-dom.idl

In a nutshell:
1) an OMG IDL "readonly" property maps to a "get" style operation.
2) a get-style operation might vary between implementations
3) This would fail differently depending on the implementation.

Example:
A user-defined property is added to HTMLElement.prototype. That
user-defined property has the same name as a |readonly| property on the
Element interface. If and how it would fail is not defined. If the
implementation mapped DOM |readonly| to a JavaScriptTM getter, then an
error would result. However, an implementation that mapped DOM
|readonly| to ECMA {ReadOnly}, the result would be silent failure.

I'll try discussing again.

Garrett
 
D

dhtml

Thomas said:
If getX() is empty, none.


True, but if getX() was not empty, you would need to pass the element as an
argument, check the argument type, determine which class of element object
was being referred to with the passed value aso.

I'm not sure what you mean by 'class'.

The getX method would only have to concern itself with getting some sort
of x value of the object, as in:-

function getX(ob) {
if('x' in ob) {
return ob.x;
} else if('xx' in ob) {
return ob.xx;
}
}

It might be a consideration for the example to check |typeof ob ==
"undefined"|, and handle accordingly.

However, that is a contrived example.

Lets see _real_ example of how Mootools modifies Host object prototypes
(your "design pattern"). Here is Mootools' Event (Mootools calls Event a
"native", and replaces window.Event).

From Event.initialize:-

if (event.$extended) return event;
this.$extended = true;

That way, when handling of events is desired, the user (of this API),
can use:-

new Event(ev)

- and expect to get back an object with Mootools Event modifications.

This uses the same approach of PrototypeJS. If the element is not
"$extended", it will be augmented in "$extend()":-

function $extend(original, extended){
for (var key in (extended || {})) original[key] = extended[key];
return original;
};

The intent seems to be to provide a common interface to an object (not a
bad goal). To accomplish this Mootools passes an object that is designed
to modify the Host object to the Native constructor function.

An event could be:-
* a w3c dom Event
* a w3c dom Event w/a modified prototype
* an IE dom Event
* a modified IE dom Event

It does not appear to add clarity to the program. It may introduce
ambiguity of a library modified [IE] dom event.

Instead of trying to know what type of object it is, the alternative is
to take advantage of ducktyping.

For example:-

| function preventDefault(ev) {
| ev = ev || event;
| if(typeof ev.preventDefault == "function") {
| ev.preventDefault();
| } else if('returnValue' in ev) {
| ev.returnValue = false;
| }
| }

accomplishes the task of preventing the default action of an event. It
isn't necessary to know what interfaces are involved.
We have discussed the efficiency of the prototype chain already.
The prototype chain in this particular case could not be shorter:

Element instance --> Element.prototype --> Node.prototype
--> Object.prototype --> null

How do you know that would be the prototype chain? Where is the
prototype chain for a Host DOM object defined? The resolution of a
|getX| method off an form element might be closer to:-

elementInstance --> HTMLFormElement.prototype --> HTMLElement.prototype
--> Element.prototype

However, the [[Get]] operation would probably involve a check to see if
the form has a control named "getX". Completely nonstandard, but
browsers do have to resolve things like |formElement.controlName|, as
many webpages still use that.
The expected loss in runtime efficiency by using it is thus negligible.
That said, this is a border case. One would seldom want to augment
Element.prototype.

The use of Mootools' Event stop

To work in IE, there would be required call to

| new Event(ev).stop().

In a hypothetical "utopia" where all browsers supported your "design
pattern", the code could use:-

| ev.stop()

which would not be more efficient than

| preventDefault(ev)
| stopPropagation(ev)

..
Consider a case of a hypothetical user-defined property |x| on
Element.prototype, Element.prototype.x. When resolving an identifier |x|
on an img object, img.x, the |x| property would be not be resolved on
Element.prototype. Instead, it would more likely be found in
HTMLImageElement.prototype, or on the object itself. The |x| property
might be implemented as a getter or it might be implemented as a property.

Node
|
Element {x:Function(user-def} EventTarget
| |
HTMLElement {style::ElementCSSInlineStyle}
|
HTMLImageElement { getter x::uint }
|
img

[...]

You are constantly ignoring the fact that e.g. HTMLImageElement.prototype
could be augmented as well, and the benefit that could bring. You must do
so because otherwise you would hurt the pointless argument which says that
using host object's prototypes is a bad idea per se.

The point of the example is that the user-defined property would be
shadowed by something on HTMLImageElement interface.

If the desire were to modify the HTMLImageElementInterface by adding an
|x| property, that would fail in error:-

HTMLImageElement.prototype.x = 1;
TypeError: setting a property that has only a getter

Even if setting HTMLImageElement.prototype "worked", the strategy could
fail for other reasons:

1) could conflict with other objects in the prototype chain that the
Host environment introduced, that have the same name
2) Special lookups (special [[Get]]).
3) New interfaces/methods added for future implementations of the same
interface.

Other programmers seem to have similar sentiments. See LoD[1][2].

Garrett

[1]http://en.wikipedia.org/wiki/Law_of_Demeter
[2]http://c2.com/cgi/wiki?LawOfDemeter

Just for fun: http://perldesignpatterns.com/?ObjectOrgy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top