flickr.com/photos/jontysewell/4526861658/             Maintainable JavaScript                                   Nicholas C...
Whos this guy?     5 years             Co-Creator                Contributor,Tech Lead, Yahoo!        csslint.net         ...
MaintainabilityWhy do we care?
flickr.com/photos/indraw/4857101224/       Most of your time is spent maintaining code
Who cares?Your Employer           Your Co-workers,                       Present and Future
flickr.com/photos/protestphotos1/4726566233/                          We all want to be rock stars                 "Dont m...
flickr.com/photos/the_junes/3120810156/                        At work, youre part of a team                  Awesome happ...
Maintainable code isUnderstandable        Adaptable   Debuggable                                         Testable         ...
Code Conventions               Understandable                         Intuitive
flickr.com/photos/29271559@N02/5799773313/      "Programs are meant to be read by humans and        only incidentally for ...
flickr.com/photos/polinasergeeva/3052378826/                                                              Tabs for        ...
if (wl && wl.length) {            for (i = 0, l = wl.length; i < l; ++i) {         p = wl[i];         type = Y.Lang.type(r...
if (wl && wl.length) {    for (i = 0, l = wl.length; i < l; ++i) {        p = wl[i];        type = Y.Lang.type(r[p]);     ...
flickr.com/photos/polinasergeeva/3052378826/                                               Comments
/** * Returns a new object containing all of the properties of * all the supplied objects. The properties from later objec...
if (mode) {    switch (mode) {        case 1: // proto to proto            return Y.mix(r.prototype, s.prototype, ov, wl, ...
while (element &&(element = element[axis])){ //NOTE: assignment    if ( (all || element[TAG_NAME]) &&       (!fn || fn(ele...
Namingflickr.com/photos/kaatje/243834320/
Naming• Use logical names for variables and functions   – Dont worry about length• Variable names should be nouns• Functio...
if (wl && wl.length) {    for (i = 0, l = wl.length; i < l; ++i) {        p = wl[i];        type = Y.Lang.type(r[p]);     ...
Loose Coupling            Adaptable   Debuggable                 Extendable
Front End LayersPresentation     Behavior   (CSS)       (JavaScript)                Base JS      Data/Structure         (H...
Dont cross the streams
<button onclick="doSomething()">Click Me</button>     Keep JavaScript out of HTML
var element = document.getElementById("container");element.innerHTML = "<div class="popup"></div>";            Keep HTML o...
.foo {    width: expression(document.offsetWidth + "px");}             Keep JavaScript out of CSS
var element = document.getElementById("container");element.style.color = "red";element.style.cssText = "background:blue;bo...
Programming Practices              Adaptable Debuggable                               Testable                 Extendable
//the wrong way!!!function handleClick(event){    var popup = document.getElementById("popup");    popup.style.left = even...
//better, but still wrongfunction handleClick(event){    showPopup(event);}function showPopup(event){    var popup = docum...
//win!!function handleClick(event){    showPopup(event.clientX, event.clientY);}function showPopup(x, y){    var popup = d...
//dont add new methodsArray.prototype.awYeah = function(){    alert("Aw yeah!");};//dont override methodsYUI.use = functio...
nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
function handleClick(event){    showPopup(event.clientX, event.clientY);}function showPopup(x, y){    var popup = document...
var Controller = {    handleClick: function(event){        this.showPopup(event.clientX, event.clientY);    },     showPop...
var Controller = {    addClass: function(element, className){        element.className += " " + className;    }};         ...
var Controller = {    addClass: function(element, className){        if (!element) {            throw new Error("addClass:...
var Controller = {    process: function(items){        if (items != null){            items.sort();            items.forEa...
var Controller = {    process: function(items){        if (items instanceof Array){            items.sort();            it...
Avoid null comparisons• Use instanceof to test for specific object  types   – object instanceof MyType• Use typeof to test...
function validate(value) {    if (!value) {        alert("Invalid value");        location.href = "/errors/invalid.php";  ...
var config = {    urls: {        invalid: "/errors/invalid.php"    },    strs: {        invalidmsg: "Invalid value"    }};...
Separate Config Data• All URLs needed by the JavaScript• Any strings that are displayed to the user• Any HTML that needs t...
Build Process                Understandable                           Testable
Build Process   Build
Build Add/Remove              Validate  Debugging               Code Concatenate                        Minify Files    Fi...
BuildDevelopment   Testing   Deployment
Recommendations• One object or object definition per file  – Track dependencies• Use a build process to combines files  – ...
http://www.julienlecomte.net/blog/2007/09/16/
Recap
Remember• Code conventions ensure everyones speaking  the same language• Loose coupling of layers make changes and  debugg...
Questions?
Etcetera• My blog:      www.nczonline.net• Twitter:      @slicknet• These Slides: slideshare.net/nzakas
Upcoming SlideShare
Loading in...5
×

Maintainable JavaScript 2011

15,634

Published on

Writing JavaScript as a hobby and writing JavaScript as a job are two very different things. Learn some common practices for making your JavaScript friendly to a team environment.

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

No Downloads
Views
Total Views
15,634
On Slideshare
0
From Embeds
0
Number of Embeds
14
Actions
Shares
0
Downloads
323
Comments
0
Likes
70
Embeds 0
No embeds

No notes for slide

Maintainable JavaScript 2011

  1. 1. flickr.com/photos/jontysewell/4526861658/ Maintainable JavaScript Nicholas C. Zakas | @slicknet
  2. 2. Whos this guy? 5 years Co-Creator Contributor,Tech Lead, Yahoo! csslint.net Creator of YUI Test Author Lead Author Contributor Lead Author
  3. 3. MaintainabilityWhy do we care?
  4. 4. flickr.com/photos/indraw/4857101224/ Most of your time is spent maintaining code
  5. 5. Who cares?Your Employer Your Co-workers, Present and Future
  6. 6. flickr.com/photos/protestphotos1/4726566233/ We all want to be rock stars "Dont mess with my process, man! Its about the music!"
  7. 7. flickr.com/photos/the_junes/3120810156/ At work, youre part of a team Awesome happens when everyone is on the same page
  8. 8. Maintainable code isUnderstandable Adaptable Debuggable Testable Intuitive Extendable
  9. 9. Code Conventions Understandable Intuitive
  10. 10. flickr.com/photos/29271559@N02/5799773313/ "Programs are meant to be read by humans and only incidentally for computers to execute." Donald Knuth
  11. 11. flickr.com/photos/polinasergeeva/3052378826/ Tabs for indentation 4 spaces for indentation Indentation
  12. 12. 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]; } } } }
  13. 13. 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]; } } }}
  14. 14. flickr.com/photos/polinasergeeva/3052378826/ Comments
  15. 15. /** * 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
  16. 16. 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
  17. 17. while (element &&(element = element[axis])){ //NOTE: assignment if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) { return element; }} Code that might seem to be wrong
  18. 18. Namingflickr.com/photos/kaatje/243834320/
  19. 19. 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", such as isValid()• Avoid useless names such as foo and temp
  20. 20. 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]; } } }}
  21. 21. Loose Coupling Adaptable Debuggable Extendable
  22. 22. Front End LayersPresentation Behavior (CSS) (JavaScript) Base JS Data/Structure (HTML)
  23. 23. Dont cross the streams
  24. 24. <button onclick="doSomething()">Click Me</button> Keep JavaScript out of HTML
  25. 25. var element = document.getElementById("container");element.innerHTML = "<div class="popup"></div>"; Keep HTML out of JavaScript
  26. 26. .foo { width: expression(document.offsetWidth + "px");} Keep JavaScript out of CSS
  27. 27. var element = document.getElementById("container");element.style.color = "red";element.style.cssText = "background:blue;border:1px solid red"; Keep CSS out of JavaScript
  28. 28. Programming Practices Adaptable Debuggable Testable Extendable
  29. 29. //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
  30. 30. //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
  31. 31. //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
  32. 32. //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
  33. 33. nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
  34. 34. 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
  35. 35. 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
  36. 36. var Controller = { addClass: function(element, className){ element.className += " " + className; }}; Throw your own errors When you know a function will fail
  37. 37. 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
  38. 38. var Controller = { process: function(items){ if (items != null){ items.sort(); items.forEach(function(item){ //do something }); } }}; Avoid null comparisons
  39. 39. 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
  40. 40. 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"
  41. 41. function validate(value) { if (!value) { alert("Invalid value"); location.href = "/errors/invalid.php"; }} Separate config data
  42. 42. 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
  43. 43. 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
  44. 44. Build Process Understandable Testable
  45. 45. Build Process Build
  46. 46. Build Add/Remove Validate Debugging Code Concatenate Minify Files Files Generate DeployDocumentation Files
  47. 47. BuildDevelopment Testing Deployment
  48. 48. Recommendations• One object or object definition per file – Track dependencies• Use a build process to combines files – Determines correct order – Validates code (JSHint) – Minifies code (YUI Compressor) – Generate documentation (YUI Doc)
  49. 49. http://www.julienlecomte.net/blog/2007/09/16/
  50. 50. Recap
  51. 51. Remember• Code conventions ensure everyones speaking the same language• Loose coupling of layers make changes and debugging easier• Good programming practices allow you to• Code organization and a build process help to bring sanity to an otherwise crazy process
  52. 52. Questions?
  53. 53. Etcetera• My blog: www.nczonline.net• Twitter: @slicknet• These Slides: slideshare.net/nzakas
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×