{"id":577,"date":"2019-02-15T10:43:05","date_gmt":"2019-02-15T08:43:05","guid":{"rendered":"http:\/\/www.jongore.com\/blog\/?p=577"},"modified":"2019-02-15T10:43:05","modified_gmt":"2019-02-15T08:43:05","slug":"building-apps-in-africa-principle-systems","status":"publish","type":"post","link":"https:\/\/www.jongore.com\/blog\/uncategorized\/building-apps-in-africa-principle-systems\/","title":{"rendered":"Building Apps In Africa: Principle Systems"},"content":{"rendered":"\n<p>This story is actually one of mine.  Before I moved to JUMO I was Head of Product for a company I <g class=\"gr_ gr_55 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del\" id=\"55\" data-gr-id=\"55\">cofounded<\/g> in Tanzania.  We ended up building a great prototype which we <g class=\"gr_ gr_145 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del\" id=\"145\" data-gr-id=\"145\">dog fooded<\/g> around the streets of Dar Es Salaam.  The data we collected ended up being more valuable than the app. That was a lesson in sales on the B2B side. We would take our prospective clients out to dinner in Dar, while SAP would fly them to Germany and treat them to a weekend.  Wasn&#8217;t tough to see we couldn&#8217;t compete.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p> One problem working in Tanzania is the lack of prevalent internet access. &nbsp;It\u2019s getting better, yes, but there are still huge areas uncovered by the telecoms. &nbsp;Network connections are unreliable, and connectivity is not guaranteed even in the major cities. &nbsp;So when we decided to build a sales and distribution company, which tracks trucks using 3G connections in tablets, we needed to make sure these things would work no matter where they were. &nbsp; How do you build a product whose value add is tracking and monitoring the sales delivery channel, when you can\u2019t track or monitor due to lack of internet? &nbsp;Well, we thought we could do it, and what follows is a quick summary of how we did it.&nbsp;<\/p><p><br><strong>Database: <\/strong>POSTGRES SQLData layer: Custom built data access layer<\/p><p><strong>Proxy Server:<\/strong> &nbsp;Proxy for caching data<br>In order to allow for an \u201coffline capable\u201d system, we moved from a client-server scenario to a more modern and lightweight API\/browser-based approach. &nbsp;We needed to implement the javascript code in a more structured manner to facilitate the presentation and caching. &nbsp;Our \u201cdashboards\u201d are where users complete all their interactions on the system. &nbsp;To make this work, we used <g class=\"gr_ gr_27 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep\" id=\"27\" data-gr-id=\"27\">backbone\u2019s<\/g> hashtag routing <g class=\"gr_ gr_28 gr-alert gr_gramm gr_inline_cards gr_run_anim Punctuation only-del replaceWithoutSep\" id=\"28\" data-gr-id=\"28\">implementation,<\/g> and then presented the data from the server using Handlebars.js combined with JSON data from our custom designed data access server. &nbsp;We also cache the data on the local device, using a proxy that is also implemented in JavaScript. &nbsp;The same proxy sends data back to the server and includes the ability to cache requests when the device is offline.&nbsp;<br>The caching works the following ways:<br><u>Datasource Component.<\/u>&nbsp;This is responsible for sending requests to the server. &nbsp;It speaks REST basically, so a request is always something like \u2018GET\u2019 \/ customer to fetch all customers. &nbsp;This is far faster than what we had implemented previously. &nbsp;It works the same the other way as well, where POST \/customer {name: \u2018etc\u2019\u2026} handles creating customers.&nbsp;<\/p><\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><u>Proxy Component:<\/u>  The application does not interact directly with the Datasource component, rather talking directly to the proxy, which is responsible for caching and fetching\/sending data to the server, via the Datasource component. &nbsp;The two main methods are \u201cGET\u201d and \u201cSEND.\u201d &nbsp;When getting data, the proxy first looks in the cache to see if the resource is available on the device. &nbsp;If not, and the device is connected, it will acquire the resource from the server and insert it into the cache. The cache is a key-value store where each key corresponds to a resource identifier. For example \u201ccustomer\/5\u201d is one entry. &nbsp;The other responsibility of the proxy is to send data back to the server. &nbsp;This is straight forward when connectivity is available, in which case the request is just forwarded to the Datasource component. &nbsp;If the device is offline, the request is instead encapsulated and pushed to a queue which will be processed once the device is online again. &nbsp;We use RabbitMQ to handle auxiliary requests, such as removing keys and receiving notifications. &nbsp;The client component connects these different parts together, handles initialization and provides the basic interface used by the dashboard application. &nbsp;Finally, a jQuery plugin handles the rendering of handlebars templates with the JSON data received from the proxy. &nbsp; <\/p><\/blockquote>\n\n\n\n<p> It was fun looking back at this and remembering those days.  The larger point is that building applications for Africa <g class=\"gr_ gr_5 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar multiReplace\" id=\"5\" data-gr-id=\"5\">requires<\/g> some offline capability.  Lots of companies have catered for this in different ways, and if you know one I could talk to please let me know<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This story is actually one of mine. Before I moved to JUMO I was Head of Product for a company I cofounded in Tanzania. We ended up building a great prototype which we dog fooded around the streets of Dar Es Salaam. The data we collected ended up being more valuable than the app. That [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-577","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/posts\/577","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/comments?post=577"}],"version-history":[{"count":1,"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/posts\/577\/revisions"}],"predecessor-version":[{"id":578,"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/posts\/577\/revisions\/578"}],"wp:attachment":[{"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/media?parent=577"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/categories?post=577"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jongore.com\/blog\/wp-json\/wp\/v2\/tags?post=577"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}