making javascript libraries more approachable

30
WHY NESTED TERNARY OPERATORS MAKE ME WANT TO KICK INANIMATE OBJECTS IN THE NUTS AKA: Making JavaScript Libraries More Approachable Pamela Fox @pamelafox http://tinyurl.com/ternaryops

Upload: pamela-fox

Post on 06-May-2015

3.416 views

Category:

Technology


2 download

DESCRIPTION

A talk given at NotConf in Phoenix, Texas in 2012.(Alternative title: Why nested ternary operators make me want to kick inanimate objects in the nuts.)

TRANSCRIPT

Page 1: Making JavaScript Libraries More Approachable

WHY NESTED TERNARY OPERATORS MAKE ME WANT TO KICK INANIMATE OBJECTS IN THE NUTS

AKA: Making JavaScript Libraries More Approachable

Pamela Fox@pamelafox

http://tinyurl.com/ternaryops

Page 2: Making JavaScript Libraries More Approachable

IN THE WORLD OF JS LIBRARIES... 

USERSAUTHORS

Page 3: Making JavaScript Libraries More Approachable

I'VE BEEN USING A LOT OF LIBRARIES THIS PAST YEAR...

bootstrap.datepicker.jsbootstrap.jscolorslider.jsconfetti.jsdate.format.jsdateinput.jsdd_belatedpng.jsfacebook.jsfacebook_js_sdk.jshandlebars.jshighcharts.js

jquery-1.7.min.jsjquery.autosuggest.jsjquery.calendrical.jsjquery.dateinput.jsjquery.fancybox.jsjquery.mobile.jsjquery.overlay.jsjquery.sparkline.jsjquery.tablesorter.jsjquery.tagfield.jsjquery.tooltip.js

jsrender.jslscache.jsmodernizr-1.7.jspersonalize.jsphonegap.jsstacktrace.jsthrottle.jstimeago.jsuseragent.jszepto.js

Page 4: Making JavaScript Libraries More Approachable

AND SOMETIMES I SEE STUFF LIKE...  (aposed

? (aposed = !apos, (aposed ? all : '"')): quoted

? (quoted = !quot, (quoted ? all : '"')):

((lftPrn

? (parenDepth++, lftPrn): "")

+ (space? (parenDepth

? "": named

? (named = FALSE, "\b"): ","

): eq

? (parenDepth && syntaxError(), named = TRUE, '\b' + path + ':'): path

? (path.replace( rPath, parsePath )+ (prn

? (fnCall[ ++parenDepth ] = TRUE, prn): operator)

): operator

? all: rtPrn

? ((fnCall[ parenDepth-- ] = FALSE, rtPrn)+ (prn

? (fnCall[ ++parenDepth ] = TRUE, prn): "")

): comma

? (fnCall[ parenDepth ] || syntaxError(), ","): lftPrn0

? "": (aposed = apos, quoted = quot, '"')

))

Page 5: Making JavaScript Libraries More Approachable

AND IT MAKES ME THINK OF.... 

Page 6: Making JavaScript Libraries More Approachable

...WOULDN'T THIS BE BETTER? 

Page 7: Making JavaScript Libraries More Approachable

THE STAGES OF BEING A USER:  1. Learn how a library works & start using it. 2. Debug a library when something goes wrong. 3. Integrate a library with their workflow. 4. BONUS: Submit a patch to the library.

Page 8: Making JavaScript Libraries More Approachable

STEP 1: THIS LOOKS LIKE A USEFUL LIBRARY, LET'S SEE HOW TO USE IT.

Document everything.  

JSDoc, JSDuck, JoDoc, Dox, NDoc,Docco, Docco-Husky,AutoObjectDocumentation

  Make the documentation easy to patch. 

Page 9: Making JavaScript Libraries More Approachable

NOT ENOUGH DOCUMENTATION. this.options.knownHelpers = { 'each': true, 'if': true, 'unless': true, 'with': true, 'log': true};

handlebars.js

Page 10: Making JavaScript Libraries More Approachable

TOO MUCH DOCUMENTATION. 

vs.

https://github.com/wycats/handlebars.js/http://handlebarsjs.com/

Page 11: Making JavaScript Libraries More Approachable

DUPLICATE DOCUMENTATION. 

vs.

Page 12: Making JavaScript Libraries More Approachable

STEP 2: UH OH, SOMETHING WENT WRONG. TIME TO DEBUG THE LIB.

Make your code readable.○ "Common conventions"

■ Idiomatic.js■ Crockford ■ Google■ Stoyan Stefanov

○ Descriptive variable names

Make your code debuggable.

○ On *all* platforms.

Page 13: Making JavaScript Libraries More Approachable

SHORTENED VARIABLE NAMES. var a = s.split("."), r = "", l = a.length;for (var i = 0; i < l; i++) { var item = a[i]; if (item.length == 2) { r += "0" + item; } else { r += item; }}

function login(a, b) { b = b || { perms: '' }; PhoneGap.exec(function(e) { FB.Auth.setSession(e.session, 'connected'); if (a) a(e); }, null, 'com.phonegap.facebook.Connect', 'login', b.perms.split(',') );}

Page 14: Making JavaScript Libraries More Approachable

SHORTENED VARIABLE NAMES. 

FOR: The shortened names make sense. AGAINST: Maybe to you. But not to people new to the code.   "Common sense" is not common.

Page 15: Making JavaScript Libraries More Approachable

SHORTENED VARIABLE NAMES. 

FOR: It makes for less bytes of code. AGAINST: Code will get compiled to least number of bytes anyway. 

Page 16: Making JavaScript Libraries More Approachable

SHORTENED VARIABLE NAMES. 

FOR: It makes for shorter lines of code. AGAINST: Readability trumps line length. 

Page 17: Making JavaScript Libraries More Approachable

MISSING SEMI-COLONS. 

Page 18: Making JavaScript Libraries More Approachable

MISSING SEMI-COLONS. 

AGAINST: It's harder to read the code.  "Readability is the single most important quality of a piece of code. Semicolons aid readability by eliminating ambiguity and ensuring that nobody ever has to spend even a second figuring out whether your code will do what it looks like it will do."

"Relying on implicit insertion can cause subtle, hard to debug problems. Don't do it. You're better than that."

Google Style Guide

Jason Kester

Page 19: Making JavaScript Libraries More Approachable

MISSING SEMI-COLONS. 

AGAINST: It's harder to make non-breaking changes to the code.

a = b + c(d + e).print()

a = b + c(d + e).print();

is interpreted as:

so you have to:

;(d + e).print()

this:

Page 20: Making JavaScript Libraries More Approachable

MISSING SEMI-COLONS. 

FOR: It's what the core team prefers. AGAINST: The core team aren't the only developers looking at the code. (But they might be if that's the philosophy.)

Don't use your library code to show off how well you know the idiosyncrasies of a language.

Page 21: Making JavaScript Libraries More Approachable

MISSING SEMI-COLONS. 

AGAINST: Hacker News agrees.

Page 22: Making JavaScript Libraries More Approachable

NESTED TERNARY OPERATORS. 

$.qsa = $$ = function(element, selector){ var found return (element === document && idSelectorRE.test(selector)) ? ( (found = element.getElementById(RegExp.$1)) ? [found] : emptyArray ) : (element.nodeType !== 1 && element.nodeType !== 9) ? emptyArray : slice.call( classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) : tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) : element.querySelectorAll(selector) ) }

zepto.js

Page 23: Making JavaScript Libraries More Approachable

NESTED TERNARY OPERATORS. AGAINST: They're hard to understand. $.qsa = $$ = function(element, selector){ var found; if (element === document && idSelectorRE.test(selector)) { found = element.getElementById(RegExp.$1); return found && [found] || []; } else if (classSelectorRE.test(selector)) { return slice.call(element.getElementsByClassName(RegExp.$1)); } else if (tagSelectorRE.test(selector)) { return slice.call(element.getElementsByTagName(selector)); } else { return slice.call(attemptQuerySelectorAll(element, selector)); }}

If you have the choice between two styles and one is more readable, choose that one.

Page 24: Making JavaScript Libraries More Approachable

NESTED TERNARY OPERATORS. 

AGAINST: It's hard to debug the nested statements. FOR: You can debug them with breakpoints. AGAINST: You can't always use fancy debuggers. See: Android, IE

Page 25: Making JavaScript Libraries More Approachable

NESTED TERNARY OPERATORS. 

FOR: They perform better than if/else. AGAINST: Compilers convert if/else to ternary. Try in UglifyJS or Closure Compiler.

Page 26: Making JavaScript Libraries More Approachable

STEP 3: OK, ALL WORKING. TIME TO INTEGRATE WITH MY WORKFLOW.

Try your code with popular JS build tools● JSHint● Closure Compiler / UglifyJS● Grunt

  If it requires options, specify them or inline them into the code.

Page 27: Making JavaScript Libraries More Approachable

UNSPECIFIED JSHINT OPTIONS. [jshint] Error(s) in ./application/static/js/libs/bootstrap.js:

Missing semicolon. (line: 24, character: 5)

> "use strict"

Comma warnings can be turned off with 'laxcomma' (line: 31, character: 9)

> , thisStyle = thisBody.style

Bad line breaking before ','. (line: 30, character: 48)

> var thisBody = document.body || document.documentElement

...

Too many errors. (8% scanned). (line: 139, character: 73)

/*jshint asi:true, laxbreak:true, laxcomma:true, expr:true, boss:true */

Page 28: Making JavaScript Libraries More Approachable

STEP 4: WHEE, IT WORKS, NOW I JUST WANNA SUBMIT THIS ONE CHANGE.

Make it easy to build. Make the tests easy to run.  ...use familiar tools and languages.

Page 29: Making JavaScript Libraries More Approachable

TOO MANY TOOLS? 

Page 30: Making JavaScript Libraries More Approachable

WHICH ONE DO YOU WANT TO BE?

vs.

SO, IF YOU'RE A LIBRARY...

USERS AUTHORS USERS AUTHORS

elite approachable