Upgrade to Pro — share decks privately, control downloads, hide ads and more …

applications: a series of states

applications: a series of states

Video: https://vimeo.com/65504071

An exploration of application structure patterns, from purely server oriented request/response flow to fully featured client applications in the browser

Trek Glowacki

November 16, 2012
Tweet

More Decks by Trek Glowacki

Other Decks in Programming

Transcript

  1. applications: a series of states
    a talk by @trek

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. View Slide


  7. View Slide

  8. View Slide

  9. View Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. View Slide

  18. View Slide

  19. View Slide

  20. View Slide

  21. View Slide

  22. View Slide

  23. View Slide

  24. View Slide

  25. View Slide

  26. GET https://simple.com/activity

    View Slide

  27. View Slide

  28. View Slide

  29. GET https://simple.com/activity/transactions/3a709ef6-
    c300-43b4-bca0-af72d1ecd4ba

    View Slide

  30. View Slide

  31. View Slide

  32. View Slide

  33. GET https://simple.com/activity/transactions/3a709ef6-
    c300-43b4-bca0-af72d1ecd4ba/edit

    View Slide

  34. View Slide

  35. View Slide

  36. View Slide

  37. PUT https://simple.com/activity/transactions/3a709ef6-
    c300-43b4-bca0-af72d1ecd4ba
    HTTP 302 Found
    GET https://simple.com/activity

    View Slide

  38. View Slide

  39. View Slide


  40. View Slide

  41. View Slide

  42. View Slide

  43. http://imgs.xkcd.com/comics/regular_expressions.png

    View Slide

  44. View Slide

  45. View Slide

  46. GET https://simple.com/activity

    View Slide

  47. View Slide

  48. View Slide

  49. $('.some-selector').click(function(){
    $.ajax({
    success: function(response){
    var html = $templates.transactionDetails(response);
    $('#some-section-of-my-page).html(html);
    }
    })
    })

    View Slide

  50. View Slide

  51. View Slide

  52. View Slide

  53. $('.some-selector').click(function(){
    $.ajax({
    success: function(response){
    var html = $templates.transactionDetails(response);
    $('#some-section-of-my-page).html(html);
    }
    })
    })

    View Slide

  54. View Slide

  55. View Slide

  56. View Slide

  57. $('.some-button').click(function(){
    $.ajax({
    type: ‘post’,
    success: function(response){
    var html = $templates.transactionDetails(response);
    $('#some-section-of-my-page).html(html);
    }
    })
    })

    View Slide

  58. View Slide

  59. View Slide

  60. decent, not great.

    View Slide

  61. {}

    View Slide

  62. truth-in-dom
    JSON, js,
    html
    JSON, js,
    html

    View Slide

  63. {
    vendor: 'Wholefds Kbs',
    amount: '20.70',
    isCredit: false,
    isPending: true,
    type: 'Groceries',
    location: {
    lat: '41.910006',
    long: '87.657166',
    address: '1070 N North Branch St,\n
    Chicago IL 60642'
    }
    }

    View Slide

  64. success: function(purchase){
    var sidebar = $('#more-info');
    if(purchase.isPending) { $('.is-pending', sidebar).show(); }
    $('.name', sidebar).html(purchase.vendor);
    $('.amount', sidebar).html('-' + purchase.amount);
    $('.category', sidebar).html(purchase.type);
    $('.map', sidebar).gMapPlugin(purchase.location);
    $('.address', sidebar).html(purchase.location.address);
    }

    View Slide

  65. success: function(purchase){
    var sidebar = $('#more-info'), template = Templates.purchase;
    sidebar.html(template(purchase));
    $('.map', sidebar).gMapPlugin(purchase.location);
    }

    View Slide

  66. truth-in-dom
    JSON, js,
    html
    JSON, js,
    html

    View Slide

  67. truth-in-dom
    JSON, js,
    html
    truth-in-dom
    JSON, js,
    html
    truth-in-dom

    View Slide

  68. View Slide

  69. View Slide

  70. View Slide

  71. success: function(purchase){
    var sidebar = $('#more-info'),
    listItem = $(‘#list .purchase-’ + purchase.id),
    purchaseTemplate = Templates.purchase.show,
    purchaseTableRowTemplate = Templates.purchase.row;
    sidebar.html(purchaseTemplate(purchase));
    listItem.html(purchaseTableRowTemplate(purchase));
    $('.map', sidebar).gMapPlugin(purchase.location);
    }

    View Slide

  72. View Slide

  73. View Slide

  74. View Slide


  75. View Slide

  76. View

    View Slide

  77. Collection of Models

    View Slide

  78. View
    View
    View
    View
    View
    View
    View

    View Slide

  79. Properties of the collection

    View Slide



  80. View Slide

  81. View

    View Slide

  82. Aggregation of
    Collection

    View Slide

  83. Different View

    View Slide

  84. Single Model

    View Slide

  85. GET https://simple.com/activity

    View Slide

  86. View Slide

  87. app.Purchase = Backbone.Model.extend();
    app.PurchaseList = Backbone.Collection.extend({
    model: app.Purchase
    });
    app.PurchaseList.url = ‘purchases’
    app.Purchases = new app.PurchaseList;

    View Slide

  88. app.PurchaseListView = Backbone.View.extend({
    el: ‘#purchase-list’,
    initialize: function(){
    this.collection = app.Purchases;
    this.collection.on('change', this.render, this)
    this.render();
    },
    render: function(){
    this.$el.append(new PurchasesFilterView().render());
    _.each(this.collection.models, function (item) {
    this.$el.append(new PurchaseRowView({model: item})
    .render());
    }, this);
    }
    });

    View Slide

  89. app.PurchaseRowView = Backbone.View.extend({
    initialize: function() {
    this.model.on( 'change', this.render, this );
    },
    tagName: 'li',
    template: ...,
    events: {
    'click': 'toggleMoreDetails', 'click .edit': 'toggleEdit'
    },
    toggleMoreDetails: function(){
    this.model.toggleMoreDetails();
    this.$el.toggleClass( 'selected', this.moreDetailsShowing);
    },
    render: function(){
    this.$el.html(this.template(this.model))
    }
    });

    View Slide

  90. app.PurchaseDetailsView = Backbone.View.extend({
    el: ‘#details’,
    initialize: function(){
    this.render();
    },
    template: '...',
    render: function(){
    this.$el.html(this.template(this.model);
    }
    });

    View Slide

  91. app.Purchases.fetch();

    View Slide


  92. View Slide

  93. render: function(){
    this.$el.append(new PurchasesFilterView().render());
    _.each(this.collection.models, function (item) {
    this.$el.append(new PurchaseRowView({model: item})
    .render());
    }, this);
    }

    View Slide

  94. View Slide

  95. View Slide

  96. View Slide

  97. app.PurchaseRowView = Backbone.View.extend({
    ...
    events: { 'click': 'toggleMoreDetails' },
    toggleMoreDetails: function(){
    this.model.toggleMoreDetails();
    this.$el.toggleClass( 'selected', this.moreDetailsShowing);
    }
    });

    View Slide

  98. View Slide

  99. View Slide

  100. View Slide

  101. View Slide

  102. View Slide

  103. View Slide

  104. View Slide

  105. truth-in-data
    truth-in-data
    truth-in-data

    View Slide

  106. model.on(‘change’)/
    collection.on(‘change’)
    -> render
    model.on(‘change’)
    -> render
    model.on(‘change’)
    -> render

    View Slide

  107. {}

    View Slide

  108. View Slide

  109. View Slide











  110. View Slide

  111. app.DashboardView = Backbone.View.extend({
    render: function(){
    this.$el.append(new app.PurchaesView().render().el);
    this.$el.append(new app.PurchaesMapView().render().el);
    this.$el.append(new app.PurcaseDetailView().render().el);
    }
    });

    View Slide

  112. http://lostechies.com/derickbailey/2011/09/15/zombies-run-
    managing-page-transitions-in-backbone-apps/

    View Slide











  113. View Slide

  114. View Slide

  115. View Slide

  116. View Slide

  117. View Slide

  118. possible, but you must be cautious

    View Slide

  119. View Slide

  120. View Slide

  121. View Slide

  122. {{view App.NavigationView}}
    {{view App.SummaryView}}

    View Slide

  123. {{ outlet }}

    View Slide

  124. View Slide

  125. View Slide

  126. View Slide

  127. View Slide

  128. View Slide

  129. View Slide

  130. View Slide

  131. View Slide

  132. Purchases
    Index Viewing Editing

    View Slide

  133. Purchases
    Index Viewing Editing

    View Slide

  134. Purchases
    Index Viewing Editing

    View Slide

  135. Purchases
    Index Viewing Editing

    View Slide

  136. Purchases
    Index Viewing Editing

    View Slide

  137. Purchases
    Index Viewing Editing

    View Slide

  138. Purchases
    Index Viewing Editing

    View Slide

  139. Purchases
    Index Viewing Editing

    View Slide

  140. Purchases
    Index Viewing Editing

    View Slide

  141. Purchases
    Index Viewing Editing

    View Slide

  142. Purchases
    Index Viewing Editing

    View Slide

  143. App = Ember.Application.create();
    App.ApplicationView = Ember.View.extend({
    templateName: 'application'
    });
    App.ApplicationController = Ember.Controller.extend();
    App.Router = Ember.Route.extend({
    root: Ember.Route.extend({})
    // this happens for you: ‘shared instance’
    // applicationController: App.ApplicationController.create()
    })

    View Slide

  144. {{view App.NavigationView}}
    {{view App.SummaryView}}
    {{outlet mainArea}}
    {{outlet detailsArea}}
    application.handlebars

    View Slide

  145. {{view App.NavigationView}}
    {{view App.SummaryView}}
    {{outlet mainArea}}
    {{outlet detailsArea}}
    application.handlebars

    View Slide

  146. {{view App.NavigationView}}
    {{view App.SummaryView}}
    {{outlet mainArea}}
    {{outlet detailsArea}}
    application.handlebars

    View Slide

  147. {{view App.NavigationView}}
    {{view App.SummaryView}}
    {{outlet mainArea}}
    {{outlet detailsArea}}
    application.handlebars

    View Slide

  148. {{view App.NavigationView}}
    {{view App.SummaryView}}
    {{outlet mainArea}}
    {{outlet detailsArea}}
    application.handlebars

    View Slide

  149. Purchases
    Index Viewing Editing

    View Slide

  150. App = Ember.Application.create();
    App.ApplicationView = Ember.View.extend({
    templateName: 'application'
    });
    App.ApplicationController = Ember.Controller.extend();
    App.Router = Ember.Route.extend({
    root: Ember.Route.extend({})
    })

    View Slide

  151. App = Ember.Application.create();
    App.ApplicationView = Ember.View.extend({
    templateName: 'application'
    });
    App.ApplicationController = Ember.Controller.extend();
    App.Router = Ember.Route.extend({
    root: Ember.Route.extend({
    purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    })
    })
    })
    });

    View Slide

  152. {{view App.NavigationView}}
    {{view App.SummaryView}}
    {{outlet mainArea}}
    {{outlet detailsArea}}
    application.handlebars

    View Slide

  153. App = Ember.Application.create();
    App.ApplicationView = Ember.View.extend({
    templateName: 'application'
    });
    App.ApplicationController = Ember.Controller.extend();
    App.Router = Ember.Route.extend({
    root: Ember.Route.extend({
    purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    })
    })
    })
    });

    View Slide

  154. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    })
    })

    View Slide

  155. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    connectOutlets: function(router){
    var controller = router.get('applicationController'),
    purchases = App.Purchase.find(),
    locations = purchases.get('locations');
    controller.connectOutlet('mainArea', 'purchaseList', purchases);
    controller.connectOutlet('detailsArea', 'map', locations);
    }
    })
    })

    View Slide

  156. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    connectOutlets: function(router){
    var controller = router.get('applicationController'),
    purchases = App.Purchase.find(),
    locations = purchases.get('locations');
    controller.connectOutlet('mainArea', 'purchaseList', purchases);
    controller.connectOutlet('detailsArea', 'map', locations);
    }
    })
    })
    where? what? data context?

    View Slide

  157. controller.connectOutlet('mainArea', 'purchaseList', purchases);

    View Slide

  158. controller.connectOutlet('mainArea', 'purchaseList', purchases);
    App.PurchaseListView = Ember.View.extend({
    templateName: 'purchaseList'
    });
    App.PurchaseListController = Ember.ArrayController.extend();

    View Slide

  159. Ember.ArrayController.extend();
    proxy/presenter/controller/thingie

    View Slide

  160. proxy
    content

    View Slide

  161. proxy
    content
    what’s your length?

    View Slide

  162. proxy
    content
    how are you sorted?

    View Slide

  163. controller.connectOutlet('mainArea', 'purchaseList', purchases);
    App.PurchaseListView = Ember.View.extend({
    templateName: 'purchaseList'
    });
    App.PurchaseListController = Ember.ArrayController.extend();

    View Slide

  164. controller.connectOutlet('mainArea', 'purchaseList', purchases);
    App.PurchaseListView = Ember.View.extend({
    templateName: 'purchaseList'
    });
    App.PurchaseListController = Ember.ArrayController.extend();
    {{#each purchase in controller}}

    {{purchase.date}}
    {{purchase.location}}
    {{purchase.amount}}

    {{/each}}

    View Slide

  165. controller.connectOutlet('mainArea', 'purchaseList', purchases);
    App.PurchaseListView = Ember.View.extend({
    templateName: 'purchaseList'
    });
    App.PurchaseListController = Ember.ArrayController.extend();
    {{#each purchase in controller}}

    {{purchase.date}}
    {{purchase.location}}
    {{purchase.amount}}

    {{/each}}

    View Slide

  166. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    connectOutlets: function(router){
    var controller = router.get('applicationController'),
    purchases = App.Purchase.find(),
    locations = purchases.get('locations');
    controller.connectOutlet('mainArea', 'purchaseList', purchases);
    controller.connectOutlet('detailsArea', 'map', locations);
    }
    })
    })

    View Slide

  167. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    connectOutlets: function(router){
    var controller = router.get('applicationController'),
    purchases = App.Purchase.find(),
    locations = purchases.get('locations');
    controller.connectOutlet('mainArea', 'purchaseList', purchases);
    controller.connectOutlet('detailsArea', 'map', locations);
    }
    })
    })
    where? what? data context?

    View Slide

  168. controller.connectOutlet('detailsArea', 'map', locations);

    View Slide

  169. App.MapView = Ember.View.extend({
    templateName: 'googleMap'
    });
    App.MapController = Ember.ArrayController.extend();
    controller.connectOutlet('detailsArea', 'map', locations);

    View Slide

  170. controller.connectOutlet('detailsArea', 'map', locations);
    App.MapView = Ember.View.extend({
    templateName: 'googleMap'
    });
    App.MapController = Ember.ArrayController.extend();

    View Slide

  171. controller.connectOutlet('detailsArea', 'map', locations);
    App.MapView = Ember.View.extend({
    templateName: 'googleMap'
    });
    App.MapController = Ember.ArrayController.extend();

    View Slide

  172. controller.connectOutlet('detailsArea', 'map', locations);
    App.MapView = Ember.View.extend({
    templateName: 'googleMap'
    });
    App.MapController = Ember.ArrayController.extend();

    View Slide

  173. Purchases
    Index Viewing Editing

    View Slide

  174. Purchases
    Index Viewing Editing

    View Slide

  175. {{#each purchase in controller}}

    {{purchase.date}}
    {{purchase.location}}
    {{purchase.amount}}

    {{/each}}

    View Slide

  176. {{#each purchase in controller}}

    {{purchase.date}}
    {{purchase.location}}
    {{purchase.amount}}

    {{/each}}

    View Slide

  177. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    connectOutlets: function(router){
    ...
    }
    })
    })

    View Slide

  178. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    })
    })

    View Slide

  179. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    viewing: Ember.Route.extend({
    })
    })

    View Slide

  180. Purchases
    Index Viewing Editing

    View Slide

  181. Purchases
    Index Viewing Editing

    View Slide

  182. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    viewing: Ember.Route.extend({
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'purchaseDetails', context);
    }
    })
    })
    where? what? data context?

    View Slide

  183. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    viewing: Ember.Route.extend({
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'purchaseDetails', context);
    }
    })
    })

    View Slide

  184. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    viewing: Ember.Route.extend({
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'purchaseDetails', context);
    }
    })
    })
    {{#each purchase in controller}}

    {{purchase.date}}
    {{purchase.location}}
    {{purchase.amount}}

    {{/each}}

    View Slide

  185. controller.connectOutlet('detailsArea', 'purchaseDetails', context);

    View Slide

  186. controller.connectOutlet('detailsArea', 'purchaseDetails', context);
    App.PurchaseDetailsView = Ember.View.extend({
    templateName: 'details'
    });
    App.PurchaseDetailsController = Ember.ObjectController.extend();

    View Slide

  187. controller.connectOutlet('detailsArea', 'purchaseDetails', context);
    App.PurchaseDetailsView = Ember.View.extend({
    templateName: 'details'
    });
    App.PurchaseDetailsController = Ember.ObjectController.extend();

    View Slide



  188. Edit

    Support

    {{#if pending}}

    This transaction is pending...

    {{/if}}
    {{name}}
    {{amount}}
    {{label}}
    App.PurchaseDetailsView = Ember.View.extend({
    templateName: 'details'
    });
    App.PurchaseDetailsController = Ember.ObjectController.extend();

    View Slide

  189. App.PurchaseDetailsView = Ember.View.extend({
    templateName: 'details'
    });
    App.PurchaseDetailsController = Ember.ObjectController.extend();


    Edit

    Support

    {{#if pending}}

    This transaction is pending...

    {{/if}}
    {{name}}
    {{amount}}
    {{label}}

    View Slide

  190. Ember.ObjectController.extend();

    View Slide

  191. proxy
    content
    Ember.ObjectController.extend();

    View Slide

  192. proxy
    content
    are you pending?

    View Slide

  193. App.PurchaseDetailsView = Ember.View.extend({
    templateName: 'details'
    });
    App.PurchaseDetailsController = Ember.ObjectController.extend();


    Edit

    Support

    {{#if pending}}

    This transaction is pending...

    {{/if}}
    {{name}}
    {{amount}}
    {{label}}

    View Slide

  194. View Slide

  195. Purchases
    Index Viewing Editing

    View Slide

  196. Purchases
    Index Viewing Editing

    View Slide



  197. Edit

    Support

    {{#if pending}}

    This transaction is pending...

    {{/if}}
    {{name}}
    {{amount}}
    {{label}}

    View Slide

  198. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    viewing: Ember.Route.extend({
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'purchaseDetails', context);
    }
    })
    })

    View Slide

  199. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    viewing: Ember.Route.extend({
    editPurchase: Ember.Route.transitionTo(‘editing’),
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'purchaseDetails', context);
    }
    })
    })

    View Slide

  200. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    editing: Ember.Route.extend({
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'editPurchaseDetails', context);
    }
    }),
    viewing: Ember.Route.extend({
    editPurchase: Ember.Route.transitionTo(‘editing’),
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'purchaseDetails', context);
    }
    })
    })

    View Slide

  201. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    editing: Ember.Route.extend({
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'editPurchaseDetails', context);
    }
    }),
    viewing: Ember.Route.extend({
    editPurchase: Ember.Route.transitionTo(‘editing’),
    connectOutlets: function(router, context){
    var controller = router.get('applicationController');
    controller.
    connectOutlet('detailsArea', 'purchaseDetails', context);
    }
    })
    })
    where? what? data context?

    View Slide

  202. connectOutlet('detailsArea', 'editPurchaseDetails', context);

    View Slide

  203. connectOutlet('detailsArea', 'editPurchaseDetails', context);
    App.EditPurchaseDetailsView = Ember.View.extend({
    templateName: 'edit-details'
    });
    App.EditPurchaseDetailsController = Ember.ObjectController.extend();

    View Slide

  204. connectOutlet('detailsArea', 'editPurchaseDetails', context);
    App.EditPurchaseDetailsView = Ember.View.extend({
    templateName: 'edit-details'
    });
    App.EditPurchaseDetailsController = Ember.ObjectController.extend();
    Save
    Cancel
    {{view Ember.TextField
    valueBinding="name"}}

    View Slide

  205. connectOutlet('detailsArea', 'editPurchaseDetails', context);
    App.EditPurchaseDetailsView = Ember.View.extend({
    templateName: 'edit-details'
    });
    App.EditPurchaseDetailsController = Ember.ObjectController.extend();
    Save
    Cancel
    {{view Ember.TextField
    valueBinding="name"}}

    View Slide

  206. Ember.ObjectController.extend();

    View Slide

  207. proxy
    content
    Ember.ObjectController.extend();

    View Slide

  208. proxy
    content
    what’s your name?

    View Slide

  209. View Slide

  210. View Slide

  211. Purchases
    Index Viewing Editing

    View Slide

  212. Purchases
    Index Viewing Editing

    View Slide

  213. purchases: Ember.Route.extend({
    index: Ember.Route.extend({
    showDetails: Ember.Route.transitionTo(‘viewing’),
    connectOutlets: function(router){
    ...
    }
    }),
    editing: Ember.Route.extend({
    saveChanges: Ember.Route.transitionTo(‘index’),
    connectOutlets: function(router, context){
    ...
    }
    }),
    viewing: Ember.Route.extend({
    editPurchase: Ember.Route.transitionTo(‘editing’),
    connectOutlets: function(router, context){
    ...
    })
    })

    View Slide

  214. Purchases
    Index Viewing Editing

    View Slide

  215. Demeter’d

    View Slide

  216. https://gist.github.com/3981133

    View Slide

  217. View Slide

  218. > 7 views

    View Slide

  219. View Slide

  220. View Slide

  221. View Slide

  222. View Slide

  223. which pattern, when?

    View Slide

  224. • app is just a series of documents
    • or you’re just coding single page
    • not a client app
    • manipulation mostly presentational
    • few data communications
    • user interaction brief, simple, infrequent

    View Slide

  225. • app is series of documents
    • with “islands of richness”
    • occassional data communications
    • multiple parts of a page need to reflect data
    • shallow view hierarchy (1-2 levels)
    • small number of views (~7)
    • user interaction brief and/or infrequent

    View Slide

  226. • frequent data communications
    • many parts of a page need to reflect data
    • deep view hierarchy (2-3+)
    • large number of views
    • user will remain for large amounts of time
    • and/or frequently return
    • server is just an api
    • you’d *almost* write a desktop/iOS app

    View Slide

  227. Mobile
    Cocoa Touch
    Android SDK
    Desktop
    Cocoa
    .NET
    Web ?

    View Slide

  228. Mobile
    Cocoa Touch
    Android SDK
    Desktop
    Cocoa
    .NET
    Web

    View Slide

  229. User Interface HTML+CSS
    Data Persistence
    Application
    Architecture

    View Slide

  230. fin

    View Slide