SlideShare ist ein Scribd-Unternehmen logo
1 von 78
Downloaden Sie, um offline zu lesen
Hardcore
                              JavaScript
                              Write it Right
      By     Mike Wilcox
      February 2013


Wednesday, February 6, 2013
Readable Code
    here(will make that book very
    |resistånt to pressure| to read.)

    there(isn’t explained properly)

    !bad Code is. like-a-book THATis badly formatted no
    indentation. incorrect punctuation misspelled words
    improper capitalizedation-ed. Or uneven.

    ?LINE HEIGHTS here() If “the” names of the char.acters
    start. Chang'ing, you dunno. where they are. && you+re
    not sure – WHAT they... are do-ing because it there(), the
    book w'ill bee pretty-difficult to [comprehend].

Wednesday, February 6, 2013
What do I know??




         me

                                        s Cro ckford
                              D o ug la

Wednesday, February 6, 2013
What do I know??




    Brend                          me
                        an Eic
                               h


Wednesday, February 6, 2013
What do I know??
      Seriously…

      Being a Dojo Committer means not only having
      your code and style scrutinized by know-it-all
      prima donnas, open source experts, but your
      results also get used by thousands of hacks
      that expect magic developers who
      expect quality code.




Wednesday, February 6, 2013
This code sucks!
      onPlayerParams = function(dfd){
      ! dfd = dfd || new this.Deferred();
      ! var o, p;
      ! if(scriptNode && scriptNode.getAttribute("config")){
      ! ! p = this.fixParams(scriptNode.getAttribute("config"));
      ! ! p.swf = this.root + "player.swf";
      ! }else if(this.embed()){
      ! ! var parts = this.embed().getAttribute("src").split("?");
      ! ! o = this.strToObj(parts[1]);
      ! ! o.swf = parts[0];
      ! ! p = this.fixParams(o);
      ! }else if(!this.domReady){
      ! ! this.ready(this, function(){
      ! ! ! this.onPlayerParams(dfd);
      ! ! }, true);
      ! ! if(!p) return dfd;
      !}
      ! if(p && p.vast){b.vast.parser.getXml(p.vast);}
      ! return dfd;
      }


Wednesday, February 6, 2013
Our Excuses
                                We
                                                     The
                           can always go
                                               project manager
                        back and fix it later
                                                needs this now




                                                                     *I*
                                                                 can read it

             No
          time for
         comments




                       It                                             My
                 was like that                                   sloppy code
                when I started.                                   means job
                                                                   security!




Wednesday, February 6, 2013
JavaScript
                                    guide
                                            Style


Wednesday, February 6, 2013
Formatting
    Formatting must be consistent. Otherwise little
    distractions make the code noisy and that much harder
    to read.
      var foo=”bar”+‘beer’+”bob”;
      for(var i=0;i<arguments.length;i++){}
      if(a&&b&&c&&d)return a;




Wednesday, February 6, 2013
Formatting
    Use single quotes, use spaces liberally, don’t use tiny,
    cryptic variable names and declare all variables at the
    beginning of the block.
      var foo = ‘bar’ + ‘beer’ + ‘bob’;

      var i;
      for( i = 0; i < arguments.length; i++ ){}

      var
        apples = true,
        bananas = true,
        coconuts = true;

          if( apples && bananas && coconuts ){
            return true;
          }
Wednesday, February 6, 2013
Typical Guides
                Indentation tabs not spaces

                Spacing / whitespace

                Curly braces rules

                variable naming conventions
                                                    Don’t be afraid of white space.

                method naming conventions
                                                            No Dojo
                Case: upper, lower, camel, Pascal
                                                           neces sar y!
                Dojo Style Guide

                http://dojotoolkit.org/community/styleGuide
Wednesday, February 6, 2013
JSLint / JSHint
                Is it automated into your build?

                It’s not just a suggestion - listen to it!

                It’s more than to help you find errors

                Helps promote consistency between devs

                Prevents unintended consequences

                If the linter thinks your code is ambiguous, so will
                other devs

                Helps you target JIT compilers, resulting in faster
                code
Wednesday, February 6, 2013
Comments




Wednesday, February 6, 2013
Comments                         Why the hell did I
                                       write that??
    OS comments vs production
    comments

    short descriptions
                              Future
    save the lazy crap         Self
    No comments is like a book
    without chapters or page
    numbers

    They aren’t just for your boss
    or your replacement

Wednesday, February 6, 2013
Levels of Documenting
          1. Verbose comments on every method and module,
             README and Wiki, instructions for setup and usage,
             guides to the software and how to edit it

          2.Comments on most methods and modules, README
            with instructions for setup and a guide to what
            modules do

          3.Brief comments on most methods and modules,
            README with instructions for setup

          4.Unfinished code



Wednesday, February 6, 2013
The Myth
    You think your code is self documenting, huh? This is not
    self documenting:
      setCommand = function(c){ this.cmds.push(c); }
      run = function(){ … }




    This looks more like self documenting:
      setListItemsWithDescritionsButNoThumbnails = function( … ){
        this.listItemDescriptions = listItemDescriptionsArgument;
      }
      renderItemsWhichIsCalledAfterEveryPageResize = function(){ … }




Wednesday, February 6, 2013
The Myth
    What your self documenting code would look like:
       setListItemsWithDescritionsButNoThumbnails = function( … ){
         if(!this.itemsSetBoolenPreventSecondAttempt){
           this.itemsSetBoolenPreventSecondAttempt = true;
           this.listItemDescriptions = listItemDescriptionsArgument;
           this.renderItemsWhichIsCalledAfterEveryPageResize();
           this.onAfterRenderFunctionalStubEvent();
         }




   “Good clean code requires very consistent and good naming
    conventions that are concise, and which don't attempt to
                 embody an extended purpose”
                              https://www.ibm.com/developerworks/mydeveloperworks/blogs/StylishGeek/entry/
                                     bloated_names_and_the_myth_of_self_documenting_code11?lang=en

Wednesday, February 6, 2013
Don’t be that guy
                                                     When a dev writes crap
    Comment quality matters                          like this, I want to
           function setParams(params){               paint him with meat
                                                     paste and drop him on a
           ! // sets params
                                                     mound of fire ants
           }
           function setVideo(video){
           ! // set video
           }




           function setParams(params){
           ! // sets parameters based on config property
           ! // from script tag
           }
           function setVideo(videoPath){
           ! // Sets the path for the video object
           }

Wednesday, February 6, 2013
Properties




Wednesday, February 6, 2013
Naming Conventions
                Should be camel case

                Upper case

                Whole names, no abbreviations
                       This isn’t your father’s code. We have minifiers and gzip
                       now. Use names we understand!

                       Exceptions for long or often used names: err for error,
                       dfd for deferred, prop for property, app for application,
                       etc.

                       i, k, j, etc, okay for iterators


Wednesday, February 6, 2013
Property Bags
                Multiple arguments (more than 3) are difficult to
                manage
                       An single argument as an object of options allows any or
                       all properties to be passed without concern of method
                       signature

                Mixins allow for simple setting

                Works with super constructors




Wednesday, February 6, 2013
ARG-uments
      function Widget(node, name, description, color, size){
         this.node = node;
         this.name = name || “Untitled”;
         this. description = description || “”;
         this.color = color || “#FF0000”;
         this.size = size || 100;
         this.code = “makes me sad”;
      }
      new Widget({});




Wednesday, February 6, 2013
Property Bag Example
      function Widget( options ){
         util.mixin( this, options ); // Done!
      }



    Even better is to set defaults and use a mixin that only
    overwrites and does not add undefined properties
      var Widget = declare{
          name:‘Untitled’,
          description:’’,
          color:’#FF0000’,
          size:100,
          constructor: function( options ){
             util.mixin(this, options); // Done!
          }
      }

Wednesday, February 6, 2013
getters & setters
    Initialization
      var object = {
      ! _x: 7,
      ! get x() { return this.x + 1; },
      ! set x( arg ) { this.x = arg / 2; }
      };


    After creation
      object.__defineGetter__("b", function() { return this.a + 1; });
      object.__defineSetter__("c", function(x) { this.a = x / 2; });



    ES5 getters and setters are still not widely used due to IE8. There are
    also issues as far as how inheritance would work. The super keyword is
    still in proposal.


Wednesday, February 6, 2013
ES3 getters & setters
    Initialization
      var object = {
      ! x: 7,
      ! get: function( key ) { return this[ key ]; },
      ! set: function( key, value ) { this[ key ] = value; }
      };


    This is a very common and standardized pattern, even
    used in Node.js (Mongoose). It works with most library
    inheritance patterns.




Wednesday, February 6, 2013
Observers & Watchers
      object.watch( 'x', function( value ){
      ! moveObject( x );
      });

      object.observe( 'x', function( value ){
      ! moveObject( x );
      });


    watch() is only available on Gecko with warnings of
    performance penalties. observe() is still an ES6
    proposal.

    Common solution is to simply connect to widget.set
    method with aspect.after.


Wednesday, February 6, 2013
Binding
      <div class='Widget'>
      ! <span data-bind='name'></name>
      </div>

      Widget = declare({
      ! name:'Untitled',
      ! set: function( key, value ){
      ! ! this[ key ] = value;
      ! ! if( this.bindings[ key ] ){
      ! ! ! this.bindings[ key ].innerHTML = value;
      !! }
      !}
      });

      new Widget({ name: 'Bob' });

    This common pattern is the key to all of these trendy MVC
    frameworks.
Wednesday, February 6, 2013
Functions and Methods




Wednesday, February 6, 2013
Naming Conventions
                Camel case

                Pascal case for constructors (Classes)

                Should be verbs

    getItems, setName, build, Widget, etc




Wednesday, February 6, 2013
Ambivalence
      function                process(){}
      function                state(){}
      function                command(){}
      function                structure(){}


               Those are not verbs.

               process could be to perform operations or a series
               of steps

               state could be to state your name, or the current
               application state

               It’s not obvious what any of these do and they
               should at least be commented

Wednesday, February 6, 2013
Side Effects
   While side effects are not forbidden, you should
   still consider the consequences
     function setImageProperties(){
        image.width = 320;
        image.height = 240;
        image.x = 100;
        image.y = 10;
        image.opacity = 0.9;
        updateImage();
        killPuppy();
     }


     Can you spot the side effect?

Wednesday, February 6, 2013
Monolithic Functions
                                                                     1970 called and wants their
      fixParams = function(o){
      ! var _vid = o.videoId || o.vid || o.siteId || "";
      ! if(/,/.test(_vid)){
      ! !
      ! !
              o.media = [];
              o.mediaParam = 'vid=' + _vid;
                                                                     GOSUB back.
      ! !     _vid.split(',').forEach(function(id){
      ! !     !    o.media.push({videoId:id});
      ! !
      ! !
              });
              if(o.titles){
                                                                     Requires extra cognition
      ! !     !    o.mediaParam += '&titles=' + o.titles;
      ! !     !    o.titles.split(',').forEach(function(title, i){
      ! !
      ! !
              !
              !
                   !
                   });
                        o.media[i].caption = unescape(title);
                                                                     Limits reusability
      ! !     !    delete o.titles;
      ! !     }
      ! !
      ! !
              delete o.videoId;
              delete o.vid;                                          Even if it means more bytes,
                                                                     should be broken into smaller
      ! !     delete o.siteId;
      ! }else if(o.media){
      ! !     o.mediaParam = 'media=' + o.media;
      ! }
      ! var vid = o.videoId || o.vid || o.siteId || "";              functions
      ! var lid = o.locationId || o.lid;
      ! var cid = Number(o.clientId) || o.cid;
      ! if(lid === 1 || lid === "1" || !lid) lid = 0;
      ! for(var nm in this.params){
      ! !     if(o[nm] === undefined) o[nm] = this.params[nm];
      ! }
      ! if(!o.videoId && !o.siteId && !o.vid && o.media){
      ! !     if(/siteId/.test(o.media)){
      ! !     !    var pms = this.strToObj(unescape(o.media));
      ! !     !    this.settings.siteId = pms.siteId;
      ! !     }
      ! }




               Actual Code! See the whole thing here!

Wednesday, February 6, 2013
Repetition
   This ain’t Java. You shouldn’t have code like this.
     function setListeners(){
     ! this.domNode.addEventListener('onmousedown', this.onMouseDown);
     ! this.domNode.addEventListener('onmouseup', this.onMouseUp);
     ! this.domNode.addEventListener('onmousemove', this.onMouseMove);
     ! this.domNode.addEventListener('onmouseover', this.onMouseOver);
     ! this.domNode.addEventListener('onmouseout', this.onMouseOut);
     ! this.domNode.addEventListener('onmouseenter', this.onMouseEnter);
     ! this.domNode.addEventListener('onmouseleave', this.onMouseLeave);
     }




Wednesday, February 6, 2013
Repetition
   JavaScript is a dynamic language and can
   handle repetition in multiple ways.
     ['onmousedown', 'onmouseup', 'onmouseover'].forEach(function(event){
     ! this.domNode.addEventListener(event, this[event]);
     }, this);

     $(this.domNode).on('onmousedown, onmouseup, onmouseover', function
     (event){
     ! handleMouseClick(event);!
     });




Wednesday, February 6, 2013
Function in Functions
   Functions inside of other functions are perfectly
   legitimate, but still should be used with care
   and consideration.
     function parseDom(node){
     ! function parseText(){}
     ! function parseAttributes(){}
     ! function parseChildren(){}
     ! function getNodeType(){}
     ! getNodeType(node);
     ! parseText(node.innerHTML);
     ! parseAttributes(node.attributes);
     ! parseChildren(node.childNodes);
     }




Wednesday, February 6, 2013
Function in Functions
                Often slower, as each time the outer is invoked, the
                inners are recreated

                They are private and not accessible by other methods

                If inners are not semantically tied very closely to
                the outer, the intention may be confusing

                The inners should never access anything outside of
                the outer - aka, the application
                       Else what was the point?




Wednesday, February 6, 2013
Loops
                Where the biggest performance boost (or hit) can
                happen

                Hot Loops
                       JIT compilers make assumptions, especially on loops

                       Not a good place for being tricky

                Sparse arrays
                       Arrays with lots of “holes” will slow down the iteration

                       Some libraries, like Lo-Dash handle these holes and speed
                       performance

Wednesday, February 6, 2013
Loops - for vs forEach
                for is much faster, used in context and can be easily
                interrupted with a break or continue’d

                for is a major chore to type - looks very “C”

                forEach has the overhead of the function, and is
                used out of context unless the this argument is
                added which is an addition performance hit

                forEach is much more finger friendly, and fine to
                use in low performance situations

                map, some, every, filter etc. have same issues
                and should be used on small arrays

Wednesday, February 6, 2013
Functions in Loops
     for( var i = 0; i < arguments.length; i++){
     ! var handler = (function(node){
     ! ! return node.addEventListener('click', blah);
     ! })( arguments[i] );
     ! handlers.push( handlers );
     }



           JSLint will complain. Listen to it!

           Creates a new function on every iteration. Slow.

           Fix this by moving the function outside of the loop
           and calling it. This allows for JIT prediction.




Wednesday, February 6, 2013
for vs for-in
           for-in is for objects, for is for arrays.   If I see you do this
                                                       I will give you a
                                                       paper cut in the
                  NO EXCEPTIONS!                       corner of your
                                                       mouth and feed you
      for( var key in array ){                         lemons
         doSomething( array[key] );
      }


                Could access unwanted properties

                Not a guarantee of order

                Intent is not clear
                       In fact, it’s more of a WTF


Wednesday, February 6, 2013
Objects




Wednesday, February 6, 2013
Don’t fight “this”
                                                             meth
                  var instance = {
                                                                 od
                 t! doit: function(){ console.log('DOIT!'); },
                c ! subobject:{
             je
            b ! ! submethod: function(){
          o
       b-                                                    calls
    su
                  ! ! ! doit(); // FAIL!
                  ! ! ! this.doit(); // FAIL!
                  ! ! ! parent.doit(); // No such thing!
                                                           metho d
                  !! }
                  !}
                  };
                  instance.subobject.submethod();


            This is a simplified version of a much larger problem




Wednesday, February 6, 2013
Don’t fight “this”
    You *could* bind the submethod to the parent object...
      var instance = {
      ! doit: function(){ console.log('DOIT!'); },
      ! subobject:{
      ! ! submethod: function(){
      ! ! ! this.doit(); // works
      !! }
      !}
      };
      instance.subobject.submethod =
         bind(instance, instance.subobject.submethod);
      instance.subobject.submethod();


   Of course, this begs the question of why you created
   subobject in the first place.


Wednesday, February 6, 2013
Don’t cross the beams!!
    One solution...
      var instance = {
      ! constructor: function(){
      ! ! aop.after(this.subobject, 'submethod', this.doit.bind(this));
      ! },
      ! doit: function(){ console.log('DOIT!'); },
      ! subobject:{
      ! ! submethod: function(){}
      !}
      };

  Understanding that communication only goes “down”, never “up”
  will go a long way toward clear code and simplified execution
  paths



Wednesday, February 6, 2013
Know thy self
    self is the common variable name used to pass around
    and change context (this)
      var self = this;
      props.forEach(function(prop){
      ! self[ prop.key ] = prop.value;
      });



    Because JavaScript is a closure based language, self can
    actually be very efficient. Believe it or not, this is slower:

      props.forEach(function(prop){
      ! this[ prop.key ] = prop.value;
      }, this);


                          http://kriszyp.name/2012/09/14/closure-based-instance-binding/
Wednesday, February 6, 2013
Alternative to self
    Context binding basically uses call or apply under the
    hood
      var bind = function(ctx, func){
      ! return function(){ func.apply(ctx, arguments); };
      };
      var instance = {
      ! constructor: function(props){
      ! ! var setProps = bind(this, this.setProps);
      ! ! props.forEach(setProps);
      ! },
      ! setProps: function(p){
      ! ! console.log(p);
      !}
      };
      instance.constructor([{a:1}, {b:2}]);




Wednesday, February 6, 2013
ES5 bind()
    All modern browsers have Function.bind which can
    change context
      var instance = {
      ! id:'binder',
      ! constructor: function(props){
      ! ! setTimeout(function(){
      ! ! ! console.log(this.id);!
      ! ! }.bind(this), 1);
      !}
      };
      instance.constructor();



    Note that even though it’s built into the language, it’s not faster
    than self. It is for readability and convenience, not hot loops.


Wednesday, February 6, 2013
Hate thy self too much
    self is like chocolate cake - some is good, too much will
    make you sick
      var self = this;
      var onLoad = function(data){
      ! self.title = data.title;
      ! self.description = data.description;
      ! self.setClients( data.clients );
      ! self.on('finished', function(){
      ! ! self.render( self.items );
      ! ! setTimeout( function(){
      ! ! ! self.emit( 'afterrender' );!
      ! ! }, 1);
      ! });
      };




Wednesday, February 6, 2013
Love thy self a little
    On solution is to immediately redirect to a properly bound
    method
      var instance = {
      ! onDataLoaded: function(data){
      ! ! // now set stuff
      ! },
      ! constructor: function(props){
      ! ! var self = this;
      ! ! var onLoad = function(data){
      ! ! ! self.onDataLoaded(data);
      ! ! };
      !}
      };




Wednesday, February 6, 2013
Don’t abuse your self
                this is specific; it can’t be changed so you always
                know to which object it points

                self is ambiguous; it can point to many objects from
                any object, which obfuscates your intent

                Don’t use self to shortcut better practices




Wednesday, February 6, 2013
Inheritance




Wednesday, February 6, 2013
Prototypal Inheritance
    If you are using the prototype keyword… you’re doing it
    wrong.                                   HMO
                                                Hot Mike Opinion
      Widget = function(props){
      ! mixin(this, this.props);
      };
      Widget.prototype = {
      ! render: function(){},
      ! setItems: function(){}
      }


    Using prototype makes multiple inheritance difficult, and
    without some kind of AOP help, the super constructors won’t
    work.


Wednesday, February 6, 2013
dcl
    A JavaScript package that implements OOP with mixins and
    AOP at both “class” and object level.
      var Base = dcl(null, {                    var Example1 = dcl([Base, Mixin1],{
      ! declaredClass: 'Base',                  ! constructor: function(params){
      ! constructor: function(params){          ! ! this.name = params.name;
      ! ! this.title = params.title;            ! },
      ! }                                       ! render: function(){
      });                                       ! ! this.prepareProps();
                                                ! ! // call Widget.render
      var Widget = dcl(null, {                  ! ! this.inherited();
      ! declaredClass: 'Widget',                ! }
      ! constructor: function(params){          });
      ! ! this.className = params
      ! },                                      /*********************************/
      ! render: function(){                     widget = new Example1({
      ! ! this.setTemplate();                   ! title:'My Widget',
      ! }                                       ! name:'widget',
      });                                       ! className:'Widget'
                                                });


                               http://www.dcljs.org/about/
Wednesday, February 6, 2013
dcl / Inheritance
                Base classes can be reused, keeping code light -
                extremely important in JavaScript

                Constructors are chained and called in all bases,
                which can’t be done in standard object creation, such
                as Object.create

                super methods can be called with inherited(), so
                all base classes can use similar method names,
                keeping code standardized and less complex

                For ES5 strict mode there is AOP inheritance



Wednesday, February 6, 2013
Other Design Patterns




Wednesday, February 6, 2013
Design Patterns
 Design Patterns: Elements of Reusable Object-Oriented
 Software is a book with solutions to common problems in
 software design. The authors are often referred to as the Gang
 of Four.

                Functional (Imperative)

                Declarative

                Decorator

                Composition

                              http://en.wikipedia.org/wiki/Design_Patterns
Wednesday, February 6, 2013
Over-Inherited
    One reason for other solutions is to protect from over-
    inheritance
                                                  Based on more
      Base                                        actual code from
      ! +! Item                                   my Flash days!
      ! ! +! ServerItem
      ! ! ! +! ImageItem
      ! ! ! ! +! ImageListItem
      ! ! ! ! ! +! ImageListItemDescription
      ! ! ! ! ! ! +! ImageListItemDescriptionClickable
      ! ! ! ! ! ! ! +! ImageListItemDescriptionClickableDraggable




    Note however, JavaScript does not have the same
    inheritance restrictions as Java, C++, Flash, or others

Wednesday, February 6, 2013
Declarative
    A problem faced by libraries is allowing the dev to choose
    discrete segments of code instead of kitchen sink solutions
      define([
      ! 'dojo/declare',
      ! 'dojo/store/Memory',
      ! 'dojo/store/Cache',
      ! 'dojo/store/JsonRest',
      ! 'dojo/store/Observable'
      ], function( declare, Memory, Cache, JsonRest, Observable ){!
      !    var Store = declare( Memory, Cache, JsonRest );
                var store = new Store( webserviceUrl );
      });


    The dev can dynamically create their own constructor with the
    mixins provided


Wednesday, February 6, 2013
Decorator
      define([
      ], function( declare, Memory, Cache, JsonRest, Observable ){
      !
      ! var Store = declare( Memory, Cache, JsonRest );
      ! var store = new Store( webserviceUrl );

          observableStore = Observable( store );
          cacheableStore = Cache( observableStore );


      });


    Decorators are not very common, but they do solve a few
    problems like working with existing objects that you can’t
    change, or creating two objects from the same base with
    different functionality.


Wednesday, February 6, 2013
Composition
    Composition often makes sense semantically. Here the model
    encapsulates properties and functionality.

      Widget = {
      ! constructor: function(model){
      ! ! this.model = model;!
      ! },
      ! get: function(key){
      ! ! return this.model.get(key);
      !}
      }




Wednesday, February 6, 2013
Functional                                      HMO
                                                    Hot Mike Opinion
               Don’t.
               Just don’t.
               Friends don’t let friends write functional.




Wednesday, February 6, 2013
App Structure




Wednesday, February 6, 2013
require.js
                You are using it, aren’t you?

                Globals are SO 2011

                Globals can clash with other code, and they do not
                garbage collect

                require.js provides a mini-framework, enforcing
                packages, namespaces, and modules




Wednesday, February 6, 2013
Naming and Arranging
              Don't expect to cram it all into preconceived model-
              view-controller folders, it's too limiting, and the app
              will grow out of it
             Remember, the code path flows
             down, not up, so the deeper modules
             should not have access to root
             modules




Wednesday, February 6, 2013
Module APIs
    Modules can use private variables, but not to hide or protect
    anybody - use them to help provide a clean API. And if you are
    doing so - make it a clear intent!
      define([], function(){
      ! var items = [];
      ! function setItem(item){
      ! ! items.push(item);
      !}
      ! function getItem(idx){
      ! ! return items[idx];
      !}
      ! return {
      ! ! setItem:setItem,
      ! ! getItem:getItem
      ! };
      });


Wednesday, February 6, 2013
Wiring




Wednesday, February 6, 2013
Wiring Types
                tight coupling (direct access)

                AOP

                events

                pubsub

                callbacks

                promises




Wednesday, February 6, 2013
Tight Coupling
    Pros:
      The intent is quite clear
      Requires no additional libraries of fancy code
    Cons:
      Over-use between modules can create a hairball
      Can break encapsulation
      define([
      ! './foo',
      ! '../../views/widgets/utils/thinger'
      ], function(foo, thinger){
      ! foo.doStuff();
      ! thinger.stopStuff();
      });

    require.js allows for clear paths to distant modules, but if you are
    connecting to something this “far” away, you should probably do some
    restructuring
Wednesday, February 6, 2013
AOP
               Uses JavaScript’s dynamic, mutable language
               Doesn’t overwrite method, so many connections can be made
               Make sure to create names to indicate they are event-
               methods
      define([
      ! 'aop',
      ! './items'
      ], function(aop, items){
      ! function onLoaded(data){
      ! ! console.log(data);
      ! }!
      ! aop(items, 'onLoad', onLoaded);
      });




Wednesday, February 6, 2013
Events
         The new hotness
         Multiple connections can be made
         Intent is clear - obvious they are events and what they do
      define(['dcl', 'Events'], function(dcl, Events){
      ! return new dcl(Events, {
      ! ! onDataLoaded: function(data){
      ! ! ! this.emit('dataloaded', data);
      !! }
      ! });
      });
      define(['./dataLoader'], function(dataLoader){
      ! function onDataLoaded(data){
      ! ! console.log(data);
      !}
      ! dataLoader.on('dataloaded', onDataLoaded);
      });

Wednesday, February 6, 2013
pubsub
    Pros:
      Library code is very simple
      Can access distant areas of app
    Cons:
      Not guaranteed - pub can fire before sub is ready
      Can be hard to follow code paths between unrelated modules
      Over-use can lead to race conditions
      define(['pubsub'], function(pubsub){
      ! pubsub.publish('/module/loaded', {success:true});
      });
      define(['pubsub'], function(pubsub){
      ! pubsub.subscribe('/module/loaded', function(object){
      ! ! console.log('load success:', object.success);
      ! });
      });

Wednesday, February 6, 2013
callbacks
  Pros: Old-school, simple way of connecting async; clear code path
  Cons: Only one connection, no propagation, multiple callback
  nesting can cause “callback hell”

      define([], function(){
      ! return {
      ! ! loadData: function(callback){
      ! ! ! xhr('/getdata', {
      ! ! ! ! load: function(data){
      ! ! ! ! ! callback(data);
      ! ! ! ! }});}};
      });
      define(['./instance'], function(instance){
      ! function onDataLoaded(data){
      ! ! console.log(data);
      !}
      ! instance.loadData(onDataLoaded);
      });
Wednesday, February 6, 2013
promises / deferreds
      define(['Deferred'], function(Deferred){
      ! return function(){
      ! ! var dfd = new Deferred();
      ! ! xhr('/getdata', {
      ! ! ! load: function(data){
      ! ! ! ! dfd.resolve(data);
      ! ! ! }!
      ! ! });
      ! ! return dfd;
      !}
      });
      define(['./loader'], function(loader){
      ! loader().then(function(data){
      ! ! console.log(data);
      ! });
      });


Wednesday, February 6, 2013
promises / deferreds
    Pros:
      Async
      A when() library can handle both async and sync
      Trendy (everybody is doing it!!)
      Multiple connections can be made
      Propagates, and can be stopped

    Cons:
      Libraries are somewhat complex
      Requires (a lot) more code than a callback
      Has a tendency to swallow errors unexpectedly
      Can dominate the stacktrace and make it hard to debug
      errors

Wednesday, February 6, 2013
Conclusion




Wednesday, February 6, 2013
Refactor!
             Little projects always become big projects

             You will never have all the information up front

             Sales can turn your app into Frankenstein




Wednesday, February 6, 2013
Make
 it small. People                Committee Refactor!            It
                                                         sure is tall. Can
    like small.                                         you make it LOOK
                                                             short?
                      But
               make it big inside.

            Oh!
      And four doors.
     Small with lots of
           doors.




                                                            My
           Don’t
                                                    son says it would
     spend too much on
                                                   be cool if you could
         the trim.
                                                       camp in it.
                                    Don’t
                              spend too much on
                                 the wheels.



Wednesday, February 6, 2013
Wednesday, February 6, 2013

Weitere ähnliche Inhalte

Ähnlich wie Hardcore JavaScript – Write it Right

Modules and EmbedJS
Modules and EmbedJSModules and EmbedJS
Modules and EmbedJSJens Arps
 
Striving towards better PHP code
Striving towards better PHP codeStriving towards better PHP code
Striving towards better PHP codeSteve Maraspin
 
TDD - Cultivating a Beginner's Mind
TDD -  Cultivating a Beginner's MindTDD -  Cultivating a Beginner's Mind
TDD - Cultivating a Beginner's MindShai Yallin
 
Lessons I Learned While Scaling to 5000 Puppet Agents
Lessons I Learned While Scaling to 5000 Puppet AgentsLessons I Learned While Scaling to 5000 Puppet Agents
Lessons I Learned While Scaling to 5000 Puppet AgentsPuppet
 
Comparing groovy and_j_ruby(neal_ford)
Comparing groovy and_j_ruby(neal_ford)Comparing groovy and_j_ruby(neal_ford)
Comparing groovy and_j_ruby(neal_ford)Dmitry Nosenko
 
Does my DIV look big in this?
Does my DIV look big in this?Does my DIV look big in this?
Does my DIV look big in this?glen_a_smith
 
Scottish Ruby Conference 2014
Scottish Ruby Conference  2014Scottish Ruby Conference  2014
Scottish Ruby Conference 2014michaelag1971
 
Infrastructure as code might be literally impossible
Infrastructure as code might be literally impossibleInfrastructure as code might be literally impossible
Infrastructure as code might be literally impossibleice799
 
Angular js recommended practices - mini
Angular js   recommended practices - miniAngular js   recommended practices - mini
Angular js recommended practices - miniRasheed Waraich
 
Developer Tests - Things to Know
Developer Tests - Things to KnowDeveloper Tests - Things to Know
Developer Tests - Things to KnowVaidas Pilkauskas
 
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLEAN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLEGavin Pickin
 
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE - CFObjective() 2017
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE - CFObjective() 2017AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE - CFObjective() 2017
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE - CFObjective() 2017Ortus Solutions, Corp
 
Infrastructure as code might be literally impossible / Joe Domato (packageclo...
Infrastructure as code might be literally impossible / Joe Domato (packageclo...Infrastructure as code might be literally impossible / Joe Domato (packageclo...
Infrastructure as code might be literally impossible / Joe Domato (packageclo...Ontico
 
Test driven development for infrastructure as-a-code, the future trend_Gianfr...
Test driven development for infrastructure as-a-code, the future trend_Gianfr...Test driven development for infrastructure as-a-code, the future trend_Gianfr...
Test driven development for infrastructure as-a-code, the future trend_Gianfr...Katherine Golovinova
 
OOScss Architecture For Rails Apps
OOScss Architecture For Rails AppsOOScss Architecture For Rails Apps
OOScss Architecture For Rails AppsNetguru
 

Ähnlich wie Hardcore JavaScript – Write it Right (20)

Modules and EmbedJS
Modules and EmbedJSModules and EmbedJS
Modules and EmbedJS
 
Striving towards better PHP code
Striving towards better PHP codeStriving towards better PHP code
Striving towards better PHP code
 
All of javascript
All of javascriptAll of javascript
All of javascript
 
TDD - Cultivating a Beginner's Mind
TDD -  Cultivating a Beginner's MindTDD -  Cultivating a Beginner's Mind
TDD - Cultivating a Beginner's Mind
 
Lessons I Learned While Scaling to 5000 Puppet Agents
Lessons I Learned While Scaling to 5000 Puppet AgentsLessons I Learned While Scaling to 5000 Puppet Agents
Lessons I Learned While Scaling to 5000 Puppet Agents
 
Comparing groovy and_j_ruby(neal_ford)
Comparing groovy and_j_ruby(neal_ford)Comparing groovy and_j_ruby(neal_ford)
Comparing groovy and_j_ruby(neal_ford)
 
Does my DIV look big in this?
Does my DIV look big in this?Does my DIV look big in this?
Does my DIV look big in this?
 
Scottish Ruby Conference 2014
Scottish Ruby Conference  2014Scottish Ruby Conference  2014
Scottish Ruby Conference 2014
 
Infrastructure as code might be literally impossible
Infrastructure as code might be literally impossibleInfrastructure as code might be literally impossible
Infrastructure as code might be literally impossible
 
TDD with Spock @xpdays_ua
TDD with Spock @xpdays_uaTDD with Spock @xpdays_ua
TDD with Spock @xpdays_ua
 
Angular js recommended practices - mini
Angular js   recommended practices - miniAngular js   recommended practices - mini
Angular js recommended practices - mini
 
Developer Tests - Things to Know
Developer Tests - Things to KnowDeveloper Tests - Things to Know
Developer Tests - Things to Know
 
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLEAN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE
 
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE - CFObjective() 2017
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE - CFObjective() 2017AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE - CFObjective() 2017
AN EXERCISE IN CLEANER CODE - FROM LEGACY TO MAINTAINABLE - CFObjective() 2017
 
Infrastructure as code might be literally impossible / Joe Domato (packageclo...
Infrastructure as code might be literally impossible / Joe Domato (packageclo...Infrastructure as code might be literally impossible / Joe Domato (packageclo...
Infrastructure as code might be literally impossible / Joe Domato (packageclo...
 
OOP Day 1
OOP Day 1OOP Day 1
OOP Day 1
 
Test driven development for infrastructure as-a-code, the future trend_Gianfr...
Test driven development for infrastructure as-a-code, the future trend_Gianfr...Test driven development for infrastructure as-a-code, the future trend_Gianfr...
Test driven development for infrastructure as-a-code, the future trend_Gianfr...
 
Gradle by Example
Gradle by ExampleGradle by Example
Gradle by Example
 
OOScss Architecture For Rails Apps
OOScss Architecture For Rails AppsOOScss Architecture For Rails Apps
OOScss Architecture For Rails Apps
 
All of Javascript
All of JavascriptAll of Javascript
All of Javascript
 

Mehr von Mike Wilcox

Accessibility for Fun and Profit
Accessibility for Fun and ProfitAccessibility for Fun and Profit
Accessibility for Fun and ProfitMike Wilcox
 
Webpack: What it is, What it does, Whether you need it
Webpack: What it is, What it does, Whether you need itWebpack: What it is, What it does, Whether you need it
Webpack: What it is, What it does, Whether you need itMike Wilcox
 
Web Components v1
Web Components v1Web Components v1
Web Components v1Mike Wilcox
 
Great Responsive-ability Web Design
Great Responsive-ability Web DesignGreat Responsive-ability Web Design
Great Responsive-ability Web DesignMike Wilcox
 
Professional JavaScript: AntiPatterns
Professional JavaScript: AntiPatternsProfessional JavaScript: AntiPatterns
Professional JavaScript: AntiPatternsMike Wilcox
 
Model View Madness
Model View MadnessModel View Madness
Model View MadnessMike Wilcox
 
The Great Semicolon Debate
The Great Semicolon DebateThe Great Semicolon Debate
The Great Semicolon DebateMike Wilcox
 
AMD - Why, What and How
AMD - Why, What and HowAMD - Why, What and How
AMD - Why, What and HowMike Wilcox
 
Webpage Design Basics for Non-Designers
Webpage Design Basics for Non-DesignersWebpage Design Basics for Non-Designers
Webpage Design Basics for Non-DesignersMike Wilcox
 
Why You Need a Front End Developer
Why You Need a Front End DeveloperWhy You Need a Front End Developer
Why You Need a Front End DeveloperMike Wilcox
 
A Conversation About REST
A Conversation About RESTA Conversation About REST
A Conversation About RESTMike Wilcox
 
The Fight Over HTML5
The Fight Over HTML5The Fight Over HTML5
The Fight Over HTML5Mike Wilcox
 
The Fight Over HTML5
The Fight Over HTML5The Fight Over HTML5
The Fight Over HTML5Mike Wilcox
 
How to get a Job as a Front End Developer
How to get a Job as a Front End DeveloperHow to get a Job as a Front End Developer
How to get a Job as a Front End DeveloperMike Wilcox
 
The History of HTML5
The History of HTML5The History of HTML5
The History of HTML5Mike Wilcox
 
Thats Not Flash?
Thats Not Flash?Thats Not Flash?
Thats Not Flash?Mike Wilcox
 

Mehr von Mike Wilcox (20)

Accessibility for Fun and Profit
Accessibility for Fun and ProfitAccessibility for Fun and Profit
Accessibility for Fun and Profit
 
WTF R PWAs?
WTF R PWAs?WTF R PWAs?
WTF R PWAs?
 
Advanced React
Advanced ReactAdvanced React
Advanced React
 
Webpack: What it is, What it does, Whether you need it
Webpack: What it is, What it does, Whether you need itWebpack: What it is, What it does, Whether you need it
Webpack: What it is, What it does, Whether you need it
 
Dangerous CSS
Dangerous CSSDangerous CSS
Dangerous CSS
 
Web Components v1
Web Components v1Web Components v1
Web Components v1
 
Great Responsive-ability Web Design
Great Responsive-ability Web DesignGreat Responsive-ability Web Design
Great Responsive-ability Web Design
 
Professional JavaScript: AntiPatterns
Professional JavaScript: AntiPatternsProfessional JavaScript: AntiPatterns
Professional JavaScript: AntiPatterns
 
Model View Madness
Model View MadnessModel View Madness
Model View Madness
 
The Great Semicolon Debate
The Great Semicolon DebateThe Great Semicolon Debate
The Great Semicolon Debate
 
AMD - Why, What and How
AMD - Why, What and HowAMD - Why, What and How
AMD - Why, What and How
 
Dojo & HTML5
Dojo & HTML5Dojo & HTML5
Dojo & HTML5
 
Webpage Design Basics for Non-Designers
Webpage Design Basics for Non-DesignersWebpage Design Basics for Non-Designers
Webpage Design Basics for Non-Designers
 
Why You Need a Front End Developer
Why You Need a Front End DeveloperWhy You Need a Front End Developer
Why You Need a Front End Developer
 
A Conversation About REST
A Conversation About RESTA Conversation About REST
A Conversation About REST
 
The Fight Over HTML5
The Fight Over HTML5The Fight Over HTML5
The Fight Over HTML5
 
The Fight Over HTML5
The Fight Over HTML5The Fight Over HTML5
The Fight Over HTML5
 
How to get a Job as a Front End Developer
How to get a Job as a Front End DeveloperHow to get a Job as a Front End Developer
How to get a Job as a Front End Developer
 
The History of HTML5
The History of HTML5The History of HTML5
The History of HTML5
 
Thats Not Flash?
Thats Not Flash?Thats Not Flash?
Thats Not Flash?
 

Kürzlich hochgeladen

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 

Kürzlich hochgeladen (20)

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 

Hardcore JavaScript – Write it Right

  • 1. Hardcore JavaScript Write it Right By Mike Wilcox February 2013 Wednesday, February 6, 2013
  • 2. Readable Code here(will make that book very |resistånt to pressure| to read.) there(isn’t explained properly) !bad Code is. like-a-book THATis badly formatted no indentation. incorrect punctuation misspelled words improper capitalizedation-ed. Or uneven. ?LINE HEIGHTS here() If “the” names of the char.acters start. Chang'ing, you dunno. where they are. && you+re not sure – WHAT they... are do-ing because it there(), the book w'ill bee pretty-difficult to [comprehend]. Wednesday, February 6, 2013
  • 3. What do I know?? me s Cro ckford D o ug la Wednesday, February 6, 2013
  • 4. What do I know?? Brend me an Eic h Wednesday, February 6, 2013
  • 5. What do I know?? Seriously… Being a Dojo Committer means not only having your code and style scrutinized by know-it-all prima donnas, open source experts, but your results also get used by thousands of hacks that expect magic developers who expect quality code. Wednesday, February 6, 2013
  • 6. This code sucks! onPlayerParams = function(dfd){ ! dfd = dfd || new this.Deferred(); ! var o, p; ! if(scriptNode && scriptNode.getAttribute("config")){ ! ! p = this.fixParams(scriptNode.getAttribute("config")); ! ! p.swf = this.root + "player.swf"; ! }else if(this.embed()){ ! ! var parts = this.embed().getAttribute("src").split("?"); ! ! o = this.strToObj(parts[1]); ! ! o.swf = parts[0]; ! ! p = this.fixParams(o); ! }else if(!this.domReady){ ! ! this.ready(this, function(){ ! ! ! this.onPlayerParams(dfd); ! ! }, true); ! ! if(!p) return dfd; !} ! if(p && p.vast){b.vast.parser.getXml(p.vast);} ! return dfd; } Wednesday, February 6, 2013
  • 7. Our Excuses We The can always go project manager back and fix it later needs this now *I* can read it No time for comments It My was like that sloppy code when I started. means job security! Wednesday, February 6, 2013
  • 8. JavaScript guide Style Wednesday, February 6, 2013
  • 9. Formatting Formatting must be consistent. Otherwise little distractions make the code noisy and that much harder to read. var foo=”bar”+‘beer’+”bob”; for(var i=0;i<arguments.length;i++){} if(a&&b&&c&&d)return a; Wednesday, February 6, 2013
  • 10. Formatting Use single quotes, use spaces liberally, don’t use tiny, cryptic variable names and declare all variables at the beginning of the block. var foo = ‘bar’ + ‘beer’ + ‘bob’; var i; for( i = 0; i < arguments.length; i++ ){} var apples = true, bananas = true, coconuts = true; if( apples && bananas && coconuts ){ return true; } Wednesday, February 6, 2013
  • 11. Typical Guides Indentation tabs not spaces Spacing / whitespace Curly braces rules variable naming conventions Don’t be afraid of white space. method naming conventions No Dojo Case: upper, lower, camel, Pascal neces sar y! Dojo Style Guide http://dojotoolkit.org/community/styleGuide Wednesday, February 6, 2013
  • 12. JSLint / JSHint Is it automated into your build? It’s not just a suggestion - listen to it! It’s more than to help you find errors Helps promote consistency between devs Prevents unintended consequences If the linter thinks your code is ambiguous, so will other devs Helps you target JIT compilers, resulting in faster code Wednesday, February 6, 2013
  • 14. Comments Why the hell did I write that?? OS comments vs production comments short descriptions Future save the lazy crap Self No comments is like a book without chapters or page numbers They aren’t just for your boss or your replacement Wednesday, February 6, 2013
  • 15. Levels of Documenting 1. Verbose comments on every method and module, README and Wiki, instructions for setup and usage, guides to the software and how to edit it 2.Comments on most methods and modules, README with instructions for setup and a guide to what modules do 3.Brief comments on most methods and modules, README with instructions for setup 4.Unfinished code Wednesday, February 6, 2013
  • 16. The Myth You think your code is self documenting, huh? This is not self documenting: setCommand = function(c){ this.cmds.push(c); } run = function(){ … } This looks more like self documenting: setListItemsWithDescritionsButNoThumbnails = function( … ){ this.listItemDescriptions = listItemDescriptionsArgument; } renderItemsWhichIsCalledAfterEveryPageResize = function(){ … } Wednesday, February 6, 2013
  • 17. The Myth What your self documenting code would look like: setListItemsWithDescritionsButNoThumbnails = function( … ){ if(!this.itemsSetBoolenPreventSecondAttempt){ this.itemsSetBoolenPreventSecondAttempt = true; this.listItemDescriptions = listItemDescriptionsArgument; this.renderItemsWhichIsCalledAfterEveryPageResize(); this.onAfterRenderFunctionalStubEvent(); } “Good clean code requires very consistent and good naming conventions that are concise, and which don't attempt to embody an extended purpose” https://www.ibm.com/developerworks/mydeveloperworks/blogs/StylishGeek/entry/ bloated_names_and_the_myth_of_self_documenting_code11?lang=en Wednesday, February 6, 2013
  • 18. Don’t be that guy When a dev writes crap Comment quality matters like this, I want to function setParams(params){ paint him with meat paste and drop him on a ! // sets params mound of fire ants } function setVideo(video){ ! // set video } function setParams(params){ ! // sets parameters based on config property ! // from script tag } function setVideo(videoPath){ ! // Sets the path for the video object } Wednesday, February 6, 2013
  • 20. Naming Conventions Should be camel case Upper case Whole names, no abbreviations This isn’t your father’s code. We have minifiers and gzip now. Use names we understand! Exceptions for long or often used names: err for error, dfd for deferred, prop for property, app for application, etc. i, k, j, etc, okay for iterators Wednesday, February 6, 2013
  • 21. Property Bags Multiple arguments (more than 3) are difficult to manage An single argument as an object of options allows any or all properties to be passed without concern of method signature Mixins allow for simple setting Works with super constructors Wednesday, February 6, 2013
  • 22. ARG-uments function Widget(node, name, description, color, size){ this.node = node; this.name = name || “Untitled”; this. description = description || “”; this.color = color || “#FF0000”; this.size = size || 100; this.code = “makes me sad”; } new Widget({}); Wednesday, February 6, 2013
  • 23. Property Bag Example function Widget( options ){ util.mixin( this, options ); // Done! } Even better is to set defaults and use a mixin that only overwrites and does not add undefined properties var Widget = declare{ name:‘Untitled’, description:’’, color:’#FF0000’, size:100, constructor: function( options ){ util.mixin(this, options); // Done! } } Wednesday, February 6, 2013
  • 24. getters & setters Initialization var object = { ! _x: 7, ! get x() { return this.x + 1; }, ! set x( arg ) { this.x = arg / 2; } }; After creation object.__defineGetter__("b", function() { return this.a + 1; }); object.__defineSetter__("c", function(x) { this.a = x / 2; }); ES5 getters and setters are still not widely used due to IE8. There are also issues as far as how inheritance would work. The super keyword is still in proposal. Wednesday, February 6, 2013
  • 25. ES3 getters & setters Initialization var object = { ! x: 7, ! get: function( key ) { return this[ key ]; }, ! set: function( key, value ) { this[ key ] = value; } }; This is a very common and standardized pattern, even used in Node.js (Mongoose). It works with most library inheritance patterns. Wednesday, February 6, 2013
  • 26. Observers & Watchers object.watch( 'x', function( value ){ ! moveObject( x ); }); object.observe( 'x', function( value ){ ! moveObject( x ); }); watch() is only available on Gecko with warnings of performance penalties. observe() is still an ES6 proposal. Common solution is to simply connect to widget.set method with aspect.after. Wednesday, February 6, 2013
  • 27. Binding <div class='Widget'> ! <span data-bind='name'></name> </div> Widget = declare({ ! name:'Untitled', ! set: function( key, value ){ ! ! this[ key ] = value; ! ! if( this.bindings[ key ] ){ ! ! ! this.bindings[ key ].innerHTML = value; !! } !} }); new Widget({ name: 'Bob' }); This common pattern is the key to all of these trendy MVC frameworks. Wednesday, February 6, 2013
  • 29. Naming Conventions Camel case Pascal case for constructors (Classes) Should be verbs getItems, setName, build, Widget, etc Wednesday, February 6, 2013
  • 30. Ambivalence function process(){} function state(){} function command(){} function structure(){} Those are not verbs. process could be to perform operations or a series of steps state could be to state your name, or the current application state It’s not obvious what any of these do and they should at least be commented Wednesday, February 6, 2013
  • 31. Side Effects While side effects are not forbidden, you should still consider the consequences function setImageProperties(){ image.width = 320; image.height = 240; image.x = 100; image.y = 10; image.opacity = 0.9; updateImage(); killPuppy(); } Can you spot the side effect? Wednesday, February 6, 2013
  • 32. Monolithic Functions 1970 called and wants their fixParams = function(o){ ! var _vid = o.videoId || o.vid || o.siteId || ""; ! if(/,/.test(_vid)){ ! ! ! ! o.media = []; o.mediaParam = 'vid=' + _vid; GOSUB back. ! ! _vid.split(',').forEach(function(id){ ! ! ! o.media.push({videoId:id}); ! ! ! ! }); if(o.titles){ Requires extra cognition ! ! ! o.mediaParam += '&titles=' + o.titles; ! ! ! o.titles.split(',').forEach(function(title, i){ ! ! ! ! ! ! ! }); o.media[i].caption = unescape(title); Limits reusability ! ! ! delete o.titles; ! ! } ! ! ! ! delete o.videoId; delete o.vid; Even if it means more bytes, should be broken into smaller ! ! delete o.siteId; ! }else if(o.media){ ! ! o.mediaParam = 'media=' + o.media; ! } ! var vid = o.videoId || o.vid || o.siteId || ""; functions ! var lid = o.locationId || o.lid; ! var cid = Number(o.clientId) || o.cid; ! if(lid === 1 || lid === "1" || !lid) lid = 0; ! for(var nm in this.params){ ! ! if(o[nm] === undefined) o[nm] = this.params[nm]; ! } ! if(!o.videoId && !o.siteId && !o.vid && o.media){ ! ! if(/siteId/.test(o.media)){ ! ! ! var pms = this.strToObj(unescape(o.media)); ! ! ! this.settings.siteId = pms.siteId; ! ! } ! } Actual Code! See the whole thing here! Wednesday, February 6, 2013
  • 33. Repetition This ain’t Java. You shouldn’t have code like this. function setListeners(){ ! this.domNode.addEventListener('onmousedown', this.onMouseDown); ! this.domNode.addEventListener('onmouseup', this.onMouseUp); ! this.domNode.addEventListener('onmousemove', this.onMouseMove); ! this.domNode.addEventListener('onmouseover', this.onMouseOver); ! this.domNode.addEventListener('onmouseout', this.onMouseOut); ! this.domNode.addEventListener('onmouseenter', this.onMouseEnter); ! this.domNode.addEventListener('onmouseleave', this.onMouseLeave); } Wednesday, February 6, 2013
  • 34. Repetition JavaScript is a dynamic language and can handle repetition in multiple ways. ['onmousedown', 'onmouseup', 'onmouseover'].forEach(function(event){ ! this.domNode.addEventListener(event, this[event]); }, this); $(this.domNode).on('onmousedown, onmouseup, onmouseover', function (event){ ! handleMouseClick(event);! }); Wednesday, February 6, 2013
  • 35. Function in Functions Functions inside of other functions are perfectly legitimate, but still should be used with care and consideration. function parseDom(node){ ! function parseText(){} ! function parseAttributes(){} ! function parseChildren(){} ! function getNodeType(){} ! getNodeType(node); ! parseText(node.innerHTML); ! parseAttributes(node.attributes); ! parseChildren(node.childNodes); } Wednesday, February 6, 2013
  • 36. Function in Functions Often slower, as each time the outer is invoked, the inners are recreated They are private and not accessible by other methods If inners are not semantically tied very closely to the outer, the intention may be confusing The inners should never access anything outside of the outer - aka, the application Else what was the point? Wednesday, February 6, 2013
  • 37. Loops Where the biggest performance boost (or hit) can happen Hot Loops JIT compilers make assumptions, especially on loops Not a good place for being tricky Sparse arrays Arrays with lots of “holes” will slow down the iteration Some libraries, like Lo-Dash handle these holes and speed performance Wednesday, February 6, 2013
  • 38. Loops - for vs forEach for is much faster, used in context and can be easily interrupted with a break or continue’d for is a major chore to type - looks very “C” forEach has the overhead of the function, and is used out of context unless the this argument is added which is an addition performance hit forEach is much more finger friendly, and fine to use in low performance situations map, some, every, filter etc. have same issues and should be used on small arrays Wednesday, February 6, 2013
  • 39. Functions in Loops for( var i = 0; i < arguments.length; i++){ ! var handler = (function(node){ ! ! return node.addEventListener('click', blah); ! })( arguments[i] ); ! handlers.push( handlers ); } JSLint will complain. Listen to it! Creates a new function on every iteration. Slow. Fix this by moving the function outside of the loop and calling it. This allows for JIT prediction. Wednesday, February 6, 2013
  • 40. for vs for-in for-in is for objects, for is for arrays. If I see you do this I will give you a paper cut in the NO EXCEPTIONS! corner of your mouth and feed you for( var key in array ){ lemons doSomething( array[key] ); } Could access unwanted properties Not a guarantee of order Intent is not clear In fact, it’s more of a WTF Wednesday, February 6, 2013
  • 42. Don’t fight “this” meth var instance = { od t! doit: function(){ console.log('DOIT!'); }, c ! subobject:{ je b ! ! submethod: function(){ o b- calls su ! ! ! doit(); // FAIL! ! ! ! this.doit(); // FAIL! ! ! ! parent.doit(); // No such thing! metho d !! } !} }; instance.subobject.submethod(); This is a simplified version of a much larger problem Wednesday, February 6, 2013
  • 43. Don’t fight “this” You *could* bind the submethod to the parent object... var instance = { ! doit: function(){ console.log('DOIT!'); }, ! subobject:{ ! ! submethod: function(){ ! ! ! this.doit(); // works !! } !} }; instance.subobject.submethod = bind(instance, instance.subobject.submethod); instance.subobject.submethod(); Of course, this begs the question of why you created subobject in the first place. Wednesday, February 6, 2013
  • 44. Don’t cross the beams!! One solution... var instance = { ! constructor: function(){ ! ! aop.after(this.subobject, 'submethod', this.doit.bind(this)); ! }, ! doit: function(){ console.log('DOIT!'); }, ! subobject:{ ! ! submethod: function(){} !} }; Understanding that communication only goes “down”, never “up” will go a long way toward clear code and simplified execution paths Wednesday, February 6, 2013
  • 45. Know thy self self is the common variable name used to pass around and change context (this) var self = this; props.forEach(function(prop){ ! self[ prop.key ] = prop.value; }); Because JavaScript is a closure based language, self can actually be very efficient. Believe it or not, this is slower: props.forEach(function(prop){ ! this[ prop.key ] = prop.value; }, this); http://kriszyp.name/2012/09/14/closure-based-instance-binding/ Wednesday, February 6, 2013
  • 46. Alternative to self Context binding basically uses call or apply under the hood var bind = function(ctx, func){ ! return function(){ func.apply(ctx, arguments); }; }; var instance = { ! constructor: function(props){ ! ! var setProps = bind(this, this.setProps); ! ! props.forEach(setProps); ! }, ! setProps: function(p){ ! ! console.log(p); !} }; instance.constructor([{a:1}, {b:2}]); Wednesday, February 6, 2013
  • 47. ES5 bind() All modern browsers have Function.bind which can change context var instance = { ! id:'binder', ! constructor: function(props){ ! ! setTimeout(function(){ ! ! ! console.log(this.id);! ! ! }.bind(this), 1); !} }; instance.constructor(); Note that even though it’s built into the language, it’s not faster than self. It is for readability and convenience, not hot loops. Wednesday, February 6, 2013
  • 48. Hate thy self too much self is like chocolate cake - some is good, too much will make you sick var self = this; var onLoad = function(data){ ! self.title = data.title; ! self.description = data.description; ! self.setClients( data.clients ); ! self.on('finished', function(){ ! ! self.render( self.items ); ! ! setTimeout( function(){ ! ! ! self.emit( 'afterrender' );! ! ! }, 1); ! }); }; Wednesday, February 6, 2013
  • 49. Love thy self a little On solution is to immediately redirect to a properly bound method var instance = { ! onDataLoaded: function(data){ ! ! // now set stuff ! }, ! constructor: function(props){ ! ! var self = this; ! ! var onLoad = function(data){ ! ! ! self.onDataLoaded(data); ! ! }; !} }; Wednesday, February 6, 2013
  • 50. Don’t abuse your self this is specific; it can’t be changed so you always know to which object it points self is ambiguous; it can point to many objects from any object, which obfuscates your intent Don’t use self to shortcut better practices Wednesday, February 6, 2013
  • 52. Prototypal Inheritance If you are using the prototype keyword… you’re doing it wrong. HMO Hot Mike Opinion Widget = function(props){ ! mixin(this, this.props); }; Widget.prototype = { ! render: function(){}, ! setItems: function(){} } Using prototype makes multiple inheritance difficult, and without some kind of AOP help, the super constructors won’t work. Wednesday, February 6, 2013
  • 53. dcl A JavaScript package that implements OOP with mixins and AOP at both “class” and object level. var Base = dcl(null, { var Example1 = dcl([Base, Mixin1],{ ! declaredClass: 'Base', ! constructor: function(params){ ! constructor: function(params){ ! ! this.name = params.name; ! ! this.title = params.title; ! }, ! } ! render: function(){ }); ! ! this.prepareProps(); ! ! // call Widget.render var Widget = dcl(null, { ! ! this.inherited(); ! declaredClass: 'Widget', ! } ! constructor: function(params){ }); ! ! this.className = params ! }, /*********************************/ ! render: function(){ widget = new Example1({ ! ! this.setTemplate(); ! title:'My Widget', ! } ! name:'widget', }); ! className:'Widget' }); http://www.dcljs.org/about/ Wednesday, February 6, 2013
  • 54. dcl / Inheritance Base classes can be reused, keeping code light - extremely important in JavaScript Constructors are chained and called in all bases, which can’t be done in standard object creation, such as Object.create super methods can be called with inherited(), so all base classes can use similar method names, keeping code standardized and less complex For ES5 strict mode there is AOP inheritance Wednesday, February 6, 2013
  • 56. Design Patterns Design Patterns: Elements of Reusable Object-Oriented Software is a book with solutions to common problems in software design. The authors are often referred to as the Gang of Four. Functional (Imperative) Declarative Decorator Composition http://en.wikipedia.org/wiki/Design_Patterns Wednesday, February 6, 2013
  • 57. Over-Inherited One reason for other solutions is to protect from over- inheritance Based on more Base actual code from ! +! Item my Flash days! ! ! +! ServerItem ! ! ! +! ImageItem ! ! ! ! +! ImageListItem ! ! ! ! ! +! ImageListItemDescription ! ! ! ! ! ! +! ImageListItemDescriptionClickable ! ! ! ! ! ! ! +! ImageListItemDescriptionClickableDraggable Note however, JavaScript does not have the same inheritance restrictions as Java, C++, Flash, or others Wednesday, February 6, 2013
  • 58. Declarative A problem faced by libraries is allowing the dev to choose discrete segments of code instead of kitchen sink solutions define([ ! 'dojo/declare', ! 'dojo/store/Memory', ! 'dojo/store/Cache', ! 'dojo/store/JsonRest', ! 'dojo/store/Observable' ], function( declare, Memory, Cache, JsonRest, Observable ){! ! var Store = declare( Memory, Cache, JsonRest ); var store = new Store( webserviceUrl ); }); The dev can dynamically create their own constructor with the mixins provided Wednesday, February 6, 2013
  • 59. Decorator define([ ], function( declare, Memory, Cache, JsonRest, Observable ){ ! ! var Store = declare( Memory, Cache, JsonRest ); ! var store = new Store( webserviceUrl ); observableStore = Observable( store ); cacheableStore = Cache( observableStore ); }); Decorators are not very common, but they do solve a few problems like working with existing objects that you can’t change, or creating two objects from the same base with different functionality. Wednesday, February 6, 2013
  • 60. Composition Composition often makes sense semantically. Here the model encapsulates properties and functionality. Widget = { ! constructor: function(model){ ! ! this.model = model;! ! }, ! get: function(key){ ! ! return this.model.get(key); !} } Wednesday, February 6, 2013
  • 61. Functional HMO Hot Mike Opinion Don’t. Just don’t. Friends don’t let friends write functional. Wednesday, February 6, 2013
  • 63. require.js You are using it, aren’t you? Globals are SO 2011 Globals can clash with other code, and they do not garbage collect require.js provides a mini-framework, enforcing packages, namespaces, and modules Wednesday, February 6, 2013
  • 64. Naming and Arranging Don't expect to cram it all into preconceived model- view-controller folders, it's too limiting, and the app will grow out of it Remember, the code path flows down, not up, so the deeper modules should not have access to root modules Wednesday, February 6, 2013
  • 65. Module APIs Modules can use private variables, but not to hide or protect anybody - use them to help provide a clean API. And if you are doing so - make it a clear intent! define([], function(){ ! var items = []; ! function setItem(item){ ! ! items.push(item); !} ! function getItem(idx){ ! ! return items[idx]; !} ! return { ! ! setItem:setItem, ! ! getItem:getItem ! }; }); Wednesday, February 6, 2013
  • 67. Wiring Types tight coupling (direct access) AOP events pubsub callbacks promises Wednesday, February 6, 2013
  • 68. Tight Coupling Pros: The intent is quite clear Requires no additional libraries of fancy code Cons: Over-use between modules can create a hairball Can break encapsulation define([ ! './foo', ! '../../views/widgets/utils/thinger' ], function(foo, thinger){ ! foo.doStuff(); ! thinger.stopStuff(); }); require.js allows for clear paths to distant modules, but if you are connecting to something this “far” away, you should probably do some restructuring Wednesday, February 6, 2013
  • 69. AOP Uses JavaScript’s dynamic, mutable language Doesn’t overwrite method, so many connections can be made Make sure to create names to indicate they are event- methods define([ ! 'aop', ! './items' ], function(aop, items){ ! function onLoaded(data){ ! ! console.log(data); ! }! ! aop(items, 'onLoad', onLoaded); }); Wednesday, February 6, 2013
  • 70. Events The new hotness Multiple connections can be made Intent is clear - obvious they are events and what they do define(['dcl', 'Events'], function(dcl, Events){ ! return new dcl(Events, { ! ! onDataLoaded: function(data){ ! ! ! this.emit('dataloaded', data); !! } ! }); }); define(['./dataLoader'], function(dataLoader){ ! function onDataLoaded(data){ ! ! console.log(data); !} ! dataLoader.on('dataloaded', onDataLoaded); }); Wednesday, February 6, 2013
  • 71. pubsub Pros: Library code is very simple Can access distant areas of app Cons: Not guaranteed - pub can fire before sub is ready Can be hard to follow code paths between unrelated modules Over-use can lead to race conditions define(['pubsub'], function(pubsub){ ! pubsub.publish('/module/loaded', {success:true}); }); define(['pubsub'], function(pubsub){ ! pubsub.subscribe('/module/loaded', function(object){ ! ! console.log('load success:', object.success); ! }); }); Wednesday, February 6, 2013
  • 72. callbacks Pros: Old-school, simple way of connecting async; clear code path Cons: Only one connection, no propagation, multiple callback nesting can cause “callback hell” define([], function(){ ! return { ! ! loadData: function(callback){ ! ! ! xhr('/getdata', { ! ! ! ! load: function(data){ ! ! ! ! ! callback(data); ! ! ! ! }});}}; }); define(['./instance'], function(instance){ ! function onDataLoaded(data){ ! ! console.log(data); !} ! instance.loadData(onDataLoaded); }); Wednesday, February 6, 2013
  • 73. promises / deferreds define(['Deferred'], function(Deferred){ ! return function(){ ! ! var dfd = new Deferred(); ! ! xhr('/getdata', { ! ! ! load: function(data){ ! ! ! ! dfd.resolve(data); ! ! ! }! ! ! }); ! ! return dfd; !} }); define(['./loader'], function(loader){ ! loader().then(function(data){ ! ! console.log(data); ! }); }); Wednesday, February 6, 2013
  • 74. promises / deferreds Pros: Async A when() library can handle both async and sync Trendy (everybody is doing it!!) Multiple connections can be made Propagates, and can be stopped Cons: Libraries are somewhat complex Requires (a lot) more code than a callback Has a tendency to swallow errors unexpectedly Can dominate the stacktrace and make it hard to debug errors Wednesday, February 6, 2013
  • 76. Refactor! Little projects always become big projects You will never have all the information up front Sales can turn your app into Frankenstein Wednesday, February 6, 2013
  • 77. Make it small. People Committee Refactor! It sure is tall. Can like small. you make it LOOK short? But make it big inside. Oh! And four doors. Small with lots of doors. My Don’t son says it would spend too much on be cool if you could the trim. camp in it. Don’t spend too much on the wheels. Wednesday, February 6, 2013