SlideShare a Scribd company logo
1 of 81
Attribute
Luke Smith
@ls_n
You know this stuff
model.get(“id”);
overlay.set(“visible”, true);


var drag = new Y.DD.Drag({
    node: “#dragme”
});
You know this stuff
Bakery.ATTRS = {
     flour: {
         value: “pastry”
     },
     ...
};
What is an attribute?

 Encapsulation of a value state and set of
 feature configurations for customizing logic
 associated with the mutation and storage of
 that state, while providing opportunities to
 monitor changes.
What is an attribute?


      Object property + magic
The magic
• What it is
• Why we need it
• Where it comes from
• How it works
• What it costs
• Is it worth it?
The magic
• What it is
• Why we need it
• Where it comes from
• How it works
• What it costs
• “Should I use a property or an attribute?”
What is the magic?
What is the magic?
• getters
• setters
• default values
• change events
ES5 has magic
Object.defineProperties(this, {
   flour: {
     value: “pastry”,
     getter: ...
     setter: ...
     ...
ES5 has magic ... except


IE6 IE7 IE8
ES5 has magic ... except


IE6 IE7 IE8
          * Dear old IE, please die in a fire.
So, here we are

obj.get(“attr”);


obj.set(“attr”, “I’m needed, thanks IE!”);
Why do we want magic?
Why do we want magic?
  Properties are dumb
Why do we want magic?
1. Properties are dumb
2. Maintenance
Where is the magic?
The Classes
         (all the things)

           Y.Base
The Classes
                 (all the things)

                   Y.Base
    Y.BaseCore              Y.BaseObservable   Y.AE
The Classes
                     (all the things)

                       Y.Base
     Y.BaseCore                 Y.BaseObservable      Y.AE

   Y.AttributeCore            Y.AttributeObservable
The Classes
                     (all the things)

                       Y.Base
     Y.BaseCore                 Y.BaseObservable      Y.AE

   Y.AttributeCore            Y.AttributeObservable

       Y.State                    Y.EventTarget
The Modules
                     (all the things)

                         base
    base-core                  base-observable        a-extras


   attribute-core              attribute-observable

  (attribute-core)           event-custom-complex
The Modules
                      (all the things)

                          base
     base-core                  base-observable        a-extras


 Y.AttributeCore
    attribute-core            Y.AttributeObservable
                                attribute-observable

   (attribute-core)           event-custom-complex
The Modules


 Y.AttributeCore    Y.AttributeObservable

   attribute-core    attribute-observable
Y.AttributeCore
obj.get(name);
obj.set(name, value);


obj.getAttrs(); // see docs
obj.setAttrs({ vals });
Y.AttributeCore
Class.ATTRS = { configs }; // sort of


obj.addAttr(name, { config }, lazy?);

obj.addAttrs({ configs }, { values }, lazy?);

obj.attrAdded(name);
Y.AttributeObservable
bakery.on(“flourChange”, callback);
bakery.after(“flourChange”, callback);


bakery.once(...);
bakery.addTarget(...);   // etc.
Creating attributes
One at a time

 bakery.addAttr(“flour”, {
       setter: “_setFlour”,
       value: “whole wheat”
 });
Creating attributes
A bunch at a time

bakery.addAttrs({
      flour: {
           setter: “_setFlour”,
           value: “whole wheat”
      }, ...
});
Creating attributes
Statically for a class

 Bakery.ATTRS = {
       flour: {
         setter: “_setFlour”,
         value: “whole wheat”
       }
 });
How does the magic work?
Configurations
• value        • valueFn
• getter       • validator
• setter       • readOnly
               • writeOnce
               • lazyAdd
 http://yuilibrary.com/yui/docs/attribute/#configuration
Configurations
• value        • valueFn                • broadcast
• getter       • validator              •   cloneDefaultValue

• setter       • readOnly
               • writeOnce
               • lazyAdd
 http://yuilibrary.com/yui/docs/attribute/#configuration
value and valueFn
• Most expensive
• lazyAdd = true to defer cost
• valueFn always called at instantiation
lazyAdd
• Minimal setup, no set()
• Full setup on first call to get() or set()
• Some might never get fully setup (good)
• Y.BaseCore defaults lazyAdd = true for all
  (override with prototype._lazyAddAttrs)
• Beware lazyAdd + setter
setter for robustness
• Use for
  a) Input normalization, or
  b) Tightly coupled state related logic
• Not for side effects (use events)
• setter + lazyAdd gotcha
setter vs validator
• validator is called before setter
• If you have a setter, validate inline
_setFlour: function (val) {
   return (typeof val === “string”) ?
     val.toLowerCase() :
     Y.Attribute.INVALID_VALUE;
getter, setter, etc
• Pass string values to late bind handlers
flour: {
   setter : “_setFlour” // this._setFlour(val)
   getter : “_getFlour”,
   validator: “_validateFlour”,
   valueFn : “_initFlour”,
cloneDefaultValue
• {undefined, true, “deep”}, “shallow”, false
• Y.Base defaults Y.clone() behavior
• Always set or use a valueFn instead
flour: {
  value: { grain: ‘fine’, gluten: false, ... },
  cloneDefaultValue: true,
Change events
•   For decoupling systems
•   Why custom events have on() and after()
•   Assigning initial value does NOT fire event
•   Change event published on first set()
Ad hoc attributes
•   From Y.BaseCore
•   Create dynamic objects with Attribute API
•   prototype._allowAdHocAttrs = true
•   static _NON_ATTRS_CFG to blacklist
Ad hoc attributes
Bakery.prototype._allowAdHocAttrs = true;


var llamaBakery = new Bakery({
    flour: “pastry”,
    llamas: “sheared” // unknown, but added
});
What does the magic cost?
Magic taxes
1. Attribute setup cost
2. get()/set() cost



     *Many Bothans died to bring us this information
Attribute setup
Attribute setup
1. Creates State object
Attribute setup
1. Creates State object
2. Depth 2 copy of configs
Attribute setup
1. Creates State object
2. Depth 2 copy of configs
3. Gets value from construction values,
   valueFn, or value
Attribute setup
1. Creates State object
2. Depth 2 copy of configs
3. Gets value from construction values,
   valueFn, or value
4. lazyAdd attributes are stowed in State
Attribute setup
1. Creates State object
2. Depth 2 copy of configs
3. Gets value from construction values,
   valueFn, or value
4. lazyAdd attributes are stowed in State
5. non-lazy populate State and set(value)
Attribute setup
                 LOC   fn calls
 no attributes   34       9
  +lazy attr     +46    +14
 +empty attr     +56    +16
+attr property   +7      +0
    +value       +80    +20
   +valueFn      +3      +1
Base setup
Base setup
1. Creates State object
Base setup
1. Creates State object
2. Aggregates ATTRS up superclass chain
Base setup
1. Creates State object
2. Aggregates ATTRS up superclass chain
3. for each class call...
Base setup
1. Creates State object
2. Aggregates ATTRS up superclass chain
3. for each class call...
  1. class extension constructors
Base setup
1. Creates State object
2. Aggregates ATTRS up superclass chain
3. for each class call...
  1. class extension constructors
  2. addAttrs with filtered list from ATTRS aggregate
Base setup
1. Creates State object
2. Aggregates ATTRS up superclass chain
3. for each class call...
  1. class extension constructors
  2. addAttrs with filtered list from ATTRS aggregate
  3. initializer
Base setup
1. Creates State object
2. Aggregates ATTRS up superclass chain
3. for each class call...
  1. class extension constructors
  2. addAttrs with filtered list from ATTRS aggregate
  3. initializer
  4. class extension initializers
Base setup
1. Creates State object
2. Aggregates ATTRS up superclass chain
3. for each class call...
  1. class extension constructors
  2. addAttrs with filtered list from ATTRS aggregate
  3. initializer            2.5. addAttrs(ad-hocs)

  4. class extension initializers
get()
1. Checks if attribute is lazy, inits if necessary
2. Gets the value and getter from State
3. Returns value or result of calling getter
get()
                 LOC    fn calls
   get(attr)      10       6
 get(sub.attr)   +3       +5
   +getter       +2       +1
  +lazy init     +100    +20
set()




  http://yuilibrary.com/yui/docs/attribute/setflow.html
set() - just attribute
                 LOC    fn calls
   set(attr)      80      20
 set(sub.attr)   +27      +4
  +lazy init     +100    +20
  +validator     +5       +1
   +setter       +6       +1
set() - events
                  LOC    fn calls
   set(attr)       80      20
 set(sub.attr)    +27      +4
+change event     +151    +24
  +first event     +100    +12
+per subscriber   +27      +5
 +per bubble      +205    +21
Avoid Subattributes
obj.set(“nested.sub.attribute”, false);


• Triggered by . in attribute name
• A lot of extra work, most is wasted
• Confusing relationship with getter/setter

                                 * sorry about this
Is the magic worth it?
Should you use a property or an attribute?
Property
           PROs                CONs
•   Fast                 •   Dumb

•   Terse                •   Can’t migrate to
                             attribute w/o API
•   Nested structs are       breakage
    the same

•   Magic allowed if
    environment
    mandated
Attribute
          PROs                   CONs
•   Stable abstraction    •   Slow

•   Code organization     •   Nested structs are
                              awkward
•   Consistent API            (subattributes--)
•   Easy loose coupling
                          •   More typing
    with events

•   Abstraction
    performance can
    improve invisibly
Property or Attribute?
• Will it be accessed a lot? Like, really A LOT.
• Will there be lots of instances? (see #1)
• Will it be public, or interesting outside the
  object?
• Might the class be extended? Plugged?
• Would it amount to a micro-optimization?
Property or Attribute?

   Justify the use of properties
             rather than
  justifying the use of attributes

    (It’s less likely to bite you in the ass)
The Future
Attribute
          PROs                   CONs
•   Stable abstraction    •   Slow

•   Code organization     •   Nested structs are
                              awkward
•   Consistent API            (subattributes--)
•   Easy loose coupling
                          •   More typing
    with events

• Abstraction
    performance can
    improve invisibly
Faster; no new features
Faster; no new features
• Replace State with ES5 objects or shim
Faster; no new features
• Replace State with ES5 objects or shim
• Compile configs once for all instances
Faster; no new features
• Replace State with ES5 objects or shim
• Compile configs once for all instances
• Event optimizations
kittens + pancakes = future
The End.
             Thanks!



Luke Smith
@ls_n

More Related Content

What's hot

Web Optimization Summit: Coding for Performance
Web Optimization Summit: Coding for PerformanceWeb Optimization Summit: Coding for Performance
Web Optimization Summit: Coding for Performancejohndaviddalton
 
Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignLightbend
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationIvan Dolgushin
 
iOS Memory Management Basics
iOS Memory Management BasicsiOS Memory Management Basics
iOS Memory Management BasicsBilue
 
Making Ajax Sexy, JSConf 2010
Making Ajax Sexy, JSConf 2010Making Ajax Sexy, JSConf 2010
Making Ajax Sexy, JSConf 2010Dave Furfero
 
Making Ajax Sexy, JSConf 2010
Making Ajax Sexy, JSConf 2010Making Ajax Sexy, JSConf 2010
Making Ajax Sexy, JSConf 2010guest3a77e5d
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the ASTJarrod Overson
 
Omnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsOmnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsJustin Edelson
 
Reflex - How does it work?
Reflex - How does it work?Reflex - How does it work?
Reflex - How does it work?Rocco Caputo
 
Building DSLs With Eclipse
Building DSLs With EclipseBuilding DSLs With Eclipse
Building DSLs With EclipsePeter Friese
 
Memory management in Objective C
Memory management in Objective CMemory management in Objective C
Memory management in Objective CNeha Gupta
 
Backbone.js Simple Tutorial
Backbone.js Simple TutorialBackbone.js Simple Tutorial
Backbone.js Simple Tutorial추근 문
 
Extending javascript part one
Extending javascript part oneExtending javascript part one
Extending javascript part oneVijaya Anand
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!Brendan Eich
 

What's hot (20)

EMF Tips n Tricks
EMF Tips n TricksEMF Tips n Tricks
EMF Tips n Tricks
 
Google Guava
Google GuavaGoogle Guava
Google Guava
 
Web Optimization Summit: Coding for Performance
Web Optimization Summit: Coding for PerformanceWeb Optimization Summit: Coding for Performance
Web Optimization Summit: Coding for Performance
 
Backbone intro
Backbone introBackbone intro
Backbone intro
 
Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System Design
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code Generation
 
iOS Memory Management Basics
iOS Memory Management BasicsiOS Memory Management Basics
iOS Memory Management Basics
 
Making Ajax Sexy, JSConf 2010
Making Ajax Sexy, JSConf 2010Making Ajax Sexy, JSConf 2010
Making Ajax Sexy, JSConf 2010
 
Making Ajax Sexy, JSConf 2010
Making Ajax Sexy, JSConf 2010Making Ajax Sexy, JSConf 2010
Making Ajax Sexy, JSConf 2010
 
Objective C Memory Management
Objective C Memory ManagementObjective C Memory Management
Objective C Memory Management
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
Omnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsOmnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the Things
 
Reflex - How does it work?
Reflex - How does it work?Reflex - How does it work?
Reflex - How does it work?
 
Building DSLs With Eclipse
Building DSLs With EclipseBuilding DSLs With Eclipse
Building DSLs With Eclipse
 
Drupal 8: Fields reborn
Drupal 8: Fields rebornDrupal 8: Fields reborn
Drupal 8: Fields reborn
 
Memory management in Objective C
Memory management in Objective CMemory management in Objective C
Memory management in Objective C
 
Backbone.js Simple Tutorial
Backbone.js Simple TutorialBackbone.js Simple Tutorial
Backbone.js Simple Tutorial
 
Extending javascript part one
Extending javascript part oneExtending javascript part one
Extending javascript part one
 
ES2015 workflows
ES2015 workflowsES2015 workflows
ES2015 workflows
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!
 

Similar to Attribute

Get started with YUI
Get started with YUIGet started with YUI
Get started with YUIAdam Lu
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntityBasuke Suzuki
 
Functional Core, Reactive Shell
Functional Core, Reactive ShellFunctional Core, Reactive Shell
Functional Core, Reactive ShellGiovanni Lodi
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldChristian Melchior
 
fuser interface-development-using-jquery
fuser interface-development-using-jqueryfuser interface-development-using-jquery
fuser interface-development-using-jqueryKostas Mavridis
 
ITB2019 RuleBox : The natural rule engine for CFML - Luis Majano
ITB2019 RuleBox : The natural rule engine for CFML - Luis MajanoITB2019 RuleBox : The natural rule engine for CFML - Luis Majano
ITB2019 RuleBox : The natural rule engine for CFML - Luis MajanoOrtus Solutions, Corp
 
RuleBox : A natural language Rule Engine
RuleBox : A natural language Rule EngineRuleBox : A natural language Rule Engine
RuleBox : A natural language Rule EngineOrtus Solutions, Corp
 
User Interface Development with jQuery
User Interface Development with jQueryUser Interface Development with jQuery
User Interface Development with jQuerycolinbdclark
 
Appengine Java Night #2a
Appengine Java Night #2aAppengine Java Night #2a
Appengine Java Night #2aShinichi Ogawa
 
Lezhin kotlin jetbrain
Lezhin kotlin jetbrainLezhin kotlin jetbrain
Lezhin kotlin jetbrainMyeongin Woo
 
Client-side MVC with Backbone.js (reloaded)
Client-side MVC with Backbone.js (reloaded)Client-side MVC with Backbone.js (reloaded)
Client-side MVC with Backbone.js (reloaded)iloveigloo
 
Client-side MVC with Backbone.js
Client-side MVC with Backbone.js Client-side MVC with Backbone.js
Client-side MVC with Backbone.js iloveigloo
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgetsscottw
 
appengine java night #1
appengine java night #1appengine java night #1
appengine java night #1Shinichi Ogawa
 
Max Koretskyi "Why are Angular and React so fast?"
Max Koretskyi "Why are Angular and React so fast?"Max Koretskyi "Why are Angular and React so fast?"
Max Koretskyi "Why are Angular and React so fast?"Fwdays
 
Lecture 03 - JQuery.pdf
Lecture 03 - JQuery.pdfLecture 03 - JQuery.pdf
Lecture 03 - JQuery.pdfLê Thưởng
 
Connect.Tech- Swift Memory Management
Connect.Tech- Swift Memory ManagementConnect.Tech- Swift Memory Management
Connect.Tech- Swift Memory Managementstable|kernel
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsJarod Ferguson
 

Similar to Attribute (20)

Get started with YUI
Get started with YUIGet started with YUI
Get started with YUI
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntity
 
Functional Core, Reactive Shell
Functional Core, Reactive ShellFunctional Core, Reactive Shell
Functional Core, Reactive Shell
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected World
 
fuser interface-development-using-jquery
fuser interface-development-using-jqueryfuser interface-development-using-jquery
fuser interface-development-using-jquery
 
ITB2019 RuleBox : The natural rule engine for CFML - Luis Majano
ITB2019 RuleBox : The natural rule engine for CFML - Luis MajanoITB2019 RuleBox : The natural rule engine for CFML - Luis Majano
ITB2019 RuleBox : The natural rule engine for CFML - Luis Majano
 
RuleBox : A natural language Rule Engine
RuleBox : A natural language Rule EngineRuleBox : A natural language Rule Engine
RuleBox : A natural language Rule Engine
 
User Interface Development with jQuery
User Interface Development with jQueryUser Interface Development with jQuery
User Interface Development with jQuery
 
Jpa
JpaJpa
Jpa
 
Appengine Java Night #2a
Appengine Java Night #2aAppengine Java Night #2a
Appengine Java Night #2a
 
Lezhin kotlin jetbrain
Lezhin kotlin jetbrainLezhin kotlin jetbrain
Lezhin kotlin jetbrain
 
Client-side MVC with Backbone.js (reloaded)
Client-side MVC with Backbone.js (reloaded)Client-side MVC with Backbone.js (reloaded)
Client-side MVC with Backbone.js (reloaded)
 
Client-side MVC with Backbone.js
Client-side MVC with Backbone.js Client-side MVC with Backbone.js
Client-side MVC with Backbone.js
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgets
 
appengine java night #1
appengine java night #1appengine java night #1
appengine java night #1
 
jQuery
jQueryjQuery
jQuery
 
Max Koretskyi "Why are Angular and React so fast?"
Max Koretskyi "Why are Angular and React so fast?"Max Koretskyi "Why are Angular and React so fast?"
Max Koretskyi "Why are Angular and React so fast?"
 
Lecture 03 - JQuery.pdf
Lecture 03 - JQuery.pdfLecture 03 - JQuery.pdf
Lecture 03 - JQuery.pdf
 
Connect.Tech- Swift Memory Management
Connect.Tech- Swift Memory ManagementConnect.Tech- Swift Memory Management
Connect.Tech- Swift Memory Management
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 

More from Luke Smith

Promises. The basics, from Promises/A+
Promises. The basics, from Promises/A+Promises. The basics, from Promises/A+
Promises. The basics, from Promises/A+Luke Smith
 
Inheritance patterns
Inheritance patternsInheritance patterns
Inheritance patternsLuke Smith
 
Debugging tips in YUI 3
Debugging tips in YUI 3Debugging tips in YUI 3
Debugging tips in YUI 3Luke Smith
 
YUI 3: Events Evolved
YUI 3: Events EvolvedYUI 3: Events Evolved
YUI 3: Events EvolvedLuke Smith
 
YUI 3 quick overview
YUI 3 quick overviewYUI 3 quick overview
YUI 3 quick overviewLuke Smith
 
YUI 3: Below the Surface
YUI 3: Below the SurfaceYUI 3: Below the Surface
YUI 3: Below the SurfaceLuke Smith
 
Front end engineering, YUI Gallery, and your future
Front end engineering, YUI Gallery, and your futureFront end engineering, YUI Gallery, and your future
Front end engineering, YUI Gallery, and your futureLuke Smith
 

More from Luke Smith (9)

Promises. The basics, from Promises/A+
Promises. The basics, from Promises/A+Promises. The basics, from Promises/A+
Promises. The basics, from Promises/A+
 
Inheritance patterns
Inheritance patternsInheritance patterns
Inheritance patterns
 
Hack with YUI
Hack with YUIHack with YUI
Hack with YUI
 
Debugging tips in YUI 3
Debugging tips in YUI 3Debugging tips in YUI 3
Debugging tips in YUI 3
 
YUI 3: Events Evolved
YUI 3: Events EvolvedYUI 3: Events Evolved
YUI 3: Events Evolved
 
YUI 3 quick overview
YUI 3 quick overviewYUI 3 quick overview
YUI 3 quick overview
 
YUI 3: Below the Surface
YUI 3: Below the SurfaceYUI 3: Below the Surface
YUI 3: Below the Surface
 
Yui3
Yui3Yui3
Yui3
 
Front end engineering, YUI Gallery, and your future
Front end engineering, YUI Gallery, and your futureFront end engineering, YUI Gallery, and your future
Front end engineering, YUI Gallery, and your future
 

Attribute

  • 1.
  • 3. You know this stuff model.get(“id”); overlay.set(“visible”, true); var drag = new Y.DD.Drag({ node: “#dragme” });
  • 4. You know this stuff Bakery.ATTRS = { flour: { value: “pastry” }, ... };
  • 5. What is an attribute? Encapsulation of a value state and set of feature configurations for customizing logic associated with the mutation and storage of that state, while providing opportunities to monitor changes.
  • 6. What is an attribute? Object property + magic
  • 7. The magic • What it is • Why we need it • Where it comes from • How it works • What it costs • Is it worth it?
  • 8. The magic • What it is • Why we need it • Where it comes from • How it works • What it costs • “Should I use a property or an attribute?”
  • 9. What is the magic?
  • 10. What is the magic? • getters • setters • default values • change events
  • 11. ES5 has magic Object.defineProperties(this, { flour: { value: “pastry”, getter: ... setter: ... ...
  • 12. ES5 has magic ... except IE6 IE7 IE8
  • 13. ES5 has magic ... except IE6 IE7 IE8 * Dear old IE, please die in a fire.
  • 14. So, here we are obj.get(“attr”); obj.set(“attr”, “I’m needed, thanks IE!”);
  • 15. Why do we want magic?
  • 16. Why do we want magic? Properties are dumb
  • 17. Why do we want magic? 1. Properties are dumb 2. Maintenance
  • 18. Where is the magic?
  • 19. The Classes (all the things) Y.Base
  • 20. The Classes (all the things) Y.Base Y.BaseCore Y.BaseObservable Y.AE
  • 21. The Classes (all the things) Y.Base Y.BaseCore Y.BaseObservable Y.AE Y.AttributeCore Y.AttributeObservable
  • 22. The Classes (all the things) Y.Base Y.BaseCore Y.BaseObservable Y.AE Y.AttributeCore Y.AttributeObservable Y.State Y.EventTarget
  • 23. The Modules (all the things) base base-core base-observable a-extras attribute-core attribute-observable (attribute-core) event-custom-complex
  • 24. The Modules (all the things) base base-core base-observable a-extras Y.AttributeCore attribute-core Y.AttributeObservable attribute-observable (attribute-core) event-custom-complex
  • 25. The Modules Y.AttributeCore Y.AttributeObservable attribute-core attribute-observable
  • 27. Y.AttributeCore Class.ATTRS = { configs }; // sort of obj.addAttr(name, { config }, lazy?); obj.addAttrs({ configs }, { values }, lazy?); obj.attrAdded(name);
  • 29. Creating attributes One at a time bakery.addAttr(“flour”, { setter: “_setFlour”, value: “whole wheat” });
  • 30. Creating attributes A bunch at a time bakery.addAttrs({ flour: { setter: “_setFlour”, value: “whole wheat” }, ... });
  • 31. Creating attributes Statically for a class Bakery.ATTRS = { flour: { setter: “_setFlour”, value: “whole wheat” } });
  • 32. How does the magic work?
  • 33. Configurations • value • valueFn • getter • validator • setter • readOnly • writeOnce • lazyAdd http://yuilibrary.com/yui/docs/attribute/#configuration
  • 34. Configurations • value • valueFn • broadcast • getter • validator • cloneDefaultValue • setter • readOnly • writeOnce • lazyAdd http://yuilibrary.com/yui/docs/attribute/#configuration
  • 35. value and valueFn • Most expensive • lazyAdd = true to defer cost • valueFn always called at instantiation
  • 36. lazyAdd • Minimal setup, no set() • Full setup on first call to get() or set() • Some might never get fully setup (good) • Y.BaseCore defaults lazyAdd = true for all (override with prototype._lazyAddAttrs) • Beware lazyAdd + setter
  • 37. setter for robustness • Use for a) Input normalization, or b) Tightly coupled state related logic • Not for side effects (use events) • setter + lazyAdd gotcha
  • 38. setter vs validator • validator is called before setter • If you have a setter, validate inline _setFlour: function (val) { return (typeof val === “string”) ? val.toLowerCase() : Y.Attribute.INVALID_VALUE;
  • 39. getter, setter, etc • Pass string values to late bind handlers flour: { setter : “_setFlour” // this._setFlour(val) getter : “_getFlour”, validator: “_validateFlour”, valueFn : “_initFlour”,
  • 40. cloneDefaultValue • {undefined, true, “deep”}, “shallow”, false • Y.Base defaults Y.clone() behavior • Always set or use a valueFn instead flour: { value: { grain: ‘fine’, gluten: false, ... }, cloneDefaultValue: true,
  • 41. Change events • For decoupling systems • Why custom events have on() and after() • Assigning initial value does NOT fire event • Change event published on first set()
  • 42. Ad hoc attributes • From Y.BaseCore • Create dynamic objects with Attribute API • prototype._allowAdHocAttrs = true • static _NON_ATTRS_CFG to blacklist
  • 43. Ad hoc attributes Bakery.prototype._allowAdHocAttrs = true; var llamaBakery = new Bakery({ flour: “pastry”, llamas: “sheared” // unknown, but added });
  • 44. What does the magic cost?
  • 45. Magic taxes 1. Attribute setup cost 2. get()/set() cost *Many Bothans died to bring us this information
  • 48. Attribute setup 1. Creates State object 2. Depth 2 copy of configs
  • 49. Attribute setup 1. Creates State object 2. Depth 2 copy of configs 3. Gets value from construction values, valueFn, or value
  • 50. Attribute setup 1. Creates State object 2. Depth 2 copy of configs 3. Gets value from construction values, valueFn, or value 4. lazyAdd attributes are stowed in State
  • 51. Attribute setup 1. Creates State object 2. Depth 2 copy of configs 3. Gets value from construction values, valueFn, or value 4. lazyAdd attributes are stowed in State 5. non-lazy populate State and set(value)
  • 52. Attribute setup LOC fn calls no attributes 34 9 +lazy attr +46 +14 +empty attr +56 +16 +attr property +7 +0 +value +80 +20 +valueFn +3 +1
  • 54. Base setup 1. Creates State object
  • 55. Base setup 1. Creates State object 2. Aggregates ATTRS up superclass chain
  • 56. Base setup 1. Creates State object 2. Aggregates ATTRS up superclass chain 3. for each class call...
  • 57. Base setup 1. Creates State object 2. Aggregates ATTRS up superclass chain 3. for each class call... 1. class extension constructors
  • 58. Base setup 1. Creates State object 2. Aggregates ATTRS up superclass chain 3. for each class call... 1. class extension constructors 2. addAttrs with filtered list from ATTRS aggregate
  • 59. Base setup 1. Creates State object 2. Aggregates ATTRS up superclass chain 3. for each class call... 1. class extension constructors 2. addAttrs with filtered list from ATTRS aggregate 3. initializer
  • 60. Base setup 1. Creates State object 2. Aggregates ATTRS up superclass chain 3. for each class call... 1. class extension constructors 2. addAttrs with filtered list from ATTRS aggregate 3. initializer 4. class extension initializers
  • 61. Base setup 1. Creates State object 2. Aggregates ATTRS up superclass chain 3. for each class call... 1. class extension constructors 2. addAttrs with filtered list from ATTRS aggregate 3. initializer 2.5. addAttrs(ad-hocs) 4. class extension initializers
  • 62. get() 1. Checks if attribute is lazy, inits if necessary 2. Gets the value and getter from State 3. Returns value or result of calling getter
  • 63. get() LOC fn calls get(attr) 10 6 get(sub.attr) +3 +5 +getter +2 +1 +lazy init +100 +20
  • 65.
  • 66. set() - just attribute LOC fn calls set(attr) 80 20 set(sub.attr) +27 +4 +lazy init +100 +20 +validator +5 +1 +setter +6 +1
  • 67. set() - events LOC fn calls set(attr) 80 20 set(sub.attr) +27 +4 +change event +151 +24 +first event +100 +12 +per subscriber +27 +5 +per bubble +205 +21
  • 68. Avoid Subattributes obj.set(“nested.sub.attribute”, false); • Triggered by . in attribute name • A lot of extra work, most is wasted • Confusing relationship with getter/setter * sorry about this
  • 69. Is the magic worth it? Should you use a property or an attribute?
  • 70. Property PROs CONs • Fast • Dumb • Terse • Can’t migrate to attribute w/o API • Nested structs are breakage the same • Magic allowed if environment mandated
  • 71. Attribute PROs CONs • Stable abstraction • Slow • Code organization • Nested structs are awkward • Consistent API (subattributes--) • Easy loose coupling • More typing with events • Abstraction performance can improve invisibly
  • 72. Property or Attribute? • Will it be accessed a lot? Like, really A LOT. • Will there be lots of instances? (see #1) • Will it be public, or interesting outside the object? • Might the class be extended? Plugged? • Would it amount to a micro-optimization?
  • 73. Property or Attribute? Justify the use of properties rather than justifying the use of attributes (It’s less likely to bite you in the ass)
  • 75. Attribute PROs CONs • Stable abstraction • Slow • Code organization • Nested structs are awkward • Consistent API (subattributes--) • Easy loose coupling • More typing with events • Abstraction performance can improve invisibly
  • 76. Faster; no new features
  • 77. Faster; no new features • Replace State with ES5 objects or shim
  • 78. Faster; no new features • Replace State with ES5 objects or shim • Compile configs once for all instances
  • 79. Faster; no new features • Replace State with ES5 objects or shim • Compile configs once for all instances • Event optimizations
  • 80. kittens + pancakes = future
  • 81. The End. Thanks! Luke Smith @ls_n

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. modeling DOM\n
  15. modeling DOM\n
  16. modeling DOM\n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. AttributeCore ATTRS less restrictive than Base\n
  37. \n
  38. \n
  39. \n
  40. \n
  41. You can also use obj.set(‘unknown’, val) and setAttrs({ ... }); but they will be magicless\n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. “Be conservative in what you send, liberal in what you accept”\nsetter code creep = serving multiple masters\n
  48. \n
  49. You can find this in the API docs, but I want to strongly recommend\n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. cloneDefaultValue for obj values during aggregation\naddAttrs() called with the aggregated configs for that class\naddAttrs() applies user values - Attribute ignores user values for unknown attrs\naddAttrs() calls Y.merge() on user value hash, so once for each level\n
  63. cloneDefaultValue for obj values during aggregation\naddAttrs() called with the aggregated configs for that class\naddAttrs() applies user values - Attribute ignores user values for unknown attrs\naddAttrs() calls Y.merge() on user value hash, so once for each level\n
  64. cloneDefaultValue for obj values during aggregation\naddAttrs() called with the aggregated configs for that class\naddAttrs() applies user values - Attribute ignores user values for unknown attrs\naddAttrs() calls Y.merge() on user value hash, so once for each level\n
  65. cloneDefaultValue for obj values during aggregation\naddAttrs() called with the aggregated configs for that class\naddAttrs() applies user values - Attribute ignores user values for unknown attrs\naddAttrs() calls Y.merge() on user value hash, so once for each level\n
  66. cloneDefaultValue for obj values during aggregation\naddAttrs() called with the aggregated configs for that class\naddAttrs() applies user values - Attribute ignores user values for unknown attrs\naddAttrs() calls Y.merge() on user value hash, so once for each level\n
  67. cloneDefaultValue for obj values during aggregation\naddAttrs() called with the aggregated configs for that class\naddAttrs() applies user values - Attribute ignores user values for unknown attrs\naddAttrs() calls Y.merge() on user value hash, so once for each level\n
  68. cloneDefaultValue for obj values during aggregation\naddAttrs() called with the aggregated configs for that class\naddAttrs() applies user values - Attribute ignores user values for unknown attrs\naddAttrs() calls Y.merge() on user value hash, so once for each level\n
  69. cloneDefaultValue for obj values during aggregation\naddAttrs() called with the aggregated configs for that class\naddAttrs() applies user values - Attribute ignores user values for unknown attrs\naddAttrs() calls Y.merge() on user value hash, so once for each level\n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. Similarly, if you capture the object returned from get(‘nested’), you can set its properties whenever.\n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. It’s not just a numbers game - maintenance, future proofing\n
  97. \n
  98. and remember, you’re talking about giving up all those yummy features\n
  99. \n
  100. \n
  101. result in the cost being replaced by kittens making you pancakes\n
  102. result in the cost being replaced by kittens making you pancakes\n
  103. result in the cost being replaced by kittens making you pancakes\n
  104. result in the cost being replaced by kittens making you pancakes\n
  105. \n
  106. \n