-
-
Save evangoer/1250052 to your computer and use it in GitHub Desktop.
/* What do we really care about when creating a Base-derived object? | |
1. the object we are deriving from | |
2. string name | |
3. properties and methods | |
4. attributes | |
Goals: simpler method with fewer args & less nesting. Simplify | |
adding attributes. No need for empty [] hack as with Y.Base.create() */ | |
Y.Example = Y.Model.derive('example-model', { | |
// prototype methods and properties here | |
hello: function () { | |
return 'hi'; | |
} | |
}, { | |
// attributes here | |
frobozz: { | |
value: 'zorkmid', | |
readOnly: true | |
}, | |
grue: 17 // MOAR sugar; equivalent to grue: { value: 17 } | |
}, { | |
// publish events here | |
'somethingSpecial': { | |
emitFacade: true, | |
broadcast: 2, | |
} | |
}); | |
/* NOTES: | |
1. Y.Base.derive() extends from Y.Base. Y.Model.derive() extends from | |
Y.Model. And so on. Eliminate an unnecessary arg. | |
2. Assumption: mixins are less important and developers can always do this | |
themselves. Perhaps allow a fourth optional [] argument to make it easier. | |
3. Assumption: adding statics like HTML_PARSER is easy. Developers can do | |
this themselves. Better to focus on making attributes less clumsy to add. */ |
If NAME could be optional without breaking anything, that would be great! I wasn't thinking that radically, I guess. :)
Attributes first -- that could work. Kind of agnostic on that.
I guess attributes first would make sense if you think that it's more likely you would only want to add attributes. I could see that being the case for things like Y.Model.
Defining events statically -- I think I see what you're getting at (maybe?) Gist updated.
What do you think of the short syntax for attributes, foo: 0 means foo: { value: 0 } ?
Yep. I think I've talked to Satyen about that shorthand before. I don't recall if he had reservations. I'd look for an enhancement request (include closed-wontfix :)), and if you don't find one, add it.
Otherwise, you think passing three objects as the primary args of the derive() function signature is easy enough to understand and flexible enough for future changes? When arg types are the same, but maybe one or more arguments (especially in the middle) is optional, I start to wonder if a nested object structure or a series of method calls might look/work better.
var SubClass = Y.Class.derive(SuperClass, [extensions]);
SubClass.attributes({ what you have in the gist })
.proto({ methods and properties })
.events({ what you have in the gist });
Or maybe the proto should go into the primary method. This could be worse than your suggestion. I'm just storming the brains.
You're right -- this is starting to have the same problems Y.Base.create() has. I like your chained methods approach, it's more flexible and it's harder to screw up.
In your example, are you trying to make Y.Class.derive() something totally generic, something you would use for extending Base and non-Base objects?
Right now there are generic extension methods on Y, then Y.Base.create(). We use the latter because it can do more, but it's an odd place for something used generically.
The generic derive method and the attribute/proto/events methods all suffer the same trap, where a user won't know if a given class has those static methods or not. This may not be too much of an issue given they're intended for the component/plugin author rather than the page implementer. With that in mind, having a derive method on the class is nice.
var SubClass = SuperClass.extend()
// I'm sure there are better names/method breakouts. This doesn't gracefully handle prototype properties.
.addMethods({ ... })
.mixin([ class extensions ])
.addAttributes({ ... })
.addEvents({ ... });
Well, I think I do like the chained methods approach as sugar for adding attributes and events. And for mixing in extensions. That approach seems cleaner to me than a single method that takes a whole bunch of arguments in a particular order.
Adding prototype methods through a special method seems weird to me, now that I'm looking at it.
I completely agree. I didn't like the proto as a method.
I like the replacement of statics with just the ATTRS and the removal of the extensions array.
I wonder if NAME could be optional. I believe it's only used for event prefix (boo) and getClassName calls, the latter of which are only appropriate for Widget derivations.
And what do you think of having the attributes first?
And if it were possible to define events statically for a class (like ATTRS) rather than publishing them once per instance, how would that affect the class building API?