Successfully reported this slideshow.
Your SlideShare is downloading. ×

From Backbone to Ember and Back(bone) Again

From Backbone to Ember and Back(bone) Again

Download to read offline

As a software consultant, I get to see a lot of interesting code. In this particular instance a client was in the process of transforming their web application to a rich, interactive interface with the help of another company.

The project kicked off using Backbone and things were great. Until they were not great. Pages starting getting more and more involved and blame started being thrown at the technology choice.

A move to Ember.js ensued and the app was rewritten. But architecturally bad decisions don't hide long, and soon the rewrite was preforming even worse. That's when I stepped in, with the help of another consultant, to solve the performance issues once and for all. Our solution used Backbone.js and it was fast. This is that journey.

As a software consultant, I get to see a lot of interesting code. In this particular instance a client was in the process of transforming their web application to a rich, interactive interface with the help of another company.

The project kicked off using Backbone and things were great. Until they were not great. Pages starting getting more and more involved and blame started being thrown at the technology choice.

A move to Ember.js ensued and the app was rewritten. But architecturally bad decisions don't hide long, and soon the rewrite was preforming even worse. That's when I stepped in, with the help of another consultant, to solve the performance issues once and for all. Our solution used Backbone.js and it was fast. This is that journey.

More Related Content

From Backbone to Ember and Back(bone) Again

  1. 1. Back(bone) Again From Backbone to Ember and
  2. 2. Partner at Coffee & Code. Lover of tech. Hi, I’m Jon.
  3. 3. Hi, I’m Jon. Partner at Coffee & Code. Lover of tech.
  4. 4. Developer module.exports = Work.create({ code: function() { return 'the solution'; } })
  5. 5. Consultant module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } }) module.exports = Work.create({ code: function() { return 'the solution'; } })
  6. 6. Widget Factory W Factory
  7. 7. Widget Factory W Factory + Vendor Co.
  8. 8. Widget Dashboard Item 1 Hunger Level 72% Room Orange # of Yawns 12.4 0 50 100 10am 12pm Item 2 Hunger Level 12% Room Salon D # of Yawns 204 0 50 100 10am 12pm Item 3 Hunger Level 45% Room Cypress # of Yawns 16 0 50 100 10am 12pm
  9. 9. Widget Dashboard • single page Javascript app, built in Backbone • pulls data from API server • more and more features caused code bloat • Widget Factory does not know much Javascript
  10. 10. Widget Dashboard • single page Javascript app, built in Backbone • pulls data from API server • more and more features caused code bloat • Widget Factory does not know much Javascript
  11. 11. Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
  12. 12. Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
  13. 13. Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
  14. 14. Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
  15. 15. Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
  16. 16. Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
  17. 17. var MyView = Backbone.View.extend({ el: '#content', template: _.template($('#template').text()), render: function() { this.$el.html(this.template({ language: 'Backbone' })); return this; } }); var myView = new MyView(); myView.render(); <div id="content"></div> <script id="template" type="text/template"> <h1>Hello from <%- language %>!</h1> </script> http://codepen.io/coffeeandcode/pen/VYmZjK
  18. 18. DOM jQuery Underscore Templates Backbone
  19. 19. : Issues • library does not do much, never will • easy to start integration, difficult things around edges • lack of project architecture leaves a lot up to the developers • easy to create memory leaks
  20. 20. Widget Dashboard 2.0 • app rewritten in Ember.js • goal was to write less code, easier to teach • less moving parts == less to screw up • Widget Factory still does not know much JS
  21. 21. Widget Dashboard 2.0 • app rewritten in Ember.js • goal was to write less code, easier to teach • less moving parts == less to screw up • Widget Factory still does not know much JS
  22. 22. A framework for creating ambitious web applications.
  23. 23. A framework for creating ambitious web applications.
  24. 24. A framework for creating ambitious web applications.
  25. 25. Ember.js is an open-source client-side JavaScript web application framework based on the model-view- controller (MVC) software architectural pattern. It allows developers to create scalable single-page applications by incorporating common idioms and best practices into a framework that provides a rich object model, declarative two-way data binding, computed properties, automatically-updating templates powered by Handlebars.js, and a router for managing application state.[1] 1. http://en.wikipedia.org/wiki/Ember.js
  26. 26. Ember.js is an open-source client-side JavaScript web application framework based on the model-view- controller (MVC) software architectural pattern. It allows developers to create scalable single-page applications by incorporating common idioms and best practices into a framework that provides a rich object model, declarative two-way data binding, computed properties, automatically-updating templates powered by Handlebars.js, and a router for managing application state.[1] 1. http://en.wikipedia.org/wiki/Ember.js
  27. 27. Ember.js is an open-source client-side JavaScript web application framework based on the model-view- controller (MVC) software architectural pattern. It allows developers to create scalable single-page applications by incorporating common idioms and best practices into a framework that provides a rich object model, declarative two-way data binding, computed properties, automatically-updating templates powered by Handlebars.js, and a router for managing application state.[1] 1. http://en.wikipedia.org/wiki/Ember.js
  28. 28. Ember.js is an open-source client-side JavaScript web application framework based on the model-view- controller (MVC) software architectural pattern. It allows developers to create scalable single-page applications by incorporating common idioms and best practices into a framework that provides a rich object model, declarative two-way data binding, computed properties, automatically-updating templates powered by Handlebars.js, and a router for managing application state.[1] 1. http://en.wikipedia.org/wiki/Ember.js
  29. 29. Ember.js is an open-source client-side JavaScript web application framework based on the model-view- controller (MVC) software architectural pattern. It allows developers to create scalable single-page applications by incorporating common idioms and best practices into a framework that provides a rich object model, declarative two-way data binding, computed properties, automatically-updating templates powered by Handlebars.js, and a router for managing application state.[1] 1. http://en.wikipedia.org/wiki/Ember.js
  30. 30. Ember.js is an open-source client-side JavaScript web application framework based on the model-view- controller (MVC) software architectural pattern. It allows developers to create scalable single-page applications by incorporating common idioms and best practices into a framework that provides a rich object model, declarative two-way data binding, computed properties, automatically-updating templates powered by Handlebars.js, and a router for managing application state.[1] 1. http://en.wikipedia.org/wiki/Ember.js
  31. 31. var App = Ember.Application.create(); App.IndexRoute = Ember.Route.extend({ model: function() { return { language: 'Ember' }; } }); <div id="content"></div> <script data-template-name="index" type="text/x-handlebars"> <h1>Hello from {{language}}!</h1> </script> http://codepen.io/coffeeandcode/pen/ZYBzad
  32. 32. DOM jQuery Handlebars Templates Ember Ember Data
  33. 33. : Issues • very opinionated, very large codebase • does black magic with Handlebars • assumes you need the big guns • two-way data binding by default • easy to shoot yourself in the foot
  34. 34. Two Main Problems W Factory
  35. 35. Performance Civic i-VTEC Engine by Kris Carillo: https://flic.kr/p/7VFLeC
  36. 36. Widget Dashboard Item 1 Hunger Level 72% Room Orange # of Yawns 12.4 0 50 100 10am 12pm Item 2 Hunger Level 12% Room Salon D # of Yawns 204 0 50 100 10am 12pm Item 3 Hunger Level 45% Room Cypress # of Yawns 16 0 50 100 10am 12pm
  37. 37. Widget Dashboard Production Data:
 500 widgets
  38. 38. Poor Man’s Testing 0 175 350 525 700 seconds 10 20 30 120 Ember App MB of memory
  39. 39. http://www.filamentgroup.com/ lab/mv-initial-load-times.html
  40. 40. $ find backbone -name '*.js' | xargs wc -wcl 12 36 197 backbone/js/app.js 41 166 1130 backbone/js/collections/todos.js 26 78 536 backbone/js/models/todo.js 26 67 499 backbone/js/routers/router.js 131 428 3703 backbone/js/views/app-view.js 132 496 3888 backbone/js/views/todo-view.js 368 1271 9953 total $ find emberjs -name '*.js' | xargs wc -wcl 6 14 159 emberjs/js/app.js 59 165 1486 emberjs/js/controllers/todo_controller.js 51 128 1195 emberjs/js/controllers/todos_controller.js 16 38 432 emberjs/js/controllers/todos_list_controller.js 11 31 262 emberjs/js/helpers/pluralize.js 9 18 158 emberjs/js/models/todo.js 38 78 816 emberjs/js/router.js 12 33 298 emberjs/js/views/todo_input_component.js 202 505 4806 total lines words chars
  41. 41. People Problem Random, funny internet photo
  42. 42. People Problem • lack of knowledge in front-end technologies • not enough pairing and information sharing • team skill level was not adequate to pick up where Vendor Co. left off • amount of documentation was lacking
  43. 43. Our Solution • focus on knowledge sharing • pair programming / technical side projects • build what the client understands • built JS workflow with the client’s help • explicit code, no magic • uses CommonJS and Browserify • use technologies with little change and a wealth of documentation
  44. 44. Explicit Code + var MainLayout = require('../views/shared/layout'); module.exports = MainLayout.extend({ template: 'dashboard/layout', ui: { tooltipFields: '[data-tooltip=true]' }, onRender: function() { // apply jQuery plugin to tooltip fields this.ui.tooltipFields.tooltip(); } });
  45. 45. Backbone.Marionette is a composite application library for Backbone.js that aims to simplify the construction of large scale JavaScript applications. It is a collection of common design and implementation patterns found in the applications that we have been building with Backbone, and includes pieces inspired by composite application architectures, event-driven architectures, messaging architectures, and more.
  46. 46. Backbone.Marionette is a composite application library for Backbone.js that aims to simplify the construction of large scale JavaScript applications. It is a collection of common design and implementation patterns found in the applications that we have been building with Backbone, and includes pieces inspired by composite application architectures, event-driven architectures, messaging architectures, and more.
  47. 47. Backbone.Marionette is a composite application library for Backbone.js that aims to simplify the construction of large scale JavaScript applications. It is a collection of common design and implementation patterns found in the applications that we have been building with Backbone, and includes pieces inspired by composite application architectures, event-driven architectures, messaging architectures, and more.
  48. 48. Backbone.Marionette is a composite application library for Backbone.js that aims to simplify the construction of large scale JavaScript applications. It is a collection of common design and implementation patterns found in the applications that we have been building with Backbone, and includes pieces inspired by composite application architectures, event-driven architectures, messaging architectures, and more.
  49. 49. Backbone.Marionette is a composite application library for Backbone.js that aims to simplify the construction of large scale JavaScript applications. It is a collection of common design and implementation patterns found in the applications that we have been building with Backbone, and includes pieces inspired by composite application architectures, event-driven architectures, messaging architectures, and more.
  50. 50. var MyView = Marionette.ItemView.extend({ el: '#content', template: '#template', serializeData: function() { return { language: 'Marionette' }; } }); var myView = new MyView(); myView.render(); <div id="content"></div> <script id="template" type="text/template"> <h1>Hello from <%- language %>!</h1> </script> http://codepen.io/coffeeandcode/pen/raWBWE
  51. 51. DOM jQuery Underscore Templates Backbone Marionette
  52. 52. Activity Monitor 0 175 350 525 700 seconds 10 20 30 120 Ember App Backbone App
  53. 53. My Challenge • build apps with production data in mind • consider non-technical needs of project • show love for all technology choices, but be hesitant to adopt new libraries
  54. 54. Thanks Jonathan Knapp
 @CoffeeAndCode http://slidesha.re/1w5yv4A
  55. 55. Resources Slide 1 image: https://flic.kr/p/8Y8T5T Slide 2 image: Keynote default :) Slide 35 image: https://flic.kr/p/7VFLeC Slide 39: TodoMVC performance work by Filament Group: http:// www.filamentgroup.com/lab/mv-initial-load-times.html Slide 41 image: the internets (don’t know source)

Editor's Notes

  • explain Coffee + Code
  • Time Machine: my cohort, Eric Browning, is talking about “No More Static Comps: Design Process in the Modern World” at 11am in Salon D.

    I’m a consultant that gets to work with lots of different clients and I get to write (and see) a lot of different code. To keep it professional, no names in presentation or during questions besides my own.
  • Most programmers get paid to write code. They work on different projects.
  • I get paid to work on MANY different projects. Get to see a lot of good/bad practices, work in different languages, solve different problems. I can bring unique perspective to projects.
  • Client = Widget Factory

    if you haven’t guessed, no real names please
  • Widget Factory hired Vendor Co to build a web application. A dashboard. Many moving pieces / parts. We will focus on front-end UI.
  • * show latest numbers from server
    * chart shows historical numbers over past X hours
    * data loaded when app loads and polls every X seconds
  • data from API server was in bloated format
    adding features felt like it was taking too much time
  • there was some code pairing and information sharing to help bridge gap
    everyone had best intentions in mind
  • best intentions in mind
    Ember has easy data binding, easily update views when data updates
  • I used Backbone in many projects before, comfortable
  • laughable, does not provide much in terms of “structure”
    organizes jQuery spaghetti code (still useful)
  • the “M” in MVC, organization of data
    JS Objects and Arrays with enumeration management methods
  • utilize events for having app adapt to changes in state
    uniform way to manage DOM events and create custom events
  • logic to map data and state changes to what the user sees and interacts with
    ends up doing most of the work
  • * views have events as well, no biggie nowadays but useful for separation of responsibility
  • pushes JSON out of the box
    can be customized, but it can be painful and require a lot of custom code
  • opinionated collection of “best practices”
    does a lot of the grunt work for you
  • * created to tackle complicated web applications
  • (highlight parts of the definition giving a real explanation of what that means for the developer)
  • * same as Backbone and most front-end “frameworks”
  • this is where Ember truly shines
    directional team very interested in providing best of breed, open to changing technologies
  • start to build relationships between data
    separate library called Ember.data that handles async data retrieval
  • Backbone all manual, Ember is automatic
  • router gets quite a bit of praise
    much more powerful than Backbones, handles tiers of triggered controllers (nice if your app plays well with well structured urls)
    I’m not used to it yet
  • surprised to see conversations of Rails bloat, but flocking to Ember
    two way data binding by default produces unnecessary overhead
    follows Rails, easy to write code, also easy to not know what you wrote (how much computation behind the scenes?)
    app still suffered from two big issues
  • * original app looked great with 10 - 20 items
    * needed to show more than 500, also limited by other architecture choices

    load all the dataz!
    write less code, bind more things
    render it all
  • Comparing Backbone w/Marionette to Vendor Co’s
  • took TodoMVC app and “productionized” assets to take performance numbers
  • I downloaded TodoMVC examples and got line counts
  • what I believe was the biggest issue with Vendor Co’s app
    Widget Factory can’t maintain something they don’t understand
    they would have been disappointed in any solution they received
  • * technical solution delivered that did not account for non-technical project needs
    * how often things broke in lib or architectural decisions
  • * keyword is “our”, built entire structure with assistance from Widget Factory employees
    * discuss how our solution addressed non-technical needs of project
    * team uplift / pairing
    * designing a workflow together
    * explicit code rather than implicit magic
    * amount (and quality) of documentation for js libs and css framework (bootstrap)
    abstracted JS workflow into common Grunt library
    abstracted common application system and code into common UI library
  • this will create a Layout based on your application’s main layout
    you “export” what you want other files to be able to require
    all dependencies must be required
    Browserify handles dependency management
    all source is concatenated into one js file (automatically skips unused source code)
  • built upon Backbone and
    Backbone.Wreqr (messaging patterns for Backbone apps)
    Backbone.BabySitter (manage child views)
    * Wreqr changing to Backbone Radio in upcoming release of Marionette
  • removes the copy/paste boilerplate for view rendering from Backbone
  • bringing design patterns into Backbone:
    Application singleton
    module loader
    view hierarchies
    view behaviors (sectioned responsibilities for a single view)
    template caching
    view regions / region managers
  • view hierarchies
    ItemView, LayoutView, CollectionView, CompositeView
    Regions and RegionManagers
    Backbone.Wreqr / Radio that uses channels (ex: “global”)
    commands (do something, don’t care about response)
    event aggregator (custom events attached to your application)
    request / response (return data from request)
  • My challege to all of you
    consider non-technical needs or else miss expectations on delivery
    hesitate to introduce new technologies to solve the problem
    think about the REAL problems and what it takes to solve them, do not focus on only technical problems
  • I’m Jonathan Knapp of Coffee and Code, thanks!

×