SlideShare a Scribd company logo
JavaScript Patterns




    Giordano Scalzo
Wednesday, November 10, 2010
I’m not a guru!




Wednesday, November 10, 2010
I’m still learning




Wednesday, November 10, 2010
Why?




Wednesday, November 10, 2010
JavaScript isn’t this anymore




Wednesday, November 10, 2010
JavaScript is everywhere!




Wednesday, November 10, 2010
JavaScript is trendy!


            Technology Radar




Wednesday, November 10, 2010
JavaScript is trendy!


            Technology Radar




Wednesday, November 10, 2010
At the beginning...




Wednesday, November 10, 2010
Hacked by Brendan Eich in one week...




Wednesday, November 10, 2010
Former Mocha, renamed to JavaScript by Netscape




Wednesday, November 10, 2010
after a while...




Wednesday, November 10, 2010
and...




Wednesday, November 10, 2010
:-(




Wednesday, November 10, 2010
and so...




Wednesday, November 10, 2010
Back to study!




Wednesday, November 10, 2010
Started a notebook...




Wednesday, November 10, 2010
Essential
                                  Scope




Wednesday, November 10, 2010
function sum(x, y){
                                   // implied global
                                   result = x + y;
                                   return result;
                               }




{antipattern}
Wednesday, November 10, 2010
Global variables are evil!




Wednesday, November 10, 2010
Variables clash




Wednesday, November 10, 2010
Always declare variables with var



                                      function sum(x, y){
                                      	 var result = x + y;
                                         return result;
                                      }




{pattern}
Wednesday, November 10, 2010
function foo(){
                                   var a = b = 0;
                                   //...
                               }




{antipattern}
Wednesday, November 10, 2010
b become global




                               function foo(){
                                   var a = (b = 0);
                                   //...
                               }




{antipattern}
Wednesday, November 10, 2010
don’t use assign chain in definition




                               function foo(){
                                   var a, b;
                                   a = b = 0;
                                   //...
                               }




{pattern}
Wednesday, November 10, 2010
Single var pattern


                                function func(){
                                    var a = 1,
                                  	 b = 2,
                                  	 sum = a + b,
                                  	 myobject = {},
                                  	 i,
                                  	 j;
                                    // function body...
                                }




{pattern}
Wednesday, November 10, 2010
Don’t forget comma otherwise...




Wednesday, November 10, 2010
... variables become globals




Wednesday, November 10, 2010
Hoisting


                               myname = "global"; // global variable
                               function func(){
                               	 // code...
                                   console.log(myname); // "undefined"

                                   // code...
                                   var myname = "local";
                                   console.log(myname); // "local"
                               }

                               func();




{antipattern}
Wednesday, November 10, 2010
Hoisting


                               myname = "global"; // global variable
                               function func(){
                                   var myname = "declared";
                               	 // code...
                                   console.log(myname); // "declared"

                                   // code...
                                   myname = "local";
                                   console.log(myname); // "local"
                               }

                               func();




{pattern}
Wednesday, November 10, 2010
Against minimum vertical distance
                               principle


              “Variables should be declared as close to
              their usage as possible”
                                Robert C. Martin - Clean Code



Wednesday, November 10, 2010
Essential
                               Literal and Constructor




Wednesday, November 10, 2010
In JavaScript almost everything is an object




Wednesday, November 10, 2010
It’s easy...



                               var person = new Object();
                               person.name = "Scott";
                               person.say = function(){
                                   return "I am " + this.name;
                               };

                               console.log(person.say());




Wednesday, November 10, 2010
but wrong! :-(



                               var person = new Object();
                               person.name = "Scott";
                               person.say = function(){
                                   return "I am " + this.name;
                               };

                               console.log(person.say());




{antipattern}
Wednesday, November 10, 2010
var person = {};
                               person.name = "Scott";
                               person.say = function(){
                                   return "I am " + this.name;
                               };

                               console.log(person.say());




{pattern}
Wednesday, November 10, 2010
What if we need similar objects...

                          var person = {};
                          person.name = "Scott";
                          person.say = function(){
                              return "I am " + this.name;
                          };
                          console.log(person.say()); // I am Scott

                          var otherPerson = {};
                          otherPerson.name = "Tiger";
                          otherPerson.say = function(){
                              return "I am " + this.name;
                          };

                          console.log(otherPerson.say()); // I am Tiger




Wednesday, November 10, 2010
A lot of duplication

                          var person = {};
                          person.name = "Scott";
                          person.say = function(){
                              return "I am " + this.name;
                          };
                          console.log(person.say()); // I am Scott

                          var otherPerson = {};
                          otherPerson.name = "Tiger";
                          otherPerson.say = function(){
                              return "I am " + this.name;
                          };

                          console.log(otherPerson.say()); // I am Tiger




Wednesday, November 10, 2010
Duplication is evil!




Wednesday, November 10, 2010
Custom Constructor Functions



                               var Person = function(name){
                                   this.name = name;
                                   this.say = function(){
                                       return "I am " + this.name;
                                   }
                               }
                               var person = new Person("Scott");

                               console.log(person.say()); // I am Scott




{pattern}
Wednesday, November 10, 2010
Behind the scenes...



                               var Person = function(name){
                                   // var this = {};
                                   this.name = name;
                                   this.say = function(){
                                       return "I am " + this.name;
                                   };
                                   // return this;
                               };




{pattern}
Wednesday, November 10, 2010
So, at the end...

                               var Person = function(name){
                                   this.name = name;
                                   this.say = function(){
                                       return "I am " + this.name;
                                   };
                               };

                               var scott = new Person('Scott');
                               var tiger = new Person('Tiger');

                               console.log(scott.say());
                               console.log(tiger.say());




{pattern}
Wednesday, November 10, 2010
What if we forget new?




Wednesday, November 10, 2010
this will point to global object

                           var Person = function(name){
                               this.name = name;
                               this.say = function(){
                                   return "I am " + this.name;
                               };
                           };

                           var scott = new Person('Scott')
                           var adam = Person('Adam')

                           console.log(typeof scott); //object
                           console.log(scott.name); // Scott
                           console.log(typeof adam); //'undefined'
                           console.log(window.name); // Adam




Wednesday, November 10, 2010
Enforce new pattern one: naming convention




Wednesday, November 10, 2010
var Person = function(name){
                                   var that = {};
                                   that.name = name;
                                   that.say = function(){
                                       return "I am " + that.name;};
                                   return that;
                               };

                               var scott = new Person('Scott')
                               var adam = Person('Adam')

                               console.log(typeof scott); //Object
                               console.log(scott.name); // Scott

                               console.log(typeof adam); //Object
                               console.log(adam.name); // Adam



{pattern}
Wednesday, November 10, 2010
Drawback: we loose prototype reference :-(

                          var Person = function(name){
                              var that = {};
                              that.name = name;
                              that.say = function(){
                                  return "I am " + that.name;
                              };
                              return that;
                          };

                          Person.prototype.iamhumanbeing = true;

                          var scott = new Person('Scott')
                          var adam = Person('Adam')

                          console.log(scott.iamhumanbeing); // undefined
                          console.log(adam.iamhumanbeing); // undefined




Wednesday, November 10, 2010
Interm!zo

                                Prototype property




Wednesday, November 10, 2010
Define ancestors chain




                               var foo = {one: 1, two: 2};
                               var bar = {three: 3};
                               foo.__proto__ = bar;
                               console.log(foo.one);
                               console.log(foo.three);




Wednesday, November 10, 2010
bar
                                        three: 3



                                foo
                               one: 1
                               two: 2
                      __proto__

Wednesday, November 10, 2010
Behind the scenes...



                          var Person = function(name){
                              // this.prototype = {constructor: this}
                              var that = {};
                              that.name = name;
                              that.say = function(){
                                  return "I am " + that.name;
                              };
                              return that;
                          };




Wednesday, November 10, 2010
Self invoking constructor
                               var Person = function(name){
                                   if (this instanceof Person) {
                                       this.name = name;
                                       this.say = function(){
                                           return "I am " + that.name;
                                       }
                                   }
                                   else {
                                       return new Person(name);
                                   }
                               };
                               Person.prototype.iamhumanbeing = true;
                               var scott = new Person('Scott')
                               var adam = Person('Adam')
                               console.log(scott.name); // Scott
                               console.log(adam.name); // Adam
                               console.log(scott.iamhumanbeing); // true
                               console.log(adam.iamhumanbeing); // true


{pattern}
Wednesday, November 10, 2010
Essential
                                  Functions




Wednesday, November 10, 2010
Functions as first class objects




Wednesday, November 10, 2010
Immediate functions




                                (function(){
                                    alert('watch out!');
                                })();




Wednesday, November 10, 2010
Initialization pattern




                               (function(){
                                   var days = ['Sun', 'Mon', 'Tue', 'Wed',
                               	              'Thu', 'Fri', 'Sat'],
                               	     today = new Date(),
                               	 	 msg = 'Today is ' +
                               	 	        days[today.getDay()] +
                               	 	 	    ', ' +
                               	 	 	    today.getDate();
                                   console.log(msg);
                               })(); // "Today is Wed, 10"




{pattern}
Wednesday, November 10, 2010
Function scope




Wednesday, November 10, 2010
5 globals...
                               // constructors
                               function Parent(){
                               }

                               function Child(){
                               }

                               // a variable
                               var some_var = 1;
                               // some objects
                               var module1 = {};
                               module1.data = {
                                   a: 1,
                                   b: 2
                               };
                               var module2 = {};



{antipattern}
Wednesday, November 10, 2010
1 global!
                         // global object
                         var MYAPP = (function(){
                             var my = {};
                                                           {pattern}
                             // constructors
                             my.Parent = function(){};
                             my.Child = function(){};
                             // a variable
                             my.some_var = 1;
                             // an object container
                             my.modules = {};
                             // nested objects
                             my.modules.module1 = {};
                             my.modules.module1.data = {
                                 a: 1,
                                 b: 2
                             };
                             my.modules.module2 = {};
                             return my;
                         })();

                         console.log(MYAPP.modules.module1.data.a); // 1

Wednesday, November 10, 2010
What about encapsulation?




Wednesday, November 10, 2010
function Gadget(){
                       this.name = 'iPod';
                       this.stretch = function(){
                           return 'iPad';
                       }
                   };

                   var toy = new Gadget();
                   console.log(toy.name); // `iPod`
                   toy.name = 'Zune'
                   console.log(toy.name); // `Zune` is public
                   console.log(toy.stretch()); // stretch() is public




{antipattern}
Wednesday, November 10, 2010
Create private member


                               function Gadget(){
                                   var name = 'iPod';
                                   this.getName = function(){
                                       return name;
                                   }
                               };

                               var toy = new Gadget();
                               console.log(toy.getName()); // `iPod`
                               toy.name = 'Zune'
                               console.log(toy.getName()); // `iPod`




{pattern}
Wednesday, November 10, 2010
for methods too
                               function Gadget() {
                                   var name = 'iPod';
                                   var upgrade = function(){
                                       return 'iPhone';
                                   }

                                    this.getName = function () {
                                        return name;
                                    }
                                    this.pay = function() {
                                        return upgrade();
                                    }
                               };

                               var toy = new Gadget();
                               console.log(toy.pay()); // `iPhone`
                               console.log(toy.upgrade()); // `error`



{pattern}
Wednesday, November 10, 2010
Advanced
                               Code reuse patterns




Wednesday, November 10, 2010
Classical vs prototypal inheritance




                                             vs

Wednesday, November 10, 2010
Classical inheritance
                               function Parent(name){
                                   this.name = name;
                               };

                               Parent.prototype.say = function(){
                                   return 'My name is ' + this.name;
                               };

                               function Child(name){
                                   this.name = name;
                               };

                               inherit(Child, Parent);

                               var dad = new Parent('Larry');
                               var kid = new Child('Scott');

                               console.log(dad.say()); // 'My name is Larry'
                               console.log(kid.say()); // 'My name is Scott'


Wednesday, November 10, 2010
function(){
                                                  return 'My name is ' + this.name;
                                              };
                                                        Parent.prototype
                                                             say()




                               new Parent()
                                name: Larry
                                __proto__


                                      console.log(dad.say());


Wednesday, November 10, 2010
Default Classical Inheritance pattern




                                      function inherit(C, P) {
                                          C.prototype = new P();
                                      };




Wednesday, November 10, 2010
function(){
                                           return 'My name is ' + this.name;
                                       };
                                                 Parent.prototype
                                                      say()




                                            new Parent()
                    new Child()              name: Larry
                    name: Scott              __proto__
                    __proto__

             console.log(kid.say());
Wednesday, November 10, 2010
Drawback: it doesn’t call parent constructor
                               function Parent(name){
                                   this.name = name;
                               };

                               Parent.prototype.say = function(){
                                   return 'My name is ' + this.name;
                               };

                               function Child(name){
                                   this.name = name;
                               };

                               inherit(Child, Parent);

                               var dad = new Parent('Larry');
                               var kid = new Child('Scott');

                               console.log(dad.say()); // 'My name is Larry'
                               console.log(kid.say()); // 'My name is Scott'


Wednesday, November 10, 2010
Drawback: it doesn’t call parent constructor
                     function Parent(name){
                         this.name = name;
                     };

                     Parent.prototype.say = function(){
                         return 'My name is ' + this.name;
                     };

                     function Child(name){ };

                     function inherit(C, P) {
                         C.prototype = new P();
                     };

                     inherit(Child, Parent);

                     var kid = new Child('Scott');

                     console.log(kid.say()); // 'My name is undefined'


Wednesday, November 10, 2010
Pattern Extension: rent a constructor




                               function Child(name){
                                   Parent.apply(this, arguments);
                               };




Wednesday, November 10, 2010
Pattern Extension: rent a constructor
                       function Parent(name){
                           this.name = name;
                       };
                       Parent.prototype.say = function(){
                           return 'My name is ' + this.name;
                       };

                       function Child(name){
                           Parent.apply(this, arguments);
                       };

                       function inherit(C, P){
                           C.prototype = new P();
                       };
                       inherit(Child, Parent);
                       var dad = new Parent('Larry');
                       var kid = new Child('Scott');
                       console.log(dad.say()); // 'My name is Larry'
                       console.log(kid.say()); // 'My name is Scott'

Wednesday, November 10, 2010
Drawback: parent constructor is called twice
                       function Parent(name){
                           this.name = name;
                       };
                       Parent.prototype.say = function(){
                           return 'My name is ' + this.name;
                       };

                       function Child(name){
                           Parent.apply(this, arguments);
                       };

                       function inherit(C, P){
                           C.prototype = new P();
                       };
                       inherit(Child, Parent);
                       var dad = new Parent('Larry');
                       var kid = new Child('Scott');
                       console.log(dad.say()); // 'My name is Larry'
                       console.log(kid.say()); // 'My name is Scott'

Wednesday, November 10, 2010
Drawback: parent constructor is called twice
                       function Parent(name){
                           this.name = name;
                       };
                       Parent.prototype.say = function(){
                           return 'My name is ' + this.name;
                       };

                       function Child(name){
                           Parent.apply(this, arguments);
                       };

                       function inherit(C, P){
                           C.prototype = new P();
                       };
                       inherit(Child, Parent);
                       var dad = new Parent('Larry');
                       var kid = new Child('Scott');
                       console.log(dad.say()); // 'My name is Larry'
                       console.log(kid.say()); // 'My name is Scott'

Wednesday, November 10, 2010
Drawback: parent constructor is called twice
                       function Parent(name){
                           this.name = name;
                       };
                       Parent.prototype.say = function(){
                           return 'My name is ' + this.name;
                       };

                       function Child(name){
                           Parent.apply(this, arguments);
                       };

                       function inherit(C, P){
                           C.prototype = new P();
                       };
                       inherit(Child, Parent);
                       var dad = new Parent('Larry');
                       var kid = new Child('Scott');
                       console.log(dad.say()); // 'My name is Larry'
                       console.log(kid.say()); // 'My name is Scott'

Wednesday, November 10, 2010
mmmm let’s try with the same prototype




Wednesday, November 10, 2010
Share the same prototype




                               function inherit(C, P){
                                   C.prototype = P.prototype;
                               };




Wednesday, November 10, 2010
Parent.prototype
                                       say()




                    new Child()                      new Parent()
                    name: Scott                       name: Larry
                    __proto__                         __proto__



Wednesday, November 10, 2010
Share the same prototype




                               Inheritance works as expected
                               Constructor called only once
                               Low memory footprint




Wednesday, November 10, 2010
Share the same prototype




                               Child objects can affect other objects




Wednesday, November 10, 2010
Enhance the pattern: temporary constructor




                               function inherit(C, P) {
                                   var F = function () {};
                                   F.prototype = P.prototype;
                                   C.prototype = new F();
                               };




Wednesday, November 10, 2010
Parent.prototype
                                    say()
            new Parent()                            new F()
             name: Larry                           __proto__
             __proto__




                                         new Child()
                                         name: Scott
                                         __proto__
Wednesday, November 10, 2010
The Holy Grail Pattern of classical inheritance




                               function inherit(C, P) {
                                   var F = function () {};
                                   F.prototype = P.prototype;
                                   C.prototype = new F();
                                   C.uber = P.prototype;
                                   C.prototype.constructor = C;
                               };




Wednesday, November 10, 2010
We got it!




Wednesday, November 10, 2010
What about Prototypal Inheritance?




Wednesday, November 10, 2010
No more classes, only objects




Wednesday, November 10, 2010
What we want in prototypal inheritance



                               var parent = {
                                   name: "Larry",
                                   say: function(){
                                       return "My name is " + this.name;
                                   }
                               };

                               var child = object(parent);
                               child.name = 'Scott'

                               console.log(child.say()); // "Scott"




Wednesday, November 10, 2010
Prototypal inheritance function




                                      function object(o) {
                                          function F() {}
                                          F.prototype = o;
                                          return new F();
                                      };




Wednesday, November 10, 2010
parent
                               name: Scott
                                  say()




                                             child = new F()
                                               name: Larry
                                               __proto__



Wednesday, November 10, 2010
With constructor function


                               var Parent = function(name){
                                   this.name = name;
                                   this.say = function(){
                                       return "My name is " + this.name;
                                   }
                               };

                               var child = object(new Parent("Larry"));
                               child.name = 'Scott'

                               console.log(child.say()); // "Scott"




Wednesday, November 10, 2010
better classical or prototypal?




Wednesday, November 10, 2010
It depends




Wednesday, November 10, 2010
Goals of inheritance is reuse and reduce duplication




Wednesday, November 10, 2010
isA relationship...
                        Liskov principle...
                  difficult to tame inheritance...




Wednesday, November 10, 2010
A modern and better approach is to use


                                   Mix-In




Wednesday, November 10, 2010
A beahviour...


                               var Serializer = function () {};
                               Serializer.prototype = {
                                   serialize: function () {
                                       var output = [];
                                       for (key in this) {
                                           // append this[key] to output
                               	 	 	      // ...
                                       }
                                       return output.join(', ');
                                   }
                               };




Wednesday, November 10, 2010
another beahviour...


                       var XmlBuilder = function () {};
                       XmlBuilder.prototype = {
                           toXml: function () {
                               var output = '';
                               for (key in this) {
                                    // append xml of this[key] to output
                                    // ...
                               }
                               return output;
                           }
                       };




Wednesday, November 10, 2010
and an object...



                               var Author = function (name, books) {
                                   this.name = name || "";
                                   this.books = books || [];
                               }




Wednesday, November 10, 2010
result!
       augment(Author, Serializer);
       augment(Author, XmlBuilder);

       var author = new Author('Umberto Eco',
                               ['Il nome della rosa',
                                'Il Pendolo di Foucault']);
       var serializedString = author.serialize();
       console.log(serializedString); // name: Umberto Eco,
                                       // books: Il nome della rosa,
                                      // Il Pendolo di Foucault
       var xmlString = author.toXml();
       console.log(xmlString); //<name>Umberto Eco</name>
                               // <book>Il nome della rosa</book>
       	 	 	 	 	 	             // <book>Il Pendolo di Focault</book>




Wednesday, November 10, 2010
The recipe



                  function augment(receivingClass, givingClass) {
                      for (methodName in givingClass.prototype) {
                          if (!receivingClass.prototype[methodName]) {
                              receivingClass.prototype[methodName] =
                               givingClass.prototype[methodName];
                          }
                      }
                  }




Wednesday, November 10, 2010
Advanced
                               Design Patterns




Wednesday, November 10, 2010
Wednesday, November 10, 2010
“A design pattern is a
                               general reusable solution to
                               a commonly occurring
                               problem”




Wednesday, November 10, 2010
JavaScript is not J@#*!




Wednesday, November 10, 2010
Factory pattern
                  creation of objects
                  subclasses decide which class to instantiate




Wednesday, November 10, 2010
var BicycleFactory = {
      createBicycle: function(model){
          var bicycle;
          switch (model) {
              case 'The Speedster':
                  bicycle = new Speedster();
                  break;
              case 'The Lowrider':
                  bicycle = new Lowrider();
                  break;
              case 'The Comfort Cruiser':
              default:
                  bicycle = new ComfortCruiser();
          }
          Interface.ensureImplements(bicycle, Bicycle);
          bicycle.assemble();
          bicycle.wash();
          return bicycle;
      }
  };
  var californiaCruisers = new BicycleFactory();
  var yourNewBike = californiaCruisers.createBicycle('The Speedster');

Wednesday, November 10, 2010
A more concrete example...

     var XMLHttpFactory = function(){
         this.createXMLHttp = function(){
             if (typeof XMLHttpRequest !== "undefined") {
                  return XMLHttpRequest();
             }
             else
                  if (typeof window.ActiveXObject !== "undefined") {
                      return ActiveXObject("MSXML2.XMLHttp");
                  }
                  else {
                      alert("XHR Object not in production");
                  }
         }
     };

     var xhr = new XMLHttpFactory().createXMLHttp();




Wednesday, November 10, 2010
It seems lightly broken....




Wednesday, November 10, 2010
var XMLHttpFactory = function(){
         this.createXMLHttp = function(){
             if (typeof XMLHttpRequest !== "undefined") {
                  return XMLHttpRequest();
             }
             else
                  if (typeof window.ActiveXObject !== "undefined") {
                      return ActiveXObject("MSXML2.XMLHttp");
                  }
                  else {
                      alert("XHR Object not in production");
                  }
         }
     };

     var xhr = new XMLHttpFactory().createXMLHttp();




Wednesday, November 10, 2010
Chain of Responsibility pattern




Wednesday, November 10, 2010
Extract condition and action....



                       var XhrStandard = function(){
                            this.canHandle = function(){
                              return typeof XMLHttpRequest !== "undefined";
                            }

                               this.xhr = function(){
                                 return XMLHttpRequest();
                               }
                         };




Wednesday, November 10, 2010
another condition and action....




                         var XhrIe = function(){
                             this.canHandle = function(){
                               return typeof ActiveXObject !== "undefined";
                             }
                            this.xhr = function(){
                               return ActiveXObject("MSXML2.XMLHttp");
                             }
                         };




Wednesday, November 10, 2010
and last one condition and action....




                               var XhrError = function(){
                                   this.canHandle = function(){
                                     return true;
                                   }
                                  this.xhr = function(){
                                     throw("XHR Object not in production");
                                   }
                               };




Wednesday, November 10, 2010
and the engine!
                var XMLHttpFactory = function(){
                    //... ChainLinks...
                    var creators = [new XhrStandard(),
                                    new XhrIe(),
                                    new XhrError()];

                         this.createXMLHttp = function(){
                                 var creator;
                                 for(var i = 0; i < creators.length; ++i){
                                     creator = creators[i];
                                     if(creator.canHandle()) {
                                         return creator.xhr();
                                     }
                                 }
                         }
                };

                var xhr = new XMLHttpFactory().createXMLHttp();
                console.log(xhr);



Wednesday, November 10, 2010
Or following the book...




Wednesday, November 10, 2010
Refactored an action...
                   var XhrStandard = function(){
                       this.canHandle = function(){
                           return typeof XMLHttpRequest !== "undefined";
                       }

                               this.xhr = function(){
                                   if (this.canHandle()) {
                                       return XMLHttpRequest();
                                   }
                                   return this.successor.xhr();
                               }

                               this.addSuccessor = function(successor){
                                   this.successor = successor;
                                   return this.successor;
                               }
                   };




Wednesday, November 10, 2010
other action...
                      var XhrIe = function(){
                          this.canHandle = function(){
                              return typeof ActiveXObject !== "undefined";
                          }
                          this.xhr = function(){
                              if (this.canHandle()) {
                                  return ActiveXObject("MSXML2.XMLHttp");
                              }
                              return this.successor.xhr();
                          }

                               this.addSuccessor = function(successor){
                                   this.successor = successor;
                                   return this.successor;
                               }
                      };




Wednesday, November 10, 2010
last action...


                         var XhrError = function(){
                             this.canHandle = function(){
                                 return true;
                             }
                             this.xhr = function(){
                                 throw ("XHR Object not in production");
                             }
                             this.addSuccessor = function(successor){
                                 this.successor = successor;
                                 return this.successor;
                             }
                         };




Wednesday, November 10, 2010
and the engine!
                   var XMLHttpFactory = function(){
                     //... ChainLinks...

                               var creator = (function(){
                                   var head = new XhrIe();
                                   head.addSuccessor(new XhrStandard())
                                       .addSuccessor(new XhrError());
                                   return head;
                               })();

                               this.createXMLHttp = function(){
                                   return creator.xhr();
                               }
                   };

                   var xhr = new XMLHttpFactory().createXMLHttp();
                   console.log(xhr);




Wednesday, November 10, 2010
mmm duplication...




Wednesday, November 10, 2010
Same for all...
                      var XhrIe = function(){
                          this.canHandle = function(){
                              return typeof ActiveXObject !== "undefined";
                          }
                          this.xhr = function(){
                              if (this.canHandle()) {
                                  return ActiveXObject("MSXML2.XMLHttp");
                              }
                              return this.successor.xhr();
                          }

                               this.addSuccessor = function(successor){
                                   this.successor = successor;
                                   return this.successor;
                               }
                      };




Wednesday, November 10, 2010
Similar for all..
                      var XhrIe = function(){
                          this.canHandle = function(){
                              return typeof ActiveXObject !== "undefined";
                          }
                          this.xhr = function(){
                              if (this.canHandle()) {
                                  return ActiveXObject("MSXML2.XMLHttp");
                              }
                              return this.successor.xhr();
                          }

                               this.addSuccessor = function(successor){
                                   this.successor = successor;
                                   return this.successor;
                               }
                      };




Wednesday, November 10, 2010
Template Method pattern




Wednesday, November 10, 2010
Template Method pattern



                               ... and a little bit of Mix-In




Wednesday, November 10, 2010
Extracted same and similar behaviours....


                var ChainLink = function() {};
                ChainLink.prototype.exec = function(){
                       if(this.canHandle()) {
                         return this.doIt();
                       }
                       return this.successor.exec();
                    };

                         ChainLink.prototype.addSuccessor = function(successor){
                             this.successor = successor;
                             return this.successor;
                         }




Wednesday, November 10, 2010
Augment an action...



                       var XhrStandard = augment(function(){
                           this.canHandle = function(){
                              return typeof XMLHttpRequest !== "undefined";
                           }
                           this.doIt = function(){
                                  return XMLHttpRequest();
                           };
                       }, ChainLink);




Wednesday, November 10, 2010
another action...




                 var XhrIe = augment(function(){
                     this.canHandle = function(){
                        return typeof ActiveXObject !== "undefined";
                     }
                     this.doIt = function(){
                          return this.doIt();
                     };
                 }, ChainLink);




Wednesday, November 10, 2010
and last one.



                               var XhrError = augment(function(){
                                   this.canHandle = function(){
                                     return true;
                                   }

                                   this.doIt = function(){
                                     throw("XHR Object not in production");
                                   }
                               },ChainLink);




Wednesday, November 10, 2010
and the engine is the same!
                   var XMLHttpFactory = function(){
                     //... ChainLinks...

                               var creator = (function(){
                                   var head = new XhrIe();
                                   head.addSuccessor(new XhrStandard())
                                       .addSuccessor(new XhrError());
                                   return head;
                               })();

                               this.createXMLHttp = function(){
                                   return creator.xhr();
                               }
                   };

                   var xhr = new XMLHttpFactory().createXMLHttp();
                   console.log(xhr);




Wednesday, November 10, 2010
It’s just a beginning...




Wednesday, November 10, 2010
peep code


Wednesday, November 10, 2010
Study




Wednesday, November 10, 2010
Wednesday, November 10, 2010
Wednesday, November 10, 2010
“Save it for a rainy day!”




Wednesday, November 10, 2010
Check your code with jslint.com




Wednesday, November 10, 2010
Wednesday, November 10, 2010
giordano.scalzo@cleancode.it
                               @giordanoscalzo
                               www.slideshare.net/giordano
                               github.com/gscalzo
Wednesday, November 10, 2010

More Related Content

PDF
JavaScript Patterns
PDF
JavaScript Survival Guide
PDF
Javascript the Language of the Web
PDF
Better Software: introduction to good code
PDF
Tkinter Does Not Suck
PDF
State Machine Presentation62 End
PPTX
YUI Tidbits
PDF
東急Ruby会議向け「rubyの細かい話」
JavaScript Patterns
JavaScript Survival Guide
Javascript the Language of the Web
Better Software: introduction to good code
Tkinter Does Not Suck
State Machine Presentation62 End
YUI Tidbits
東急Ruby会議向け「rubyの細かい話」

What's hot (19)

PDF
TypoScript 2.0
PDF
Basic Mechanism of OOPL
PDF
Java synchronizers
PDF
Prototype
PDF
Js in the open
PPTX
Tech Talks - Fundamentos JavaScript
PPT
Floggy-M3DD-2009-01-21
PDF
The Ring programming language version 1.7 book - Part 83 of 196
PDF
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
PDF
不自然なcar/ナチュラルにconsして
PDF
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
PPTX
PDF
Objective-C for Beginners
PDF
Java Concurrency Gotchas
PDF
Swift 3 Programming for iOS : subscript init
PDF
Python for text processing
PDF
Python introduction
ZIP
Cleanup and new optimizations in WPython 1.1
PDF
PyFoursquare: Python Library for Foursquare
TypoScript 2.0
Basic Mechanism of OOPL
Java synchronizers
Prototype
Js in the open
Tech Talks - Fundamentos JavaScript
Floggy-M3DD-2009-01-21
The Ring programming language version 1.7 book - Part 83 of 196
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
不自然なcar/ナチュラルにconsして
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
Objective-C for Beginners
Java Concurrency Gotchas
Swift 3 Programming for iOS : subscript init
Python for text processing
Python introduction
Cleanup and new optimizations in WPython 1.1
PyFoursquare: Python Library for Foursquare
Ad

Viewers also liked (7)

PPT
Loosely Coupled Complexity - Unleash the power of your domain model
PPTX
"Don't call us, we'll call you" - AngularJS meets Event-Driven Architecture
PDF
[Alam aeki] Guida illustrata alla modellazione di un dominio con Event Sourci...
PDF
Layered Expression Trees feat. CQRS
PPT
SUE AGILE Architettura (Italiano)
PPTX
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
PDF
Architetttura Della Soluzione
Loosely Coupled Complexity - Unleash the power of your domain model
"Don't call us, we'll call you" - AngularJS meets Event-Driven Architecture
[Alam aeki] Guida illustrata alla modellazione di un dominio con Event Sourci...
Layered Expression Trees feat. CQRS
SUE AGILE Architettura (Italiano)
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Architetttura Della Soluzione
Ad

Similar to Java scriptpatterns (20)

PDF
JavaScript: Advanced Scoping & Other Puzzles
PDF
Javascript Basics - part 1
PDF
03 Advanced JavaScript
PDF
JSLent: give it up for JavaScript
PPT
Wakanday JS201 Best Practices
PPT
Java Script Patterns
PDF
Javascript the Interlingua of the Web
PDF
Javascript classes and scoping
PPTX
Awesomeness of JavaScript…almost
PDF
Understanding JavaScript
PPTX
Wintellect - Devscovery - Enterprise JavaScript Development 1 of 2
PDF
JavaScript Primer
PPTX
Introduction to Client-Side Javascript
PDF
Design patterns in java script, jquery, angularjs
PPT
Goodparts
PDF
Future-proofing Your JavaScript Apps (Compact edition)
PDF
Enterprise javascriptsession1
PPTX
Javascript fundamentals and not
PDF
JavaScript - Like a Box of Chocolates
PDF
Responsible JavaScript
JavaScript: Advanced Scoping & Other Puzzles
Javascript Basics - part 1
03 Advanced JavaScript
JSLent: give it up for JavaScript
Wakanday JS201 Best Practices
Java Script Patterns
Javascript the Interlingua of the Web
Javascript classes and scoping
Awesomeness of JavaScript…almost
Understanding JavaScript
Wintellect - Devscovery - Enterprise JavaScript Development 1 of 2
JavaScript Primer
Introduction to Client-Side Javascript
Design patterns in java script, jquery, angularjs
Goodparts
Future-proofing Your JavaScript Apps (Compact edition)
Enterprise javascriptsession1
Javascript fundamentals and not
JavaScript - Like a Box of Chocolates
Responsible JavaScript

More from Francesca1980 (9)

PPT
Map meshup
PPTX
Advanced JQuery
PDF
Java scriptpatterns
PDF
Event driven javascript
PDF
Event driven javascript
PDF
Simple Cloud API: accesso semplificato al cloud computing
PPTX
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
ODP
Writing cool web 2.0 apps with GWT and UI Bindings
PDF
Programmazione web libera dai framework
Map meshup
Advanced JQuery
Java scriptpatterns
Event driven javascript
Event driven javascript
Simple Cloud API: accesso semplificato al cloud computing
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
Writing cool web 2.0 apps with GWT and UI Bindings
Programmazione web libera dai framework

Java scriptpatterns

  • 1. JavaScript Patterns Giordano Scalzo Wednesday, November 10, 2010
  • 2. I’m not a guru! Wednesday, November 10, 2010
  • 5. JavaScript isn’t this anymore Wednesday, November 10, 2010
  • 7. JavaScript is trendy! Technology Radar Wednesday, November 10, 2010
  • 8. JavaScript is trendy! Technology Radar Wednesday, November 10, 2010
  • 9. At the beginning... Wednesday, November 10, 2010
  • 10. Hacked by Brendan Eich in one week... Wednesday, November 10, 2010
  • 11. Former Mocha, renamed to JavaScript by Netscape Wednesday, November 10, 2010
  • 12. after a while... Wednesday, November 10, 2010
  • 16. Back to study! Wednesday, November 10, 2010
  • 17. Started a notebook... Wednesday, November 10, 2010
  • 18. Essential Scope Wednesday, November 10, 2010
  • 19. function sum(x, y){ // implied global result = x + y; return result; } {antipattern} Wednesday, November 10, 2010
  • 20. Global variables are evil! Wednesday, November 10, 2010
  • 22. Always declare variables with var function sum(x, y){ var result = x + y; return result; } {pattern} Wednesday, November 10, 2010
  • 23. function foo(){ var a = b = 0; //... } {antipattern} Wednesday, November 10, 2010
  • 24. b become global function foo(){ var a = (b = 0); //... } {antipattern} Wednesday, November 10, 2010
  • 25. don’t use assign chain in definition function foo(){ var a, b; a = b = 0; //... } {pattern} Wednesday, November 10, 2010
  • 26. Single var pattern function func(){ var a = 1, b = 2, sum = a + b, myobject = {}, i, j; // function body... } {pattern} Wednesday, November 10, 2010
  • 27. Don’t forget comma otherwise... Wednesday, November 10, 2010
  • 28. ... variables become globals Wednesday, November 10, 2010
  • 29. Hoisting myname = "global"; // global variable function func(){ // code... console.log(myname); // "undefined" // code... var myname = "local"; console.log(myname); // "local" } func(); {antipattern} Wednesday, November 10, 2010
  • 30. Hoisting myname = "global"; // global variable function func(){ var myname = "declared"; // code... console.log(myname); // "declared" // code... myname = "local"; console.log(myname); // "local" } func(); {pattern} Wednesday, November 10, 2010
  • 31. Against minimum vertical distance principle “Variables should be declared as close to their usage as possible” Robert C. Martin - Clean Code Wednesday, November 10, 2010
  • 32. Essential Literal and Constructor Wednesday, November 10, 2010
  • 33. In JavaScript almost everything is an object Wednesday, November 10, 2010
  • 34. It’s easy... var person = new Object(); person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); Wednesday, November 10, 2010
  • 35. but wrong! :-( var person = new Object(); person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); {antipattern} Wednesday, November 10, 2010
  • 36. var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); {pattern} Wednesday, November 10, 2010
  • 37. What if we need similar objects... var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); // I am Scott var otherPerson = {}; otherPerson.name = "Tiger"; otherPerson.say = function(){ return "I am " + this.name; }; console.log(otherPerson.say()); // I am Tiger Wednesday, November 10, 2010
  • 38. A lot of duplication var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); // I am Scott var otherPerson = {}; otherPerson.name = "Tiger"; otherPerson.say = function(){ return "I am " + this.name; }; console.log(otherPerson.say()); // I am Tiger Wednesday, November 10, 2010
  • 39. Duplication is evil! Wednesday, November 10, 2010
  • 40. Custom Constructor Functions var Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; } } var person = new Person("Scott"); console.log(person.say()); // I am Scott {pattern} Wednesday, November 10, 2010
  • 41. Behind the scenes... var Person = function(name){ // var this = {}; this.name = name; this.say = function(){ return "I am " + this.name; }; // return this; }; {pattern} Wednesday, November 10, 2010
  • 42. So, at the end... var Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; }; }; var scott = new Person('Scott'); var tiger = new Person('Tiger'); console.log(scott.say()); console.log(tiger.say()); {pattern} Wednesday, November 10, 2010
  • 43. What if we forget new? Wednesday, November 10, 2010
  • 44. this will point to global object var Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; }; }; var scott = new Person('Scott') var adam = Person('Adam') console.log(typeof scott); //object console.log(scott.name); // Scott console.log(typeof adam); //'undefined' console.log(window.name); // Adam Wednesday, November 10, 2010
  • 45. Enforce new pattern one: naming convention Wednesday, November 10, 2010
  • 46. var Person = function(name){ var that = {}; that.name = name; that.say = function(){ return "I am " + that.name;}; return that; }; var scott = new Person('Scott') var adam = Person('Adam') console.log(typeof scott); //Object console.log(scott.name); // Scott console.log(typeof adam); //Object console.log(adam.name); // Adam {pattern} Wednesday, November 10, 2010
  • 47. Drawback: we loose prototype reference :-( var Person = function(name){ var that = {}; that.name = name; that.say = function(){ return "I am " + that.name; }; return that; }; Person.prototype.iamhumanbeing = true; var scott = new Person('Scott') var adam = Person('Adam') console.log(scott.iamhumanbeing); // undefined console.log(adam.iamhumanbeing); // undefined Wednesday, November 10, 2010
  • 48. Interm!zo Prototype property Wednesday, November 10, 2010
  • 49. Define ancestors chain var foo = {one: 1, two: 2}; var bar = {three: 3}; foo.__proto__ = bar; console.log(foo.one); console.log(foo.three); Wednesday, November 10, 2010
  • 50. bar three: 3 foo one: 1 two: 2 __proto__ Wednesday, November 10, 2010
  • 51. Behind the scenes... var Person = function(name){ // this.prototype = {constructor: this} var that = {}; that.name = name; that.say = function(){ return "I am " + that.name; }; return that; }; Wednesday, November 10, 2010
  • 52. Self invoking constructor var Person = function(name){ if (this instanceof Person) { this.name = name; this.say = function(){ return "I am " + that.name; } } else { return new Person(name); } }; Person.prototype.iamhumanbeing = true; var scott = new Person('Scott') var adam = Person('Adam') console.log(scott.name); // Scott console.log(adam.name); // Adam console.log(scott.iamhumanbeing); // true console.log(adam.iamhumanbeing); // true {pattern} Wednesday, November 10, 2010
  • 53. Essential Functions Wednesday, November 10, 2010
  • 54. Functions as first class objects Wednesday, November 10, 2010
  • 55. Immediate functions (function(){ alert('watch out!'); })(); Wednesday, November 10, 2010
  • 56. Initialization pattern (function(){ var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], today = new Date(), msg = 'Today is ' + days[today.getDay()] + ', ' + today.getDate(); console.log(msg); })(); // "Today is Wed, 10" {pattern} Wednesday, November 10, 2010
  • 58. 5 globals... // constructors function Parent(){ } function Child(){ } // a variable var some_var = 1; // some objects var module1 = {}; module1.data = { a: 1, b: 2 }; var module2 = {}; {antipattern} Wednesday, November 10, 2010
  • 59. 1 global! // global object var MYAPP = (function(){ var my = {}; {pattern} // constructors my.Parent = function(){}; my.Child = function(){}; // a variable my.some_var = 1; // an object container my.modules = {}; // nested objects my.modules.module1 = {}; my.modules.module1.data = { a: 1, b: 2 }; my.modules.module2 = {}; return my; })(); console.log(MYAPP.modules.module1.data.a); // 1 Wednesday, November 10, 2010
  • 61. function Gadget(){ this.name = 'iPod'; this.stretch = function(){ return 'iPad'; } }; var toy = new Gadget(); console.log(toy.name); // `iPod` toy.name = 'Zune' console.log(toy.name); // `Zune` is public console.log(toy.stretch()); // stretch() is public {antipattern} Wednesday, November 10, 2010
  • 62. Create private member function Gadget(){ var name = 'iPod'; this.getName = function(){ return name; } }; var toy = new Gadget(); console.log(toy.getName()); // `iPod` toy.name = 'Zune' console.log(toy.getName()); // `iPod` {pattern} Wednesday, November 10, 2010
  • 63. for methods too function Gadget() { var name = 'iPod'; var upgrade = function(){ return 'iPhone'; } this.getName = function () { return name; } this.pay = function() { return upgrade(); } }; var toy = new Gadget(); console.log(toy.pay()); // `iPhone` console.log(toy.upgrade()); // `error` {pattern} Wednesday, November 10, 2010
  • 64. Advanced Code reuse patterns Wednesday, November 10, 2010
  • 65. Classical vs prototypal inheritance vs Wednesday, November 10, 2010
  • 66. Classical inheritance function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ this.name = name; }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 67. function(){ return 'My name is ' + this.name; }; Parent.prototype say() new Parent() name: Larry __proto__ console.log(dad.say()); Wednesday, November 10, 2010
  • 68. Default Classical Inheritance pattern function inherit(C, P) { C.prototype = new P(); }; Wednesday, November 10, 2010
  • 69. function(){ return 'My name is ' + this.name; }; Parent.prototype say() new Parent() new Child() name: Larry name: Scott __proto__ __proto__ console.log(kid.say()); Wednesday, November 10, 2010
  • 70. Drawback: it doesn’t call parent constructor function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ this.name = name; }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 71. Drawback: it doesn’t call parent constructor function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ }; function inherit(C, P) { C.prototype = new P(); }; inherit(Child, Parent); var kid = new Child('Scott'); console.log(kid.say()); // 'My name is undefined' Wednesday, November 10, 2010
  • 72. Pattern Extension: rent a constructor function Child(name){ Parent.apply(this, arguments); }; Wednesday, November 10, 2010
  • 73. Pattern Extension: rent a constructor function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 74. Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 75. Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 76. Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 77. mmmm let’s try with the same prototype Wednesday, November 10, 2010
  • 78. Share the same prototype function inherit(C, P){ C.prototype = P.prototype; }; Wednesday, November 10, 2010
  • 79. Parent.prototype say() new Child() new Parent() name: Scott name: Larry __proto__ __proto__ Wednesday, November 10, 2010
  • 80. Share the same prototype Inheritance works as expected Constructor called only once Low memory footprint Wednesday, November 10, 2010
  • 81. Share the same prototype Child objects can affect other objects Wednesday, November 10, 2010
  • 82. Enhance the pattern: temporary constructor function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); }; Wednesday, November 10, 2010
  • 83. Parent.prototype say() new Parent() new F() name: Larry __proto__ __proto__ new Child() name: Scott __proto__ Wednesday, November 10, 2010
  • 84. The Holy Grail Pattern of classical inheritance function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; C.prototype.constructor = C; }; Wednesday, November 10, 2010
  • 85. We got it! Wednesday, November 10, 2010
  • 86. What about Prototypal Inheritance? Wednesday, November 10, 2010
  • 87. No more classes, only objects Wednesday, November 10, 2010
  • 88. What we want in prototypal inheritance var parent = { name: "Larry", say: function(){ return "My name is " + this.name; } }; var child = object(parent); child.name = 'Scott' console.log(child.say()); // "Scott" Wednesday, November 10, 2010
  • 89. Prototypal inheritance function function object(o) { function F() {} F.prototype = o; return new F(); }; Wednesday, November 10, 2010
  • 90. parent name: Scott say() child = new F() name: Larry __proto__ Wednesday, November 10, 2010
  • 91. With constructor function var Parent = function(name){ this.name = name; this.say = function(){ return "My name is " + this.name; } }; var child = object(new Parent("Larry")); child.name = 'Scott' console.log(child.say()); // "Scott" Wednesday, November 10, 2010
  • 92. better classical or prototypal? Wednesday, November 10, 2010
  • 94. Goals of inheritance is reuse and reduce duplication Wednesday, November 10, 2010
  • 95. isA relationship... Liskov principle... difficult to tame inheritance... Wednesday, November 10, 2010
  • 96. A modern and better approach is to use Mix-In Wednesday, November 10, 2010
  • 97. A beahviour... var Serializer = function () {}; Serializer.prototype = { serialize: function () { var output = []; for (key in this) { // append this[key] to output // ... } return output.join(', '); } }; Wednesday, November 10, 2010
  • 98. another beahviour... var XmlBuilder = function () {}; XmlBuilder.prototype = { toXml: function () { var output = ''; for (key in this) { // append xml of this[key] to output // ... } return output; } }; Wednesday, November 10, 2010
  • 99. and an object... var Author = function (name, books) { this.name = name || ""; this.books = books || []; } Wednesday, November 10, 2010
  • 100. result! augment(Author, Serializer); augment(Author, XmlBuilder); var author = new Author('Umberto Eco', ['Il nome della rosa', 'Il Pendolo di Foucault']); var serializedString = author.serialize(); console.log(serializedString); // name: Umberto Eco, // books: Il nome della rosa, // Il Pendolo di Foucault var xmlString = author.toXml(); console.log(xmlString); //<name>Umberto Eco</name> // <book>Il nome della rosa</book> // <book>Il Pendolo di Focault</book> Wednesday, November 10, 2010
  • 101. The recipe function augment(receivingClass, givingClass) { for (methodName in givingClass.prototype) { if (!receivingClass.prototype[methodName]) { receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } } } Wednesday, November 10, 2010
  • 102. Advanced Design Patterns Wednesday, November 10, 2010
  • 104. “A design pattern is a general reusable solution to a commonly occurring problem” Wednesday, November 10, 2010
  • 105. JavaScript is not J@#*! Wednesday, November 10, 2010
  • 106. Factory pattern creation of objects subclasses decide which class to instantiate Wednesday, November 10, 2010
  • 107. var BicycleFactory = { createBicycle: function(model){ var bicycle; switch (model) { case 'The Speedster': bicycle = new Speedster(); break; case 'The Lowrider': bicycle = new Lowrider(); break; case 'The Comfort Cruiser': default: bicycle = new ComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); bicycle.assemble(); bicycle.wash(); return bicycle; } }; var californiaCruisers = new BicycleFactory(); var yourNewBike = californiaCruisers.createBicycle('The Speedster'); Wednesday, November 10, 2010
  • 108. A more concrete example... var XMLHttpFactory = function(){ this.createXMLHttp = function(){ if (typeof XMLHttpRequest !== "undefined") { return XMLHttpRequest(); } else if (typeof window.ActiveXObject !== "undefined") { return ActiveXObject("MSXML2.XMLHttp"); } else { alert("XHR Object not in production"); } } }; var xhr = new XMLHttpFactory().createXMLHttp(); Wednesday, November 10, 2010
  • 109. It seems lightly broken.... Wednesday, November 10, 2010
  • 110. var XMLHttpFactory = function(){ this.createXMLHttp = function(){ if (typeof XMLHttpRequest !== "undefined") { return XMLHttpRequest(); } else if (typeof window.ActiveXObject !== "undefined") { return ActiveXObject("MSXML2.XMLHttp"); } else { alert("XHR Object not in production"); } } }; var xhr = new XMLHttpFactory().createXMLHttp(); Wednesday, November 10, 2010
  • 111. Chain of Responsibility pattern Wednesday, November 10, 2010
  • 112. Extract condition and action.... var XhrStandard = function(){ this.canHandle = function(){ return typeof XMLHttpRequest !== "undefined"; } this.xhr = function(){ return XMLHttpRequest(); } }; Wednesday, November 10, 2010
  • 113. another condition and action.... var XhrIe = function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.xhr = function(){ return ActiveXObject("MSXML2.XMLHttp"); } }; Wednesday, November 10, 2010
  • 114. and last one condition and action.... var XhrError = function(){ this.canHandle = function(){ return true; } this.xhr = function(){ throw("XHR Object not in production"); } }; Wednesday, November 10, 2010
  • 115. and the engine! var XMLHttpFactory = function(){ //... ChainLinks... var creators = [new XhrStandard(), new XhrIe(), new XhrError()]; this.createXMLHttp = function(){ var creator; for(var i = 0; i < creators.length; ++i){ creator = creators[i]; if(creator.canHandle()) { return creator.xhr(); } } } }; var xhr = new XMLHttpFactory().createXMLHttp(); console.log(xhr); Wednesday, November 10, 2010
  • 116. Or following the book... Wednesday, November 10, 2010
  • 117. Refactored an action... var XhrStandard = function(){ this.canHandle = function(){ return typeof XMLHttpRequest !== "undefined"; } this.xhr = function(){ if (this.canHandle()) { return XMLHttpRequest(); } return this.successor.xhr(); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 118. other action... var XhrIe = function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.xhr = function(){ if (this.canHandle()) { return ActiveXObject("MSXML2.XMLHttp"); } return this.successor.xhr(); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 119. last action... var XhrError = function(){ this.canHandle = function(){ return true; } this.xhr = function(){ throw ("XHR Object not in production"); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 120. and the engine! var XMLHttpFactory = function(){ //... ChainLinks... var creator = (function(){ var head = new XhrIe(); head.addSuccessor(new XhrStandard()) .addSuccessor(new XhrError()); return head; })(); this.createXMLHttp = function(){ return creator.xhr(); } }; var xhr = new XMLHttpFactory().createXMLHttp(); console.log(xhr); Wednesday, November 10, 2010
  • 122. Same for all... var XhrIe = function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.xhr = function(){ if (this.canHandle()) { return ActiveXObject("MSXML2.XMLHttp"); } return this.successor.xhr(); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 123. Similar for all.. var XhrIe = function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.xhr = function(){ if (this.canHandle()) { return ActiveXObject("MSXML2.XMLHttp"); } return this.successor.xhr(); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 125. Template Method pattern ... and a little bit of Mix-In Wednesday, November 10, 2010
  • 126. Extracted same and similar behaviours.... var ChainLink = function() {}; ChainLink.prototype.exec = function(){ if(this.canHandle()) { return this.doIt(); } return this.successor.exec(); }; ChainLink.prototype.addSuccessor = function(successor){ this.successor = successor; return this.successor; } Wednesday, November 10, 2010
  • 127. Augment an action... var XhrStandard = augment(function(){ this.canHandle = function(){ return typeof XMLHttpRequest !== "undefined"; } this.doIt = function(){ return XMLHttpRequest(); }; }, ChainLink); Wednesday, November 10, 2010
  • 128. another action... var XhrIe = augment(function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.doIt = function(){ return this.doIt(); }; }, ChainLink); Wednesday, November 10, 2010
  • 129. and last one. var XhrError = augment(function(){ this.canHandle = function(){ return true; } this.doIt = function(){ throw("XHR Object not in production"); } },ChainLink); Wednesday, November 10, 2010
  • 130. and the engine is the same! var XMLHttpFactory = function(){ //... ChainLinks... var creator = (function(){ var head = new XhrIe(); head.addSuccessor(new XhrStandard()) .addSuccessor(new XhrError()); return head; })(); this.createXMLHttp = function(){ return creator.xhr(); } }; var xhr = new XMLHttpFactory().createXMLHttp(); console.log(xhr); Wednesday, November 10, 2010
  • 131. It’s just a beginning... Wednesday, November 10, 2010
  • 136. “Save it for a rainy day!” Wednesday, November 10, 2010
  • 137. Check your code with jslint.com Wednesday, November 10, 2010
  • 139. giordano.scalzo@cleancode.it @giordanoscalzo www.slideshare.net/giordano github.com/gscalzo Wednesday, November 10, 2010