• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Java scriptpatterns
 

Java scriptpatterns

on

  • 1,084 views

Un design pattern è soluzione generale e riusabile ad un problema ricorrente; ma tutti i design patterns "classici" possono essere utilizzati in Javascript? Esistono design patterns tipici di ...

Un design pattern è soluzione generale e riusabile ad un problema ricorrente; ma tutti i design patterns "classici" possono essere utilizzati in Javascript? Esistono design patterns tipici di Javascript? In questo talk vedremo quali design pattern classici si possono implementare in Javascript, e come, così come nuovi pattern possono sfruttare al massimo le caratteristiche del linguaggio.

Statistics

Views

Total Views
1,084
Views on SlideShare
1,082
Embed Views
2

Actions

Likes
3
Downloads
37
Comments
0

1 Embed 2

http://www.scoop.it 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Java scriptpatterns Java scriptpatterns Presentation Transcript

    • JavaScript Patterns Giordano ScalzoWednesday, November 10, 2010
    • I’m not a guru!Wednesday, November 10, 2010
    • I’m still learningWednesday, November 10, 2010
    • Why?Wednesday, November 10, 2010
    • JavaScript isn’t this anymoreWednesday, November 10, 2010
    • JavaScript is everywhere!Wednesday, November 10, 2010
    • JavaScript is trendy! Technology RadarWednesday, November 10, 2010
    • JavaScript is trendy! Technology RadarWednesday, 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 NetscapeWednesday, 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 ScopeWednesday, 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 clashWednesday, 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 globalsWednesday, 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 CodeWednesday, November 10, 2010
    • Essential Literal and ConstructorWednesday, November 10, 2010
    • In JavaScript almost everything is an objectWednesday, 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 TigerWednesday, 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 TigerWednesday, 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); // AdamWednesday, November 10, 2010
    • Enforce new pattern one: naming conventionWednesday, 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); // undefinedWednesday, November 10, 2010
    • Interm!zo Prototype propertyWednesday, 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 FunctionsWednesday, November 10, 2010
    • Functions as first class objectsWednesday, 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 scopeWednesday, 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); // 1Wednesday, 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 patternsWednesday, November 10, 2010
    • Classical vs prototypal inheritance vsWednesday, 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 ScottWednesday, 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 ScottWednesday, 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 undefinedWednesday, 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 ScottWednesday, 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 ScottWednesday, 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 ScottWednesday, 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 ScottWednesday, November 10, 2010
    • mmmm let’s try with the same prototypeWednesday, 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 footprintWednesday, November 10, 2010
    • Share the same prototype Child objects can affect other objectsWednesday, 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 objectsWednesday, 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 dependsWednesday, November 10, 2010
    • Goals of inheritance is reuse and reduce duplicationWednesday, November 10, 2010
    • isA relationship... Liskov principle... difficult to tame inheritance...Wednesday, November 10, 2010
    • A modern and better approach is to use Mix-InWednesday, 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 PatternsWednesday, 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 instantiateWednesday, 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 patternWednesday, 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 patternWednesday, November 10, 2010
    • Template Method pattern ... and a little bit of Mix-InWednesday, 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 codeWednesday, November 10, 2010
    • StudyWednesday, 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.comWednesday, November 10, 2010
    • Wednesday, November 10, 2010
    • giordano.scalzo@cleancode.it @giordanoscalzo www.slideshare.net/giordano github.com/gscalzoWednesday, November 10, 2010