Best Practices in JavaScript Library Design

Video

Writing Solid API

Orthagonal code

  • Perfom Universal Action
  • CRUD your methods add/remove/delete/modify
  • Fuel has the following on ecery object .all, add, .remove, .get
  • Made a grid for FUEL, filled in the blanks

Fear Adding Methods

  • Methods can cause a support nightmare
  • Avoid adding, if you can
  • Defer to extensibility

Embrace removing code

  • Remove unused code
  • Reduce the size of your API
  • Reduces your filesize
  • Make your code more maintainable

Provide an Upgrade Path

  • Expect compatibility changes
  • Provide traditional plugin

Reduce to a common root

  • Look for common patterns
  • Reduce to its core and build up
  • jQuery .eq, .gt and .lt –> implement slice

    Consistency

  • Users can expect good naming
  • Pick a naming shhme and stick with it – click() vs onclick()
  • Argument position (method(options, arg,… callback)
  • Callback context
.method (function() {
  // this == DOMElement
}

Implementation

Evolution of a JS COder

  • Everything is a reference
  • You can do OO code
  • Huh, so that’s how Object Prototupes work
  • Thank God for closures

Functional Programming

  • Closures are essential
  • Undersstand this snippet
(function() {
})();
  • Great for local variables
  • Perfect for macros
var event = ['click','focus','blur' ...];
jQuery.each(event, function(i, name) {
jQuery.prototype[name] = function(fn) {
return.this.bind(name, fn);
};

Quick tip: Local Vars

(function() {
// code
var test = false;
this method(function() {
return test;
});
}).call(this);
  • Localy scoped variables
  • Access to instance

Encapsulation

  • contain all of your code to a scope
  • Hide your code and prevent it from leaking
  • All of your code should be wrapped in a
(function() {
})();

BONUS! Your code compresses really well with Dojo Compressor

Namespacing

  • USe as few global variables as feasible
  • One namespace is optimal (see Dojo, Yahoo UI, jQuery, MochiKit)
  • Questions to ask:
  • Can my code coexist with other random code on the site?
  • Can my code coexist with other copies of my own library
  • Can my code be embedded inside another namespace?

Don’t wxtend native objects

  • Impossible to get DOM Extensions working cross-browser
  • Object.prototype kills kittens

Perform Type checking

  • Make your API mor fault resistant
  • Coerce values wherever possible
  • css(Number) becomes css(Number + ‘px’)
  • map(String) becomes .map(new function(String))
  • Error messages
  • Quite useful
  • Byte-costly
  • Solution: Move to ‘debugging; extension

Quick Tip for OO

  • Tweak your Object constructor
function jquery(str, con) {
    if (window == this )
                return new jQuery(str, con);
}
  • Make it easier for users
new jQuery('#foo') becomes jquery('#foo);

Quick Tip for Errors

  • Newer gobble errors
  • Ignore the temptation to try{} catch(e){}
  • Improves debug-ability for everyone

Complex Applications

Extensibility

  • Your code should be easily extensible
// Methods
jQuery.fn.method = fn; 
$(...).method()

// Selectors
jQuery.expr[':'].foo = '... '
$(":foo")

// Animations
jQuery.easing.easeout = fn;
.animate({height:100}, 'slow', 'easeout');;
  • write less, defer to others
  • Makes for cleaner code
  • Foster community and growth

Custom events

  • The answer lies in custon events
  • Dojo, jQuery, Yahoo UI – just added to Prototype
  • Components trigger events and listen for others
.bind('drag', fn)
.trigger('refresh')

Browser Bugs

The Quirksmode Problem

  • Fantastic resource
  • Tells you where the problems are
  • Doesn’t tell you how to fix them
  • Need to focus on problem sets (Events, Get attribute, Get element style)

Solving a problem

  • Some issues are solved in Depth (DOM Events, DOM Traversal)
  • Many still require hard work (getAttribure, getComputedStyle)
  • Permute your test cases, look for edge cases

When to run the fix

  • Typical thought progression:
  • Ill just look at the useragent
  • I’ll just detect to see if an object exists
  • I’ll just think of an elegant solution to the problem
  • I’ll ust look at the useragent

    Documentation

    Structured

    • Provide a clear format
    • Users can build new views with it – no API view is perfect
    • jQuery users build – API browsers, CHeet sheets, Widgets, Translations
    • An API fro your API

USers Want to Help

  • Make barriet to helping very low
  • Answer: Keep your docs in a wiki
  • Only do this if you’ve already writte all of your docs
  • Wiki != Documentation
  • Use templates to maintain structure

Focus on Leverage

  • Write the docs tha will get the most benefit
  • Rough Priority:
  • User-centric API
  • Plugin authoring
  • Docs on writing docs
  • Advanced plugin authoring

    Testing

    1000% Essential

    • Don’t trust any library that doesn’t have a test suite
    • Write your own suite
    • Be sure to handle async tests (Ajax, animations)
    • Pass in all supported browsers

Test-drive Development

  • Write test cases before you tackle bugs
  • Find devs who love to write test cases
  • Check for failures before commit
  • Pure JS DOM (running in Rhino) can help spot obvious errors

Maintinence

Tackling new Bugs

  • create a rapid test environment
  • your test suite must be passing
  • have good coverage
  • always test in all supported browsers to avoid regressions
  • check unsupported browsers before release