Java scriptpatterns

1,069 views

Published on

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.

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,069
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
45
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Java scriptpatterns

  1. 1. JavaScript Patterns Giordano ScalzoWednesday, November 10, 2010
  2. 2. I’m not a guru!Wednesday, November 10, 2010
  3. 3. I’m still learningWednesday, November 10, 2010
  4. 4. Why?Wednesday, November 10, 2010
  5. 5. JavaScript isn’t this anymoreWednesday, November 10, 2010
  6. 6. JavaScript is everywhere!Wednesday, November 10, 2010
  7. 7. JavaScript is trendy! Technology RadarWednesday, November 10, 2010
  8. 8. JavaScript is trendy! Technology RadarWednesday, November 10, 2010
  9. 9. At the beginning...Wednesday, November 10, 2010
  10. 10. Hacked by Brendan Eich in one week...Wednesday, November 10, 2010
  11. 11. Former Mocha, renamed to JavaScript by NetscapeWednesday, November 10, 2010
  12. 12. after a while...Wednesday, November 10, 2010
  13. 13. and...Wednesday, November 10, 2010
  14. 14. :-(Wednesday, November 10, 2010
  15. 15. and so...Wednesday, November 10, 2010
  16. 16. Back to study!Wednesday, November 10, 2010
  17. 17. Started a notebook...Wednesday, November 10, 2010
  18. 18. Essential ScopeWednesday, November 10, 2010
  19. 19. function sum(x, y){ // implied global result = x + y; return result; }{antipattern}Wednesday, November 10, 2010
  20. 20. Global variables are evil!Wednesday, November 10, 2010
  21. 21. Variables clashWednesday, November 10, 2010
  22. 22. Always declare variables with var function sum(x, y){ var result = x + y; return result; }{pattern}Wednesday, November 10, 2010
  23. 23. function foo(){ var a = b = 0; //... }{antipattern}Wednesday, November 10, 2010
  24. 24. b become global function foo(){ var a = (b = 0); //... }{antipattern}Wednesday, November 10, 2010
  25. 25. don’t use assign chain in definition function foo(){ var a, b; a = b = 0; //... }{pattern}Wednesday, November 10, 2010
  26. 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. 27. Don’t forget comma otherwise...Wednesday, November 10, 2010
  28. 28. ... variables become globalsWednesday, November 10, 2010
  29. 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. 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. 31. Against minimum vertical distance principle “Variables should be declared as close to their usage as possible” Robert C. Martin - Clean CodeWednesday, November 10, 2010
  32. 32. Essential Literal and ConstructorWednesday, November 10, 2010
  33. 33. In JavaScript almost everything is an objectWednesday, November 10, 2010
  34. 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. 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. 36. var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say());{pattern}Wednesday, November 10, 2010
  37. 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 TigerWednesday, November 10, 2010
  38. 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 TigerWednesday, November 10, 2010
  39. 39. Duplication is evil!Wednesday, November 10, 2010
  40. 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. 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. 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. 43. What if we forget new?Wednesday, November 10, 2010
  44. 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); // AdamWednesday, November 10, 2010
  45. 45. Enforce new pattern one: naming conventionWednesday, November 10, 2010
  46. 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. 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); // undefinedWednesday, November 10, 2010
  48. 48. Interm!zo Prototype propertyWednesday, November 10, 2010
  49. 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. 50. bar three: 3 foo one: 1 two: 2 __proto__Wednesday, November 10, 2010
  51. 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. 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. 53. Essential FunctionsWednesday, November 10, 2010
  54. 54. Functions as first class objectsWednesday, November 10, 2010
  55. 55. Immediate functions (function(){ alert(watch out!); })();Wednesday, November 10, 2010
  56. 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
  57. 57. Function scopeWednesday, November 10, 2010
  58. 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. 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); // 1Wednesday, November 10, 2010
  60. 60. What about encapsulation?Wednesday, November 10, 2010
  61. 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. 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. 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. 64. Advanced Code reuse patternsWednesday, November 10, 2010
  65. 65. Classical vs prototypal inheritance vsWednesday, November 10, 2010
  66. 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 ScottWednesday, November 10, 2010
  67. 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. 68. Default Classical Inheritance pattern function inherit(C, P) { C.prototype = new P(); };Wednesday, November 10, 2010
  69. 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. 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 ScottWednesday, November 10, 2010
  71. 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 undefinedWednesday, November 10, 2010
  72. 72. Pattern Extension: rent a constructor function Child(name){ Parent.apply(this, arguments); };Wednesday, November 10, 2010
  73. 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 ScottWednesday, November 10, 2010
  74. 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 ScottWednesday, November 10, 2010
  75. 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 ScottWednesday, November 10, 2010
  76. 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 ScottWednesday, November 10, 2010
  77. 77. mmmm let’s try with the same prototypeWednesday, November 10, 2010
  78. 78. Share the same prototype function inherit(C, P){ C.prototype = P.prototype; };Wednesday, November 10, 2010
  79. 79. Parent.prototype say() new Child() new Parent() name: Scott name: Larry __proto__ __proto__Wednesday, November 10, 2010
  80. 80. Share the same prototype Inheritance works as expected Constructor called only once Low memory footprintWednesday, November 10, 2010
  81. 81. Share the same prototype Child objects can affect other objectsWednesday, November 10, 2010
  82. 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. 83. Parent.prototype say() new Parent() new F() name: Larry __proto__ __proto__ new Child() name: Scott __proto__Wednesday, November 10, 2010
  84. 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. 85. We got it!Wednesday, November 10, 2010
  86. 86. What about Prototypal Inheritance?Wednesday, November 10, 2010
  87. 87. No more classes, only objectsWednesday, November 10, 2010
  88. 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. 89. Prototypal inheritance function function object(o) { function F() {} F.prototype = o; return new F(); };Wednesday, November 10, 2010
  90. 90. parent name: Scott say() child = new F() name: Larry __proto__Wednesday, November 10, 2010
  91. 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. 92. better classical or prototypal?Wednesday, November 10, 2010
  93. 93. It dependsWednesday, November 10, 2010
  94. 94. Goals of inheritance is reuse and reduce duplicationWednesday, November 10, 2010
  95. 95. isA relationship... Liskov principle... difficult to tame inheritance...Wednesday, November 10, 2010
  96. 96. A modern and better approach is to use Mix-InWednesday, November 10, 2010
  97. 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. 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. 99. and an object... var Author = function (name, books) { this.name = name || ""; this.books = books || []; }Wednesday, November 10, 2010
  100. 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. 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. 102. Advanced Design PatternsWednesday, November 10, 2010
  103. 103. Wednesday, November 10, 2010
  104. 104. “A design pattern is a general reusable solution to a commonly occurring problem”Wednesday, November 10, 2010
  105. 105. JavaScript is not J@#*!Wednesday, November 10, 2010
  106. 106. Factory pattern creation of objects subclasses decide which class to instantiateWednesday, November 10, 2010
  107. 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. 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. 109. It seems lightly broken....Wednesday, November 10, 2010
  110. 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. 111. Chain of Responsibility patternWednesday, November 10, 2010
  112. 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. 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. 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. 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. 116. Or following the book...Wednesday, November 10, 2010
  117. 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. 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. 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. 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
  121. 121. mmm duplication...Wednesday, November 10, 2010
  122. 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. 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
  124. 124. Template Method patternWednesday, November 10, 2010
  125. 125. Template Method pattern ... and a little bit of Mix-InWednesday, November 10, 2010
  126. 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. 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. 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. 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. 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. 131. It’s just a beginning...Wednesday, November 10, 2010
  132. 132. peep codeWednesday, November 10, 2010
  133. 133. StudyWednesday, November 10, 2010
  134. 134. Wednesday, November 10, 2010
  135. 135. Wednesday, November 10, 2010
  136. 136. “Save it for a rainy day!”Wednesday, November 10, 2010
  137. 137. Check your code with jslint.comWednesday, November 10, 2010
  138. 138. Wednesday, November 10, 2010
  139. 139. giordano.scalzo@cleancode.it @giordanoscalzo www.slideshare.net/giordano github.com/gscalzoWednesday, November 10, 2010

×