ZombieCode

583 views

Published on

by Marco Cedaro on Frontend DEV Conf'13
http://bit.ly/Marco_Cedaro

Published in: Technology, Design
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
583
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

ZombieCode

  1. 1. TALK
  2. 2. Zombie Code
  3. 3. Zombie Codehow to survive a JavascriptZombiecodeapocalypse
  4. 4. First things firstmy name is@cedmaxI work for ShazamI organizeconferences withFrom The Front
  5. 5. DISCLAIMER
  6. 6. DISCLAIMERI’m strongly opinionated
  7. 7. DISCLAIMERI’m strongly opinionatedit’s a gift and a curse
  8. 8. BasicallyZombies?
  9. 9. BasicallyZombies?
  10. 10. Zombies!“Brains, BRAINS, BRains, brains, BRAINS.BRaiNS, brains, Brains, BRAINS, BRains,brains, BRAINS.BRAINS, BRains, brains, BRAINS, brains.”Ryan Mecum
  11. 11. ZOMBIE CODE?
  12. 12. it’s not dead codehttp://alfasin.com/i-see-dead-code-homage-for-intellij-idea/
  13. 13. How to identifyZombie CODE?
  14. 14. What I can tell is..
  15. 15. It may seems harmlesshttp://couchpotatofiles.wordpress.com/2012/03/20/the-walking-dead-ups-the-death-count-and-the-ratings/
  16. 16. http://couchpotatofiles.wordpress.com/2012/03/20/the-walking-dead-ups-the-death-count-and-the-ratings/but it’s NOT
  17. 17. and it will, eventuallyhttp://imgur.com/r/SRDBroke/JimqKCODE
  18. 18. during estimation
  19. 19. during debugging
  20. 20. during development
  21. 21. It is dumb codethat makes you dumb as well
  22. 22. Hopefully it’s not too latehttp://tacticaltshirts.com/shop/shirt-zombies-eat-brains/
  23. 23. Whats that smell?Zombies smell worse thananything you can imagineLilith Saintcrow, Strange Angels
  24. 24. TIp #1Code should be appealing
  25. 25. function validate( options ) {// if nothing is selected, return nothing; cant chain anywayif ( !this.length ) {if ( options && options.debug && window.console ) {console.warn( "Nothing selected, cant validate, returning nothing." );}return;}// check if a validator for this form was already createdvar validator = $.data( this[0], "validator" );if ( validator ) {return validator;}// Add novalidate tag if HTML5.this.attr( "novalidate", "novalidate" );validator = new $.validator( options, this[0] );$.data( this[0], "validator", validator );if ( validator.settings.onsubmit ) {this.validateDelegate( ":submit", "click", function( event ) {if ( validator.settings.submitHandler ) {validator.submitButton = event.target;}
  26. 26. // allow suppressing validation by adding a cancel class to thesubmit buttonif ( $(event.target).hasClass("cancel") ) {validator.cancelSubmit = true;}// allow suppressing validation by adding the html5 formnovalidateattribute to the submit buttonif ( $(event.target).attr("formnovalidate") !== undefined ) {validator.cancelSubmit = true;}});// validate the form on submitthis.submit( function( event ) {if ( validator.settings.debug ) {// prevent form submit to be able to see console outputevent.preventDefault();}function handle() {var hidden;if ( validator.settings.submitHandler ) {if ( validator.submitButton ) {// insert a hidden input as a replacement for the missingsubmit buttonhidden = $("<input type=hidden/>").attr("name",validator.submitButton.name).val( $(validator.submitButton).val() ).appendTo(validator.currentForm);}
  27. 27. validator.settings.submitHandler.call( validator,validator.currentForm, event );if ( validator.submitButton ) {// and clean up afterwards; thanks to no-block-scope, hiddencan be referencedhidden.remove();}return false;}return true;}// prevent submit for invalid forms or custom submit handlersif ( validator.cancelSubmit ) {validator.cancelSubmit = false;return handle();}if ( validator.form() ) {if ( validator.pendingRequest ) {validator.formSubmitted = true;return false;}return handle();} else {validator.focusInvalid();return false;}});}return validator;}
  28. 28. HOW LONG IS THAT?
  29. 29. function validate( options ) {// if nothing is selected, return nothing; cant chain anywayif ( !this.length ) {if ( options && options.debug && window.console ) {console.warn( "Nothing selected, cant validate, returning nothing." );}return;}// check if a validator for this form was already createdvar validator = $.data( this[0], "validator" );if ( validator ) {return validator;}// Add novalidate tag if HTML5.this.attr( "novalidate", "novalidate" );validator = new $.validator( options, this[0] );$.data( this[0], "validator", validator );if ( validator.settings.onsubmit ) {this.validateDelegate( ":submit", "click", function( event ) {if ( validator.settings.submitHandler ) {validator.submitButton = event.target;}// allow suppressing validation by adding a cancel class to the submit buttonif ( $(event.target).hasClass("cancel") ) {validator.cancelSubmit = true;}// allow suppressing validation by adding the html5 formnovalidate attribute to the submit buttonif ( $(event.target).attr("formnovalidate") !== undefined ) {validator.cancelSubmit = true;}});
  30. 30. // validate the form on submitthis.submit( function( event ) {if ( validator.settings.debug ) {// prevent form submit to be able to see console outputevent.preventDefault();}function handle() {var hidden;if ( validator.settings.submitHandler ) {if ( validator.submitButton ) {// insert a hidden input as a replacement for the missing submit buttonhidden = $("<input type=hidden/>").attr("name", validator.submitButton.name).val( $(validator.submitButton).val() ).appendTo(validator.currentForm);}validator.settings.submitHandler.call( validator, validator.currentForm, event );if ( validator.submitButton ) {// and clean up afterwards; thanks to no-block-scope, hidden can be referencedhidden.remove();}return false;}return true;}// prevent submit for invalid forms or custom submit handlersif ( validator.cancelSubmit ) {validator.cancelSubmit = false;return handle();}if ( validator.form() ) {if ( validator.pendingRequest ) {validator.formSubmitted = true;return false;}return handle();} else {validator.focusInvalid();return false;}});}return validator;}
  31. 31. 14 (FOURTEEN!) ifs
  32. 32. function validate( options ) {// if nothing is selected, return nothing; cant chain anywayif ( !this.length ) {if ( options && options.debug && window.console ) {console.warn( "Nothing selected, cant validate, returning nothing." );}return;}// check if a validator for this form was already createdvar validator = $.data( this[0], "validator" );if ( validator ) {return validator;}// Add novalidate tag if HTML5.this.attr( "novalidate", "novalidate" );validator = new $.validator( options, this[0] );$.data( this[0], "validator", validator );if ( validator.settings.onsubmit ) {this.validateDelegate( ":submit", "click", function( event ) {if ( validator.settings.submitHandler ) {validator.submitButton = event.target;}// allow suppressing validation by adding a cancel class to the submit buttonif ( $(event.target).hasClass("cancel") ) {validator.cancelSubmit = true;}// allow suppressing validation by adding the html5 formnovalidate attribute to the submit buttonif ( $(event.target).attr("formnovalidate") !== undefined ) {validator.cancelSubmit = true;}});
  33. 33. // validate the form on submitthis.submit( function( event ) {if ( validator.settings.debug ) {// prevent form submit to be able to see console outputevent.preventDefault();}function handle() {var hidden;if ( validator.settings.submitHandler ) {if ( validator.submitButton ) {// insert a hidden input as a replacement for the missing submit buttonhidden = $("<input type=hidden/>").attr("name", validator.submitButton.name).val( $(validator.submitButton).val() ).appendTo(validator.currentForm);}validator.settings.submitHandler.call( validator, validator.currentForm, event );if ( validator.submitButton ) {// and clean up afterwards; thanks to no-block-scope, hidden can be referencedhidden.remove();}return false;}return true;}// prevent submit for invalid forms or custom submit handlersif ( validator.cancelSubmit ) {validator.cancelSubmit = false;return handle();}if ( validator.form() ) {if ( validator.pendingRequest ) {validator.formSubmitted = true;return false;}return handle();} else {validator.focusInvalid();return false;}});}return validator;}
  34. 34. are comments a bad thing?
  35. 35. TIp #2Code should talk to you
  36. 36. _$ = (function(_) {return {pub: function(a, b, c, d) {for (d=-1, c=[].concat(_[a]); c[++d];) c[d](b)},sub: function(a, b) {(_[a] || (_[a] = [])).push(b)}}})({})
  37. 37. _$ = (function(_) {return {pub: function(a, b, c, d) {for (d=-1, c=[].concat(_[a]); c[++d];) c[d](b)},sub: function(a, b) {(_[a] || (_[a] = [])).push(b)}}})({})#140bytes
  38. 38. _$ = (function() {var registered = {};return {pub: function(event, memo) {if (registered[event] instanceof Array){var handlers = [].concat(registered[event]);for (var i=0, handler; (handler = handlers[i]); i++){handler.call(this, memo);}}},sub: function(event, handler) {if (typeof registered[event] === "undefined"){registered[event] = [];}registered[event].push(handler);}};})();
  39. 39. don’t use comments as anexcuse to write bad code
  40. 40. //used translate3d to trigger hardware acceleration in webViews//http://www.youtube.com/watch?v=IKl78ZgJzm4.animated {translate: translate3d(0,0,0)}/*** Returns a unique ID for use in HTML id attribute.* @param {String/Number} nr A name or number of the ID.* @param {String} [prefix="id-"] The prefix for the ID.* @return {String} the new ID*/function createId(nr, prefix){//TODO implementation}
  41. 41. //used translate3d to trigger hardware acceleration in webViews//http://www.youtube.com/watch?v=IKl78ZgJzm4.animated {translate: translate3d(0,0,0)}/*** Returns a unique ID for use in HTML id attribute.* @param {String/Number} nr A name or number of the ID.* @param {String} [prefix="id-"] The prefix for the ID.* @return {String} the new ID*/function createId(nr, prefix){//TODO implementation}un-avoidablehacks explanation
  42. 42. //used translate3d to trigger hardware acceleration in webViews//http://www.youtube.com/watch?v=IKl78ZgJzm4.animated {translate: translate3d(0,0,0)}/*** Returns a unique ID for use in HTML id attribute.* @param {String/Number} nr A name or number of the ID.* @param {String} [prefix="id-"] The prefix for the ID.* @return {String} the new ID*/function createId(nr, prefix){//TODO implementation}un-avoidablehacks explanationAUTOMATED DOCGENERATION
  43. 43. //used translate3d to trigger hardware acceleration in webViews//http://www.youtube.com/watch?v=IKl78ZgJzm4.animated {translate: translate3d(0,0,0)}/*** Returns a unique ID for use in HTML id attribute.* @param {String/Number} nr A name or number of the ID.* @param {String} [prefix="id-"] The prefix for the ID.* @return {String} the new ID*/function createId(nr, prefix){//TODO implementation}un-avoidablehacks explanationAUTOMATED DOCGENERATIONTODOs
  44. 44. TIp #3Code should have boundaries
  45. 45. Singleresponsibilityprincipleyour best toolagainst Zombie Codesince1902(guaranteed 20 years)
  46. 46. No globalpollutionhttp://leosabanganii.blogspot.co.uk/2012/10/zombie-dressed-activists-protest.html
  47. 47. No couplinghttp://leosabanganii.blogspot.co.uk/2012/10/zombie-dressed-activists-protest.htmlhttp://ajandcharli.blogspot.co.uk/2011/05/we-dont-do-dead-people.html
  48. 48. worst case smell
  49. 49. worst case smellLong methods
  50. 50. worst case smellLong methodsDeep Level of Indentation
  51. 51. worst case smellLong methodsDeep Level of IndentationHard to tell what it does
  52. 52. worst case smellLong methodsDeep Level of IndentationHard to tell what it doesLack of portability
  53. 53. worst case smellLong methodsDeep Level of IndentationHard to tell what it doesLack of portabilityHardcoded style/templating
  54. 54. worst case smellLong methodsDeep Level of IndentationHard to tell what it doesLack of portabilityHardcoded style/templatingLogic block duplication
  55. 55. worst case smellLong methodsDeep Level of IndentationHard to tell what it doesLack of portabilityHardcoded style/templatingLogic block duplicationCallback hell
  56. 56. And now what?
  57. 57. Play cool!
  58. 58. BasicallyQuarantine
  59. 59. BasicallyQuarantine
  60. 60. QUARANTINEMost teams are trying to stop furtherspread only through quarantines. Its a goodshort-term solution, but it wont preventlong-term population loss.http://cdmx.it/quarantinequote
  61. 61. The broken window
  62. 62. “Dont leave "broken windows" (baddesigns, wrong decisions, or poor code)unrepaired. Fix each one as soon as it isdiscovered.”Programming is insanely detail oriented, and perhaps this is why:if youre not on top of the details, the perception is that thingsare out of control, and its only a matter of time before yourproject spins out of control. Maybe we should be sweating thesmall stuff.Jeff Atwoodhttp://www.codinghorror.com/blog/2005/06/the-broken-window-theory.htmlThe broken window
  63. 63. Maybe we should be sweatingthe small stuff.Jeff Atwoodhttp://www.codinghorror.com/blog/2005/06/the-broken-window-theory.htmlThe broken window
  64. 64. Isolate the Zombies
  65. 65. define style guidelines
  66. 66. function Zombie(personName){function do_something() {console.log(personName + " just ate a brain!");}return {doSomethingZombiesDo: do_something};}var adam = new Zombie("Adam");adam.doSomethingZombiesDo();
  67. 67. function Zombie(personName){function do_something() {console.log(personName + " just ate a brain!");}return {doSomethingZombiesDo: do_something};}var adam = new Zombie("Adam");adam.doSomethingZombiesDo();
  68. 68. function Zombie(personName){function do_something() {console.log(personName + " just ate a brain!");}return {doSomethingZombiesDo: do_something};}var adam = new Zombie("Adam");adam.doSomethingZombiesDo();
  69. 69. function Zombie(personName){function do_something() {console.log(personName + " just ate a brain!");}return {doSomethingZombiesDo: do_something};}var adam = new Zombie("Adam");adam.doSomethingZombiesDo();
  70. 70. define style guidelines
  71. 71. start linting your code
  72. 72. Inversion of control freaknessAM I A CONTROL FREAK?
  73. 73. start testing your code
  74. 74. Unit or Functional?
  75. 75. Do both
  76. 76. What to testUnit testing issupposed to test asingle atomic “unit” offunctionality withoutdependencies onanything else
  77. 77. What to testUnit testing issupposed to test asingle atomic “unit” offunctionality withoutdependencies onanything elseThis is where you startto run into seriousdependency problemsdue to the interrelationHTML and CSS
  78. 78. What to testUnit testing issupposed to test asingle atomic “unit” offunctionality withoutdependencies onanything elseThis is where you startto run into seriousdependency problemsdue to the interrelationHTML and CSSWhat do you test?Usually how the userinterface responds touser input.Actually, the realm offunctional testing
  79. 79. No matter which toolsetGruntPhantomJSJsTestDriverBuster.jsKarmaChutzpahTestemQunitMochaJasmine
  80. 80. No matter which toolsetGruntPhantomJSJsTestDriverBuster.jsKarmaChutzpahTestemQunitMochaJasmine
  81. 81. As long as it can be automatedshareidentifybuildmake itcontinuous
  82. 82. Make it part of the process
  83. 83. Make it part of the processhttp://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/Estimate testinghttp://malyn.edublogs.org/2011/10/16/process-tools-people/
  84. 84. Make it part of the processDo code reviewhttp://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/http://malyn.edublogs.org/2011/10/16/process-tools-people/
  85. 85. Make it part of the processhttp://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/Involve peoplehttp://malyn.edublogs.org/2011/10/16/process-tools-people/
  86. 86. Fear the living? DON’T
  87. 87. The team
  88. 88. DEVOPS PRODUCT OWNERqa
  89. 89. QA
  90. 90. QACrucial role in theprocess
  91. 91. QACrucial role in theprocessQuality should be yourgoal too
  92. 92. QACrucial role in theprocessQuality should be yourgoal tooGet help for functionaltest coverage not toscrew up refactoring
  93. 93. Devops
  94. 94. DevopsThe tough guy
  95. 95. DevopsThe tough guyIt could be hard to dealwith
  96. 96. DevopsThe tough guyIt could be hard to dealwithGet help setting up theautomated process
  97. 97. Product owner
  98. 98. Product ownerThe less interested incode itself
  99. 99. Product ownerThe less interested incode itselfBring numbers, nottheories
  100. 100. Product ownerThe less interested incode itselfBring numbers, nottheoriesGet help not wastingtime, staying focused onfunctionalities
  101. 101. Others in the team
  102. 102. juniorsexternallobbyist
  103. 103. Juniors
  104. 104. JuniorsPair with them, codereview their (and your)code
  105. 105. JuniorsPair with them, codereview their (and your)codeInvolve them during thewhole process definition
  106. 106. JuniorsPair with them, codereview their (and your)codeInvolve them during thewhole process definitionGet help keeping thingseasy and accessible
  107. 107. Lobbyists
  108. 108. LobbyistsThey will slow youdown, your brain will bemore prone to be eaten
  109. 109. LobbyistsThey will slow youdown, your brain will bemore prone to be eatenRedirect them to theproduct owner
  110. 110. BasicallyKILL ‘EM ALL (AGAIN?)
  111. 111. BasicallyKILL ‘EM ALL (AGAIN?)
  112. 112. KILL ‘EM ALL (AGAIN?)“Nothing is impossible to kill.”Mira Grant, Feed
  113. 113. but
  114. 114. “Without requirements or design,programming is the art of adding bugsto an empty text file”Louis SrygleyDesign for your goal
  115. 115. Design for your goal
  116. 116. Modular Architecture
  117. 117. Scalable JavaScriptApplicationArchitectureby Nicholas Zakas
  118. 118. core.register("module-name", function(sandbox){return {init:function(){},destroy:function(){}};});
  119. 119. core.register("module-name", function(sandbox){return {init:function(){},destroy:function(){}};});
  120. 120. core.register("module-name", function(sandbox){return {init:function(){},destroy:function(){}};});
  121. 121. core.register("module-name", function(sandbox){return {init:function(){var user = sandbox.getUser();},destroy:function(){}};});
  122. 122. core.register("module-name", function(sandbox){return {init:function(){var user = sandbox.getUser();},destroy:function(){}};});
  123. 123. core.register(module-name, function(sandbox){return {init:function(config){console.log(config.id);}};});core.configure(module-name, {id: container,});core.start(module-name);core.stop(module-name);
  124. 124. core.register(module-name, function(sandbox){return {init:function(config){console.log(config.id);}};});core.configure(module-name, {id: container,});core.start(module-name);core.stop(module-name);
  125. 125. core.register(module-name, function(sandbox){return {init:function(config){console.log(config.id);}};});core.configure(module-name, {id: container,});core.start(module-name);core.stop(module-name);
  126. 126. core.register(module-name, function(sandbox){return {init:function(config){console.log(config.id);}};});core.configure(module-name, {id: container,});core.start(module-name);core.stop(module-name);
  127. 127. core.register(module-name, function(sandbox){return {init:function(config){console.log(config.id);}};});core.configure(module-name, {id: container,});core.start(module-name);core.stop(module-name);
  128. 128. core.register(module-name, function(sandbox){return {init:function(config){console.log(config.id);}};});core.configure(module-name, {id: container,});core.start(module-name);core.stop(module-name);
  129. 129. Event Driven Pattern
  130. 130. core.register("module-name", function(sandbox){return {init:function(){sandbox.layer("an error occured");}};});
  131. 131. core.register("module-name", function(sandbox){return {init:function(){sandbox.layer("an error occured");}};});
  132. 132. sandbox.layer("an error occured");
  133. 133. sandbox.publish("error", {msg: "an error occured"});
  134. 134. sandbox.publish("error", {msg: "an error occured"});core.register("errManager", function(sandbox){return {init:function(){sandbox.subscribe("error", function(err) {console.log(err.msg)});}};});
  135. 135. sandbox.publish("error", {msg: "an error occured"});core.register("errManager", function(sandbox){return {init:function(){sandbox.subscribe("error", function(err) {console.log(err.msg)});}};});
  136. 136. sandbox.publish("error", {msg: "an error occured"});core.register("errManager", function(sandbox){return {init:function(){sandbox.subscribe("error", function(err) {console.log(err.msg)});}};});
  137. 137. sandbox.publish("error", {msg: "an error occured"});core.register("errManager", function(sandbox){return {init:function(){sandbox.subscribe("error", function(err) {console.log(err.msg)});}};});
  138. 138. sandbox.publish("error", {msg: "an error occured"});core.register("errManager", function(sandbox){return {init:function(){sandbox.subscribe("error", function(err) {console.log(err.msg)});}};});
  139. 139. sandbox.publish("error", {msg: "an error occured"});core.register("errManager", function(sandbox){return {init:function(){sandbox.subscribe("error", function(err) {console.log(err.msg)});}};});
  140. 140. sandbox.publish("error", {msg: "an error occured"});core.register("errManager", function(sandbox){return {init:function(){sandbox.subscribe("error", function(err) {console.log(err.msg)});}};});
  141. 141. sandbox.publish("error", {msg: "an error occured"});core.register("errManager", function(sandbox){return {init:function(){sandbox.subscribe("error", function(err) {console.log(err.msg)});}};});
  142. 142. sandbox.subscribe("error", function(payload){console.log(payload.msg);});Advantages
  143. 143. sandbox.subscribe("error", function(payload){console.log(payload.msg);});AdvantagesSEMANTIC
  144. 144. sandbox.subscribe("error", function(payload){console.log(payload.msg);});AdvantagesSEMANTICflexibility
  145. 145. AdvantagesDECOUPLING
  146. 146. “The key is to acknowledge from thestart that you have no idea how this willgrow.When you accept that you don’tknow everything, you begin to designthe system defensively.”Nicholas ZakasOverengineering?
  147. 147. AMD
  148. 148. icon by http://www.deleket.com/jQueryMustacheLibraries Plugins Your scripts
  149. 149. icon by http://www.deleket.com/jQueryMustacheLibraries Plugins Your scripts
  150. 150. <script src="jquery.min.js"></script><script src="mustache.js"></script><?php if ($env == "prod") : ?><script src="my-code-bundle.js"></script><?php else: ?><script src="jquery.plugin_1.js"></script><script src="jquery.plugin_2.js"></script><script src="my-code_1.js"></script><script src="my-code_2.js"></script><script src="my-code_3.js"></script><script src="my-code_4.js"></script><script src="my-code_5.js"></script><?php endif; ?>
  151. 151. var MyNamespace = {};MyNamespace.MyAwesomeLibrary = function() {//implementation};MyNamespace.AnotherCoolOne = function() {//implementation};MyNamespace.SlightlyCrappyLibrary = function() {//implementation};MyNamespace.BestLibEver = function() {//implementation};
  152. 152. //API: define(id?, dependencies?, factory);define("My-Module", ["Another-Module"], function(AnotherModule){// Do Something});one define to rule them all
  153. 153. //API: define(id?, dependencies?, factory);define("My-Module", ["Another-Module"], function(AnotherModule){// Do Something});one define to rule them all
  154. 154. //app/config.jsdefine([], function() {return {url: "http://whatever.it/is/",debug: true};});
  155. 155. //app/config.jsdefine([], function() {return {url: "http://whatever.it/is/",debug: true};});//app/config.jsdefine({url: "http://whatever.it/is/",debug: true});
  156. 156. //app/config.jsdefine([], function() {return {url: "http://whatever.it/is/",debug: true};});//app/config.jsdefine({url: "http://whatever.it/is/",debug: true});
  157. 157. //app/config.jsdefine([], function() {return {url: "http://whatever.it/is/",debug: true};});//app/config.jsdefine({url: "http://whatever.it/is/",debug: true});
  158. 158. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  159. 159. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  160. 160. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  161. 161. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  162. 162. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  163. 163. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  164. 164. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  165. 165. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  166. 166. //app/myProduct.jsdefine(["app/config"], function(config) {return function(id){return {getProductUrl: function(){var prodPath = config.url + "product/" + id;if (config.debug){console.log(prodPath)}return prodPath;}};};});
  167. 167. <script data-main="app/main" src="require.js"></script>
  168. 168. <script data-main="app/main" src="require.js"></script>//app/main.jsrequire(["jQuery", "app/myProduct"], function($, Product) {$(".product").on("click", function(){var prodID = $(this).data("id");var prod = new Product(prodID);document.location.href = prod.getProductUrl();})});
  169. 169. <script data-main="app/main" src="require.js"></script>//app/main.jsrequire(["jQuery", "app/myProduct"], function($, Product) {$(".product").on("click", function(){var prodID = $(this).data("id");var prod = new Product(prodID);document.location.href = prod.getProductUrl();})});
  170. 170. <script data-main="app/main" src="require.js"></script>//app/main.jsrequire(["jQuery", "app/myProduct"], function($, Product) {$(".product").on("click", function(){var prodID = $(this).data("id");var prod = new Product(prodID);document.location.href = prod.getProductUrl();})});
  171. 171. <script data-main="app/main" src="require.js"></script>//app/main.jsrequire(["jQuery", "app/myProduct"], function($, Product) {$(".product").on("click", function(){var prodID = $(this).data("id");var prod = new Product(prodID);document.location.href = prod.getProductUrl();})});
  172. 172. <script data-main="app/main" src="require.js"></script>//app/main.jsrequire(["jQuery", "app/myProduct"], function($, Product) {$(".product").on("click", function(){var prodID = $(this).data("id");var prod = new Product(prodID);document.location.href = prod.getProductUrl();})});
  173. 173. Pulling all together
  174. 174. define(function(){use strict;return function(sandbox){//the logic of the modulefunction doSomething(){//do something}return {init:function(config){//the initialization codesandbox.subscribe(myEventName, doSomething)},destroy: function(){//optional destroy method}};};});
  175. 175. define(function(){use strict;return function(sandbox){//the logic of the modulefunction doSomething(){//do something}return {init:function(config){//the initialization codesandbox.subscribe(myEventName, doSomething)},destroy: function(){//optional destroy method}};};});
  176. 176. define(function(){use strict;return function(sandbox){//the logic of the modulefunction doSomething(){//do something}return {init:function(config){//the initialization codesandbox.subscribe(myEventName, doSomething)},destroy: function(){//optional destroy method}};};});
  177. 177. define(function(){use strict;return function(sandbox){//the logic of the modulefunction doSomething(){//do something}return {init:function(config){//the initialization codesandbox.subscribe(myEventName, doSomething)},destroy: function(){//optional destroy method}};};});
  178. 178. define(function(){use strict;return function(sandbox){//the logic of the modulefunction doSomething(){//do something}return {init:function(config){//the initialization codesandbox.subscribe(myEventName, doSomething)},destroy: function(){//optional destroy method}};};});
  179. 179. require(["akase"], function(core) {core.start("module1");core.start("module2", {config: {debug: true}});core.start("module3", { event: "audio:stop" });});
  180. 180. require(["akase"], function(core) {core.start("module1");core.start("module2", {config: {debug: true}});core.start("module3", { event: "audio:stop" });});
  181. 181. require(["akase"], function(core) {core.start("module1");core.start("module2", {config: {debug: true}});core.start("module3", { event: "audio:stop" });});
  182. 182. require(["akase"], function(core) {core.start("module1");core.start("module2", {config: {debug: true}});core.start("module3", { event: "audio:stop" });});
  183. 183. require(["akase"], function(core) {core.start("module1");core.start("module2", {config: {debug: true}});core.start("module3", { event: "audio:stop" });});
  184. 184. ākāśesanskrit for "in the sky"/"to the sky"https://github.com/cedmax/akase
  185. 185. No such this thing!
  186. 186. BasicallyHappy Endings?
  187. 187. BasicallyHappy Endings?
  188. 188. you are going to write zombie codezombie code will always be out therelive with it, embrace it, have a strategy to deal with it

×