Last active
December 20, 2015 11:19
-
-
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!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Awesome! Much better note-taker than I am. Thanks a lot for sharing!