Successfully reported this slideshow.
Your SlideShare is downloading. ×

Maintainable JavaScript 2012

Maintainable JavaScript 2012

Download to read offline

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.

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.

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Maintainable JavaScript 2012

  1. flickr.com/photos/jontysewell/4526861658/ Maintainable JavaScript Nicholas C. Zakas | Chief Architect, WellFurnished
  2. New
  3. @slicknet
  4. Maintainability Why 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 "Don't mess with my process, man! It's about the music!"
  9. http://flickr.com/photos/12832008@N04/3027812968/
  10. Maintainability What is maintainable code?
  11. Maintainable code works for five years without major changes • Intuitive • Understandable • Adaptable • Extendable • Debuggable • Testable http://flickr.com/photos/simax/3390895249/
  12. Be kind to your future self. Chris Eppstein, Creator of Compass
  13. Code Conventions Programming Code Style Practices
  14. Code Style Guide Communicating with each other through code
  15. Programs are meant to be read by humans and only incidentally for computers to execute. H. Abelson and G. Sussman, The Structure and Interpretation of 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. Naming http://flickr.com/photos/kaatje/243834320/
  34. Naming • Use logical names for variables and functions – Don't 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 methods var 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 variables var HOVER_CLASS = "mouse-over"; // Constructors function Person(name) { this.name = name; } var me = new Person("Nicholas"); Camel Casing- Exceptions
  40. Programming Practices Small patterns for common problems
  41. There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies. C.A.R. Hoare, Quicksort Developer
  42. Front End Layers Presentation Behavior (CSS) (JavaScript) Base JS Data/Structure (HTML)
  43. Don’t cross the streams
  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 wrong function 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"; } Don't 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. //don't add new methods Array.prototype.awYeah = function(){ alert("Aw yeah!"); }; //don't override methods YUI.use = function(){ alert("Aw yeah!"); }; Don't modify objects you don't own If you didn't define the object yourself, you don't 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. Automation Make everyone’s life easier
  65. Build Process Build
  66. Build Add/Remove Validate Debugging Code Concatenate Test Code Files Generate Minify Files Documentation Deploy Files
  67. Add/Remove Debugging https://github.com/moxiecode/js-build-tools
  68. Generate Documentation http://usejsdoc.org
  69. Generate Documentation http://yuilibrary.com/projects/yuidoc/
  70. Generate Documentation http://jashkenas.github.com/docco/
  71. Validate Code http://jslint.com
  72. Validate Code http://jshint.com
  73. Minify Files http://yuilibrary.com/projects/yuicompressor/
  74. Minify Files https://github.com/mishoo/UglifyJS/
  75. Minify Files https://developers.google.com/closure/compiler/
  76. Build https://ant.apache.org
  77. Build http://www.julienlecomte.net/blog/2007/09/16/
  78. Build https://github.com/cowboy/grunt
  79. Build http://weblog.bocoup.com/introducing-grunt/
  80. Build Development 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 Concatenate Documentation Files Files Minify Files Minify Files Deploy Files
  81. Recap
  82. Remember • Code style guidelines ensure everyone's 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

Editor's Notes

  • Over the past couple of years, we&apos;ve seen JavaScript development earn recognition as a true discipline. The idea that you should architect your code, use patterns and good programming practices has really elevated the role of the front end engineer. In my opinion, part of this elevation has been the adoption of what has traditionally been considered back end methodologies. We now focus on performance and algorithms, there&apos;s unit testing for JavaScript, and so much more. One of the areas that I&apos;ve seen a much slower than adoption that I&apos;d like is in the area of error handling.How many people have an error handling strategy for their backend? How many have dashboards that display problems with uptime and performance? How many have anything similar for the front end?Typically, the front end has been this black hole of information. You may get a few customer reports here and there, but you have no information about what&apos;s going on, how often it&apos;s occurring, or how many people have been affected.
  • So what have we talked about? Maintainable JavaScript is made up of four components.First is Code Conventions that describe the format of the code you’re writing.Second is Loose Coupling – keeping HTML, JavaScript, and CSS on separate layers and keeping application logic out of event handlers.Third is Programming Practices that ensure your code is readable and easily debugged.Fourth is creating a Build Process

×