Skip to content

Instantly share code, notes, and snippets.

@jakelazaroff
Last active December 20, 2015 11:19
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jakelazaroff/6122988 to your computer and use it in GitHub Desktop.
Save jakelazaroff/6122988 to your computer and use it in GitHub Desktop.
BackboneConf 2013 notes! http://backboneconf.com/ Disclaimer: sorry for anything I may have missed!
code delimiters: <% %>
# keynote
- your business logic will live longer than your interface
- stateless
- no "spaghetti state"
- application should be able to reflect any combination of data
- views should transparently reflect models
- backbone patterns
- custom model methods
- don't treat models as just deserialized json
- anything with a reference to the model can call custom methods
- [a.k.a. business logic goes here!]
- example: "share a book with one user" <% user.shareWith(me) %>
- custom collection methods
- example: search models in a collection by string <% accounts.search("Joe Brooklyn") %>
- filtered collections <% documents.published() %>
- method 1: define filter functions that return an array of values you need
- method 2: create another collection that listens to events on the original, only picks models matching a certain condition
- harmonizing with garbage collection
- remove references you no longer need
- events are references! clean them up!
- don't create references you don't need to create
- have shorter-lived entities listen to longer-lasting ones, not vice versa
- lazy loading
- used deferred objects (promises)
- example: lookup function either returns the local object, or fetches it from the server
- relations <—> objects
- entities probably won't exactly mimic your database schema
- timing
- debounce a method (such as rendering) <% _.debounce() %>
- render in chunks so as not to block the UI thread
- subclassing models
- <% Account = Backbone.Model.extend({ ... }); Publisher = Account.extend({ ... }) %>
- global events
- from Backbone 1.0, events is mixed in to the Backbone object <% Backbone.on('switchuser', ...) %>
- model snapshots
- models can represent hypothetical or previous states
- keep them on the client side
- example: undo <% this.on('change', function () { changes.push(this.previousAttributes() }) %>
- example: <% draft = model.clone() %>
- virtual sub-models
- just because something is represented together on the server doesn't mean it should be the same model on the client
- model on the client doesn't have to correspond to the server
- q&a
- mediator (two views "talking" with no model in between)
- an event is still a reference
- just create a reference between the two
- listening to events on nested models
- plugins!
- or, model has a collection with references to submodels
# tools & ptterns for building large-scale Backbone applications
- talk
- slides: https://speakerdeck.com/backbonerails/little-opinions-big-possibilities-the-tools-and-patterns-for-building-large-scale-backbone-applications
- library
- marionette.js
- what is a large-scale JavaScript application? (generally)
- non-trivial
- significant dedicated developer effort
- most work on the browser
- tip: devote significant time to planning/modeling
- case study: rdio
- collections of songs
- changing sort order, filtering
- push state to update URL
- etc.
- characteristics of large-scale apps
- multiple routers
- view management
- nesting
- cleanup
- complex events
- lots of state changes
- many entities (models/collections)
- specialized objects
- [Application]
- objects that should be globally accessible
- example: current user
- [App Modules]
- [Router]
- [Controllers]
- [Specialized Views]
- [Components]
- take specialized behavior out of views
- "decorators"
- example: forms
- example: spinner
- [Mixins]
- [Entities]
- shared namespace for models/collections
- [Config]
- [Modules]
- [Messaging Bus]
- [Request]
- [Command]
- [Pub/Sub]
- give views a standard set of events and methods
- example: 'onRender', after the view has been rendered
- controller
- keep views thin
- delegate responsibilities to controllers
- specialized views
- ItemView
- related to a single model
- CollectionView
- iterates through a collection, creating ItemViews
- Layout
- keep track of subviews
- folder organization
- backbone
- app.js
- apps
- playlists
- playlist_app.js
- list
- show
- edit
- new
- playlist_songs
- playlist_songs_app.js
- list
- currently_playing
- currently_playing_app.js
- show
- config
- entities
- components
- mixins
# test-driven development
- talk
- slides: https://speakerdeck.com/landau/test-driven-backbone-development
- code: https://github.com/landau/tddbackbone
- libraries
- mocha
- chai
- sinon.js
- jasmine
- writing a test
- assert
- accepts a boolean value and an error string
- if the boolean is false, throw an error
- describe
- accepts a string and a function
- string indicates what we're testing
- nest describes <% describe('Todo View', function () { describe('.initialize', function () { ... }) }) %>
- before/after
- actions to set up/clean up tests
- example: instantiating a collection, etc
- it
- assertions live in these functions
- example: <% it('should be a list tag', function () { assert(app.Todo.prototype.tagName === 'li') }) %>
- spy (sinon.js)
- check whether a function is called, parameters, etc
- stubs (sinon.js)
- functions with preprogrammed behavior
- can return known data (dependency injection)
- running the tests
- automate tests
- grunt.js
- continuous integration
- what not to test
- third-party code
- integration testing
- q&a
- code coverage tools? integration testing tools (with node)?
- code coverage
- jscoverage
- integration testing
- selenium
- karma
- recommended grunt packages
- grunt template
- grunt connect
- DOM testing recommendation: jsdom
- tip: render views in memory, don't insert into DOM
# breakout session: developer power ups!
- writeup: http://caliper.io/blog/2013/backboneconf-tooling-and-services-session/
- errors
- loggly
- sentry raven
- catcherize
- errorception
- crashlytics
- dependencies
- npm
- requirejs
- requirejs-rails
- browsify
- testing
- selenium
- sauce labs
- venus
- qunit
- phantom
- (not great for stack traces)
- mocha
- poltergeist
- capybara
- cucumber
- continuous integration
- travis
- jenkins
- teamcity
- circleci
- deploying
- (s)ftp
- fabric
- puppet
- capistrano
- grunt
- chef
- monitoring
- new relic
- mpulse
- miscellaneous
- yoda
# dependency injection for fun and profit
- what is it?
- pass dependencies into constructors and check for them
- easy to test
- constructors
- "plans" for application
- namespace blues
- don't rely on globals
- requrejs/commonjs
- modules help organize your constructors
- dependency injection helps organize your instances
- keep module system and instance management separate
- two dependency graphs
- the constructors that form your app blueprint
- dependo
- the instances of which your app is composed
- refactoring
- altering structure while keeping behavior intact
- refactoring without tests is just changing stuff
- patterns
- application view
- check dependencies during instantiation
- tests enforce the contract of dependencies
- single point of entry to access instances
- apps should be accessible to the outside world (e.g. console)
- SOLID (object-oriented) design principles
- single responsibility
- a class/method should only be responsible for one thing
- if it does two (or more), split it up!
- open / closed
- classes should be open for extension, closed for modification
- liskov substitution
- objects should be replaceable with instances of their subtypes (a.k.a. polymorphism)
- interface segregation
- many client-specific interfaces are better than one general-purpose one
- make functions responsible for less
- dependency inversion
- depend on abstractions, not concretions
- example: don't poll a model, listen for change events
- modules
- use them
- fight with your manager
- long-lived section views
- components are the future
- aura.js
- shameless plug: backbone.js in action
- promo: MLBBJSCO
q&a
- why expose your application to the window?
- console access
- closer checks for dependencies than just for existence?
- type
- properties/methods
# domain-driven web applications using Backbone
- talk
- slides: http://bobholt.me/bbconf-bos-2013
- domain-driven design
- it's a book! go buy it!
- domain
- the application's "world"
- example: for a stock application, the trading floor, stocks, people, etc
- domain model
- image of the business logic that exists in the head of an expert
- conceptual model; has nothing to do with software (yet)
- process
- discovery
- consult with experts, project managers, etc
- ubiquitous language
- terminology everyone who touches the project uses (including clients)
- modify the model to accommodate new constraints
- iteratively change the model throughout the process
- layers
- interface layer
- accepts and responds to user input (presentation)
- application layer
- transactions, activities, creates/access/deletes domain objects (application logic)
- domain layer
- the state and behavior of the domain (business logic)
- infrastructure layer
- supports the layers on top: servers, repos, etc
- organization
- app
- domain
- framework
- pages
- services
- widgets
- express the model in software
- clarify relationship between objects
- entities
- has an identity (id)
- example: airline seat (each is unique and assigned)
- value objects
- commodity objects
- passed as parameters, attached as attributes, etc
- example: bus seat (not uniquely assigned)
- services
- "actions"
- repositories
- centralizes management of domain objects
- retrieves from cache or server as necessary
- returns existing objects
- factories
- creates domain objects given attributes
- takeaway
- don't start coding right away
- q&a
- tip: incorporate all the key stakeholders (designers, programmers, clients, etc) in the discovery phase
# geologic time scale
- talk
- slides: https://speakerdeck.com/mwunsch/the-geologic-time-scale-of-gilt-dot-coms-view-layer
- stratigraphy (layers)
- technology layers continue to build up
- end result: technical debt
- asynchronous javascript and xml
- fundamental piece of the modern web experience (yup!)
- old approach
- <% GET /add_to_card?sku=12345 %>
- not idempotent
- not RESTful
- append returned markup directly to DOM
- new approach
- client-side templating
- push state
- always be scrolling
- http://tumbledry.org/2011/05/12/screw_hashbangs_building
- optimizing for robots
- make sure data is available for search engines, et. al
- server-side rendering still needed for SEO
- templates
- different client-side and server-side templates for same thing?
- solution: use (or build) template parser for both
- https://github.com/mwunsch/handlebars.scala
- flexibility vs. maintainability
- maintainability
- no intrinsic value to users or business
- enables velocity; enables the programmer to create more value
- flexiblity
- allows the developer to add flexibility "ad hoc"
- the future
- "Backbone.js is the kernel for modern web development"
- more and more frameworks will be written on top of it
- mobile and desktop will converge
- http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/
- with dynamic typing, test coverage is essential
- a statically-typed language enforces API contracts
- TypeScript: a typed superset of javascript
- q&a
- handlebars vs. mustache at gilt?
- mustache is logic-less
- pro: language agnostic
- con: no logic
# building Reflow
- talk
- slides: http://kristoferjoseph.com/Building-Reflow-BackboneConf-2013/
- the problem
- difficult to design responsive websites
- often multiple PSDs
- using web technologies in a native app
- framework?
- onboarding
- easier to point people to Backbone documentation than homegrown framework
- pink wheel syndrome
- it's not better just because you made it
- prototype like you mean it
- write as if it were final, shippable code
- work til you can't scale, then refactor
- write tests for your prototype
- prototype the things you don't think are possible
- modularity
- RequireJS
- namespace events to prevent dependencies
- multiple inheritance
- functional mixins
- http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins
- views
- Backbone.LayoutManager
- Marionette
- templates
- _.template
- use as little logic in templates as possible!
- underscore templates are faster when not using "with"
- testing
- test-driven from day zero
- "you simply cannot make quality software without test-driven development"
- "you can't refactor without tests"
- sinon.js
- squire.js
- sonar
- code coverage
- graphs!
- topcoat
- http://topcoat.io
- q&a
- why and how did Reflow ship as a desktop application (not a web application)?
- why?
- cater to the current design workflow
- how?
- team at adobe is dedicated to adding features to webkit
- chromium
- developed in the browser
- CEF (chrome embedded framework)
- loading/saving
- decide on a strategy early
- vs. native
- working prototype in a week
- demo-able prototype in three months
- finished in sixty weeks
- DOM or canvas?
- performance tips
- debounced
- requestAnimationFrame
# growing up with Backbone
- talk
- slides: http://tbranyen.com/talks/growing-up-with-backbone
- source: https://github.com/tbranyen/growing-up-with-backbone
- build step
- makes code more portable
- structure
- separate your code from third-party code
- make your JavaScript as small as possible and still debuggable
- enable source maps (fundamental for development)
- modules
- easier to test and maintain
- organize modules so the template, JavaScript and CSS are all together
- package managers
- makes third party code a higher class citizen
- build only what you reference
- decouple loading the configuration from loading the application (RequireJS specific)
# advanced architectural patterns with Backbone and cujoJS
- problems with many script and link tags
- blocking/synchronous
- dependency management?
- globals
- identifier conflicts
- no clear dependencies
- JavaScript modules
- loaders are non-blocking
- organize code better
- explicit dependencies
- too many dependencies
- need to mock or stub each dependency to test
- inversion of control
- dependency injection
- components don't deal with own dependencies; another entity provides them
- use constructors to inject dependencies
- problem: main module is huge
- solution: composition plans
- describe components and their lifecycles
- components have own view, HTML and (potentially) CSS
- aspect-oriented programming
- decorate methods of a component to provide additonal behavior
- mediator
- "meld"
- before/after actions
- DOM manipulation
- lots of code
- difficult to test
- solution: OOCSS
- DOM should reflect application state
- CSS defines visualization of state
- toggle classes instead of directly manipulating DOM elements
# becoming a control freak with controllers and promises
- promises
- background
- serialize asynchronous operations
- supported by Backbone and jQuery
- <% doSomething.then(doSomethingElse) %>
- everything should belong somewhere
- controllers
- MVC is well-known
- drain your routers
- controllers are "finite"
- they can be paused (if not displayed)
- they can be destroyed
- monogamous components
- components should only interact with one application layer
- expand your component toolbox to what fits
- component toolkit
- ViewModel
- exports array of properties (passed to view)
- no events, just reflects the model
- DataStore
- model factory method
- RouterMap
- PageController
- enables a dependency graph of every page
- mobile constraints
- less memory & CPU power
- less screen space
- higher cost of requests
- page bundle (bundle of all the javascript for one page)
- concepts
- make extension easy
- mixins
- helpers (not member functions)
- helper modules, just add as a dependency
- create/document hooks
- pre/post route
- pre/post render
- small, unintrusive changes
- avoid branching and merging
- modify in place
- train release model
- train leaves every day (code is released)
- if you're ready, hop on the train (push a commit)
- otherwise, catch the next train (push to the next release)
- the frontend has a backend
- models are "backend"
- views are "frontend"
- think slowly
- Backbone's friends
- Fiber (inheritance)
- Q (promises)
- FastClick (touch events)
- Venus (test runner)
- AMD (module pattern)
# soundcloud breakout session
- waveforms
- generated on the server
- served to the client as JSON
- rendered using canvas
- views
- ID passed to the constructor
- instantiate models themselves
- models
- identity map to keep track of instances
- override the constructor
- if ID is found in custom store, return reference
- if not, fetch from server
- no relationships
- reference counting (to keep identity map from growing too big)
- custom store
- identity map
- iterated through once a minute
- models with a reference count of zero are removed
- play button
- uses a global event bus to propagate through application
- remote refresh
- client polls server every set interval
- used to force clients to update
- CSS
- loaded by component using require
- added as a style tag
- SEO
- no rendering on the server
- possibly putting information in a noscript tag
# i like my jQuery plugins warm and toasty
- talk
- slides: http://johnkpaul.github.io/presentations/backboneconf/2013/toasty-plugins/
- Backbone views can be used to encapsulate widgets
- Backbone views
- widget initialization
- event binding
- organization
- Backbone view + jQuery plugin?
- old and busted: throw everything into initialize! (or render)
- new hotness: use defaults for plugin options
- design pattern: facade
- a simple interface that abstracts a more complicated process
- which parts differ between instances?
- does it need external configuration?
- hide plugin-specific parameters
- view's configuration should abstract the plugin
- does it need external control?
- expose methods on the view that call the plugin's methods
- does it need proxied events?
- bind jQuery plugins' events to methods on the view
- law of demeter: principle of least knowledge
# beyond jQuery widgets: JS UI library design
- talk
- slides: http://slid.es/pamelafox/js-ui-library-design
- jQsuery plugins
- standard to write UI libraries
- not perfect
- depend on jQuery
- inconsistent/non-existent architecture
- hide private functionality
- closures!
- idempotent constructor
- save instantiation info in the DOM
- customization
- parameters for widget options
- if instantiated on same element, take new options
- clear defaults
- declarative
- data-elements for specifying options in the DOM
- data-elements for construction
- observable
- should emit events developers can listen for
- AMD compatible
- should work with or without AMD
- dependencies
- jQuery (DOM manipulation)
- LucidJS (events)
- Q (promises)
- underscore (helpers)
- testable
- mocha
- jsdom
- chai
- sinon
# enterprise and the mobile web
- enterprise
- slow to adapt
- long-term view
- Backbone is closest to snap-in solution
- most popular framework
- plenty of plugins
- modularity
- built into Backbone's philosophy
- if you deleted all the view-related code, the library would still function
- extract reusable functionality into base classes
- composition can be used to resolve inheritance issues
- caching
- data stores
- local storage
- 5mb limit
- webSQL
- deprecated standard
- better support (for now)
- indexedDB
- transactional database
- key/value store
- polyfill
- asynchronous queries
- cacheable models
- name property to indicate bucket
- transaction to retrieve from cache
- fetch latest data from server
- offline
- offline actions should be synced to server when connection is restored
- override sync functions
- write model to local storage or server, depending whether or not online
- ask for write permission from database (serial instead of parallel transactions)
- what to write to the server when client comes back online?
- special bucket for unsynced actions
- only trigger success callback once event has fired twice (once locally, once to server)
- <% success = _.after(options.success, 2) %>
- create a cursor that loops through the store, syncing all the actions
- conflict resolution
- strategies
- client always wins
- if there's a conflict, server copy is overwritten
- server always wins
- if there's a conflict, client copy is overwritten
- custom resolution
- security
- keys
- app secret key
- create new user
- API granted key
- graduated levels of permissions
- q&a
- why override individual model sync functions instead of core Backbone ones?
- what if another model doesn't need the overridden version?
- functionality that is specific to a particular method
- tip (from someone who works at Simperium): use Simperium for syncing!
- why do conflict resolution client-side?
- enterprises want "data integration apps"
- all the data won't be in one silo
- APIs might not have built-in conflict resolution
- how to sync multiple items at once? (batch request or serial XHRs)
- depends on the backend
# Backbone at Disqus: a postmortem
- pre-Backbone
- inconsistent product experience
- CSS arms race
- overly-specific selectors
- !important
- difficult to introduce new features
- brittle, buggy
- ran a lot of code on the host page
- conflicts
- security and privacy issues
- user identity rendered on DOM in host page
- publisher can extract visitor information
- iframe
- Same-Origin Policy prevents access from parent
- can't be modified or inspected
- no more conflicts
- XSS vulnerabilities are contained
- not typical web application
- no address bar or permalinks
- loaded repeatedly, potentially multiple times per page
- short-lived
- backbone refactor
- project start: december 2011
- beta: may 2012
- release: june 2012
- hurdles/solutions
- iframe
- problems
- no reference to the parent page
- doesn't resize to fit content
- doesn't know viewport size, URL, document fragment
- solution: Backbone + postMessage
- use postMessage to trigger events on message bus
- content-security policy
- http://benvinegar.github.io/csp-talk-2013
- instance wrangling
- problems
- models appear multiple times, in different collections
- some models are "fresher" than others
- solution: Backbone.UniqueModel
- wraps the constructor of a model
- model is always unique
- later models are canonical
- event proxies
- problems
- instance replacement
- example: replacing different user models (guest, logged in user) on authentication
- solution: proxy model
- session is a model that contains a user
# resources
- http://backplug.io
- a searchable archive of Backbone plugins
- http://ricostacruz.com/backbone-patterns
- a list of Backbone patterns
- http://backbonerails.com
- series/screencasts on building apps with Backbone and Rails
@mulderp
Copy link

mulderp commented Jul 31, 2013

Very nice! Thanks for sharing!

@brad808
Copy link

brad808 commented Jul 31, 2013

Awesome, thanks! I'm so lazy... :-)

@nickcooley
Copy link

Great work. Thanks!

@kalv
Copy link

kalv commented Jul 31, 2013

I did a write up on the session I ran at our blog - thanks to those that came along.

@anupam11
Copy link

Thanks for sharing!

@livestreamer
Copy link

👍

@beaulebens
Copy link

Brilliant notes, thanks! Hope you keep it up tomorrow ;)

@jareware
Copy link

jareware commented Aug 1, 2013

Thank you, good read!

@poormansevo
Copy link

Thanks all, backboneconf rocked! Already making plans for next year's!

@gbedardsice
Copy link

Thanks for this! :D

@mindpivot
Copy link

Awesome! Much better note-taker than I am. Thanks a lot for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment