Design Patterns forJavaScript Web Apps     Stefan ScheidtOPITZ CONSULTING GmbH
About me ...stefan.scheidt@opitz-consulting.com          (@stefanscheidt)
Mission                                      MarketsThe companys ambition is to help             Branchspreadingorganizat...
And … who are you?
This talk is about ...  ... the development oftestable and maintainable   JavaScript Web Apps
This talk is about ...  ... the development oftestable and maintainable   JavaScript Web Apps
Our Sample App ...http://tigbro.github.com/todo-mobilehttps://github.com/tigbro/todo-mobile
Software Design
"Multi Page Web App"Browser                             Server           HTML-Page                       Controller   Data...
"AJAX Web App"Browser                           Server            ChangeAJAX-                Controller            Backend...
"Single Page Web App"  Browser             Server  Controller   Data   Backend
UI Component Libraries
jQuery Mobile http://jquerymobile.com/
How can you create this?
<div id="main" data-role="page">  <div data-role="header">    <h1>Todos</h1>    <a href="">Save</a>    <a href="#settings"...
<div id="main" data-role="page">  <div data-role="header">    <h1>Todos</h1>    <a href="">Save</a>    <a href="#settings"...
<div id="main" data-role="page">  <div data-role="header">    <h1>Todos</h1>    <a href="">Save</a>    <a href="#settings"...
<div id="main" data-role="page">  <div data-role="header">    <h1>Todos</h1>    <a href="">Save</a>    <a href="#settings"...
<div id="main" data-role="page">  <div data-role="header">    <h1>Todos</h1>    <a href="">Save</a>    <a href="#settings"...
DOM Transformations
<input type="checkbox" id="todo1"/><label for="todo1">create a mobile todo app</label><div class="ui-checkbox">  <input ty...
<input type="checkbox" id="todo1"/><label for="todo1">create a mobile todo app</label><div class="ui-checkbox">  <input ty...
Two Way Data Binding
Do it yourself "binding" ...
$(#addTodo).submit(function(event) {    addTodo();    event.preventDefault();});function addTodo() {    var inputText = $(...
$(#addTodo).submit(function(event) {    addTodo();    event.preventDefault();});function addTodo() {    var inputText = $(...
$(#addTodo).submit(function(event) {    addTodo();    event.preventDefault();});function addTodo() {    var inputText = $(...
$(#addTodo).submit(function(event) {    addTodo();    event.preventDefault();});function addTodo() {    var inputText = $(...
$(#addTodo).submit(function(event) {    addTodo();    event.preventDefault();});function addTodo() {    var inputText = $(...
$(#addTodo).submit(function(event) {    addTodo();    event.preventDefault();});function addTodo() {    var inputText = $(...
$(#addTodo).submit(function(event) {    addTodo();    event.preventDefault();});function addTodo() {    var inputText = $(...
$(#addTodo).submit(function(event) {    addTodo();    event.preventDefault();});function addTodo() {    var inputText = $(...
Wouldnt this be better ... ?function TodoController() {    this.todos = [];    this.inputText = ;}TodoController.prototype...
Angular JSDeclarative                       MVC withUI Templates                      Dependency InjectionTwo-Way         ...
Two Way Databinding       read              read       write    Data-    writeDOM                              Controller ...
Scopes                               Scope                                         Expressions       $get(<expr>)         ...
Demo
<div id="main" data-role="page">  <div data-role="header">    <h1>Todos</h1>    <a href="">Save</a>    <a href="#settings"...
function TodoController() {    this.todos = [];    this.inputText = ;}TodoController.prototype.addTodo = function() {    t...
<div data-role="page"                         TodoController Scope     ng:controller="TodoController">                    ...
We are almost there, but ...
jQuery Mobile & AngularJS        The problem:       DOM transformationsdone by jQuery Mobile and AngularJS      need to be...
jQuery Mobile & AngularJS       Our Solution: jQuery Mobile Angular Adapter
jQuery Mobile Angular Adapter Integration of jQuery Mobile & AngularJS  Extentions for mobile web development            O...
Dependency Injection
Dependency Injection is a design patternwhose purpose is to reduce the dependencies          between components.It delegat...
Dependency Injection is a design patternwhose purpose is to reduce the dependencies          between components.It delegat...
Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;TodoController.prototype.refreshTodos() {    var s...
Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;TodoController.prototype.refreshTodos() {    var s...
Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;function read(key, success) {    var url = readUrl...
Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;function read(key, success) {    var url = readUrl...
Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;function read(key, success) {    var url = readUrl...
Sample: Calling the backend                                                   waitDialogtodoController           todoStore...
Sample: Calling the backend                                                  waitDialogtodoController               todoSt...
Angular: DI for Servicesangular.service(jsonp, jsonpFactory);angular.service(waitdialog, waitdialogFactory);
Angular: DI for Servicesangular.service(jsonp, jsonpFactory);angular.service(waitdialog, waitdialogFactory);function todoS...
Angular: DI for Servicesangular.service(jsonp, jsonpFactory);angular.service(waitdialog, waitdialogFactory);function todoS...
Angular: DI for Servicesangular.service(jsonp, jsonpFactory);angular.service(waitdialog, waitdialogFactory);function todoS...
Angular: DI for Controller// ...angular.service(todoStore, ...);
Angular: DI for Controller// ...angular.service(todoStore, ...);function TodoController(todoStore) {  // do something with...
SummaryThere are quite a lot of useful design patternsfor the development of JavaScript Web Apps!                  Use them!
Summary     Libraries and Frameworkscan help you to get your stuff done!
In the hive 11: nectar and pollen      by Max xx, http://www.flickr.com/photos/max_westby/4567762490                      ...
The End ...@stefanscheidt   @tigbro
Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ CONSULTING - Stefan Scheidt
Upcoming SlideShare
Loading in …5
×

Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ CONSULTING - Stefan Scheidt

3,137 views

Published on

http://www.opitz-consulting.com/go/3-4-11
JavaScript applications have yet become increasingly powerful but likewise increasingly complex. How can such an application remain maintainable and testable in spite of its growth? Design pattern like data binding, dependency injection and modular design.

OPITZ CONSULTING Senior Solution Architect Stefan Scheidt at JavaScript Conference, Düsseldorf, Germany, 27/02/2012.

Published in: Technology

Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ CONSULTING - Stefan Scheidt

  1. 1. Design Patterns forJavaScript Web Apps Stefan ScheidtOPITZ CONSULTING GmbH
  2. 2. About me ...stefan.scheidt@opitz-consulting.com (@stefanscheidt)
  3. 3. Mission MarketsThe companys ambition is to help  Branchspreadingorganizations to be better than their  Over 600 customerscompetitors. 29% Trade / Logistics /Our services take place in partnership and 29% Supplier Industry / Services /are aimed at co-operation of many years. Telecommunications 42% Public Clients / Banks and Insurance Associations and FederationsPortfolio Basic Data Business IT Alignment  Founded in 1990 Business Information Management  400 employees Business Process Management  8 offices Application Development SOA and System Integration IT Infrastructure Management © OPITZ CONSULTING GmbH 2012 Seite 3
  4. 4. And … who are you?
  5. 5. This talk is about ... ... the development oftestable and maintainable JavaScript Web Apps
  6. 6. This talk is about ... ... the development oftestable and maintainable JavaScript Web Apps
  7. 7. Our Sample App ...http://tigbro.github.com/todo-mobilehttps://github.com/tigbro/todo-mobile
  8. 8. Software Design
  9. 9. "Multi Page Web App"Browser Server HTML-Page Controller Data Backend UI Values
  10. 10. "AJAX Web App"Browser Server ChangeAJAX- Controller Backend DataEngine Events
  11. 11. "Single Page Web App" Browser Server Controller Data Backend
  12. 12. UI Component Libraries
  13. 13. jQuery Mobile http://jquerymobile.com/
  14. 14. How can you create this?
  15. 15. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  16. 16. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  17. 17. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  18. 18. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  19. 19. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  20. 20. DOM Transformations
  21. 21. <input type="checkbox" id="todo1"/><label for="todo1">create a mobile todo app</label><div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label></div> jQuery Mobile Markup Transformation
  22. 22. <input type="checkbox" id="todo1"/><label for="todo1">create a mobile todo app</label><div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label></div> jQuery Mobile Markup Transformation
  23. 23. Two Way Data Binding
  24. 24. Do it yourself "binding" ...
  25. 25. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  26. 26. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  27. 27. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  28. 28. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  29. 29. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  30. 30. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  31. 31. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  32. 32. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  33. 33. Wouldnt this be better ... ?function TodoController() { this.todos = []; this.inputText = ;}TodoController.prototype.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ;}
  34. 34. Angular JSDeclarative MVC withUI Templates Dependency InjectionTwo-Way FrameworkData Binding http://angularjs.org/#/
  35. 35. Two Way Databinding read read write Data- writeDOM Controller binding watch watch
  36. 36. Scopes Scope Expressions $get(<expr>) inputText todos.length $set(<expr>, <value>) Object ...$watch(<expr>, <callback>)
  37. 37. Demo
  38. 38. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> The DOM
  39. 39. function TodoController() { this.todos = []; this.inputText = ;}TodoController.prototype.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ;} The Controller
  40. 40. <div data-role="page" TodoController Scope ng:controller="TodoController"> inputText: new todo create <input type="text" todos: [...] name="inputText" bind bind <div ng:repeat="todo in todos"> create Repeater Scope Repeater Scope Repeater Scope todo: { todo: todo: { { <input type="checkbox" name="todo.done"/> done: false done: false done: false bind name: makemoney name: makemoney name: makemoney <label> {{todo.name}} } </label> bind }}
  41. 41. We are almost there, but ...
  42. 42. jQuery Mobile & AngularJS The problem: DOM transformationsdone by jQuery Mobile and AngularJS need to be coordinated!
  43. 43. jQuery Mobile & AngularJS Our Solution: jQuery Mobile Angular Adapter
  44. 44. jQuery Mobile Angular Adapter Integration of jQuery Mobile & AngularJS Extentions for mobile web development Open source on GitHubhttps://github.com/tigbro/jquery-mobile-angular-adapter
  45. 45. Dependency Injection
  46. 46. Dependency Injection is a design patternwhose purpose is to reduce the dependencies between components.It delegates the responsibility for creation and wiring of objects to an externaly configurable framework. http://de.wikipedia.org/wiki/Dependency_Injection
  47. 47. Dependency Injection is a design patternwhose purpose is to reduce the dependencies between components.It delegates the responsibility for creation and wiring of objects to an externaly configurable framework. http://de.wikipedia.org/wiki/Dependency_Injection
  48. 48. Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;TodoController.prototype.refreshTodos() { var self = this; read(readUrl, function(response) { self.todos = response; });}
  49. 49. Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;TodoController.prototype.refreshTodos() { var self = this; read(readUrl, function(response) { self.todos = response; });}
  50. 50. Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); });}
  51. 51. Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); });}
  52. 52. Sample: Calling the backendvar readUrl = https://secure.openkeyval.org/;function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); });}
  53. 53. Sample: Calling the backend waitDialogtodoController todoStore key valuekey value key value ... ...refreshToDos ... read ...todoStore waitDialog jsonp jsonp key value ... ... created created by with "new" Factories
  54. 54. Sample: Calling the backend waitDialogtodoController todoStore key valuekey value key value ... ...refreshToDos ... read ...todoStore waitDialog jsonp jsonp key value ... ... created by Dependency Injection
  55. 55. Angular: DI for Servicesangular.service(jsonp, jsonpFactory);angular.service(waitdialog, waitdialogFactory);
  56. 56. Angular: DI for Servicesangular.service(jsonp, jsonpFactory);angular.service(waitdialog, waitdialogFactory);function todoStoreFactory() { function read(key, success) { ... } // ... return { read: read // ... }}
  57. 57. Angular: DI for Servicesangular.service(jsonp, jsonpFactory);angular.service(waitdialog, waitdialogFactory);function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { ... } // ... return { read: read, // ... }}todoStoreFactory.$inject = [jsonp, waitdialog];
  58. 58. Angular: DI for Servicesangular.service(jsonp, jsonpFactory);angular.service(waitdialog, waitdialogFactory);function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { ... } // ... return { read: read // ... }}todoStoreFactory.$inject = [jsonp, waitdialog];angular.service(todoStore, todoStoreFactory);
  59. 59. Angular: DI for Controller// ...angular.service(todoStore, ...);
  60. 60. Angular: DI for Controller// ...angular.service(todoStore, ...);function TodoController(todoStore) { // do something with todoStore ...}TodoController.$inject = [todoStore];
  61. 61. SummaryThere are quite a lot of useful design patternsfor the development of JavaScript Web Apps! Use them!
  62. 62. Summary Libraries and Frameworkscan help you to get your stuff done!
  63. 63. In the hive 11: nectar and pollen by Max xx, http://www.flickr.com/photos/max_westby/4567762490 BooksBy Rodrigo Galindez, http://www.flickr.com/photos/rodrigogalindez/4637637337/ IMG_1300-Edit by Susan E Adams, http://www.flickr.com/photos/susanad813/3912914836/ Doble Via by amslerPIX, http://www.flickr.com/photos/amslerpix/6242266697/ MacBook Pro Keyboardby superstrikertwo, http://www.flickr.com/photos/superstrikertwo/4989727256/ Stubborn Last Drop by RogueSun Media, http://www.flickr.com/photos/shuttercat7/627798443/
  64. 64. The End ...@stefanscheidt @tigbro

×