Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
From one, many From many, oneClass inheritance and composition         patterns in YUI           Luke Smith
It’s war
Being a web developer       is hard.     We got it.
Time
Development time   VSMaintenance time
Development time
Development time   • Prototyping   • Structuring
• Prototyping• Structuring
ad er★L o         nd G rids     S Re set a★ CS ★ Module   system ★ Custom Event system
Class structure strategies   • Pseudo-classical   • Prototypal   • Augmentation (Class A + Class B)   • Plugins   • Class ...
Class structure strategies   • Pseudo-classical   • Prototypal   • Augmentation   • Plugins   • Class extensions   • MVC
Class structure strategies                • Pseudo-classical  Native                  Pseudo-classical                • Pr...
Class structure strategies                • Pseudo-classical  Native                • Prototypal
Pseudo-classical     (Old school)
Pseudo-classicalfunction SubClass() {  // constructor}SubClass.prototype = new SuperClass();SubClass.prototype.somePropert...
Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)function SubClass() {  // constructor}SubClass.pr...
Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)function SubClass() {  // constructor}Y.extend(Su...
Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)function SubClass() {  // constructor}Y.extend(Su...
Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)function SubClass() {  // constructor}Y.extend(Su...
Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)Y.SubClass = Y.extend(  function() {     // const...
Y.extend() PROs•   Creates a “clean” subclass relationship•   no YUI class requirement•   Preserves instanceof•   SubClass...
Y.extend() CONs•   No multiple inheritance•   Manual constructor chaining required•   Constructor chaining is awkward•   C...
Y.extend() CONs•       No multiple inheritance•       Manual constructor chaining required•       Constructor chaining is ...
Y.extend() CONs•       No multiple inheritance•       Manual constructor chaining required•       Constructor chaining is ...
Y.extend() CONs•       No multiple inheritance•       Manual constructor chaining required•       Constructor chaining is ...
To sum up•   Good for basic class inheritance•   If you can extend Y.Base, there are more options
Prototypal
PrototypalY.extend = function(SubClass, SuperClass,...) {  var superProto = SuperClass.prototype,      subProto   = Y.Obje...
PrototypalY.extend = function(SubClass, SuperClass,...) {  var superProto = SuperClass.prototype,      subProto   = Y.Obje...
PrototypalY.Object = (function () {  function F() {}  return function (obj) {     F.prototype = obj;     return new F();  ...
Prototypal // Old and busted SubClass.prototype = new SuperClass(); SuperClass                                  SubClassf(...
Prototypal // Old and busted SubClass.prototype = new SuperClass(); SuperClass                                  SubClassf(...
Prototypal // Old and busted SubClass.prototype = new SuperClass();                   BA SuperClass           D           ...
Prototypal // Old and busted SubClass.prototype = new SuperClass(); SuperClass                                  SubClassf(...
Prototypal Y.Object = (function () {   function F() {}   return function (obj) {      F.prototype = obj;      return new F...
Prototypal Y.Object = (function () {   function F() {}   return function (obj) {      F.prototype = obj;      return new F...
Prototypal Y.Object = (function () {   function F() {}   return function (obj) {      F.prototype = obj;      return new F...
Prototypal Y.Object = (function () {   function F() {}   return function (obj) {      F.prototype = obj;      return new F...
PrototypalY.Object = (function () {  function F() {}  return function (obj) {     F.prototype = obj;     return new F();  ...
PrototypalY.Object = (function () {  function F() {}  return function (obj) {     F.prototype = obj;     return new F();  ...
PrototypalY.Object = (function () {  function F() {}  return function (obj) {     F.prototype = obj;     return new F();  ...
Factory constructorfunction Set() {  var that = (this instanceof Set) ?                 this :                Y.Object(Set...
Factory constructorfunction Set() {  var that = (this instanceof Set) ?                 this :                Y.Object(Set...
Factory constructorfunction Set() {  var that = (this instanceof Set) ?                 this :                Y.Object(Set...
Factory constructorfunction Set() {  var that = (this instanceof Set) ?                 this :                Y.Object(Set...
Factory constructorfunction Set() {  var that = (this instanceof Set) ?                 this :                Y.Object(Set...
Y.Object() PROs•   Avoids copying a lot of properties•   Can be used to make factory constructors•   Can be used to store ...
Y.Object() CONs•   No multiple inheritance•   Factory constructor can promote sloppiness•   Can’t use hasOwnProperty in fo...
To sum up•   Useful for some internal logic patterns•   Not a good fit for most web app problems•   Common use suggests ne...
To sum up•     Useful for some internal logic patterns•     Not a good fit for most web app problems•     Common use sugge...
To sum up•     Useful for some internal logic patterns•     Not a good fit for most web app problems•     Common use sugge...
To sum up•     Useful for some internal logic patterns•     Not a good fit for most web app problems•     Common use sugge...
To sum up•     Useful for some internal logic patterns•     Not a good fit for most web app problems•     Common use sugge...
Class structure strategies                ✓ Pseudo-classical  Native                ✓ Prototypal                • Augmenta...
Class structure strategies                ✓ Pseudo-classical   Native                ✓ Prototypal                • Augment...
instanceof
Augmentation    B    A   C
AugmentationY.augment = function (to, from, force, whitelist, config)Y.ModelList = Y.extend(  function () {     /* constru...
AugmentationY.augment = function (to, from, force, whitelist, config)Y.ModelList = Y.extend(  function () {     /* constru...
AugmentationY.augment = function (to, from, force, whitelist, config)Y.ModelList = Y.extend(  function () {     /* constru...
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); Mo...
AugmentationY.augment(Y.ModelList, Y.ArrayList);  augmentvar list = new Y.ModelList({ ... });list.each(function (item) { ....
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); Mo...
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); Mo...
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); Mo...
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); Mo...
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });     eachlist.each(function (item) { ....
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });     eachlist.each(function (item) { ....
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });     eachlist.each(function (item) { ....
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });     eachlist.each(function (item) { ....
AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); Mo...
AugmentationY.augment = function (to, from, force, whitelist, config)Y.augment(Y.HistoryBase, Y.EventTarget, null, null, {...
Y.augment() PROs•   Defers constructor overhead•   Can augment with multiple classes•   Supports class or instance augment...
Y.augment() CONs•   First augmented method call is costly•   instanceof is false for augmenting classes•   Consumes more m...
To sum up•   Use it to simulate lazy multiple inheritance•   Y.Base-based classes should use class extensions•   Beware th...
To sum up•     Use it to simulate lazy multiple inheritance•     Y.Base-based classes should use class extensions•     Bew...
PluginsA    a   a   a   a
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);...
The requirementsHost class •   Y.Plugin.Host (free in Y.Base, or add with Y.augment)Plugin class •   Static NS property
The requirementsHost class •   Y.Plugin.Host (free in Y.Base, or add with Y.augment)Plugin class •   Static NS property   ...
Plugins (instance) Y.Plugin.Host.prototype.plug = function (Plugin, config) {   ...   if (Plugin && Plugin.NS) {     confi...
Plugins (instance) Y.Plugin.Host.prototype.plug = function (Plugin, config) {   ...   if (Plugin && Plugin.NS) {     confi...
The contractSHOULD✓ Expect an object  constructor argument  with ‘host’ property
The contractSHOULD                   MAY✓ Expect an object       ✓ Provide namespaced API  constructor argument   ✓ Modify...
The contractSHOULD                   MAY✓ Expect an object       ✓ Provide namespaced API  constructor argument   ✓ Modify...
The contractSHOULD                   MAY✓ Expect an object       ✓ Provide namespaced API  constructor argument   ✓ Modify...
Plugins (class) Y.Plugin.Host.plug(Y.Overlay, Y.Plugin.Drag, {   handles: [.yui3-widget-hd] }); var overlay = new Y.Overla...
Plugin PROs•   Avoids method/property naming collisions•   Preserves host behavior when unplug()ed•   Plug classes or inst...
Plugin CONs•   Fragments API•   Plugin contract to restore host can add code weight•   Difficult to manage competing plugi...
to sum up•   Flexible•   Better in smaller numbers•   Class Plugins vs Augmentation?•   Free with Y.Base-based classes and...
Class Extensions           B         Y.Base     A            C
Class extensionsY.extend = function (SubClass, SuperClass, proto, static)Y.SubClass = Y.extend(  function() {     SubClass...
Class extensionsY.extend = function (SubClass, SuperClass, proto, static)Y.SubClass = Y.extend(  NAME: ‘subsub’,  /* NAME ...
Class extensionsY.extend = function (SubClass, SuperClass, proto, static)Y.SubClass = Y.extend(  NAME: ‘subsub’,  /* NAME ...
Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.SubClass = Y.extend(  NAME: ‘subsub’,  /* ...
Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.LineSeries = Y.Base.create(lineSeries, Y.C...
Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.LineSeries = Y.Base.create(lineSeries, Y.C...
Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.LineSeries = Y.Base.create(lineSeries, Y.C...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries,   [ Y.Lines ], { ... }); var series = new Y.L...
Two types of extensions    1. Class decoration       Add feature APIs and Attributes    2. Core functionality       Satisf...
Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.Overlay = Y.Base.create(overlay, Y.Widget,...
Class extensionsY.Base.mix = function(Class, ext)Y.Slider = Y.Base.create(slider, Y.SliderBase,   [Y.SliderValueRange]);Y....
Extensions PROs•   Promotes code reuse across environments•   Feature APIs are added to the prototype•   Can be used to mi...
Extensions CONs•   Requires Y.Base•   Initialization overhead•   Class definition only (no instance feature additions)•   ...
Extension vs Plugin•   Extensions can be used to contribute core behavior•   Extensions modify the class prototype, plugin...
MVC
MVCGo see Eric’s talk tomorrow
There ain’t just one   way to do it.
You owe it to future-you to structure your code
Try out plugins and    extensions
Invest in the future
Invest in the future    (and use Y.Base)
Invest in the future    (and use Y.Base)   (and join us in #yui)
Thank you            Luke Smith            @ls_n
Inheritance patterns
Upcoming SlideShare
Loading in …5
×

Inheritance patterns

  • Be the first to comment

Inheritance patterns

  1. 1. From one, many From many, oneClass inheritance and composition patterns in YUI Luke Smith
  2. 2. It’s war
  3. 3. Being a web developer is hard. We got it.
  4. 4. Time
  5. 5. Development time VSMaintenance time
  6. 6. Development time
  7. 7. Development time • Prototyping • Structuring
  8. 8. • Prototyping• Structuring
  9. 9. ad er★L o nd G rids S Re set a★ CS ★ Module system ★ Custom Event system
  10. 10. Class structure strategies • Pseudo-classical • Prototypal • Augmentation (Class A + Class B) • Plugins • Class extensions (mixins) • MVC
  11. 11. Class structure strategies • Pseudo-classical • Prototypal • Augmentation • Plugins • Class extensions • MVC
  12. 12. Class structure strategies • Pseudo-classical Native Pseudo-classical • Prototypal • Prototypal • Augmentation • Plugins Artificial • Class extensions • MVC
  13. 13. Class structure strategies • Pseudo-classical Native • Prototypal
  14. 14. Pseudo-classical (Old school)
  15. 15. Pseudo-classicalfunction SubClass() { // constructor}SubClass.prototype = new SuperClass();SubClass.prototype.someProperty = "booga!";SubClass.prototype.someMethod = function () { ... };...SubClass.someStaticMethod = function () { ... };...
  16. 16. Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)function SubClass() { // constructor}SubClass.prototype = new SuperClass();SubClass.prototype.someProperty = "booga!";SubClass.prototype.someMethod = function () { ... };...SubClass.someStaticMethod = function () { ... };...
  17. 17. Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)function SubClass() { // constructor}Y.extend(SubClass, SuperClass);SubClass.prototype.someProperty = "booga!";SubClass.prototype.someMethod = function () { ... };...SubClass.someStaticMethod = function () { ... };...
  18. 18. Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)function SubClass() { // constructor}Y.extend(SubClass, SuperClass, { someProperty: "booga!", someMethod : function () { ... }, ...});SubClass.someStaticMethod = function () { ... };...
  19. 19. Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)function SubClass() { // constructor}Y.extend(SubClass, SuperClass, { someProperty: "booga!", someMethod : function () { ... }, ...}, { someStaticMethod: function () { ... }, ...});
  20. 20. Pseudo-classicalY.extend = function (SubClass, SuperClass, proto, static)Y.SubClass = Y.extend( function() { // constructor }, /* extends */ SuperClass, { // Instance members someProperty: "booga!", someMethod : function () { ... } }, { // Static members someStaticMethod: function () { ... } });
  21. 21. Y.extend() PROs• Creates a “clean” subclass relationship• no YUI class requirement• Preserves instanceof• SubClass.superclass (not super, but close)• Control superclass constructor execution
  22. 22. Y.extend() CONs• No multiple inheritance• Manual constructor chaining required• Constructor chaining is awkward• Constructor chaining may be costly
  23. 23. Y.extend() CONs• No multiple inheritance• Manual constructor chaining required• Constructor chaining is awkward• Constructor chaining may be costly function SubClass() { // Chain superclass constructor SubClass.superclass.constructor.apply(this, arguments); // My constructor stuff ... }
  24. 24. Y.extend() CONs• No multiple inheritance• Manual constructor chaining required• Constructor chaining is awkward• Constructor chaining may be costly function SubClass() { // Chain superclass constructor SubClass.superclass.constructor.apply(this, arguments); A RD W KW // My constructor stuff A ... }
  25. 25. Y.extend() CONs• No multiple inheritance• Manual constructor chaining required• Constructor chaining is awkward• Constructor chaining may be costly function SubClass() { // Chain superclass constructor SubClass.superclass.constructor.apply(this, arguments); A RD W KW COST // My constructor stuff A LY? ... }
  26. 26. To sum up• Good for basic class inheritance• If you can extend Y.Base, there are more options
  27. 27. Prototypal
  28. 28. PrototypalY.extend = function(SubClass, SuperClass,...) { var superProto = SuperClass.prototype, subProto = Y.Object(superProto); SubClass.prototype = subProto; ...
  29. 29. PrototypalY.extend = function(SubClass, SuperClass,...) { var superProto = SuperClass.prototype, subProto = Y.Object(superProto); SubClass.prototype = subProto; ...
  30. 30. PrototypalY.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); };})();
  31. 31. Prototypal // Old and busted SubClass.prototype = new SuperClass(); SuperClass SubClassf(n) f(n) Constructor Constructor{} {} Prototype Prototype
  32. 32. Prototypal // Old and busted SubClass.prototype = new SuperClass(); SuperClass SubClassf(n) f(n) Constructor Constructor{} {} Prototype Prototype
  33. 33. Prototypal // Old and busted SubClass.prototype = new SuperClass(); BA SuperClass D SubClassf(n) f(n) Constructor Constructor{} {} Prototype Prototype
  34. 34. Prototypal // Old and busted SubClass.prototype = new SuperClass(); SuperClass SubClassf(n) f(n) Constructor Constructor{} {} Prototype Prototype
  35. 35. Prototypal Y.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); }; })(); SuperClass (anon) SubClassf(n) f(n) f(n) EMPTY Constructor Constructor Constructor{} {} {} Prototype Prototype Prototype
  36. 36. Prototypal Y.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); }; })(); SuperClass (anon) SubClassf(n) f(n) f(n) EMPTY Constructor Constructor Constructor{} {} {} Prototype Prototype Prototype
  37. 37. Prototypal Y.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); }; })(); SuperClass (anon) SubClassf(n) f(n) f(n) EMPTY Constructor Constructor Constructor{} {} {} Prototype Prototype Prototype
  38. 38. Prototypal Y.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); }; })(); SuperClass (anon) SubClassf(n) f(n) f(n) EMPTY Constructor Constructor Constructor{} {} {} Prototype Prototype Prototype
  39. 39. PrototypalY.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); };})(); (anon) f(n) EMPTY Constructor{} {} Any Object Prototype
  40. 40. PrototypalY.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); };})(); (anon) f(n) EMPTY Constructor{} {} Any Object Prototype
  41. 41. PrototypalY.Object = (function () { function F() {} return function (obj) { F.prototype = obj; return new F(); };})(); (anon) f(n) EMPTY Constructor{} {} f(n) (anon) EMPTY Constructor Any Object Prototype New Object {} Prototype
  42. 42. Factory constructorfunction Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}
  43. 43. Factory constructorfunction Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}var set = new Set(‘a’,’b’);
  44. 44. Factory constructorfunction Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}var set = new Set(‘a’,’b’);set instanceof Set; // true
  45. 45. Factory constructorfunction Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}var set = Set(‘a’,’b’); // <-- OOPS! I forgot new!
  46. 46. Factory constructorfunction Set() { var that = (this instanceof Set) ? this : Y.Object(Set.prototype); // use that instead of this [].push.apply(that._items, arguments); return that;}var set = Set(‘a’,’b’);set instanceof Set; // true
  47. 47. Y.Object() PROs• Avoids copying a lot of properties• Can be used to make factory constructors• Can be used to store original values for revert• Any object can be the prototype• Avoids class explosion
  48. 48. Y.Object() CONs• No multiple inheritance• Factory constructor can promote sloppiness• Can’t use hasOwnProperty in for/in loops
  49. 49. To sum up• Useful for some internal logic patterns• Not a good fit for most web app problems• Common use suggests need for a constructor
  50. 50. To sum up• Useful for some internal logic patterns• Not a good fit for most web app problems• Common use suggests need for a constructor var account1 = Y.Object(accountProto); account1.id = 1234; account1.holder = John Q. Consumer; var account2 = Y.Object(accountProto); account2.id = 1235; account2.holder = Jane B. Investor;
  51. 51. To sum up• Useful for some internal logic patterns• Not a good fit for most web app problems• Common use suggests need for a constructor var account1 = Y.Object(accountProto); account1.id = 1234; account1.holder = John Q. Consumer; var account2 = Y.Object(accountProto); account2.id = 1235; account2.holder = Jane B. Investor;
  52. 52. To sum up• Useful for some internal logic patterns• Not a good fit for most web app problems• Common use suggests need for a constructor var account1 = Y.Object(accountProto); CO account1.id = 1234; NS account1.holder = John Q. Consumer; TR UC var account2 = Y.Object(accountProto); TO account2.id = 1235; R account2.holder = Jane B. Investor;
  53. 53. To sum up• Useful for some internal logic patterns• Not a good fit for most web app problems• Common use suggests need for a constructor function Account(id, holder) { this.id = id; this.holder = holder; } var account1 = new Account(1234, John Q. Consumer); var account2 = new Account(1235, Jane B. Invester);
  54. 54. Class structure strategies ✓ Pseudo-classical Native ✓ Prototypal • Augmentation • Plugins Artificial • Class extensions • MVC
  55. 55. Class structure strategies ✓ Pseudo-classical Native ✓ Prototypal • Augmentation • Plugins Artificial • Class extensions • MVC
  56. 56. instanceof
  57. 57. Augmentation B A C
  58. 58. AugmentationY.augment = function (to, from, force, whitelist, config)Y.ModelList = Y.extend( function () { /* constructor */ ModeList.superclass.constructor.apply(this, arguments); }, Y.Base, { /* prototype */ }, { /* static */ });Y.augment(Y.ModelList, Y.ArrayList);
  59. 59. AugmentationY.augment = function (to, from, force, whitelist, config)Y.ModelList = Y.extend( function () { /* constructor */ ModeList.superclass.constructor.apply(this, arguments); }, Y.Base, { /* prototype */ }, { /* static */ });Y.augment(Y.ModelList, Y.ArrayList);
  60. 60. AugmentationY.augment = function (to, from, force, whitelist, config)Y.ModelList = Y.extend( function () { /* constructor */ ModeList.superclass.constructor.apply(this, arguments); }, Y.Base, { /* prototype */ }, { /* static */ });Y.augment(Y.ModelList, Y.ArrayList);
  61. 61. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); ModelList Constructor ArrayList Prototype Constructor create init Prototype each item
  62. 62. AugmentationY.augment(Y.ModelList, Y.ArrayList); augmentvar list = new Y.ModelList({ ... });list.each(function (item) { ... }); ModelList Constructor ArrayList Prototype Constructor create init Prototype each each item item
  63. 63. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); ModelList Constructor ArrayList Prototype Constructor create init Prototype each each item item
  64. 64. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); ModelList Constructor ArrayList list Prototype Prototype Constructor create create init Prototype ModelList Constructor Prototype create init init each item each each each item item item
  65. 65. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); ModelList Constructor ArrayList list Prototype Constructor create init Prototype ModelList Constructor Prototype create init each item each each item item Prototype
  66. 66. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); ModelList Constructor ArrayList list Prototype Constructor create init Prototype each each item item Prototype
  67. 67. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... }); eachlist.each(function (item) { ... }); ModelList Constructor ArrayList list Prototype Constructor create init Prototype each each item item Prototype
  68. 68. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... }); eachlist.each(function (item) { ... }); ModelList Constructor ArrayList list Prototype Constructor create init Prototype each each item item Prototype
  69. 69. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... }); eachlist.each(function (item) { ... }); ModelList Constructor ArrayList list Prototype each create Constructor 1. Copy item init Prototype each each item item Prototype
  70. 70. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... }); eachlist.each(function (item) { ... }); ModelList Constructor ArrayList list Prototype each create Constructor 1. Copy item init Prototype 2. Construct each each item item Prototype
  71. 71. AugmentationY.augment(Y.ModelList, Y.ArrayList);var list = new Y.ModelList({ ... });list.each(function (item) { ... }); ModelList Constructor ArrayList list Prototype each create Constructor 1. Copy item init Prototype 2. Construct each each 3. Execute item item Prototype
  72. 72. AugmentationY.augment = function (to, from, force, whitelist, config)Y.augment(Y.HistoryBase, Y.EventTarget, null, null, { emitFacade : true, prefix : history, preventable: false, queueable : true});
  73. 73. Y.augment() PROs• Defers constructor overhead• Can augment with multiple classes• Supports class or instance augmentation• No YUI class requirement
  74. 74. Y.augment() CONs• First augmented method call is costly• instanceof is false for augmenting classes• Consumes more memory• Limited control of constructor invocation
  75. 75. To sum up• Use it to simulate lazy multiple inheritance• Y.Base-based classes should use class extensions• Beware the diamond problem• Weigh the importance of constructor deferral
  76. 76. To sum up• Use it to simulate lazy multiple inheritance• Y.Base-based classes should use class extensions• Beware the diamond problem• Weigh the importance of constructor deferral Y.SubClass = Y.extend( function () { Y.SuperClass.apply(this, arguments); Y.EventTarget.apply(this, { /* config */ }); }, Y.SuperClass, // <-- one "official" extention class Y.mix({ /* prototype */ }, Y.EventTarget.prototype), { /* static */ });
  77. 77. PluginsA a a a a
  78. 78. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd);
  79. 79. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor Attributes x y
  80. 80. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor Attributes x y
  81. 81. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay overlay Constructor Attributes Attributes x x y y
  82. 82. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor overlay Plugin.Drag Constructor ATTRS Attributes x x ATTRS y y lock
  83. 83. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor overlay Plugin.Drag Constructor ATTRS Attributes x x ATTRS y y lock
  84. 84. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor overlay overlay.dd Plugin.Drag Attributes Constructor Attributes lock ATTRS x x ATTRS y y lock
  85. 85. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor overlay overlay.dd Plugin.Drag dd Attributes Constructor Attributes lock ATTRS x x ATTRS y y lock
  86. 86. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor overlay overlay.dd Plugin.Drag dd Attributes Constructor Attributes lock ATTRS x x ATTRS y y lock
  87. 87. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor overlay overlay.dd Plugin.Drag dd Attributes Constructor Attributes lock ATTRS x x ATTRS y y lock
  88. 88. Plugins var overlay = new Y.Overlay({ ... }); overlay.plug(Y.Plugin.Drag); overlay.dd.set(lock, true); overlay.unplug(dd); Overlay Constructor overlay Plugin.Drag Constructor ATTRS Attributes x x ATTRS y y lock
  89. 89. The requirementsHost class • Y.Plugin.Host (free in Y.Base, or add with Y.augment)Plugin class • Static NS property
  90. 90. The requirementsHost class • Y.Plugin.Host (free in Y.Base, or add with Y.augment)Plugin class • Static NS property That’s it
  91. 91. Plugins (instance) Y.Plugin.Host.prototype.plug = function (Plugin, config) { ... if (Plugin && Plugin.NS) { config.host = this; this[Plugin.NS] = new Plugin(config); } };
  92. 92. Plugins (instance) Y.Plugin.Host.prototype.plug = function (Plugin, config) { ... if (Plugin && Plugin.NS) { config.host = this; this[Plugin.NS] = new Plugin(config); } }; overlay.dd.set(lock, true); overlay.unplug(dd);
  93. 93. The contractSHOULD✓ Expect an object constructor argument with ‘host’ property
  94. 94. The contractSHOULD MAY✓ Expect an object ✓ Provide namespaced API constructor argument ✓ Modify core behavior via with ‘host’ property events or AOP
  95. 95. The contractSHOULD MAY✓ Expect an object ✓ Provide namespaced API constructor argument ✓ Modify core behavior via with ‘host’ property events or AOPMUST✓ Remove all traces when unplugged
  96. 96. The contractSHOULD MAY✓ Expect an object ✓ Provide namespaced API constructor argument ✓ Modify core behavior via with ‘host’ property events or AOPMUST MUST NOT✓ Remove all traces ✓ Modify host directly when unplugged other than add the namespace
  97. 97. Plugins (class) Y.Plugin.Host.plug(Y.Overlay, Y.Plugin.Drag, { handles: [.yui3-widget-hd] }); var overlay = new Y.Overlay({ ... }); overlay.dd.set(lock, true);
  98. 98. Plugin PROs• Avoids method/property naming collisions• Preserves host behavior when unplug()ed• Plug classes or instances• Generic plugins can work for multiple host types• Works on Nodes
  99. 99. Plugin CONs• Fragments API• Plugin contract to restore host can add code weight• Difficult to manage competing plugins• plug() could use a little sugar
  100. 100. to sum up• Flexible• Better in smaller numbers• Class Plugins vs Augmentation?• Free with Y.Base-based classes and Y.Nodes (have I mentioned that you should use Y.Base?)
  101. 101. Class Extensions B Y.Base A C
  102. 102. Class extensionsY.extend = function (SubClass, SuperClass, proto, static)Y.SubClass = Y.extend( function() { SubClass.superclass.constructor.apply(this, arguments); }, /* extends */ Y.Base { someProperty: ‘booga!’, someMethod : function () { ... } }, { NAME: ‘subsub’, /* NAME */ ‘subsub’, ATTRS: { ... } });
  103. 103. Class extensionsY.extend = function (SubClass, SuperClass, proto, static)Y.SubClass = Y.extend( NAME: ‘subsub’, /* NAME */ ‘subsub’, /* extends */ Y.Base { someProperty: ‘booga!’, someMethod : function () { ... } }, { ATTRS: { ... } });
  104. 104. Class extensionsY.extend = function (SubClass, SuperClass, proto, static)Y.SubClass = Y.extend( NAME: ‘subsub’, /* NAME */ ‘subsub’, /* extends */ Y.Base [], // <-- class extensions! { someProperty: ‘booga!’, someMethod : function () { ... } }, { ATTRS: { ... } });
  105. 105. Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.SubClass = Y.extend( NAME: ‘subsub’, /* NAME */ ‘subsub’, /* extends */ Y.Base [], // <-- class extensions! { someProperty: ‘booga!’, someMethod : function () { ... } }, { ATTRS: { ... } });
  106. 106. Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ });
  107. 107. Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ });Y.ComboSeries = Y.Base.create(comboSeries, Y.CartesianSeries, [ Y.Fills, Y.Lines, Y.Plots ], { /* Glue Y.Fills etc APIs to Y.CartesianSeries APIs */ }, { ATTRS: { ... } });
  108. 108. Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { /* Glue Y.Lines APIs to Y.CartesianSeries APIs */ });Y.ComboSeries = Y.Base.create(comboSeries, Y.CartesianSeries, [ Y.Fills, Y.Lines, Y.Plots ], { /* Glue Y.Fills etc APIs to Y.CartesianSeries APIs */ }, { ATTRS: { ... } });
  109. 109. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS Prototype Prototype ATTRS Prototype
  110. 110. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor Constructor ATTRS ATTRS Constructor Prototype Prototype ATTRS Prototype
  111. 111. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor Constructor Constructor ATTRS ATTRS Constructor Prototype Prototype ATTRS Prototype
  112. 112. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS direction type type Prototype Prototype Prototype
  113. 113. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS direction styles type type Prototype Prototype Prototype
  114. 114. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS direction styles type type direction Prototype type Prototype Prototype
  115. 115. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS direction styles type type direction Prototype type Prototype Prototype
  116. 116. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS direction styles type type direction Prototype type Prototype Prototype
  117. 117. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS Prototype Prototype Prototype draw drawLines
  118. 118. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS Prototype Prototype Prototype draw drawLines
  119. 119. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS Prototype Prototype Prototype Prototype draw Prototype draw drawLines draw drawLines drawSeries
  120. 120. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... }); Cartesian LineSeries Lines Constructor Constructor Constructor ATTRS ATTRS ATTRS Prototype Prototype Prototype draw initializer initializer drawLines initializer initializer initializer initializer
  121. 121. Class extensions Y.LineSeries = Y.Base.create(lineSeries, Y.CartesianSeries, [ Y.Lines ], { ... }); var series = new Y.LineSeries({ ... });1. Constructors are called2. Attributes are set3. initializers are called
  122. 122. Two types of extensions 1. Class decoration Add feature APIs and Attributes 2. Core functionality Satisfy abstract class implementation
  123. 123. Class extensionsY.Base.create = function(NAME, SuperClass, ext, proto, static)Y.Overlay = Y.Base.create(overlay, Y.Widget, [ Y.WidgetStdMod, Y.WidgetPosition, Y.WidgetStack, Y.WidgetPosition, Y.WidgetPositionConstrain]);
  124. 124. Class extensionsY.Base.mix = function(Class, ext)Y.Slider = Y.Base.create(slider, Y.SliderBase, [Y.SliderValueRange]);Y.Base.mix(Y.Slider, [Y.ClickableRail]);
  125. 125. Extensions PROs• Promotes code reuse across environments• Feature APIs are added to the prototype• Can be used to mimic MVC breakdown
  126. 126. Extensions CONs• Requires Y.Base• Initialization overhead• Class definition only (no instance feature additions)• Does not work on Nodes• Increased potential for accidental name collisions
  127. 127. Extension vs Plugin• Extensions can be used to contribute core behavior• Extensions modify the class prototype, plugins are always namespaced• Feature extension constructors are always executed, plugin constructors on plug()• Feature APIs/attributes on the prototype vs class plugins in namespace is a stylistic choice
  128. 128. MVC
  129. 129. MVCGo see Eric’s talk tomorrow
  130. 130. There ain’t just one way to do it.
  131. 131. You owe it to future-you to structure your code
  132. 132. Try out plugins and extensions
  133. 133. Invest in the future
  134. 134. Invest in the future (and use Y.Base)
  135. 135. Invest in the future (and use Y.Base) (and join us in #yui)
  136. 136. Thank you Luke Smith @ls_n

×