Successfully reported this slideshow.

Rp 6 session 2 naresh bhatia

1,228 views

Published on

Published in: Technology, Education
  • Be the first to comment

  • Be the first to like this

Rp 6 session 2 naresh bhatia

  1. 1. Architecting Web ApplicationsBuild Modular Web Applications Using Backbone.js and RequireJS
  2. 2. Naresh BhatiaCTO, Sapient Global MarketsCo-lead Visualization PracticeExperienceTrading and Risk Management applications usingJavaScript, Java and .NETFounder Archfirst (http://archfirst.org)A place for software developers to learn and comparetechnologies through real world examples
  3. 3. A case study in visualization
  4. 4. A technologist’s side-project that wasfunctional, but lacked finesse.
  5. 5. Before
  6. 6. In Between
  7. 7. After
  8. 8. What does it take to build suchapplications?
  9. 9. JavaScript Space used to beThe Wild WestSliding banners5000 lines of procedural code in a single fileComplex DOM spaghetti
  10. 10. The landscape is changing now
  11. 11. Recent Advances in JavaScript• AJAX enables changing of content without refreshing the entire page• Browsers implement better and faster JavaScript engines• Rise of smart web “applications” (vs. static web sites)– Gmail– Facebook– Twitter• People start talking about “architecture” of their JavaScript applications– Object-orientation– Design patterns– MVC– In-application messaging– Modularity
  12. 12. JavaScript is a respectableplatform todaySerious JavaScript developers do worryabout architecture these days!
  13. 13. Model-View-Controller (MVC)A pattern that encourages separation of concerns and code reuse
  14. 14. MVC Philosophy
  15. 15. Separate application state fromits presentationSeparate models from their viewsGet the truth out of the DOM
  16. 16. MVC Philosophy – Get the truth out of the DOMDoesn’t matter what flavor of MVC you are usingMVC, MVP, MVVM, MV*, MVWhateverModelsViews
  17. 17. Introducing Backbone – A Lightweight MV* Framework• Organize your interface into logical views backed by models– Each view responsible for one DOM element– Each view can be updated independently when the model changes– Reduces DOM traversal, increasing performance• See here for an example (slide 8)• No need to dig into a JSON object, look up an element in the DOM, andupdate the HTML by hand– Bind your views render function to the models "change" event– Now every view that displays this model is updated immediately on a change
  18. 18. Backbone MVC Examplehttp://archfirst.googlecode.com/svn/trunk/html/examples/backbone-mvc-example/index.htmlTilecolor: F89F1B
  19. 19. Backbone Models• Models are Backbone objects that contain “attributes”• Whenever an attribute’s value changes, the model triggers a change event// Define a modelvar Tile = Backbone.Model.extend({});// Create an instance of the modelvar tile = new Tile( );// Set an attribute to fire the change eventtile.set({color: 0xF89F1B});“change”eventTilecolor: F89F1B
  20. 20. Updating views from change eventstiletileRectViewcolor: F89F1Bel:model:// 1. Create an instance of the modelvar tile = new Tile( );// 2. Create a view, attach it to the model & DOMvar tileRectView =new TileRectView ({el: #tile‘, model: tile});// 3. (constructor) Bind view to model change eventthis.model.on(change, this.render);// 4. Change a model attributetile.set({color: 0xF89F1B});// 5. Model fires a ‘change’ event// 6. View catches the event & calls render( )this.$el.css(background-color, # +color2hex(this.model.get(color)));12render( )4‘change’event6DOM<div id="tile" ></div>53
  21. 21. CollectionsbrokerageAccountsaccountTableViewel:collection:this.$el.empty();this.collection.each(function(account, i) {var view = new AccountView({model: account});this.$el.append(view.render().el);}, this);DOM<table id="accounts_table"><thead>...</thead><tbody></tbody></table>initialize( )render( )this.collection.bind(reset, this.render);brokerageAccountbrokerageAccountbrokerageAccount
  22. 22. Composing an interface from multiple views – View HierarchyAccountsPageAccountsTabUserPageHeaderWidgetAccountTableWidget AccountChartWidgetAccountViewFooterWidgetAccountViewAccountViewAccountView
  23. 23. Inserting pages and widgets dynamicallyindex.html<!DOCTYPE html><html><head>...</head><body><div id="container"><!-- Pages go here --></div></body></html>
  24. 24. A typical pageAccountsPage.jsBaseView.extend({postRender: function() {this.addChildren([{viewClass: UserPageHeaderWidget,parentElement: this.$el},{viewClass: AccountsTab,parentElement: this.$el},{viewClass: FooterWidget,parentElement: this.$el}]);}}
  25. 25. A typical widgetUserPageHeaderWidget.jsBaseView.extend({tagName: header,className: user-page-header,template: {name: UserPageHeaderTemplate,source: UserPageHeaderTemplate}});UserPageHeaderTemplate.html<div class="user-info"><span>{{firstName}} {{lastName}}</span><img src="img/person-icon-small.png" alt="seperator" /><a class="js-signOut" href="#">Sign Out</a></div><h1 class="ir">Bullsfirst</h1>
  26. 26. Classic Server-Side Layered ArchitectureUser InterfaceLayerAccepts user commands and presentsinformation back to the userApplicationLayerManages transactions, translates DTOs,coordinates application activities, creates andaccesses domain objectsDomainLayerContains the state and behavior of the domainInfrastructureLayerSupports all other layers, includes repositories,adapters, frameworks etc.
  27. 27. Bullsfirst Client-Side Layered ArchitectureFrameworkPresentationLayerDomain
  28. 28. In-Application Messaging• Interactions between table and chart• If theses widgets interacted directly, the coupling would be too tight• Use a message bus (a.k.a. pub/sub) to decouple the componentsAccount :mouseover
  29. 29. JavaScript ModularityA pattern that supports large scale application development
  30. 30. How much of your application canyou hold in your head at once?Bullsfirst is about 2000 lines of JS
  31. 31. Have you ever been inDependency Hell?<script src="js/form2js.js"></script><script src="js/toObject.js"></script><script src="js/base64_encode.js"></script><script src="js/utf8_encode.js"></script><script src="js/format.js"></script><script src="js/treeTable.js"></script><script src="js/jalerts.js"></script>
  32. 32. AMD and RequireJS to the rescueAMD: Asynchronous Module Definition(an API for defining and loading JS modules)RequireJS: A popular implementation of AMD
  33. 33. Modules allow you to break largeapplications into bite-size chunksCode reuse & separation of concernsComplements the MVC pattern
  34. 34. Structure of a Modular Appsrc|-- js| |-- app| | |-- domain| | | |-- Repository.js| | | |-- BrokerageAccount.js| | | `-- ...| | |-- pages| | | |-- home| | | |-- accounts| | | `-- ...| | `-- widgets| | `-- account-table| | `-- account-chart| | `-- ...| |-- framework| | |-- Baseview.js| | |-- Router.js| | `-- ...| `-- vendor| |-- backbone.js| |-- jquery.js| `-- ...|-- sass|-- img`-- index.html60+ JavaScript files2000 lines of codeBut much easier to find things!JavaScript andtemplates (markup)JavaScript andtemplates (markup)
  35. 35. Defining a ModuleRequireJS loads all code relative to a baseUrl(set to the same directory as the script used in a data-main)// app/widgets/login/LoginWidget// Defines a widget called LoginWidgetdefine([],function() {return BaseView.extend({...});});
  36. 36. Using a ModuleDefining dependency on a module makes sure that themodule is pulled in before the dependent code.// app/pages/home/HomePage// Defines the home page that uses the LoginWidgetdefine([app/widgets/login/LoginWidget],function(LoginWidget) {return BaseView.extend({postRender: function() {this.addChild({id: LoginWidget,viewClass: LoginWidget,parentElement: this.$el});}...});});
  37. 37. Moving templates into text modules<td class="name">{{name}}</td><td class="market-value">{{formatMoney marketValue}}</td><td class="cash">{{formatMoney cashPosition}}</td>...AccountTemplate.html
  38. 38. Using templates defined in text modulesdefine([text!app/widgets/account-table/AccountTemplate.html],function(AccountTemplate) {return BaseView.extend({template: {name: AccountTemplate,source: AccountTemplate},...});});AccountView.js
  39. 39. Optimizing for Production – The Build System• A web application consisting of hundreds of JavaScript files could havesevere performance implications in a production environment• RequireJS comes with an optimizer that walks the dependency tree andconcatenates all the required JavaScript files into one• The Bullsfirst build system runs the RequireJS optimizer plus otheroptimizations such as yuicompressor and uglifyjs to reduce the downloadsize of the application– The build system is based on Grunt.js, a task-based command line build tool forJavaScript projects– It cuts down application load time to approximately 2 seconds on a 3 Mbps network
  40. 40. Summary
  41. 41. Summary• Use the MVC pattern to enforce separation of concerns• Compose your application using smaller Reusable Components• Create a Domain Layer as a central place for views to access information• Use In-Application Messaging to decouple application components• Use Modules to break large applications into bite-size chunksA strong architecture is key to building engaging web applications
  42. 42. References
  43. 43. References• Backbone.js – https://github.com/documentcloud/backbone• RequireJS – https://github.com/jrburke/requirejs• Bullsfirst is an open-source project under http://archfirst.org– Sharing best practices with the developer community– Live demo at http://archfirst.org/apps/bullsfirst-jquery-backbone– Source repository: https://github.com/archfirst/bullsfirst-jquery-backbone– Discussion/feedback at http://archfirst.org/forums/general-discussion43

×