Upgrade to Pro — share decks privately, control downloads, hide ads and more …

When Not to Use YUI

Ryan Grove
November 15, 2012

When Not to Use YUI

Video: http://youtu.be/8cTz73zdDuc?hd=1

In this talk from YUIConf 2012, I provide code samples and real-world anecdotes to illustrate how to decide when to use YUI, when to use vanilla JavaScript, when to consider other libraries, and what the tradeoffs are in terms of performance and maintainability. Advice ranges from simple rules of thumb to more nuanced discussion of complex architectural decisions, with examples drawn from my time working on YUI at Yahoo! and using YUI at SmugMug.

Ryan Grove

November 15, 2012
Tweet

More Decks by Ryan Grove

Other Decks in Programming

Transcript

  1. Howdy!
    I’m Ryan Grove
    @yaypie on Twitter and ADN

    View full-size slide

  2. I used to work at

    View full-size slide

  3. I once modeled for a Japanese
    clothing catalog
    me

    View full-size slide

  4. Things I like:

    View full-size slide

  5. kittens
    movies with happy endings
    pie awesomeness
    JavaScript
    movies with sad endings
    the ocean
    not giving talks
    YUI
    driving really fast
    gadgets
    old-ass sailing ships
    coffee
    unit tests
    sleeping in
    Pocky
    thunderstorms

    View full-size slide

  6. kittens
    movies with happy endings
    pie awesomeness
    JavaScript
    movies with sad endings
    the ocean
    not giving talks
    driving really fast
    old-ass sailing ships
    gadgets
    coffee
    unit tests
    sleeping in
    Pocky
    thunderstorms
    YUI

    View full-size slide

  7. YUI
    When Not to Use

    View full-size slide

  8. A library makes hard or
    annoying tasks easier

    View full-size slide

  9. Libraries are awesome

    View full-size slide

  10. But a library shouldn’t try
    to do everything
    http://www.flickr.com/photos/justinbaeder/5318402022/

    View full-size slide

  11. A good library does
    one thing well
    http://www.flickr.com/photos/scttw/1335967584/

    View full-size slide

  12. Despite the name,
    YUI is a framework

    View full-size slide

  13. A framework is a
    collection of like-
    minded libraries

    View full-size slide

  14. Library == tool
    Framework == toolbox
    http://www.flickr.com/photos/caldwellian/504891328/

    View full-size slide

  15. Don’t try to use every tool
    in the toolbox
    http://www.flickr.com/photos/75905404@N00/7126147125/

    View full-size slide

  16. Don’t use a tool just
    because you have a tool
    http://www.flickr.com/photos/carlwain/3555650607/

    View full-size slide

  17. http://quibly.deviantart.com/art/Admiral-Ackbar-156351053

    View full-size slide

  18. Understand the
    tradeoffs

    View full-size slide

  19. Don’t be lazy
    http://www.flickr.com/photos/ggunson/21535407/

    View full-size slide

  20. Be curious
    http://www.flickr.com/photos/giaky88/4189310121/

    View full-size slide

  21. Don’t use YUI when
    vanilla JavaScript
    will do

    View full-size slide

  22. Enough philosophy.
    Let’s get real.
    The Matrix (1999), Warner Bros. Pictures

    View full-size slide

  23. Don’t use the following
    Y.Lang methods
    AVOID

    View full-size slide

  24. Y.Lang.isBoolean()
    Chrome 22 IE 9 Firefox 16 iOS 6
    1% slower 45% slower 9% slower 5% slower
    Compared to typeof value === ‘boolean’
    http://jsperf.com/y-lang-isboolean
    AVOID
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0

    View full-size slide

  25. Y.Lang.isFunction()
    Chrome 22 IE 9 Firefox 16 iOS 6
    58% slower 68% slower 64% slower 75% slower
    Compared to typeof value === ‘function’
    http://jsperf.com/y-lang-isfunction
    AVOID
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0

    View full-size slide

  26. Y.Lang.isNull()
    Chrome 22 IE 9 Firefox 16 iOS 6
    3% slower 48% slower 10% slower 3% slower
    Compared to value === null
    http://jsperf.com/y-lang-isnull
    AVOID
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0

    View full-size slide

  27. Y.Lang.isString()
    Chrome 22 IE 9 Firefox 16 iOS 6
    1% slower 49% slower 8% slower 6% slower
    Compared to typeof value === ‘string’
    http://jsperf.com/y-lang-isstring
    AVOID
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0

    View full-size slide

  28. Chrome 22 IE 9 Firefox 16 iOS 6
    0.4% slower 47% slower 7% slower 5% slower
    Y.Lang.isUndefined()
    Compared to typeof value === ‘undefined’
    http://jsperf.com/y-lang-isundefined
    AVOID
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0

    View full-size slide

  29. Chrome 22 IE 9 Firefox 16 iOS 6
    isBoolean()
    isFunction()
    isNull()
    isString()
    isUndefined()
    1% slower 45% slower 9% slower 5% slower
    58% slower 68% slower 64% slower 75% slower
    3% slower 48% slower 10% slower 3% slower
    1% slower 49% slower 8% slower 6% slower
    0.4% slower 47% slower 7% slower 5% slower

    View full-size slide

  30. Consider not using these
    Y.Lang methods:
    isNumber()
    isObject()
    caution

    View full-size slide

  31. These ones are cool:
    isArray()
    isDate()
    isValue()
    now()
    type()
    Okay!

    View full-size slide

  32. Y.instanceOf()
    Chrome 22 IE 9 Firefox 16 iOS 6
    26% slower 58% slower 53% slower 49% slower
    Compared to the instanceof operator
    http://jsperf.com/y-instanceof
    AVOID
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0

    View full-size slide

  33. Let’s go after the big fish
    Jaws (1975), Universal Studios

    View full-size slide

  34. Y.Base
    caution

    View full-size slide

  35. Y.Base
    caution
    •Initializer/destructor lifecycle
    •Y.Attribute
    •Y.EventTarget
    •Attribute aggregation

    View full-size slide

  36. Y.Base.create()
    caution
    Y.Base.create('myClass', Y.Base, [...], {
    ...
    }, {
    ...
    });

    View full-size slide

  37. Chrome 22 IE 9 Firefox 16 iOS 6
    99.7% slower 99.6% slower 99.9% slower 99.8% slower
    Y.Base vs. vanilla JS
    Comparing instantiation speed
    http://jsperf.com/y-base
    caution
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0

    View full-size slide

  38. Y.Base vs. vanilla JS
    Comparing instantiation speed (ops/sec)
    http://jsperf.com/y-base
    caution
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0
    Chrome 22 IE 9 Firefox 16 iOS 6
    Y.Base
    vanilla JS
    10,924 2,323 6,196 1,717
    4,013,182 544,036 8,189,437 713,684

    View full-size slide

  39. caution
    •~2,040 bytes per Y.Base instance
    •1,000 Y.Base instances: ~1.9MB
    •~12 bytes per vanilla JS instance
    •1,000 vanilla instances: ~11.7KB
    Y.Base memory usage

    View full-size slide

  40. You may be using Y.Base
    without realizing it

    View full-size slide

  41. Y.Anim
    Y.App
    Y.AutoComplete
    Y.Button
    Y.Cache
    Y.Calendar
    Y.DataSource.*
    Y.DataTable
    Y.DD.*
    Y.Dial
    Y.EditorBase
    Y.LazyModelList
    Y.Model
    Y.ModelList
    Y.Overlay
    Y.Panel
    Y.Pjax
    Y.Record
    Y.Recordset
    Y.Resize
    Y.Router
    Y.ScrollView
    Y.Slider
    Y.Sortable
    Y.Tab
    Y.TabView
    Y.ToggleButton
    Y.Uploader
    Y.View
    Y.Widget
    Y.WidgetParent
    Y.WidgetChild

    View full-size slide

  42. •When you need attributes
    •...and events
    •...and an initializer/destructor lifecycle
    •...and extensions
    When is Y.Base worth using?

    View full-size slide

  43. Use only what you need

    View full-size slide

  44. Consider how many
    instances you’ll be
    creating

    View full-size slide

  45. Be careful with
    Y.Model and Y.View
    caution

    View full-size slide

  46. Case study:
    SmugMug Search

    View full-size slide

  47. Not so fast...

    View full-size slide

  48. My God, it’s full of
    models and views
    2001: A Space Odyssey (1968), MGM Studios

    View full-size slide

  49. Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View
    Model +
    View

    View full-size slide

  50. http://www.flickr.com/photos/koskisuomi/1453645876/
    Don’t forget about users
    with old, slow machines

    View full-size slide

  51. Memory leaks suck
    http://www.flickr.com/photos/vrogy/511644410/

    View full-size slide

  52. One view to rule them all

    View full-size slide

  53. •Throttled scroll event handlers
    •Efficiently-computed scroll metrics
    •Convenient events for actions like
    scrollToBottom and scrollToTop
    Y.Plugin.ScrollInfo
    http://yuilibrary.com/yui/docs/api/classes/Plugin.ScrollInfo.html

    View full-size slide

  54. Remodeling Model

    View full-size slide

  55. • Same API as ModelList
    • Contains vanilla JavaScript objects instead
    of Model instances
    • revive() and free() Model instances as
    needed
    Y.LazyModelList
    http://yuilibrary.com/yui/docs/model-list/#lazymodellist

    View full-size slide

  56. SmugMug Search benchmarks
    Before After
    Time to initial results
    Initial memory usage
    Time to manually scroll to
    1,000 results
    Memory usage after
    1,000 results
    1,410ms 950ms (33% faster)
    8.26MB 7.23MB (12% less)
    30s 22s (27% faster)
    42.82MB 15.64MB (63% less)

    View full-size slide

  57. This got me thinking...

    View full-size slide

  58. •Y.Lang.sub() doesn’t do enough
    •Y.Handlebars is often overkill
    •Underscore templates were just right
    Templating

    View full-size slide

  59. Y.Handlebars Underscore Y.Template.Micro
    Render
    Compile & Render
    146,446 ops/s 197,123 ops/s 205,716 ops/s
    4,501 ops/s 28,966 ops/s 36,737 ops/s
    Y.Template.Micro vs. others
    http://jsperf.com/y-template-vs-others/6
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2

    View full-size slide

  60. Y.TreeView
    A victim of the YUI Way

    View full-size slide

  61. Y.Tree
    Extends Y.Base

    View full-size slide

  62. Y.Tree
    Extends Y.Base
    Y.Tree.Node
    Vanilla JS constructor

    View full-size slide

  63. Y.Tree
    Extends Y.Base
    Y.Tree.Node
    Vanilla JS constructor
    Y.TreeView
    Extends Y.View

    View full-size slide

  64. Y.Menu
    Building on lessons learned

    View full-size slide

  65. Brainstorm!
    Brainstorm (1983), MGM Studios

    View full-size slide

  66. •Native ECMAScript 5 feature
    •Supported by all modern browsers
    •Getters/setters
    •Read-only properties
    •Super cheap vs. Y.Attribute
    Object.defineProperty()

    View full-size slide

  67. Y.Property vs. Y.Attribute
    Comparing instantiation speed (ops/sec) of base classes
    http://jsperf.com/y-property-vs-y-attribute/4
    Benchmarked on a Mac Pro, 2.8GHz quad-core Xeon, 16 GB RAM, OS X 10.8.2
    and an iPhone 4S, iOS 6.0
    Chrome 22 IE 9 Firefox 16 iOS 6
    Y.Attribute
    Y.Property
    22,919 7,140 15,669 4,794
    56,222
    145% faster
    48,276
    576% faster
    110,163
    603% faster
    28,508
    495% faster

    View full-size slide

  68. Coming soon to a YUI near you?
    Maybe. Until then:
    https://github.com/smugmug/yui3

    View full-size slide

  69. Breaking out of YUI
    The Shawshank Redemption (1994), Castle Rock Entertainment

    View full-size slide

  70. YUI isn’t a religion

    View full-size slide

  71. Micro-(libraries|frameworks)
    to the rescue

    View full-size slide

  72. But what about
    dependency management?

    View full-size slide

  73. Just use YUI Loader

    View full-size slide

  74. YUI({
    groups: {
    'cdnjs': {
    base: '//cdnjs.cloudflare.com/ajax/libs',
    modules: {
    xregexp: {
    path: '/xregexp/2.0.0/xregexp-min.js'
    }
    }
    }
    },
    onProgress: function (e) {
    if (e.data[0].name === 'xregexp') {
    YUI.add('xregexp', function (Y) {
    Y.XRegExp = XRegExp;
    });
    }
    }
    }).use('xregexp', function (Y) {
    console.log('xregexp is now available at Y.XRegExp');
    });

    View full-size slide

  75. YUI({
    groups: {
    'cdnjs': {
    base: '//cdnjs.cloudflare.com/ajax/libs',
    modules: {
    xregexp: {
    path: '/xregexp/2.0.0/xregexp-min.js'
    }
    }
    }
    },
    onProgress: function (e) {
    if (e.data[0].name === 'xregexp') {
    YUI.add('xregexp', function (Y) {
    Y.XRegExp = XRegExp;
    });
    }
    }
    }).use('xregexp', function (Y) {
    console.log('xregexp is now available at Y.XRegExp');
    });

    View full-size slide

  76. YUI({
    groups: {
    'cdnjs': {
    base: '//cdnjs.cloudflare.com/ajax/libs',
    modules: {
    xregexp: {
    path: '/xregexp/2.0.0/xregexp-min.js'
    }
    }
    }
    },
    onProgress: function (e) {
    if (e.data[0].name === 'xregexp') {
    YUI.add('xregexp', function (Y) {
    Y.XRegExp = XRegExp;
    });
    }
    }
    }).use('xregexp', function (Y) {
    console.log('xregexp is now available at Y.XRegExp');
    });

    View full-size slide

  77. YUI({
    groups: {
    'cdnjs': {
    base: '//cdnjs.cloudflare.com/ajax/libs',
    modules: {
    xregexp: {
    path: '/xregexp/2.0.0/xregexp-min.js'
    }
    }
    }
    },
    onProgress: function (e) {
    if (e.data[0].name === 'xregexp') {
    YUI.add('xregexp', function (Y) {
    Y.XRegExp = XRegExp;
    });
    }
    }
    }).use('xregexp', function (Y) {
    console.log('xregexp is now available at Y.XRegExp');
    });

    View full-size slide

  78. YUI({
    groups: {
    'cdnjs': {
    base: '//cdnjs.cloudflare.com/ajax/libs',
    modules: {
    xregexp: {
    path: '/xregexp/2.0.0/xregexp-min.js'
    }
    }
    }
    },
    onProgress: function (e) {
    if (e.data[0].name === 'xregexp') {
    YUI.add('xregexp', function (Y) {
    Y.XRegExp = XRegExp;
    });
    }
    }
    }).use('xregexp', function (Y) {
    console.log('xregexp is now available at Y.XRegExp');
    });

    View full-size slide

  79. YUI({
    groups: {
    'cdnjs': {
    base: '//cdnjs.cloudflare.com/ajax/libs',
    modules: {
    xregexp: {
    path: '/xregexp/2.0.0/xregexp-min.js'
    }
    }
    }
    },
    onProgress: function (e) {
    if (e.data[0].name === 'xregexp') {
    YUI.add('xregexp', function (Y) {
    Y.XRegExp = XRegExp;
    });
    }
    }
    }).use('xregexp', function (Y) {
    console.log('xregexp is now available at Y.XRegExp');
    });

    View full-size slide

  80. YUI wants you to
    succeed

    View full-size slide

  81. Be pragmatic

    View full-size slide

  82. Read the source

    View full-size slide

  83. Be loyal to your users,
    not your tools

    View full-size slide

  84. Thank you!
    @yaypie on Twitter and ADN
    rgrove on GitHub & Freenode
    https://speakerdeck.com/yaypie/when-not-to-use-yui

    View full-size slide