Building Non-shit APIs with JavaScript

13,521
-1

Published on

As given at JSConf 2011.

Published in: Technology
1 Comment
18 Likes
Statistics
Notes
  • POWERBOAT ADVENTURES SCHEVENINGEN
    POWERBOAT VAREN OP NOORDZEE VOOR DE KUST VAN SCHEVENINGEN
    JETSKI VERHUUR FUN-FANTASY
    BANAANBOOT VAREN OP SCHEVENINGEN
    POWERBOOT VAREN SCHEVENINGEN
    POWERBOAT ADVENTURES SCHEVENINGEN IS HET BEDRIJF VOOR
    EEN UITJE MET EEN POWERBOAT
    POWERBOATS VAN POWERBOATADVENTURES SCHEVENINGEN
    ZIJN GOED VOOER EEN RIT MET 10 PERSONEN TEGELIJK
    DUS EEN BEDRIJFS UITJE MET POWERBOATADVENTURES SCHEVENINGEN IS ZEKER EEN AANRADER
    POWERBOAT ADVENTURES
    JETSKI VERHUUR
    JETSKI HUREN
    WWW.FUN-FANTASY.NL
    WWW.POWERBOOTVAREN.NL
    WWW.POWERBOATADVENTURES.NL

    POWERBOAT ADVENTURES SCHEVENINGEN

    BEDRIJFS UITJE VRIJGEZELLEN FEEST

    FUN-FANTASY JETSKI VERHUUR SCHEVENINGEN

    POWERBOOT VAREN OP NOORDZEE

    INFO 0646711340

    WWW.FUN-FANTASY.NL
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
13,521
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
94
Comments
1
Likes
18
Embeds 0
No embeds

No notes for slide

Building Non-shit APIs with JavaScript

  1. 1. Your JS Library Dan Webb AKA @danwrongTuesday, May 3, 2011
  2. 2. Tuesday, May 3, 2011
  3. 3. In the beginning...Tuesday, May 3, 2011
  4. 4. In the beginning...Tuesday, May 3, 2011
  5. 5. $("p.surprise").addClass("ohmy").show("slow");Tuesday, May 3, 2011
  6. 6. We all know what happened next... jQuery The RestTuesday, May 3, 2011
  7. 7. Why?Tuesday, May 3, 2011
  8. 8. Internals were not important...Tuesday, May 3, 2011
  9. 9. ...what had John created was a great interfaceTuesday, May 3, 2011
  10. 10. "All programmers are API designers" Joshua Bloch (http://lcsd05.cs.tamu.edu/slides/keynote.pdf)Tuesday, May 3, 2011
  11. 11. The API is priority #1Tuesday, May 3, 2011
  12. 12. ❖ Predictability ❖ Simplicity ❖ FlexibilityTuesday, May 3, 2011
  13. 13. PredictabilityTuesday, May 3, 2011
  14. 14. Tuesday, May 3, 2011 RTFM
  15. 15. Short attention spanTuesday, May 3, 2011
  16. 16. Think about your audience...Tuesday, May 3, 2011
  17. 17. ...use conventions people already knowTuesday, May 3, 2011
  18. 18. Language conventions and standard libraryTuesday, May 3, 2011
  19. 19. THIS IS JAVASCRIPTTuesday, May 3, 2011
  20. 20. useCamelCase, yesReally.Tuesday, May 3, 2011
  21. 21. Be careful with polyfillsTuesday, May 3, 2011
  22. 22. Popular JS librariesTuesday, May 3, 2011
  23. 23. var paper = Raphael(10, 50, 320, 200); var c = paper.circle(50, 40, 10); c.attr("fill", "#f00"); c.show();Tuesday, May 3, 2011
  24. 24. The problem domainTuesday, May 3, 2011
  25. 25. a.internal { color: #44e534; text-decoration: none; } $(a.external).css({ color: #44e534, textDecoration: none });Tuesday, May 3, 2011
  26. 26. Example: creating a DOM BuilderTuesday, May 3, 2011
  27. 27. node.innerHTML = <form method="post" action="/action"> + <p> + <label> + Username: <input type="text" name="username"> + </label> + <label> + Password: <input type="password" name="password"> + </label> + </p> + </form>; var form = document.createElement(form); var p = document.createElement(p); form.setAttribute(action, /login); form.setAttribute(method, post); var usernameLabel = document.createElement(label); var usernameText = document.createTextElement(Username: ); var usernameInput = document.createElement(input); usernameInput.setAttribute(type, text); usernameInput.setAttribute(name, username); form.appendChild(p); p.appendChild(usernameLabel); // ... at this point I decided to give // all this up and become a farmerTuesday, May 3, 2011
  28. 28. var html = { element: function(name, attributes, children) { var node = document.createElement(name); for (var attr in attributes) { node.setAttribute(attr, attributes[attr]); } for (var i=0, len=children.length; i < len; i++) { node.appendChild(children[i]); } return node; } }Tuesday, May 3, 2011
  29. 29. var form = html.element( form, { action: /login, method: post } [ html.element(p, {}, [ html.element(label, {}, [ document.createTextElement(Username: ), html.element(input, { type: text, name: username }, []), // ... you get the idea ]) ]) ] );Tuesday, May 3, 2011
  30. 30. var form = html.form({ action: /login, method: post }, [ html.p({}, [ html.label({}, [ document.createTextElement(Username: ), html.input({ type: text, name: username }, []), // ... you still get the idea, right? ]) ]) ] );Tuesday, May 3, 2011
  31. 31. function elementBuilder(name) { return function(attributes, children) { return html.element(name, attributes, children); } } function generateBuilderFunctions(elements) { for (var i=0, len=elements.length; i < len; i++) { html[elements[i]] = createElementBuilder(elements[i]); } } generateBuilderFunctions("p|div|span|strong|em|img|table|tr| td|th|thead|tbody|tfoot|pre|code|h1|h2|h3|h4|h5|h6|ul|ol|li| form|input|textarea|legend|fieldset|select|option| blockquote|cite|br|hr|dd|dl|dt|address|a|button|abbr| acronym|script|link|style|bdo|ins|del|object|param|col| colgroup|optgroup|caption|label|dfn|kbd|samp|var".split ("|"));Tuesday, May 3, 2011
  32. 32. SimplicityTuesday, May 3, 2011
  33. 33. Tuesday, May 3, 2011
  34. 34. Don’t make me RTFM again...Tuesday, May 3, 2011
  35. 35. Sensible defaultsTuesday, May 3, 2011
  36. 36. Tuesday, May 3, 2011
  37. 37. Tuesday, May 3, 2011
  38. 38. var evt = document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);Tuesday, May 3, 2011
  39. 39. element.addEventListener(input, function() { // do some front-end magic }, false);Tuesday, May 3, 2011
  40. 40. var evt = document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);Tuesday, May 3, 2011
  41. 41. Use options hashes for optional argumentsTuesday, May 3, 2011
  42. 42. evt.initMouseEvent("click", { bubble: false, relatedTarget: thing });Tuesday, May 3, 2011
  43. 43. http://blog.rebeccamurphey.com/objects-as- arguments-in-javascript-where-do-yTuesday, May 3, 2011
  44. 44. Function calls should read wellTuesday, May 3, 2011
  45. 45. // replace oldNode with newNode - DOM API oldNode.parentNode.replaceChild(newNode, oldNode); // Dojo dojo.place(newNode, oldNode, "replace"); // jQuery $(oldNode).replaceWith(newNode);Tuesday, May 3, 2011
  46. 46. Mask complexity if possibleTuesday, May 3, 2011
  47. 47. var con = xd.connect({ src: http://danwebb.net/receiver }); con.bind(ready, function() { rpc(con).call(getData, function(result) { alert(result); }); });Tuesday, May 3, 2011
  48. 48. xd.connect({ src: http://danwebb.net/receiver }, function(con) { rpc(con).call(getData, function(result) { alert(result); }); });Tuesday, May 3, 2011
  49. 49. var con = xd.connect({ src: http://danwebb.net/receiver }); rpc(con).call(getData, function(result) { alert(result); });Tuesday, May 3, 2011
  50. 50. Back to the DOM BuilderTuesday, May 3, 2011
  51. 51. var form = html.form({ action: /login, method: post }, [ html.p({}, [ html.label({}, [ document.createTextElement(Username: ), html.input({ type: text, name: username }, []), // ... you still get the idea, right? ]) ]) ] );Tuesday, May 3, 2011
  52. 52. var form = html.form({ method: post, action: /login }, html.p( html.label( Username: , html.input({ type: text, name: username }) ), html.label( Password: , html.input({ type: password, name: pass }) ), html.input({ type: submit, value: Login}) ) );Tuesday, May 3, 2011
  53. 53. function elementBuilder(name) { return function() { var attributes = {}, children = [], args = Array.prototype.slice.call(arguments); // if the first arg is not a element or a string then its an attributes hash if (!args[0].nodeType && typeof args[0] != string) { attributes = args.unshift(); } // children can be an array or remaining args if (Array.isArray(args[0])) { args = args[0]; } // add rest of args as children converting any strings to text nodes for (var i=0, len=args.length; i < len; i++) { if (typeof args[i] == string) { children.push(document.createTextNode(args[i])); } else { children.push(args[i]); } } return html.element(name, attributes, children); } }Tuesday, May 3, 2011
  54. 54. FlexibilityTuesday, May 3, 2011
  55. 55. Tuesday, May 3, 2011
  56. 56. Tuesday, May 3, 2011
  57. 57. Tuesday, May 3, 2011
  58. 58. Remember: you cant please everyoneTuesday, May 3, 2011
  59. 59. Don’t try to second guess every use caseTuesday, May 3, 2011
  60. 60. Options hashes != flexibilityTuesday, May 3, 2011
  61. 61. 28 options!Tuesday, May 3, 2011
  62. 62. Add hackabilityTuesday, May 3, 2011
  63. 63. public, internal, protectedTuesday, May 3, 2011
  64. 64. var lib = (function() { var private = function() { // you cant mess with me }; return { _internal: function() { // you probably shouldnt mess with me }, public: function() { // Im part of the API - call me sometime } } }());Tuesday, May 3, 2011
  65. 65. ...using functionsTuesday, May 3, 2011
  66. 66. // https://github.com/ender-js/Ender $._select = function(selector, root) { return Sizzle(selector, root); } $._select = function (selector, root) { return (root || document).querySelectorAll(selector); });Tuesday, May 3, 2011
  67. 67. ..inheritanceTuesday, May 3, 2011
  68. 68. // github.com/danwrong/loadrunner function Mustache(path) { this.path = path; } Mustache.prototype = new loadrunner.Dependency; Mustache.prototype.start = function() { var me = this; $.get(this.path, function(result) { var template = Mustache.parse(result); me.complete(template); }); } using(new Mustache(thing.mustache), function(template) { template.evaluate({ a: yep, b: nope }); });Tuesday, May 3, 2011
  69. 69. ..duck typingTuesday, May 3, 2011
  70. 70. Meanwhile, back in DOM Builder land...Tuesday, May 3, 2011
  71. 71. function elementBuilder(name) { return function() { // code collapsed for clarity // add rest of args as children // converting any strings to text nodes for (var i=0, len=args.length; i < len; i++) { if (typeof args[i] == string) { node = document.createTextNode(args[i]); } else { if (typeof args[i].toDOM == function) { node = args[i].toDOM(); } else { node = args[i]; } } children.push(node); } return html.element(name, attributes, children); } }Tuesday, May 3, 2011
  72. 72. function Tweet(text, author, timestamp) { this.text = text; this.author = author; this.timestamp = timestamp; } Tweet.prototype.toDOM = function() { return html.p( { class: tweet }, html.strong(this.author.name), this.text, html.span({ class: time }, this.timestamp) ); } var timeline = // an array of Tweet objects document.appendChild(html.div({ id: timeline }, timeline));Tuesday, May 3, 2011
  73. 73. Create a framework for solving your problem...Tuesday, May 3, 2011
  74. 74. ...then build your library on top of thatTuesday, May 3, 2011
  75. 75. You got yourself a plugin systemTuesday, May 3, 2011
  76. 76. Build tools to solve the problemTuesday, May 3, 2011
  77. 77. ❖ Design up front ❖ Make use of conventions ❖ Don’t make me think ❖ Build in hackabilityTuesday, May 3, 2011
  78. 78. Questions? @danwrongTuesday, May 3, 2011
  79. 79. @jointheflock twitter.com/jobs dan@twitter.comTuesday, May 3, 2011
  80. 80. Eye of the BeholderTuesday, May 3, 2011
  81. 81. ChainingTuesday, May 3, 2011

×