SlideShare uma empresa Scribd logo
Lessons from a rewrite
                 Rebecca Murphey • Gotham JS • New York, New York




Saturday, July 9, 2011
ere’s a subtle reason that programmers always
          want to throw away the code and start over. e
          reason is that they think the old code is a mess. ...
          e reason that they think the old code is a mess
          is because of a cardinal, fundamental law of
          programming: It’s harder to read code than to
          write it.
                                                   Joel Spolsky




Saturday, July 9, 2011
A content management system for the rapid
          creation of content-rich mobile applications.
          A PhoneGap & Dojo system that consumes the
          output of the CMS to generate the application.



Saturday, July 9, 2011
Saturday, July 9, 2011
Where a new system concept or new technology
          is used, one has to build a system to throw away,
          for even the best planning is not so omniscient as
          to get it right the rst time. Hence plan to
          throw one away; you will, anyhow.
                                                Fred Brooks




Saturday, July 9, 2011
If data is required for a
                                                                                                                  route, such as node data
                                                                                                                  or the user's favorites, the
                                                                                                                  route requests the data
                                                                                                                  prior to creating the page.




                                                                                                                             Data                                                                                                                                                    Page Controller
                                                                                                                                                                                                                                                      Component

                                                                                                                                                                                                                                                                                       Component


                                                                                                                                                                                                         Page Controller                              Component                        Component



                                                                                                                                                                                                                                                                                       Component
                                                                                                                                                                                                                                                      Component

           When the app is booted
           from a "cold" state (that   URL Change                               Router                                                                            Page Factory
           is, it's not fast-app-                                                                                                                                                           Page controllers are responsible for           Components are responsible for            Once components are placed on the
           switched), it goes                                                                                                                                                               receiving data from the Page Factory. Once     receiving and rendering data and          page, the Page Controller brokers
           through a bootstrapping                                     The Router detects a                                                                 The Route asks the page         the page controller receives that data, it     reacting to user interaction.             communication between components.
                                                                                                                            Route                                                           determines which components to display in
           process. This process                                       change in the URL, looks                                                             factory to generate a page
                                                                       for a matching route in                                                              controller. If the page         its postMixInProperties method and sets up     Components whose content can change       Components announce events either by
           ensures the application                                                                                                                                                          "placements," which define the components       during a single page view should expose   publishing a topic (for events that may
                                                                       toura.app.Routes, and                                                                controller is for a node, the
           is working with the                                                                                                                                                              that will be placed on the page and the data   an API using setters (i.e.                have app-wide significance) or by calling
                                                                       parses any additional                                                                Page Factory figures out
           most recent data, and                                       parameters out of the URL                                                            which template (Audios,         that needs to be passed to them. The           _setContentAttr) that allows Page         a method (such as onClick). Page
           also sets up various                                        (such as the node ID,                                                                Images, etc.) the node          actual instantiation and placement of          Controllers to update their content.      Controllers can subscribe to these
           application-wide                 Device Storage             asset type, etc.).                                                                   uses. The page factory          components is handled in the postCreate                                                  topics or connect to these method calls
                                                                                                                                                            creates an instance of the      method of toura.pageControllers._Page,         Alternately, a component can define an     (much like connecting to events). This
           functionality, including
                                                                                                                                                            page controller and hands       which is inherited by all Page Controllers.    attributeMap object that specifies how     happens in the Page Controller's
           the Router, UI, Page                                                                                                                                                                                                            the component should react when a         postCreate method.
                                                                                                                                                            the created instance back
           Factory, Data Store,                                                                                                                             to the Route.                                                                  property is set.
           and several others.

           Once these pieces are
           in place, the app                    Remote
           triggers a URL change
           to the home node, and
           the process outlined
           here begins.



                                       Every time the user goes                                                               UI
                                       to a new page, we check
                                       the age of the local data; if
                                       it is more than 8 hours old,
                                       we see whether we need
                                       to do an over-the-air
                                       update.




                                                                                                                          Browser

                                                                               Page Container

                                                                                  Old Page Controller                               New Page Controller

                                                                                     Component                                         Component


                                                                                     Component                                         Component



                                                                                     Component                                         Component




                                                                       The Route asks toura.app.UI to place the Page Controller in the UI; in turn, toura.app.UI sets the content
                                                                       attribute of the Page Container. If there is already a page on screen, the Page Container handles the animation
                                                                       between the pages, and calls the destroy method of the old page, which results in the proper teardown of the old
                                                                       page and its components.




          Understand
          what you’re rewriting
Saturday, July 9, 2011
Have we
                                      no
                         loaded the           Populate DB
                           bundled         with bundled data
                            data?



                                yes




                                      no
                     Is the remote
                                             dfd.resolve()
                      reachable?




                    Get the remote
                       version



Saturday, July 9, 2011
{
                             "name": "Audio Player",
                             "audios": [{
                                 "audio": {
                                     "_reference": "audio-23"
                                  },
                                 "caption": {
                                     "_reference": "text-asset-64"
                                  }
                             }],
                             "parent": {
                                 "_reference": "node-365"
                             },
                             "page_controller": "Audios1",
                             "id": "node-369",
                             "sharing_text": null,
                             "sharing_url": null,
                             "images": [{
                                 "caption": {
                                     "_reference": "text-asset-60"
                                  },
                                 "image": {
                                     "_reference": "image-174"
                                  }
                             }, {
                                 "caption": {
                                     "_reference": "text-asset-61"
                                  },
                                 "image": {
                                     "_reference": "image-182"
                                  }
                             }, {
Saturday, July 9, 2011           "image": {
Identify pain points
Saturday, July 9, 2011
Saturday, July 9, 2011
/* {{^android}} */
          var mediaPath = "www/media/" + toura.pages.currentId +
          "/";
          /* {{/android}} */
          /* {{#android}} */
          var mediaPath = [Toura.getTouraPath(),
          toura.pages.currentId].join("/");
          /* {{/android}} */
          var imagesList = [], dimensionsList = [], namesList = [],
          thumbsList = [];
          var pos = -1, count = 0;
          /* {{#android}} */
          var pos = 0, count = 0;
          /* {{/android}} */




Saturday, July 9, 2011
toura.app.Has = function() {
                    var device = toura.app.Config.get('device');

                         return {
                           cssBackgroundContain : function() {
                             return !(
                                 device.os === 'android' &&
                                 device.version === '2-1'
                              );
                           },

                           html5Player : function() {
                             return device.os !== 'android';
                           },

                           iScrollZoom : function() {
                              return device.os !== 'android';
                            }
                         };
                  };



Saturday, July 9, 2011
//>>excludeStart('production', kwArgs.production);
          if (toura.features.debugToolbar) { toura.app._Debug(); }
          //>>excludeEnd('production');




Saturday, July 9, 2011
Develop a
                         communication
                         manifesto




Saturday, July 9, 2011
Writing to be read means writing code ... with
          the idea that someone else will read it. is
          fact alone will make you edit and think of better
          ways to solve the problem you have at hand.
                                              Stoyan Stefanov


Saturday, July 9, 2011
myComponent.set(key, val)
          to change state

          myComponent.on<Evt>(data)
          to announce state changes

          myComponent.connect(evt, handler)
          to listen for events & methods

          myComponent.subscribe(topic)
          to react to published topics

          dojo.publish(topic, data)
          to announce occurrences of app-wide interest


Saturday, July 9, 2011
Saturday, July 9, 2011
Search Input


                                                            toura.app.Data.search(term)
              searchInputInstance.onSearch(term)




                                             Search Page
                                             Controller          Application Data



     searchResults.set('results', resultSet)
                                                            return resultSet



                                           Search Results
                                              Display




Saturday, July 9, 2011
dojo.declare(
            'toura.pageControllers.search.Search',
            [ toura.pageControllers._Page ], {

               // ...

               postCreate : function() {
                 // ...
                 this.connect(this.searchInput, 'onSearch', '_handleSearch');
               },

               _handleSearch : function(term) {
                 if (term === this.lastSearchTerm) { return; }
                 this.searchResults.set('results', toura.app.Data.search(term));
               },

            // ...
          });




Saturday, July 9, 2011
Sanify
                         asynchronicity

Saturday, July 9, 2011
old & busted
          images = toura.sqlite.getMedias(id, "image");

          var onGetComplete = setInterval(function() {
            if (images.incomplete)
              return;

            clearInterval(onGetComplete);
            showImagesHelper(images.objs, choice)
          }, 10);




          new hotness
          toura.app.Data.get(id, 'image').then(showImages, showImagesFail);




Saturday, July 9, 2011
var myAsyncThing = function() {
              var dfd = new dojo.Deferred();
              setTimeout(function() {
                dfd.resolve('hello');
              }, 1000);
              return dfd.promise;
           };

           myAsyncThing().then(function(result){
             console.log(result);
           });



Saturday, July 9, 2011
dojo.when(fn(), win, fail)
          react to maybe-asynchronous things,
          including promises




Saturday, July 9, 2011
Naming things is hard
Saturday, July 9, 2011
ere are only two hard things in
            Computer Science: cache invalidation
            and naming things.
                                            Phil Karlton




Saturday, July 9, 2011
Saturday, July 9, 2011
Saturday, July 9, 2011
Saturday, July 9, 2011
Saturday, July 9, 2011
yellow
                          red
                          blue
Saturday, July 9, 2011
Never write large apps




Saturday, July 9, 2011
e secret to building large apps is
            never build large apps. Break up your
            applications into small pieces. en,
            assemble those testable, bite-sized pieces
            into your big application.
                                             Justin Meyer




Saturday, July 9, 2011
function nodeRoute(route, nodeId, pageState) {
                   pageState = pageState || {};

                         var nodeModel = toura.app.Data.getModel(nodeId),
                             page = toura.app.UI.getCurrentPage();

                         if (!page || !page.node || nodeId !== page.node.id) {
                           page = toura.app.PageFactory.createPage('node', nodeModel);

                           page.init(pageState);
                           toura.app.UI.showPage(page, nodeModel);
                         } else {
                           page.init(pageState);
                         }

                         // record node pageview if it is node-only
                         if (nodeId && !pageState.assetType) {
                           dojo.publish('/node/view', [ route.hash ]);
                         }

                         return true;
                 }



Saturday, July 9, 2011
Saturday, July 9, 2011
Saturday, July 9, 2011
this.connect(this.videoList, 'onSelect', function(assetId) {
            var video = this._videoById(assetId);
            this.videoCaption.set('content', video.caption || '');
            this.videoPlayer.play(assetId);
          });




Saturday, July 9, 2011
videoPlayer.set('mediaId', mediaId);




                         _setMediaIdAttr : function(mediaId) {
                           var media = this.media = this.mediasCache[mediaId];

                              if (this.useHtml5Player && !this.player) {
                                this._queuedMedia = media;
                                return;
                              }

                              this._queuedMedia = null;

                              if (this.player) {
                                this.player.src = media.url;
                              }
                         },



Saturday, July 9, 2011
It takes con dence to throw work away ...
          When people rst start drawing, they’re often
          reluctant to redo parts that aren’t right ...
          they convince themselves that the drawing
          is not that bad, really — in fact, maybe they
          meant it to look that way.
                                                Paul Graham




Saturday, July 9, 2011
Saturday, July 9, 2011
http://pinboard.in/u:rmurphey/t:lessons-from-a-rewrite/

                                  http://spkr8.com/t/7930




                         rebeccamurphey.com • blog.rebeccamurphey.com • @rmurphey




Saturday, July 9, 2011

Mais conteúdo relacionado

Semelhante a Lessons from-a-rewrite-gotham

ScrapeXpress-Standalone-solution
ScrapeXpress-Standalone-solutionScrapeXpress-Standalone-solution
ScrapeXpress-Standalone-solution
Andy Yang
 
Spatial Data Integrator - Software Presentation and Use Cases
Spatial Data Integrator - Software Presentation and Use CasesSpatial Data Integrator - Software Presentation and Use Cases
Spatial Data Integrator - Software Presentation and Use Cases
mathieuraj
 

Semelhante a Lessons from-a-rewrite-gotham (20)

Lessons from a Rewrite
Lessons from a RewriteLessons from a Rewrite
Lessons from a Rewrite
 
NASA Facilities GIS
NASA Facilities GISNASA Facilities GIS
NASA Facilities GIS
 
Data Sharing Between Child and Parent Components in AngularJS
Data Sharing Between Child and Parent Components in AngularJSData Sharing Between Child and Parent Components in AngularJS
Data Sharing Between Child and Parent Components in AngularJS
 
CSSDP Presentation April 09
CSSDP Presentation April 09CSSDP Presentation April 09
CSSDP Presentation April 09
 
CSSDP Presentation April 09
CSSDP Presentation April 09CSSDP Presentation April 09
CSSDP Presentation April 09
 
Web Server-based Distributed Machine Socialization System
Web Server-based Distributed Machine Socialization System Web Server-based Distributed Machine Socialization System
Web Server-based Distributed Machine Socialization System
 
Asp.net control
Asp.net controlAsp.net control
Asp.net control
 
Parallelminds.asp.net with sp
Parallelminds.asp.net with spParallelminds.asp.net with sp
Parallelminds.asp.net with sp
 
Getting started with react &amp; redux
Getting started with react &amp; reduxGetting started with react &amp; redux
Getting started with react &amp; redux
 
ScrapeXpress-Standalone-solution
ScrapeXpress-Standalone-solutionScrapeXpress-Standalone-solution
ScrapeXpress-Standalone-solution
 
React - The JavaScript Library for User Interfaces
React - The JavaScript Library for User InterfacesReact - The JavaScript Library for User Interfaces
React - The JavaScript Library for User Interfaces
 
15 asp.net session22
15 asp.net session2215 asp.net session22
15 asp.net session22
 
Component based User Interface Rendering with State Caching Between Routes
Component based User Interface Rendering with State Caching Between RoutesComponent based User Interface Rendering with State Caching Between Routes
Component based User Interface Rendering with State Caching Between Routes
 
Synopsis
SynopsisSynopsis
Synopsis
 
Spatial Data Integrator - Software Presentation and Use Cases
Spatial Data Integrator - Software Presentation and Use CasesSpatial Data Integrator - Software Presentation and Use Cases
Spatial Data Integrator - Software Presentation and Use Cases
 
Reactjs
Reactjs Reactjs
Reactjs
 
Full-Stack Observability for IoT Event Stream Data Processing at Penske
Full-Stack Observability for IoT Event Stream Data Processing at PenskeFull-Stack Observability for IoT Event Stream Data Processing at Penske
Full-Stack Observability for IoT Event Stream Data Processing at Penske
 
Automatic Web Service Composition For SaaS Business Intelligence
Automatic Web Service Composition For SaaS Business IntelligenceAutomatic Web Service Composition For SaaS Business Intelligence
Automatic Web Service Composition For SaaS Business Intelligence
 
Next.js - ReactPlayIO.pptx
Next.js - ReactPlayIO.pptxNext.js - ReactPlayIO.pptx
Next.js - ReactPlayIO.pptx
 
DashMash: a Mashup Environment for End User Development
DashMash: a Mashup Environment for End User DevelopmentDashMash: a Mashup Environment for End User Development
DashMash: a Mashup Environment for End User Development
 

Mais de Rebecca Murphey

Getting Started with Mulberry
Getting Started with MulberryGetting Started with Mulberry
Getting Started with Mulberry
Rebecca Murphey
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
Rebecca Murphey
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UI
Rebecca Murphey
 

Mais de Rebecca Murphey (9)

Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
 
BVJS
BVJSBVJS
BVJS
 
Getting Started with Mulberry
Getting Started with MulberryGetting Started with Mulberry
Getting Started with Mulberry
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code Organization
 
The jQuery Divide
The jQuery DivideThe jQuery Divide
The jQuery Divide
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UI
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
 
Jquery Fundamentals
Jquery FundamentalsJquery Fundamentals
Jquery Fundamentals
 

Último

Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Peter Udo Diehl
 

Último (20)

Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
 
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
 
Enterprise Security Monitoring, And Log Management.
Enterprise Security Monitoring, And Log Management.Enterprise Security Monitoring, And Log Management.
Enterprise Security Monitoring, And Log Management.
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024
 
10 Differences between Sales Cloud and CPQ, Blanka Doktorová
10 Differences between Sales Cloud and CPQ, Blanka Doktorová10 Differences between Sales Cloud and CPQ, Blanka Doktorová
10 Differences between Sales Cloud and CPQ, Blanka Doktorová
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
The architecture of Generative AI for enterprises.pdf
The architecture of Generative AI for enterprises.pdfThe architecture of Generative AI for enterprises.pdf
The architecture of Generative AI for enterprises.pdf
 
Motion for AI: Creating Empathy in Technology
Motion for AI: Creating Empathy in TechnologyMotion for AI: Creating Empathy in Technology
Motion for AI: Creating Empathy in Technology
 
ECS 2024 Teams Premium - Pretty Secure
ECS 2024   Teams Premium - Pretty SecureECS 2024   Teams Premium - Pretty Secure
ECS 2024 Teams Premium - Pretty Secure
 
AI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekAI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří Karpíšek
 
IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
Connecting the Dots in Product Design at KAYAK
Connecting the Dots in Product Design at KAYAKConnecting the Dots in Product Design at KAYAK
Connecting the Dots in Product Design at KAYAK
 
Optimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityOptimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through Observability
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
Speed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in MinutesSpeed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in Minutes
 

Lessons from-a-rewrite-gotham

  • 1. Lessons from a rewrite Rebecca Murphey • Gotham JS • New York, New York Saturday, July 9, 2011
  • 2. ere’s a subtle reason that programmers always want to throw away the code and start over. e reason is that they think the old code is a mess. ... e reason that they think the old code is a mess is because of a cardinal, fundamental law of programming: It’s harder to read code than to write it. Joel Spolsky Saturday, July 9, 2011
  • 3. A content management system for the rapid creation of content-rich mobile applications. A PhoneGap & Dojo system that consumes the output of the CMS to generate the application. Saturday, July 9, 2011
  • 5. Where a new system concept or new technology is used, one has to build a system to throw away, for even the best planning is not so omniscient as to get it right the rst time. Hence plan to throw one away; you will, anyhow. Fred Brooks Saturday, July 9, 2011
  • 6. If data is required for a route, such as node data or the user's favorites, the route requests the data prior to creating the page. Data Page Controller Component Component Page Controller Component Component Component Component When the app is booted from a "cold" state (that URL Change Router Page Factory is, it's not fast-app- Page controllers are responsible for Components are responsible for Once components are placed on the switched), it goes receiving data from the Page Factory. Once receiving and rendering data and page, the Page Controller brokers through a bootstrapping The Router detects a The Route asks the page the page controller receives that data, it reacting to user interaction. communication between components. Route determines which components to display in process. This process change in the URL, looks factory to generate a page for a matching route in controller. If the page its postMixInProperties method and sets up Components whose content can change Components announce events either by ensures the application "placements," which define the components during a single page view should expose publishing a topic (for events that may toura.app.Routes, and controller is for a node, the is working with the that will be placed on the page and the data an API using setters (i.e. have app-wide significance) or by calling parses any additional Page Factory figures out most recent data, and parameters out of the URL which template (Audios, that needs to be passed to them. The _setContentAttr) that allows Page a method (such as onClick). Page also sets up various (such as the node ID, Images, etc.) the node actual instantiation and placement of Controllers to update their content. Controllers can subscribe to these application-wide Device Storage asset type, etc.). uses. The page factory components is handled in the postCreate topics or connect to these method calls creates an instance of the method of toura.pageControllers._Page, Alternately, a component can define an (much like connecting to events). This functionality, including page controller and hands which is inherited by all Page Controllers. attributeMap object that specifies how happens in the Page Controller's the Router, UI, Page the component should react when a postCreate method. the created instance back Factory, Data Store, to the Route. property is set. and several others. Once these pieces are in place, the app Remote triggers a URL change to the home node, and the process outlined here begins. Every time the user goes UI to a new page, we check the age of the local data; if it is more than 8 hours old, we see whether we need to do an over-the-air update. Browser Page Container Old Page Controller New Page Controller Component Component Component Component Component Component The Route asks toura.app.UI to place the Page Controller in the UI; in turn, toura.app.UI sets the content attribute of the Page Container. If there is already a page on screen, the Page Container handles the animation between the pages, and calls the destroy method of the old page, which results in the proper teardown of the old page and its components. Understand what you’re rewriting Saturday, July 9, 2011
  • 7. Have we no loaded the Populate DB bundled with bundled data data? yes no Is the remote dfd.resolve() reachable? Get the remote version Saturday, July 9, 2011
  • 8. { "name": "Audio Player", "audios": [{ "audio": { "_reference": "audio-23" }, "caption": { "_reference": "text-asset-64" } }], "parent": { "_reference": "node-365" }, "page_controller": "Audios1", "id": "node-369", "sharing_text": null, "sharing_url": null, "images": [{ "caption": { "_reference": "text-asset-60" }, "image": { "_reference": "image-174" } }, { "caption": { "_reference": "text-asset-61" }, "image": { "_reference": "image-182" } }, { Saturday, July 9, 2011 "image": {
  • 11. /* {{^android}} */ var mediaPath = "www/media/" + toura.pages.currentId + "/"; /* {{/android}} */ /* {{#android}} */ var mediaPath = [Toura.getTouraPath(), toura.pages.currentId].join("/"); /* {{/android}} */ var imagesList = [], dimensionsList = [], namesList = [], thumbsList = []; var pos = -1, count = 0; /* {{#android}} */ var pos = 0, count = 0; /* {{/android}} */ Saturday, July 9, 2011
  • 12. toura.app.Has = function() { var device = toura.app.Config.get('device'); return { cssBackgroundContain : function() { return !( device.os === 'android' && device.version === '2-1' ); }, html5Player : function() { return device.os !== 'android'; }, iScrollZoom : function() { return device.os !== 'android'; } }; }; Saturday, July 9, 2011
  • 13. //>>excludeStart('production', kwArgs.production); if (toura.features.debugToolbar) { toura.app._Debug(); } //>>excludeEnd('production'); Saturday, July 9, 2011
  • 14. Develop a communication manifesto Saturday, July 9, 2011
  • 15. Writing to be read means writing code ... with the idea that someone else will read it. is fact alone will make you edit and think of better ways to solve the problem you have at hand. Stoyan Stefanov Saturday, July 9, 2011
  • 16. myComponent.set(key, val) to change state myComponent.on<Evt>(data) to announce state changes myComponent.connect(evt, handler) to listen for events & methods myComponent.subscribe(topic) to react to published topics dojo.publish(topic, data) to announce occurrences of app-wide interest Saturday, July 9, 2011
  • 18. Search Input toura.app.Data.search(term) searchInputInstance.onSearch(term) Search Page Controller Application Data searchResults.set('results', resultSet) return resultSet Search Results Display Saturday, July 9, 2011
  • 19. dojo.declare( 'toura.pageControllers.search.Search', [ toura.pageControllers._Page ], { // ... postCreate : function() { // ... this.connect(this.searchInput, 'onSearch', '_handleSearch'); }, _handleSearch : function(term) { if (term === this.lastSearchTerm) { return; } this.searchResults.set('results', toura.app.Data.search(term)); }, // ... }); Saturday, July 9, 2011
  • 20. Sanify asynchronicity Saturday, July 9, 2011
  • 21. old & busted images = toura.sqlite.getMedias(id, "image"); var onGetComplete = setInterval(function() { if (images.incomplete) return; clearInterval(onGetComplete); showImagesHelper(images.objs, choice) }, 10); new hotness toura.app.Data.get(id, 'image').then(showImages, showImagesFail); Saturday, July 9, 2011
  • 22. var myAsyncThing = function() { var dfd = new dojo.Deferred(); setTimeout(function() { dfd.resolve('hello'); }, 1000); return dfd.promise; }; myAsyncThing().then(function(result){ console.log(result); }); Saturday, July 9, 2011
  • 23. dojo.when(fn(), win, fail) react to maybe-asynchronous things, including promises Saturday, July 9, 2011
  • 24. Naming things is hard Saturday, July 9, 2011
  • 25. ere are only two hard things in Computer Science: cache invalidation and naming things. Phil Karlton Saturday, July 9, 2011
  • 30. yellow red blue Saturday, July 9, 2011
  • 31. Never write large apps Saturday, July 9, 2011
  • 32. e secret to building large apps is never build large apps. Break up your applications into small pieces. en, assemble those testable, bite-sized pieces into your big application. Justin Meyer Saturday, July 9, 2011
  • 33. function nodeRoute(route, nodeId, pageState) { pageState = pageState || {}; var nodeModel = toura.app.Data.getModel(nodeId), page = toura.app.UI.getCurrentPage(); if (!page || !page.node || nodeId !== page.node.id) { page = toura.app.PageFactory.createPage('node', nodeModel); page.init(pageState); toura.app.UI.showPage(page, nodeModel); } else { page.init(pageState); } // record node pageview if it is node-only if (nodeId && !pageState.assetType) { dojo.publish('/node/view', [ route.hash ]); } return true; } Saturday, July 9, 2011
  • 36. this.connect(this.videoList, 'onSelect', function(assetId) { var video = this._videoById(assetId); this.videoCaption.set('content', video.caption || ''); this.videoPlayer.play(assetId); }); Saturday, July 9, 2011
  • 37. videoPlayer.set('mediaId', mediaId); _setMediaIdAttr : function(mediaId) { var media = this.media = this.mediasCache[mediaId]; if (this.useHtml5Player && !this.player) { this._queuedMedia = media; return; } this._queuedMedia = null; if (this.player) { this.player.src = media.url; } }, Saturday, July 9, 2011
  • 38. It takes con dence to throw work away ... When people rst start drawing, they’re often reluctant to redo parts that aren’t right ... they convince themselves that the drawing is not that bad, really — in fact, maybe they meant it to look that way. Paul Graham Saturday, July 9, 2011
  • 40. http://pinboard.in/u:rmurphey/t:lessons-from-a-rewrite/ http://spkr8.com/t/7930 rebeccamurphey.com • blog.rebeccamurphey.com • @rmurphey Saturday, July 9, 2011