arturadib / agility

Javascript MVC for the "write less, do more" programmer
http://agilityjs.com
MIT License
542 stars 70 forks source link

Revisiting differential inheritance - extend by default? #42

Closed arturadib closed 13 years ago

arturadib commented 13 years ago

This debate has been sparked by the work of @tristanls, who implemented the extend (~) syntax for controllers.

Originally, Agility tried to stick to a differential inheritance paradigm. This meant that all properties of Agility objects were passed on to their descendants as prototype methods, except when overridden by the children:

// parent defines controller
var parent = $$({}, '<div/>', {
  'create': function(){}
});
// child redefines controller of parent
var child = $$(parent, {}, {}, {
  'create': function(){... new controller ...}
})

That was not the desired behavior, mainly because there would be no way to extend previously defined controllers. So @tristanls proposed the new syntax ~ for controllers, which would allow one to keep the previously defined handler create, and add some more logic to it:

// child *extends* controller of parent
var child = $$(parent, {}, {}, {
  '~create': function(){... more logic in addition to parent's...}
})

Then Darren Mason pointed out that a similar issue arises with CSS styles:

// parent defines style
var parent = $$({}, {format:'<div/>', 
  style:'& {color:red}'
});
// child redefines style, losing the color above
var child = $$({}, {format:'<div/>', 
  style:'& {float:right}'
});

Again, @tristanls proposed a similar solution:

// child *extends* style, keeping color from parent
var child = $$({}, {format:'<div/>', 
  '~style':'& {float:right}'
});

This seems to reveal a pattern - whenever some properties can be extended, it seems like the desired default behavior is to extend, and not override. This includes CSS styles and controllers. (There doesn't seem to exist a way to naturally extend models and formats, so these would have to be overridden by default).

So I am considering the possibility to make extend the default behavior for controllers and styles, and to introduce a new syntax ! to allow children objects to override inherited properties, e.g.

// parent defines style
var parent = $$({}, {format:'<div/>', 
  style:'& {color:red}'
});
// extend style (default behavior), keeping color above
var child = $$({}, {format:'<div/>', 
  style:'& {float:right}'
});
// redefine style, losing the color above
var child2 = $$({}, {format:'<div/>', 
  '!style':'& {float:right}'
});

The pros and cons I can see are:

What do you think?

quartzo commented 13 years ago

First, let me say I am not experiencing problems related to that now, so I will just give my totally unbased opinion.

For controllers, a call to "this.parent.create.call(this)" could be enough to get the parent "create" behavior. It seems simple to implement and is similar to the javascript inheritance behavior.

For style, I would prefer to always extend, and not having a way to disable it. It's more similar to the way we operate on css files.

darrenmason commented 13 years ago

I think properties that can be extended should have that behavior by default, with the ! syntax to override.

tristanls commented 13 years ago

In my opinion, the ~ v. ! syntax is largely driven by what the default behavior is.

If the default behavior is to extend the previous function, then !method makes intuitive sense as the override notation. On the other hand, if the default behavior is to override, I like ~method as an extend notation because it makes me feel like something is being extended when i look at that. That's my bit for what I think the syntax should be.

As to what the default should be, I've made an argument before that differential inheritance is the JavaScript default, and having that as the default makes it consistent with the language. But I'm all for what's more intuitive to use, and for my part after looking at the guts of Agility for a while, it's all the same to me.

alcinnz commented 13 years ago

The use of ! makes sense to me. However, I haven't started using Agility heavily yet, so my word shouldn't be taken as law.

arturadib commented 13 years ago

OK, let's keep things as they are for now (using ~), and maybe come back to this if it starts bothering other people :)