Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Maintainable JavaScript 2012

94,637 views

Published on

Writing code as an individual and writing code as part of the team are two very different things. Learn the tips and tricks for writing JavaScript code as part of the team so that your code will continue to work for years to come.

Published in: Technology, Sports

Maintainable JavaScript 2012

  1. flickr.com/photos/jontysewell/4526861658/ Maintainable JavaScript Nicholas C. Zakas | Chief Architect, WellFurnished
  2. New
  3. @slicknet
  4. MaintainabilityWhy do we care?
  5. http://flickr.com/photos/indraw/4857101224/ Most of your time is spent maintaining code
  6. Maintainability Who cares?
  7. http://www.flickr.com/photos/jbiljr/1935937825/
  8. http://flickr.com/photos/protestphotos1/4726566233/ We all want to be rock stars "Dont mess with my process, man! Its about the music!"
  9. http://flickr.com/photos/12832008@N04/3027812968/
  10. MaintainabilityWhat is maintainable code?
  11. Maintainable code works for five years without major changes • Intuitive • Understandable • Adaptable • Extendable • Debuggable • Testablehttp://flickr.com/photos/simax/3390895249/
  12. Be kind to your futureself.Chris Eppstein,Creator of Compass
  13. Code Conventions ProgrammingCode Style Practices
  14. Code Style GuideCommunicating with each other through code
  15. Programs are meant to beread by humans andonly incidentally forcomputers to execute.H. Abelson and G. Sussman,The Structure and Interpretationof Computer Programs
  16. https://twitter.com/sh1mmer/status/21446028923
  17. http://javascript.crockford.com/code.html
  18. http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
  19. http://docs.jquery.com/JQuery_Core_Style_Guidelines
  20. http://dojotoolkit.org/community/styleGuide
  21. https://github.com/rwldrn/idiomatic.js/
  22. http://flickr.com/photos/polinasergeeva/3052378826/ Tabs for indentation 4 spaces for indentation
  23. if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == object) { Y.mix(r[p], s[p]);} else if (ov || !(p in r)) { r[p] = s[p]; } } } }
  24. if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == object) { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } }}
  25. https://twitter.com/slicknet/status/169903570047614977
  26. if (found) { doSomething(); doSomethingElse(); }else { doAThirdThing(); doAFourthThing(); }
  27. if (found) { doSomething(); doSomethingElse();} else { doAThirdThing(); doAFourthThing();}
  28. http://flickr.com/photos/polinasergeeva/3052378826/ Comments
  29. https://twitter.com/slicknet/statuses/3559283285
  30. /** * Returns a new object containing all of the properties of * all the supplied objects. The properties from later objects * will overwrite those in earlier objects. Passing in a * single object will create a shallow copy of it. For a deep * copy, use clone. * @method merge * @for YUI * @param arguments {Object*} the objects to merge. * @return {object} the new merged object. */Y.merge = function() { var a = arguments, o = {}, i, l = a.length; for (i = 0; i < l; i = i + 1) { Y.mix(o, a[i], true); } return o;}; Every method
  31. if (mode) { switch (mode) { case 1: // proto to proto return Y.mix(r.prototype, s.prototype, ov, wl, 0, merge); case 2: // object to object and proto to proto Y.mix(r.prototype, s.prototype, ov, wl, 0, merge); break; // pass through case 3: // proto to static return Y.mix(r, s.prototype, ov, wl, 0, merge); case 4: // static to proto return Y.mix(r.prototype, s, ov, wl, 0, merge); default: // object to object is what happens below }} Difficult-to-understand code
  32. while (element &&(element = element[axis])){ //NOTE: assignment if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) { return element; }} Code that might seem to be wrong
  33. Naminghttp://flickr.com/photos/kaatje/243834320/
  34. Naming• Use logical names for variables and functions – Dont worry about length• Variable names should be nouns• Function names should begin with a verb (i.e. getName()) – Functions return booleans should begin with "is" or "has", such as isValid() or hasItem()• Avoid useless names such as foo and temp
  35. if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == object) { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } }}
  36. // Variables, functions, properties methodsvar myName = "Nicholas";function sayName() { alert(myName);}var person = { name: "Nicholas", sayName: function() { alert(this.name); }}; Camel Casing
  37. What about acronyms?
  38. var element = document.getElementById("my-div");element.innerHTML = "Hello world!"; WTF?var xhr = new XMLHttpRequest(); No, seriously WTF? Camel Casing
  39. // Constant-like variablesvar HOVER_CLASS = "mouse-over";// Constructorsfunction Person(name) { this.name = name;}var me = new Person("Nicholas"); Camel Casing- Exceptions
  40. Programming PracticesSmall patterns for common problems
  41. There are two ways ofconstructing a softwaredesign: One way is to make itso simple that there areobviously no deficiencies andthe other way is to make it socomplicated that there are noobvious deficiencies.C.A.R. Hoare,Quicksort Developer
  42. Front End LayersPresentation Behavior (CSS) (JavaScript) Base JS Data/Structure (HTML)
  43. Don’t cross thestreams
  44. <button onclick="doSomething()">Click Me</button> Keep JavaScript out of HTML
  45. var element = document.getElementById("container");element.innerHTML = "<div class="popup"></div>"; Keep HTML out of JavaScript
  46. .foo { width: expression(document.offsetWidth + "px");} Keep JavaScript out of CSS
  47. var element = document.getElementById("container");element.style.color = "red";element.style.cssText = "background:blue;border:1px solid red"; Keep CSS out of JavaScript
  48. //the wrong way!!!function handleClick(event){ var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal";} Event handlers should only handle events
  49. //better, but still wrongfunction handleClick(event){ showPopup(event);}function showPopup(event){ var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal";} Dont pass the event object around
  50. //win!!function handleClick(event){ showPopup(event.clientX, event.clientY);}function showPopup(x, y){ var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal";} Properly separated event handling
  51. //dont add new methodsArray.prototype.awYeah = function(){ alert("Aw yeah!");};//dont override methodsYUI.use = function(){ alert("Aw yeah!");}; Dont modify objects you dont own If you didnt define the object yourself, you dont own it
  52. http://nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
  53. function handleClick(event){ showPopup(event.clientX, event.clientY);}function showPopup(x, y){ var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal";} Avoid global functions and variables
  54. var Controller = { handleClick: function(event){ this.showPopup(event.clientX, event.clientY); }, showPopup: function (x, y){ var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; }}; Avoid global functions and variables Create a single global (if necessary) and attach everything to it
  55. var Controller = { addClass: function(element, className){ element.className += " " + className; }}; Throw your own errors When you know a function will fail
  56. var Controller = { addClass: function(element, className){ if (!element) { throw new Error("addClass: 1st argument missing."); } element.className += " " + className; }}; Throw your own errors When you know a function will fail
  57. var Controller = { process: function(items){ if (items != null){ items.sort(); items.forEach(function(item){ //do something }); } }}; Avoid null comparisons
  58. var Controller = { process: function(items){ if (items instanceof Array){ items.sort(); items.forEach(function(item){ //do something }); } }}; Avoid null comparisons Test for precisely what you want to know if it matters
  59. Avoid null comparisons• Use instanceof to test for specific object types – object instanceof MyType• Use typeof to test for primitive types – typeof value == "string" – BEWARE: typeof null == "object"
  60. function validate(value) { if (!value) { alert("Invalid value"); location.href = "/errors/invalid.php"; }} Separate config data
  61. var config = { urls: { invalid: "/errors/invalid.php" }, strs: { invalidmsg: "Invalid value" }};function validate(value) { if (!value) { alert(config.strs.invalidmsg); location.href = config.urls.invalid; }} Separate config data
  62. Separate Config Data• All URLs needed by the JavaScript• Any strings that are displayed to the user• Any HTML that needs to be created from JavaScript• Settings (i.e., items per page)• Repeated unique values• Any value that may change in the future
  63. https://github.com/nzakas/props2js
  64. AutomationMake everyone’s life easier
  65. Build Process Build
  66. Build Add/Remove Validate Debugging Code Concatenate Test Code Files Generate Minify FilesDocumentation Deploy Files
  67. Add/Remove Debugginghttps://github.com/moxiecode/js-build-tools
  68. Generate Documentationhttp://usejsdoc.org
  69. Generate Documentationhttp://yuilibrary.com/projects/yuidoc/
  70. Generate Documentationhttp://jashkenas.github.com/docco/
  71. Validate Codehttp://jslint.com
  72. Validate Codehttp://jshint.com
  73. Minify Fileshttp://yuilibrary.com/projects/yuicompressor/
  74. Minify Fileshttps://github.com/mishoo/UglifyJS/
  75. Minify Fileshttps://developers.google.com/closure/compiler/
  76. Buildhttps://ant.apache.org
  77. Buildhttp://www.julienlecomte.net/blog/2007/09/16/
  78. Buildhttps://github.com/cowboy/grunt
  79. Buildhttp://weblog.bocoup.com/introducing-grunt/
  80. BuildDevelopment Testing Deployment Add/Remove Add/Remove Add/Remove Debugging Debugging Debugging Validate Validate Validate Code Code Code Test Code Test Code Test Code Generate Concatenate ConcatenateDocumentation Files Files Minify Files Minify Files Deploy Files
  81. Recap
  82. Remember• Code style guidelines ensure everyones speaking the same language• Loose coupling of layers make changes and debugging easier• Good programming practices allow for easier debugging• Code organization and automation help to bring sanity to an otherwise crazy process
  83. https://twitter.com/kylerichter/status/15101151292694529
  84. Etcetera•My company: wellfurnished.com•My blog: nczonline.net•Twitter: @slicknet•These Slides: slideshare.net/nzakas

×