<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>The Shine Technologies Blog</title>
	<atom:link href="http://blog.shinetech.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.shinetech.com</link>
	<description>Thoughts from the Shine team</description>
	<lastBuildDate>Thu, 17 May 2012 19:08:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='blog.shinetech.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://0.gravatar.com/blavatar/6b531261b8d086fb4ffbdf82064fb878?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>The Shine Technologies Blog</title>
		<link>http://blog.shinetech.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://blog.shinetech.com/osd.xml" title="The Shine Technologies Blog" />
	<atom:link rel='hub' href='http://blog.shinetech.com/?pushpress=hub'/>
		<item>
		<title>How to Stop Cucumber Becoming Technology Roadkill</title>
		<link>http://blog.shinetech.com/2012/04/15/how-to-stop-cucumber-becoming-technology-roadkill/</link>
		<comments>http://blog.shinetech.com/2012/04/15/how-to-stop-cucumber-becoming-technology-roadkill/#comments</comments>
		<pubDate>Sun, 15 Apr 2012 10:23:06 +0000</pubDate>
		<dc:creator>Ben Teese</dc:creator>
				<category><![CDATA[Testing]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=2204</guid>
		<description><![CDATA[I&#8217;ve worked on a number of projects with Cucumber now, and I think it is a terrific tool. However, I&#8217;ve been seeing it used in ways that it was not originally intended for, the consequence being acceptance-test suites that grow &#8230; <a href="http://blog.shinetech.com/2012/04/15/how-to-stop-cucumber-becoming-technology-roadkill/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=2204&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://shinetechblog.files.wordpress.com/2012/04/squashed_cucumber.jpg"><img class="alignnone size-full wp-image-2211" title="squashed_cucumber" src="http://shinetechblog.files.wordpress.com/2012/04/squashed_cucumber.jpg?w=640" alt=""   /></a></p>
<p>I&#8217;ve worked on a number of projects with Cucumber now, and I think it is a terrific tool. However, I&#8217;ve been seeing it used in ways that it was not originally intended for, the consequence being acceptance-test suites that grow increasingly slow, brittle and difficult to maintain.</p>
<p>These problems occur when developers start using Cucumber to drive overly-detailed tests. The problem of excessive UI testing with Cucumber has been <a href="http://aslakhellesoy.com/post/11055981222/the-training-wheels-came-off">blogged</a> about in the past by Aslak Hellesøy &#8211; the creator of Cucumber &#8211; but I thought I&#8217;d cover some of my own experiences and opinions in this post.</p>
<p><span id="more-2204"></span></p>
<p><strong>The Thing About Developers</strong></p>
<p>We developers are a funny bunch &#8211; we&#8217;ll take a new tool and flog it to death, often pushing it <em>way</em> past what it was originally intended for. In some ways, this is only human, but the problem is that these failed experiments stay with us in the form of difficult-to-maintain code.</p>
<p>To make matters worse, when we discover the tool can&#8217;t do absolutely everything we hoped, there&#8217;ll be a backlash and we&#8217;ll declare the tool to be rubbish. Those of us lucky enough to have the chance will move onto the next big thing, sometimes going right back to where we were in the first place, and failing to acknowledge the more modest (but not insignificant) advancement that the tool gave us in the first place. Those unlucky souls left behind will have to clean up the post-party mess, cursing those who moved on and the wretched tools and techniques that they used.</p>
<p>The technology and process landscape is littered with such roadkill. And I believe Cucumber is in danger of suffering the same fate.</p>
<p><strong>What Should Happen&#8230;</strong></p>
<p>So how is Cucumber supposed to be used? Well, it&#8217;s worth remembering that Cucumber is primarily intended to be a collaboration tool, and only secondarily an automated testing tool. This is a point emphasised in the recently-published <a href="http://pragprog.com/book/hwcuc/the-cucumber-book">Cucumber Book</a> by Hellesøy and Matt Wynne.</p>
<p>However, in my experience, this collaboration can be difficult to achieve. Business people mightn&#8217;t want to write acceptance tests in that format, or might not even be able to; the format might be too far from what they&#8217;re used to. They need developers to help them, but developers aren&#8217;t particularly well known for their collaboration skills. Which brings me to&#8230;</p>
<p><strong>What Actually Happens</strong></p>
<p>So what usually happens is that developers dive in and start to write the features and scenarios themselves. At first this goes well, but it rapidly spirals out of control. For developers are, by necessity, detail-focussed, and their acceptance tests rapidly begin to reflect this fact. Being obsessed with DRY principles, they begin to re-use steps.  To achieve this, step arguments are introduced. Data tables next. Examples get out of control. Lots of state begins to be stored between step definitions. Steps need to be executed in a particular order.</p>
<p>And before you know it, you&#8217;ve got a real mess on your hands. New team members find it harder and harder to understand the step implementations. When they want to add another small feature, they try and contrive extra data that will wend and weave its way through the system and exercise their code change. And if it all gets too hard, they&#8217;ll start copying-and-pasting scenarios and tweaking them slightly to test the particular path they want to cover. The number of scenarios explodes and the test suite slows down.</p>
<p>It can get to a point where Cucumber starts to replace the role of unit-testing. This is unfortunate because whilst Cucumber is great, it&#8217;s a poor choice for a unit testing tool. There are two reasons this is the case. Firstly: acceptance tests, functional tests, integration tests; call them what you will, but one property they all share is that they test the system as a whole rather than particular units. Hence the increasingly convoluted test-data gymnastics that we have to contrive in order to test new changes. Secondly,  compared to writing your tests in code, all Cucumber is adding is an additional layer of indirection via a pseudo-natural-language syntax. If non-technical people aren&#8217;t reading those steps, all you&#8217;re adding is additional hoops to jump through for no benefit.</p>
<p><strong>The Golden Rule</strong></p>
<p>I have a basic criteria for whether Cucumber is going to add value to your project. In short, if your scenarios aren&#8217;t understandable to business people, there&#8217;s no point in using Cucumber.</p>
<p>If developers are going to write the acceptance tests, they need to exercise extreme diligence. They need to ensure that each scenario should be almost immediately comprehensible to a business person. A scenario should not be full of so many gory details and twists and turns that a business person glazes over when reading it.</p>
<p>Of course, this is easier said than done. It&#8217;d require developers to regularly go and get a business person to take a look at our new feature files and scenario definitions. Yet, for many developers, this is an inexplicably <em>hard thing to do</em>.</p>
<p>A strategy that I&#8217;ve seen some developers use to stop their Cucumber tests getting out of control is to avoid tables, examples, and even arguments in steps unless absolutely necessary. Better to have comprehensible steps with some repetition than highly-refactored steps, but unreadable scenarios.</p>
<p>If you&#8217;re a developer who doesn&#8217;t think you&#8217;re going to be able to keep your feature files comprehensible, that&#8217;s OK &#8211; just don&#8217;t use Cucumber. Whilst in some ways this is a shame (because I think that it&#8217;s healthy and beneficial for developers to write a couple of high-level scenarios for new functionality that they are going to implement), in other ways it&#8217;s a relief, because if you just can&#8217;t help yourself when it comes to getting down to the nitty-gritty, I&#8217;d much rather you wrote your tests in code than that you wrote them in Cucumber.</p>
<p><strong>A Third Way</strong></p>
<p>So what if you still really want to use Cucumber, despite the fact that you can&#8217;t trust yourself to write scenarios that are comprehensible to the business, and the business is incapable of writing scenarios at all?</p>
<p>I have found testers to be great people to drive the development of feature files (or at least have a red-hot go at kicking them off). They can interact with the business to get a high-level picture, fill out the details, then get developers to write the step definition code (which developers just<em> love</em> to do because they just <em>love</em> to code). Testers are far enough away from the code to avoid unit-testing, yet close enough to check the important details.</p>
<p>The only trap testers should avoid falling into is this: when the developers have got all of the automated acceptance tests passing, testers should most definitely <em>not</em> use those tests as a script for their own manual testing (a strange phenomenon I have seen on a couple of occasions). Instead, they should use their new-found time and freedom to engage in exploratory testing.</p>
<p><span style="color:#000000;"><strong>Summing Up</strong></span></p>
<p>I believe that Cucumber is only appropriate if non-technical people are going to be reading (and preferably writing) the steps.  Whilst in theory Cucumber is a great tool for behaviour-driven development at any level, I&#8217;ve seen too many developers struggling to write comprehensible scenarios and step-definition code that is understandable to other developers, let alone non-technical people. The result is often a Cucumber test suite that is slow, brittle and difficult to maintain.</p>
<p>I&#8217;d rather that developers wrote their test in plain-old code, unless a business person is going to look a them. I also believe that, rather than trying to put a natural-language wrapper around their tests, developer effort would be better expended just trying to make test code more understandable.</p>
<p>High-level acceptance tests written in Cucumber are great, but let&#8217;s not go overboard. Let&#8217;s not let Cucumber become another technology roadkill, run down by over-zealous developers. And let&#8217;s not leave ourselves a test-suite legacy that we&#8217;ll all regret.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/2204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/2204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/2204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/2204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/2204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/2204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/2204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/2204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/2204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/2204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/2204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/2204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/2204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/2204/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=2204&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2012/04/15/how-to-stop-cucumber-becoming-technology-roadkill/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9aeb1c3afc77a51d314df6f2ad996f6c?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">benteeseshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2012/04/squashed_cucumber.jpg" medium="image">
			<media:title type="html">squashed_cucumber</media:title>
		</media:content>
	</item>
		<item>
		<title>Bootstrap makes me look good</title>
		<link>http://blog.shinetech.com/2012/03/07/bootstrap-makes-me-look-good/</link>
		<comments>http://blog.shinetech.com/2012/03/07/bootstrap-makes-me-look-good/#comments</comments>
		<pubDate>Wed, 07 Mar 2012 06:07:34 +0000</pubDate>
		<dc:creator>Nick Letts</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=2178</guid>
		<description><![CDATA[Before we begin, let me give you a quick background. I&#8217;m a web developer who likes to dabble a bit in UI design. The majority of the projects I work on are non public facing, so they are often without &#8230; <a href="http://blog.shinetech.com/2012/03/07/bootstrap-makes-me-look-good/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=2178&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://shinetechblog.files.wordpress.com/2012/03/zoolander.jpg"><img class="alignnone size-large wp-image-2200" title="zoolander" src="http://shinetechblog.files.wordpress.com/2012/03/zoolander.jpg?w=1024&h=674" alt="" width="1024" height="674" /></a></p>
<p>Before we begin, let me give you a quick background. I&#8217;m a web developer who likes to dabble a bit in UI design. The majority of the projects I work on are non public facing, so they are often without the aid of a graphic designer. This usually leads to the production of a fully functioning web app that looks like a mixed bag of CSS tutorials. Sounding familar?</p>
<p>Enter <a href="http://twitter.github.com/bootstrap/index.html">Twitter Bootstrap</a>.</p>
<p>Bootstrap is an open-source, cross-browser collection of CSS and HTML conventions. It is essentially a front-end toolkit for rapidly developing stylish web applications. It covers everything from forms, typography, tables and buttons to layouts and dynamic components like tabs, menus and pagination. It is built on with the power of <a href="http://lesscss.org/">LESS</a> and has support for many jQuery plugins (modals, dropdowns, alerts etc).</p>
<p><span id="more-2178"></span>One of the strong points of Bootstrap is how easy it is to integrate into a project and use in conjunction with other technologies. To give you an example, my most recent project used Bootstrap in conjunction with <a href="http://www.displaytag.org/1.2/">display tag</a>. Display tag is a JSP tag library for displaying tabled data, with built in column sorting and pagination. The integration between Boostrap and display tag was seamless. I only needed to set the CSS classes on the display table to use Boostrap CSS classes:</p>
<p><pre class="brush: xml;">
&lt;display:table class=&quot;table table-striped table-condensed&quot; name=&quot;results&quot;&gt;
...
&lt;/display:table&gt;
</pre></p>
<p>Bootstrap even took care of the table row stripping (although display tag has support for this too). Here is a picture of the result:<a href="http://shinetechblog.files.wordpress.com/2012/03/bootstrap-demo-31.png"><img class="aligncenter size-full wp-image-2185" title="Bootstrap Demo" src="http://shinetechblog.files.wordpress.com/2012/03/bootstrap-demo-31.png?w=640&h=271" alt="Bootstrap Demo" width="640" height="271" /></a> Another thing I like about Bootstrap is that it makes use of custom HTML 5 data attributes to activate/link the majority of it&#8217;s dynamic content. For example, have a look at the code required to pop up a modal:</p>
<p><pre class="brush: xml;">
&lt;a class=&quot;btn&quot; data-toggle=&quot;modal&quot; href=&quot;#theModal&quot;&gt;Launch Modal&lt;/a&gt;

&lt;div class=&quot;modal&quot; id=&quot;theModal&quot;&gt;
  &lt;div class=&quot;modal-header&quot;&gt;
    &lt;a class=&quot;close&quot; data-dismiss=&quot;modal&quot;&gt;×&lt;/a&gt;
    &lt;h3&gt;Super Cool Modal&lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class=&quot;modal-body&quot;&gt;
    &lt;p&gt;Some body text&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;modal-footer&quot;&gt;
    &lt;a href=&quot;#&quot; class=&quot;btn btn-primary&quot;&gt;Save&lt;/a&gt;
    &lt;a href=&quot;#&quot; class=&quot;btn&quot;&gt;Close&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;
</pre></p>
<p>Note the <strong>data-toggle=&#8221;modal&#8221;</strong> attribute on the button, which means clicking the &#8216;Launch Modal&#8217; button will make &#8216;theModal&#8217; div appear as a modal. There is absolutely no JavaScript required! I like this because it keeps the code clean and I don&#8217;t need a high working knowledge of JavaScript to make basic UI components work. This also helps minimise code on the &#8216;view&#8217; side of things. If you&#8217;re not already sold, here is another code example for creating drop down menus:<br />
<a href="http://shinetechblog.files.wordpress.com/2012/03/bootstrap-dropdowns.png"><img class="aligncenter size-full wp-image-2198" title="Bootstrap Dropdowns" src="http://shinetechblog.files.wordpress.com/2012/03/bootstrap-dropdowns.png?w=640" alt="Bootstrap Dropdown Menu"   /></a></p>
<p><pre class="brush: xml;">
&lt;ul class=&quot;nav&quot;&gt;
  &lt;li class=&quot;dropdown active&quot; id=&quot;menu1&quot;&gt;
    &lt;a class=&quot;dropdown-toggle&quot; data-toggle=&quot;dropdown&quot; href=&quot;#menu1&quot;&gt;
      Listings
      &lt;b class=&quot;caret&quot;&gt;&lt;/b&gt;
    &lt;/a&gt;
    &lt;ul class=&quot;dropdown-menu&quot;&gt;
      &lt;li&gt;&lt;a href=&quot;/list/1.html&quot;&gt;Update&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/list/2.html&quot;&gt;Create&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/list/3.html&quot;&gt;Delete&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li class=&quot;dropdown&quot; id=&quot;menu2&quot;&gt;
    &lt;a class=&quot;dropdown-toggle&quot; data-toggle=&quot;dropdown&quot; href=&quot;#menu2&quot;&gt;
      Other
      &lt;b class=&quot;caret&quot;&gt;&lt;/b&gt;
    &lt;/a&gt;
    &lt;ul class=&quot;dropdown-menu&quot;&gt;
      &lt;li&gt;&lt;a href=&quot;/other/1.html&quot;&gt;Reviews&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/other/2.html&quot;&gt;Users&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</pre></p>
<p>As you can see, no JavaScript! The drop down menu&#8217;s are identified with <strong>data-toggle=&#8221;dropdown&#8221;</strong>, and Bootstrap takes care of the rest!</p>
<p>Although I&#8217;m extremely pleased with Boostrap, there are a few concerns/issues that I have. The most obvious is that if you use Boostrap on all your projects, guess what all your projects are going to look like? I think the Twitter look and feel is very nice, but the novelty may wear off after a while. I know you can get around this by overlaying your own CSS customisations to the Boostrap core, but we are starting to head back into a mixed bag of CSS tutorials problem. Maybe to a lesser degree though, since we would have a solid CSS base (using LESS) to work off. Another issue I&#8217;ve found with Bootstrap, is that it doesn&#8217;t have native support for a date picker. This was unfortunate because our search UI required the user to enter a start and end date. Thankfully with a bit of googling I was able to find <a href="http://dl.dropbox.com/u/143355/datepicker/datepicker.html">this</a> little widget, which did the job fine. I&#8217;m pretty sure something like this will makes it&#8217;s way into Bootstrap soon.</p>
<p>I should also point out that Bootstrap isn&#8217;t the first or only one of it&#8217;s kind, there are quiet a few floating around the web. I&#8217;ve also looked into <a href="http://jqueryui.com/">jQuery UI</a>, <a href="http://foundation.zurb.com/">Zurb Foundation</a>, <a href="http://yuilibrary.com/projects/yui3">YUI</a> and <a href="http://www.99lime.com/">HTML Kickstart</a>. Zurb Foundation and HTML Kickstart are very similar in offerings to Boostrap, but in my opinion Twitter Bootstrap has that little bit of extra visual design polish to it&#8217;s UI. YUI and jQuery UI are heavier frameworks with a bit more emphasis on JavaScript than Boostrap. I always felt like I needed to do a lot more work on the CSS side of things when using jQuery UI or YUI. To their credit though, I think they have better API&#8217;s and documentation than Bootstrap. Though this is possibly because they need it? I found Bootstrap to have a very small learning curve compared to jQuery UI or YUI.</p>
<p>As stated on the official website, Bootstrap is &#8216;built for and by nerds&#8217;. It allows me as a developer to create a gorgeous UIs in less time, which means a happy client and in turn a happy boss. Bootstrap makes me look good. So if you&#8217;re a front-end developer and have yet to use Bootstrap, I&#8217;d recommend giving it a shot.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/2178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/2178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/2178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/2178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/2178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/2178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/2178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/2178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/2178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/2178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/2178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/2178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/2178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/2178/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=2178&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2012/03/07/bootstrap-makes-me-look-good/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d40b71180613b127bc6f4cfce6856dc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nicholaslettsshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2012/03/zoolander.jpg?w=1024" medium="image">
			<media:title type="html">zoolander</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2012/03/bootstrap-demo-31.png" medium="image">
			<media:title type="html">Bootstrap Demo</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2012/03/bootstrap-dropdowns.png" medium="image">
			<media:title type="html">Bootstrap Dropdowns</media:title>
		</media:content>
	</item>
		<item>
		<title>Processing Huge JSON Files with Jackson</title>
		<link>http://blog.shinetech.com/2011/12/23/processing-huge-json-files-with-jackson/</link>
		<comments>http://blog.shinetech.com/2011/12/23/processing-huge-json-files-with-jackson/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 02:41:34 +0000</pubDate>
		<dc:creator>Grant Ruwoldt</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[jackson]]></category>
		<category><![CDATA[json]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=1585</guid>
		<description><![CDATA[A couple of months ago I was asked to build a processor that would take a JSON file; perform a few elementary checks and transformations and upload the resulting records into a Couch DB. I hadn&#8217;t done any JSON, or &#8230; <a href="http://blog.shinetech.com/2011/12/23/processing-huge-json-files-with-jackson/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1585&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div id="attachment_1628" class="wp-caption alignnone" style="width: 310px"><a href="http://shinetechblog.files.wordpress.com/2011/12/weirdal.jpg"><img src="http://shinetechblog.files.wordpress.com/2011/12/weirdal.jpg?w=300&h=209" alt="" title="weirdal" width="300" height="209" class="size-medium wp-image-1628" /></a><p class="wp-caption-text">Weird Al&#039;s not the only one who knows how to go large with Jackson</p></div>
<p>A couple of months ago I was asked to build a processor that would take a JSON file; perform a few elementary checks and transformations and upload the resulting records into a Couch DB. I hadn&#8217;t done any JSON, or Couch and, naturally, the whole thing had to be done yesterday &#8211; but at first glance it didn&#8217;t look like much of a challenge.</p>
<p>However, looking a little deeper, my processor was going to be part of a replication process across two databases housed in separate enterprises. The replication was going to be based on a daily snapshot &#8211; each JSON file would be a copy of the entire database &#8211; and a few back-of-the-envelope calculations suggested that the files may become rather large (40+GB) over time.<br />
<span id="more-1585"></span><br />
There was also a fairly tight processing window within which the upload had to be complete. Repressed memories of chasing down and remediating an old DOM based XML project plagued with OutOfMemoryExceptions and very slow processing times warned that some thought was required. </p>
<p>Obviously I wasn&#8217;t going to be able to be able to read the whole file into RAM to transform it and fortunately, I didn&#8217;t need to &#8211; the file was a collection of a couple of million simple objects with no cross references. So to minimize the amount of memory required by the processor, I simply needed to parse the large file into a stream of objects and transform them either individually or in small collections.</p>
<h2>Jackson</h2>
<p>Key &#8220;JSON Parsing&#8221; into your favourite search engine and you find about thirty different technologies competing for your attention. Also about a hundred different opinions as to which was &#8220;the best&#8221;. After a brief review, Jackson recommended itself though the <a title="tutorial" href="http://wiki.fasterxml.com/JacksonInFiveMinutes" target="_blank">tutorial</a> which indicated that it included a Streaming API, as well as a DOM like Tree Model and JAXB style object bindings.</p>
<p>Given the memory and time concerns above, my first concept was to use the Streaming API to identify object boundaries within the input file to break it down into small chunks and to then use a JAXB style object binding to do the simple transformations required (mostly field name changes). The object binding piece was beautifully trivial:</p>
<p><pre class="brush: java;">
public class Business {
    @JsonView({ BriefView.class, FullView.class })
    private String businessId;

    @JsonView({ BriefView.class, FullView.class })
    private String name;

    @JsonView({ FullView.class })
    private String address;

    ...
}
</pre></p>
<p>Using the JsonView concept, I was able to use the same value class to render different JSON requests for various external services supporting the checking and transformations required.</p>
<p>The Streaming API piece wasn&#8217;t going so smoothly. Although it was straight-forward to identify the object boundaries in the JSON token stream, there didn&#8217;t seem to be a natural (i.e. easy) way of accessing the underlying character stream in order to create the smaller work unit for the object bindings to use.  A re-think was necessary.</p>
<p>The object bindings were giving me an easy way of creating a collection of value objects in memory from a JSON stream &#8211; and conversely of creating a JSON stream from a collection of value objects. If I could get the Jackson object binding to create a stream of value objects, then I could dispense with the streaming API altogether. Some trawling through the Jackson API soon showed this wasn&#8217;t only possible, but easy:</p>
<p><pre class="brush: java;">
JsonFactory f = new MappingJsonFactory();
JsonParser jp = f.createJsonParser(reader);

do {
    Business business = jp.readValueAs(Business.class);

    if (business == null) {
        handler.complete(context);
        break;
    }

    numberOfBusinessesReceived++;
    handler.handleBusiness(business, context);

} while (true);
jp.close();
</pre></p>
<p>The object handler here applies some cheap validation rules and aggregates a bunch of objects into a file for later (in memory) processing and upload to Couch. The context object carries some extra information &#8211; like the name of the file being processsed.</p>
<p>The magic provided by Jackson is the readValueAs method, which reads enough of the stream to create an object. Pushing a 10GB of two million records file through the processor running on an ordinary desktop with 256M of heap space yielded a processing time of 6 minutes &#8211; well within the required processing time window.\</p>
<h2>Conclusion</h2>
<p>The creators of Jackson have learnt the lessons from XML parsing well. Jackson offers a range of parsing approaches that allows developers to choose the right approach to the task at hand. In short, Jackson eats massive JSON files &#8211; without raising a sweat.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/1585/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/1585/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/1585/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/1585/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/1585/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/1585/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/1585/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/1585/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/1585/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/1585/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/1585/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/1585/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/1585/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/1585/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1585&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2011/12/23/processing-huge-json-files-with-jackson/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1d553d32dad28c30ad164220150e4119?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grantruwoldtshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/12/weirdal.jpg?w=300" medium="image">
			<media:title type="html">weirdal</media:title>
		</media:content>
	</item>
		<item>
		<title>Yow! Developer Conference Brisbane.</title>
		<link>http://blog.shinetech.com/2011/12/12/yow-developers-conference-brisbane/</link>
		<comments>http://blog.shinetech.com/2011/12/12/yow-developers-conference-brisbane/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 05:46:48 +0000</pubDate>
		<dc:creator>Alistair Sutton</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Opinion]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=1564</guid>
		<description><![CDATA[Yow! Brisbane 2011 I recently had the pleasure of attending the Brisbane Yow! Conference.  This was a great conference with talks to interest developers across many languages platforms and experience. This blog is a summary of the more interesting talks &#8230; <a href="http://blog.shinetech.com/2011/12/12/yow-developers-conference-brisbane/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1564&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1 style="text-align:center;"><a href="http://shinetechblog.files.wordpress.com/2011/12/photo-2.jpg"><img class="alignnone size-medium wp-image-1572" title="photo-2" src="http://shinetechblog.files.wordpress.com/2011/12/photo-2.jpg?w=300&h=225" alt="" width="300" height="225" /></a></h1>
<h1 style="text-align:center;">Yow! Brisbane 2011</h1>
<p>I recently had the pleasure of attending the <a href="http://yowaustralia.com.au/YOW2011/index.html">Brisbane Yow! Conference</a>.  This was a great conference with talks to interest developers across many languages platforms and experience.</p>
<p>This blog is a summary of the more interesting talks that I attended and my thoughts on them.<br />
<span id="more-1564"></span><br />
<strong>Keynote – <a href="http://yowaustralia.com.au/YOW2011/general/details.html?speakerId=2312">Top 10 JVM Erroneous Zones</a> – Cameron Purdy</strong></p>
<p>The opening talk of day one was a very technical discussion from an Oracle VP, taking us through what he thought were areas that can/could/should be improved in the Java Virtual Machine.  It was a reasonably low level talk for a Keynote but this was a developer’s conference so not entirely unexpected.</p>
<p>Purdy spoke about low-level extensibility in terms of abstracting on primitive types and the limitations of building word length into compilers.  He also touched on precision, lack of continuations support and made comparisons with other languages such as C++ and Scala to support his points.</p>
<p>These points were then used to relate back to development work being done at Oracle on the JVM.  The case was made that since Oracle took over JVM development and maintenance, many improvements and efficiencies in the language have been made. As Java remains a flagship product for Oracle they will continue to do so going forward.</p>
<p>What I took from the talk was that someone driving development is being constructively critical of the language, which is undergoing a lot of criticism in  light of the popularity of dynamic languages such as Groovy.</p>
<p><strong>Lean and Agile  &#8211; <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3490">Continuous Design –</a> Mary Poppendieck</strong></p>
<p>This talk from the Lean Luminary was not quite what I expected. It focused more on a wider view of product design from conception to market place whereas I thought it would be covering incremental design, how best to manage that within an agile environment and how best to integrate that with a continuous delivery approach.</p>
<p>Although the talk was a little broader than I expected, Mary continually reaffirmed the 3M philosophy of make a little, sell a little and learn a little.  This was then discussed in terms of product cycles and how important design conception is and how it can then be refined through iterations of testing and using the design to the point that it can be taken to market.</p>
<p>A lot of comparisons were made between Google, Apple and Dropbox in terms of defining and refining products before they go to market and what comes after go live in terms of design.</p>
<p>An interesting point was her discussion on enabling toggling of features in production so that unfinished features do not disrupt the continuous delivery cycle. She discussed doing small releases via load balancing to test out new features on a smaller audience in case they fail and drive people away.</p>
<p>Overall this was a great talk to be listening to if you were taking a new product to market or worked within a start up type environment.   Of course it was quite a privilege to hear Mary Poppendieck present and she is an excellent presenter.</p>
<p><strong> DevOps – <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3613">We’re all Developers Now</a> – Julian Simpson</strong></p>
<p>This talk eventually got underway after a few technical hitches with the speaker’s laptop not co-operating with the projector.  You definitely don’t want technical difficulties in front of a room full of developers.</p>
<p>Once the talk began, it was basically a quick overview of DevOps and then mainly a comparison of Puppet and Chef.  Both Puppet and Chef are automation tools for Sys Admins.   The talk was very interesting showing how a sys admin would manage the installation of an application using the Nginx web server and Jetty.  Examples of how this is configured in Puppet and Chef where then shown illustrating how the configuration is then version controlled to provide change control management and one version of truth.</p>
<p>The power of this was demonstrated very well as Julian discussed how the configuration defined where specific components were to be installed across many virtual servers, allowing the administrator to roll out changes very quickly to a scalable number of machines.  Very powerful and quite dangerous – all the more reason for source control and proper change control!</p>
<p>DevOps is a fast growing and very interesting development in the industry and is leading to more responsibility for the developer as the gap between development and production is closing….</p>
<p>I thought this was a very good talk and I am looking closely at the various DevOps movements within our clients.</p>
<p><a href="http://shinetechblog.files.wordpress.com/2011/12/photo9.jpg"><img class="alignright size-medium wp-image-1571" title="Action shot -  Yow! Brisbane 2011" src="http://shinetechblog.files.wordpress.com/2011/12/photo9-e1323658432449.jpg?w=225&h=300" alt="Action shot - Yow! Brisbane 2011" width="225" height="300" /></a></p>
<p><strong>Transitioning To The Cloud – <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3585">Challenges Transitioning To The Cloud</a> – Rod Johnson</strong></p>
<p>A very interesting talk from Rod Johnson, the founder of Spring.  This talk was Rod discussing what he sees as the issues and challenges facing the drive of software into the cloud.</p>
<p>He defined the differences between Infrastructure as a service (IaaS), Platforms as a service (PaaS) and Software as a service (SaaS) and then spoke of the trends he thinks will happen with these.  These were namely that there will be more growth in PaaS and likened it to the second coming of the main frame.  He talked about a standardized stack such as a Ruby or a Java stack, which might see developer’s choice narrow and will also see the tools as part of the platform.</p>
<p>It was very interesting hearing someone of Rod’s experience and foresight discussing the cloud and what he saw it meaning for developers in the future.</p>
<p><strong>The Interactive Web &#8211; <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3254">The Live Web</a> – Dan Ingalls.</strong></p>
<p>Dan Ingalls is one of the founders of Smalltalk so it was quite surreal to have him present a demonstration on a JavaScript web IDE for building HTML 5 applications.</p>
<p>The Living Kernel is a component architecture for HTML and runs in the browser.  It lets developers build and compose with existing components in a canvas like fashion and then tie them together with events, animations and scripting to quickly pull together visual applications.</p>
<p>While the examples shown in the talk were all relatively lightweight there was some scope of the power of this show when he quickly generated a graph based on Unix output to show CPU utilization of a server.  This would then be saved as a HTML report.  His entire presentation was also built using the tool, which showed its versatility.</p>
<p>What was missing in this talk was the business benefits of these tools.  He mentioned towards the end that they generate some reporting for come clients using this but it was only mentioned in passing.</p>
<p><strong>Better Testing for Less Work – <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3598">QuickCheck</a> – John Hughes<br />
</strong></p>
<p>This very entertaining talk was based around the speakers experience using QuickCheck.</p>
<p>QuickCheck is a testing tool, which based on a set of rules will then generate a specified number of tests with random data.  If an error is found, then the tool will focus on reproducing that error as many times as possible to determine the simplest cause of the error from the random data it generated.</p>
<p>John Hughes explained the tool at a high level and briefly showed how to specify a property rule but the basis of his talk was his experiences using QuickCheck in industry.  He discussed the use of the tool in car industry software and how he identified an issue in a production database.</p>
<p>John Hughes was such an entertaining presenter the entire audience was hanging on every word and we all erupted in applause at the end of the talk.  His passion for his work was evident and this translated into a surprisingly interesting talk on a low level-testing tool.</p>
<p><strong><a href="http://shinetechblog.files.wordpress.com/2011/12/yow2011squarebanner.png"><img class="alignleft size-full wp-image-1574" title="YOW2011SquareBanner" src="http://shinetechblog.files.wordpress.com/2011/12/yow2011squarebanner.png?w=640" alt=""   /></a>Keynote &#8211; <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3586">Escape from the Ivory Tower</a> – Simon Peyton-Jones</strong></p>
<p>You could be forgiven for calling Simon Peyton-Jones  “Monty” and John Hughes&#8217; “Python”.</p>
<p>Both went to university together at Cambridge and have the same passion, humour and comic delivery which makes for an excellent presentation. This was a wonderful follow on from the John Hughes talk.</p>
<p>This talk covered the history of Haskell, a functional programming language which has largely been academic until recently.</p>
<p>With the rise of parallel programming Haskell has attracted far more interest and suddenly Simon as a co-creator of Haskell is very much in demand as a speaker.</p>
<p>The speech centered around the history of Haskell and the differences between Haskell and other functional programming languages.  For non-functional programmers Simon recommended some exposure to Haskell to help them think about programming in a different way.</p>
<p>Again the speaker was very passionate about his topic and his presentation was so well put together that the audience was very much engaged.</p>
<p><strong>JavaScript Everywhere</strong></p>
<p>The next few talks that I attended painted a better picture for me on the rise and rise of JavaScript.</p>
<p><strong>Web As A Platform &#8211; <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3644">Dart, a new programming language for structured web programming</a>  – Kasper Lund</strong></p>
<p>This talk introduced Dart, a new programming language (almost) released by Google, still very much in its formative years.</p>
<p>Through coding up examples, the presenter highlighted a number of the language features mainly comparing them to JavaScript.   I took it that Dart was positioning itself to rival JavaScript. Dart can either run on it’s own VM or can be compiled down to JavaScript… which leads me into the next talk.</p>
<p><strong>Web As A Platform &#8211; <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3549">The Web Browser is a Transitional Technology</a> – Allen Wirfs-Brock</strong></p>
<p>This talk was based on the premise that we are moving into a new era of computing. We went from corporate computing to personal computing and now into what Mozilla’s Allen Wirfs-Brock labeled the Ambient Computing era.</p>
<p>Ambient is defined as “completely enveloping” so I take it he was trying to capture the fact the now people have multiple devices which they want and use all the time, therefore we are enveloped in the technology.  Bit of a stretch for me I’m afraid… I don’t think that phrase is going to stick.</p>
<p>In any case, he made good points that the new gadgets entering the market do not typically use a browser any more to interact with the web.  However a lot of them still use the same technology stack just without the browser chrome.  This web platform can sit directly on new hardware losing the PC and the browser.  To relate back to the title of the speech, the browser was a PC based, transitional technology to get us to this point.</p>
<p>The biggest point I believe Allen made was that JavaScript was directly built into this technology stack and was the only language present.  By this fact alone it foretells a bright future for JavaScript as it would be very difficult for an emerging technology (such as Dart) to proliferate to the point that all vendors across the Internet and gadget market will replace JavaScript in this platform.</p>
<p>I guess that’s why the Dart guys have ensured Dart can compile down to JavaScript….</p>
<p><strong>Web As A Platform &#8211; <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3563">NodeJS and the JavaScript-Everywhere Strategy</a> &#8211; Matthew Eernisse</strong></p>
<p>Yammer’s Matthew Eernisse talked about JavaScript on the server side and the rise of NodeJS.  In the talk Eernisse wrote a web server from scratch to show how quickly you can get off and running with NodeJS.  He discussed some of the tools available to help with NodeJS development and highlighted some of the trouble shooting lessons he had learned.  With so many callbacks and asynchronous code it can be difficult finding root causes of issues.  Eernisse showed how he changed his debug to help address those issues.</p>
<p>The majority of the Yammer upload apps are NodeJS applications and Shine Technologies has also done some major project work with a Melbourne client on various NodeJS apps.</p>
<p>This talk complemented the previous ones on highlighting the rise and rise of JavaScript to me.</p>
<p>The only other talk I should mention was the <a href="http://www.yowconference.com.au/YOW2011/general/workshopDetails.html?eventId=3496">Keynote</a> by Damien Conway on extending Perl to implement quantum physics. This was genius in PowerPoint but while I enjoyed it and followed it to a degree, I could not hope to summarise it due to its complexity.  Presentations like Conway’s go a long way to inspiring people in the field to take their profession far beyond what anyone thought was possible.  Sensational stuff!</p>
<p><strong>Summary</strong></p>
<p>There were some other interesting talks, which rounded out the conference plus a good chance to meet other developers and people in the industry as well as the speakers themselves who were very approachable.</p>
<p>This was a very well run conference and I will be lining up next year again for it.</p>
<p><em>Alistair Sutton is a Senior Consultant for Shine Technologies and has recently moved to Brisbane to open a Brisbane branch for Shine.</em></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/1564/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/1564/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/1564/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/1564/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/1564/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/1564/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/1564/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/1564/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/1564/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/1564/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/1564/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/1564/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/1564/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/1564/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1564&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2011/12/12/yow-developers-conference-brisbane/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7167efd68f982e19a174e78d5b2c7c4a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">alistairsuttonshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/12/photo-2.jpg?w=300" medium="image">
			<media:title type="html">photo-2</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/12/photo9-e1323658432449.jpg?w=225" medium="image">
			<media:title type="html">Action shot -  Yow! Brisbane 2011</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/12/yow2011squarebanner.png" medium="image">
			<media:title type="html">YOW2011SquareBanner</media:title>
		</media:content>
	</item>
		<item>
		<title>CouchDb on Android</title>
		<link>http://blog.shinetech.com/2011/11/14/couchdb-on-android/</link>
		<comments>http://blog.shinetech.com/2011/11/14/couchdb-on-android/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 06:13:41 +0000</pubDate>
		<dc:creator>Daniel Brain</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=1479</guid>
		<description><![CDATA[Synchronising advanced data structures with a backend sucks. Especially when the sync is both ways; user updates to server, server updates to user. Couchbase for Mobile attempts to solve this issue by bringing CouchDb and it&#8217;s spiffy replication to Android. What? &#8230; <a href="http://blog.shinetech.com/2011/11/14/couchdb-on-android/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1479&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p style="text-align:center;"><img class="aligncenter size-medium wp-image-1501" title="Android on Couch" src="http://shinetechblog.files.wordpress.com/2011/11/android-on-couchdb.jpg?w=300&h=170" alt="" width="300" height="170" /></p>
<p>Synchronising advanced data structures with a backend sucks. Especially when the sync is both ways; user updates to server, server updates to user. <a title="Couchbase for Mobile" href="http://www.couchbase.com/products-and-services/mobile-couchbase" target="_blank">Couchbase for Mobile</a> attempts to solve this issue by bringing <a title="CouchDb" href="http://couchdb.apache.org/" target="_blank">CouchDb</a> and it&#8217;s spiffy replication to Android.<span id="more-1479"></span></p>
<h2>What? Why?</h2>
<p><img class="alignright size-full wp-image-1506" title="Doctor What Is This" src="http://shinetechblog.files.wordpress.com/2011/11/doctor-whatisthis.jpeg?w=640" alt=""   />Why would you ever want CouchDb on your phone, you ask. Well, along with giving you some fancy pants replication, which I&#8217;ll rant about soon, some of the benefits over Android&#8217;s built in <a title="SQLite" href="http://sqlite.org/" target="_blank">SQLite</a> support are:</p>
<ul>
<li>Unstructured data storage in JSON documents</li>
<li>Map/reduce for querying</li>
<li>Versioning of documents</li>
<li>And more..</li>
</ul>
<p>In a bit more detail ..</p>
<h3>JSON documents with whatever you want in them</h3>
<p>The data in CouchDb is document oriented, in that it stores and returns your content in JSON documents. These documents can have whatever fields and whatever JSON acceptable values you wish without any table changes. This gives you the power to support dynamically added fields. If you wanted to create a form that accepts additional user defined fields, CouchDb or something like it is what you want.</p>
<p>A CouchDb document, requested with a GET to /database/boo, is read and written something like</p>
<p><pre class="brush: jscript;">
{
  &quot;_id&quot;: &quot;booboo&quot;,
  &quot;_rev&quot;: &quot;gibberish&quot;,
  &quot;favouriteFoods&quot;: [ &quot;Bangers&quot;, &quot;Mash&quot; ],
  &quot;bodyWeight&quot;: 300
}
</pre></p>
<p>While a horribly non standard representation of a SQL table structure, that allows dynamically added fields, would be something like</p>
<pre>Form#1()
FormValue#1(
  formId: 1,
  fieldName: "favouriteFoods",
  fieldValue: "Bangers",
  fieldType: "String"
)
FormValue#2(
  formId: 1,
  fieldName: "favouriteFoods",
  fieldValue: "Mash",
  fieldType: "String"
)
FormValue#3(
  formId: 1,
  fieldName: "bodyWeight",
  fieldValue: "300",
  fieldType: "Number"
)</pre>
<p>Retrieved with queries like</p>
<p><pre class="brush: sql;">
SELECT * FROM Form
SELECT * FROM FormValue WHERE formId = 1
</pre></p>
<p>As you can see the CouchDb approach is much nicer, and in SQLite&#8217;s case the structure of Form and FormValue need to be defined when the table is created. Meaning updates to the structure of these tables involve fancy scripts or complicated <a title="SQLiteOpenHelper.onUpgrade" href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)" target="_blank">SQLiteOpenHelper.onUpgrade</a> functions.</p>
<h3>Map/reduce functions</h3>
<p><img class="alignleft size-thumbnail wp-image-1507" title="MapReduce" src="http://shinetechblog.files.wordpress.com/2011/11/mapreduce.jpg?w=150&h=115" alt="" width="150" height="115" />CouchDb has a different method of querying the data compared to normal SQL databases, depending on your usage this could be a deal maker or a deal breaker.</p>
<p>In CouchDB you create views of your data, written in Javascript, emitting a key and a value. You then look up the data you want using the key you specified. You can also reduce the values for summing or other fun things. For example:</p>
<p><pre class="brush: jscript;">
&quot;byName&quot;: {
  &quot;map&quot;: function (doc) {
    if (doc.name) {
      emit(doc.name, 1);
    }
  },
  &quot;reduce&quot;: function (key, values, rereduce) {
    return sum(values);
  }
}
</pre></p>
<p>When this has been indexed you will have an index like:</p>
<pre>"Jim", 1
"Jim", 1
"Jack", 1</pre>
<p>Calling it with reduce will give you:</p>
<pre>"Jim", 2
"Jack", 1</pre>
<h3>Versioning of documents</h3>
<p>CouchDb versions documents. Every time you update a document the previous revision will still exist and be accessible (until compaction which I&#8217;ll ignore), which may be useful for basic undo or rollback functionality.</p>
<h3>Everything CouchDb gives you</h3>
<p><img class="aligncenter size-medium wp-image-1509" title="Obese Cat" src="http://shinetechblog.files.wordpress.com/2011/11/obesecat.jpg?w=300&h=155" alt="" width="300" height="155" /><br />
And all of the other things CouchDb provides, like hugs, kittens and obese indexes (don&#8217;t quote me).</p>
<h2>Replication</h2>
<p><img class="aligncenter size-full wp-image-1504" title="Replicators" src="http://shinetechblog.files.wordpress.com/2011/11/10-points-for-reference.jpg?w=640" alt="10 points if you get the reference"   /><br />
The main benefit you&#8217;ll see with using CouchDb for your application (presumably) is data synchronisation via replication.</p>
<p>CouchDb supports really easy start and stop replication, with it&#8217;s own conflict resolution. You could have multiple databases that haven&#8217;t seen each other in months, tell them about each other and each of them will eventually catch up with the other as far as documents go. This is awesome for &#8220;when I want&#8221; syncing, and offline editing of data that syncs when a connection is established again. Some use cases:</p>
<h3>Taking notes</h3>
<p>This would be great for a note taking application that supports mobile as well as web edits. The user could add notes on both sides and sync to make both sides consistent when they want / when a wireless connection is available.</p>
<h3>Real time when available</h3>
<p>You could have replication going any time the application is in the foreground. This would allow for applications that work in real time but don&#8217;t explode when the network is lost.</p>
<p>And I&#8217;m sure other more exciting things my boring brain chose to shield me from.</p>
<h2>I&#8217;m sold. How do I make the magic happen?</h2>
<p><img class="alignleft size-medium wp-image-1505" title="Magic Happening" src="http://shinetechblog.files.wordpress.com/2011/11/magic-happening.jpg?w=256&h=300" alt="" width="256" height="300" />First up, make an Android 2.x project in your favourite Java IDE (Eclipse), which you have obviously already set up for Android development.</p>
<p>Next you need to get the latest version of CouchDb for Android (still in Developer preview), <a title="here" href="http://www.couchbase.org/get/couchbase-mobile-for-android/current" target="_blank">here</a>. This website also covers the instructions for getting your project CouchDb friendly, basically it&#8217;s &#8220;run an Ant script and hope it&#8217;s not doing anything too horrible&#8221;. Without going too into it, it&#8217;s configuring your project for CouchDb, Erlang (which CouchDb uses behind the scenes) and some funky native libraries.</p>
<p>You can also add <a title="Ektorp" href="http://ektorp.org" target="_blank">Ektorp</a>, a Java API for CouchDb with Android support. This wraps the CouchDb calls so you don&#8217;t have to generate your own HTTP requests. That&#8217;s really up to you, but the code examples below use this, and Couchbase recommends it as far as Android CouchDb libraries go.</p>
<h2>I&#8217;m listening..</h2>
<p>If you&#8217;re anything like me, you&#8217;ve probably skipped to this section or closed the page when you didn&#8217;t instantly see code, but here goes.</p>
<p><img class="aligncenter size-full wp-image-1503" title="Super Duper Programmer" src="http://shinetechblog.files.wordpress.com/2011/11/super-duper-programmer.jpg?w=640" alt=""   /></p>
<h3>Starting CouchDb</h3>
<p>First we&#8217;ll set up a CouchbaseDelegate in our main Activity. You use this to capture startup errors and kick off initialisation steps / replication when the database has started.</p>
<p><pre class="brush: java;">
ICouchbaseDelegate couchDelegate = new ICouchbaseDelegate() {
  @Override
  public void exit(String error) {
    // Show the error to the user
  }

  @Override
  public void couchbaseStarted(String host, int port) {
    // CouchDb has started, set up your connector
    // in our case initialise Ektorp
    startEktorp(host, port);
  }
};
</pre></p>
<p>Now we&#8217;ll actually request for CouchDb to be started, referencing the delegate we created above. In my case I&#8217;m calling this when the activity starts.</p>
<p><pre class="brush: java;">
private void startCouch() {
  CouchbaseMobile couch = new CouchbaseMobile(
    getBaseContext(), couchDelegate
  );
  couchConnection = couch.startCouchbase();
}
</pre></p>
<p>CouchbaseMobile will do its magic and eventually call your delegate.</p>
<h3>Connecting to the database</h3>
<p>Now that CouchDb has started, we&#8217;ll connect using the host and port the delegate gave us.</p>
<p><pre class="brush: java;">
clientBuilder = new AndroidHttpClient.Builder();
httpClient = (AndroidHttpClient)clientBuilder
  .host(host)
  .port(port)
  .build();
dbInstance = new StdCouchDbInstance(httpClient);
// The last parameter true will create the database
// if it doesn't exist.
dbConnector = dbInstance.createConnector(DATABASE_NAME, true);
</pre></p>
<p>The dbConnector is now ready for normal database use. Let the CRUD begin.</p>
<h3>Creating the initial design documents</h3>
<p>CouchDb is pretty useless without a view over your data (unless you know ids or want to just work with all documents). So after CouchDb has started you should create (or update) the design documents specifying your views.</p>
<p><pre class="brush: java;">
designDocId = &quot;_design/slyncy&quot;;
byNameView = &quot;byName&quot;;
byNameMap = &quot;function(doc) {if (doc.name) emit(doc.name, doc);}&quot;;
DesignDocument dDoc = new DesignDocument(designDocId);
dDoc.addView(byNameView, new DesignDocument.View(
  byNameMap
));
dbConnector.create(dDoc);
</pre></p>
<h3>Putting a list adapter on top of the view</h3>
<p>Assuming you&#8217;re displaying the data in a list, you&#8217;d want to wrap a view in a custom CouchbaseViewListAdapter. There&#8217;s a horrible implementation in the example code showing basic view mapping.</p>
<p><pre class="brush: java;">
ViewQuery query = new ViewQuery()
  .designDocId(designDocId)
  .viewName(byNameViewName)
  .descending(true);

// The third parameter specifies that you should listen to
// the _changes feed from CouchDb enabling this means the
// list will automatically update for you when data changes
adapter = new CouchbaseViewListAdapterImpl(
  dbConnector, query, true
);
</pre></p>
<p>The final parameter (_changes: true) is pretty powerful. It works like Android content provider data change notifications, allowing the list to update when the data changes. Delete a document and it will be removed from the list.</p>
<p>Something Ektorp is missing with their base CouchbaseViewListAdapter class is support for include_docs when querying the view. This means your document will have to be emitted as an indexed value, which could lead to obese indexes if your data set is big enough.</p>
<h3>Starting replication</h3>
<p>Starting replication is pretty simple. You build a ReplicationCommand, specifying the source, target and continuous (once until complete (false), or continually run until shut down (true)).</p>
<p><pre class="brush: java;">
pushReplicationCommand = new ReplicationCommand.Builder()
  .source(DATABASE_NAME)
  .target(syncUrl)
  .continuous(true)
  .build();

EktorpAsyncTask pushReplication = new EktorpAsyncTask() {
  @Override
  protected void doInBackground() {
    dbInstance.replicate(pushReplicationCommand);
  }
};
pushReplication.execute();
</pre></p>
<p>Switch the source and target around for pull replication. Depending on how your system is you would probably want both (user updates -&gt; server, server updates -&gt; user).</p>
<h3>CRUD</h3>
<p>After the connection is set up, CRUD is simple. You just call create/update on a document (where document is a Map in my case), or delete with a given id and revision.</p>
<p><pre class="brush: java;">
dbConnector.create(document);
dbConnector.get(Map.class, id);
dbConnector.update(document);
dbConnector.delete(id, revision);
</pre></p>
<h3>Summing up</h3>
<p><img class="alignleft size-full wp-image-1516" title="Easy Peasy" src="http://shinetechblog.files.wordpress.com/2011/11/easypeasy.jpg?w=640" alt=""   />So, as you can see, connecting to CouchDb on Android is fairly simple, if a little verbose, but that&#8217;s the Java way.</p>
<p>You can find a working (you know, sometimes) example application <a title="here" href="https://github.com/dbrain/slyncy" target="_blank">here</a>, based on <a title="AndroidGrocerySync" href="https://github.com/couchbaselabs/AndroidGrocerySync" target="_blank">AndroidGrocerySync</a>.</p>
<h2>Concerns</h2>
<h3><img class="alignleft size-full wp-image-1510" title="Scared Orangutan" src="http://shinetechblog.files.wordpress.com/2011/11/scared-orangutan.jpg?w=640" alt=""   />Data Security</h3>
<p>Sure, replication sounds dandy, but how do I stop the user replicating changes of documents they don&#8217;t own?</p>
<p>CouchDb has a method for this called <a title="Validation Functions" href="http://guide.couchdb.org/draft/validation.html" target="_blank">Validation Functions</a>. Basically you can define a Javascript function that will look at an update and allow you to reject the change. The last parameter of these functions is a user context. So using this you can work out who&#8217;s writing and if their write is valid. For example:</p>
<p><pre class="brush: jscript;">
function (newDoc, savedDoc, userCtx) {
  if (savedDoc) {
    // This is an update, make sure the user
    // isn't watching the world burn.
    if (newDoc.userName !== userCtx.name) {
      throw({ unauthorised: 'You shall not pass ' + userCtx.name });
    }
  }
}
</pre></p>
<h3>Internal phone security</h3>
<p>A completely uninformed concern (I&#8217;m sure Couchbase has thought of it) is security from other applications running on the phone. What if you have private data you don&#8217;t want Mr Naughty&#8217;s application to push to his cloud of deceit?</p>
<p>Completely based on a Stack Overflow thread <a title="here" href="http://stackoverflow.com/questions/5670131/couchdb-security-for-android-devices-and-ios" target="_blank">here</a>, it seems that connecting to Couch and access the database itself is secure enough, but the data is written to external storage, which isn&#8217;t secure at all.</p>
<h2>Conclusion</h2>
<p>I&#8217;ll sum it up in pros and cons form.</p>
<h3><img class="size-thumbnail wp-image-1517 alignleft" title="Good News Everyone" src="http://shinetechblog.files.wordpress.com/2011/11/good-news-everyone.png?w=150&h=120" alt="" width="150" height="120" />Pros:</h3>
<ul>
<li>CouchDb on Android makes replication easy. It&#8217;s basically allout of the box, just point and say go</li>
<li>The JSON strucure of CouchDb documents gives your application a lot of flexibility and a nice way to store data.</li>
<li>The actual code behind it isn&#8217;t too painful or that far away from &#8216;typical Android&#8217; code.</li>
</ul>
<h3><img class="alignleft size-thumbnail wp-image-1518" title="Bender" src="http://shinetechblog.files.wordpress.com/2011/11/cons.jpg?w=150&h=150" alt="" width="150" height="150" />Cons:</h3>
<ul>
<li>Starting up CouchDb is slow, from what I&#8217;ve heard mostly due to loading an Erlang interpeter. You&#8217;ll see the lag between starting the application and initialising CouchDb if you run the example application</li>
<li>Map/Reduce while providing some friendliness also removes the possibility of on the fly SQL style queries</li>
<li>Packaging CouchDb with your application adds about 10mb of bloat to your installation.</li>
</ul>
<p>All up I&#8217;ll give it 3.33 out of 5 overly intelligent mice, ready to take over the world.<br />
<img class="aligncenter size-full wp-image-1512" title="3.33 Out Of 5" src="http://shinetechblog.files.wordpress.com/2011/11/3-33outof5.gif?w=640" alt=""   /></p>
<h3>Links / More interesting reads:</h3>
<ul>
<li>Example Github project: <a title="https://github.com/dbrain/slyncy" href="https://github.com/dbrain/slyncy" target="_blank">https://github.com/dbrain/slyncy</a></li>
<li>A nice setup guide <a title="here" href="http://www.couchbase.org/wiki/display/membase/Getting+Started+with+Android+and+CouchDB" target="_blank">here</a></li>
</ul>
<p><strong>Note</strong>: Images randomly pilfered from Google Image Search.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/1479/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/1479/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/1479/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/1479/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/1479/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/1479/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/1479/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/1479/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/1479/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/1479/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/1479/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/1479/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/1479/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/1479/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1479&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2011/11/14/couchdb-on-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/aa2b7b475f8b31201696bfbe160dca86?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">danielbrainshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/android-on-couchdb.jpg?w=300" medium="image">
			<media:title type="html">Android on Couch</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/doctor-whatisthis.jpeg" medium="image">
			<media:title type="html">Doctor What Is This</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/mapreduce.jpg?w=150" medium="image">
			<media:title type="html">MapReduce</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/obesecat.jpg?w=300" medium="image">
			<media:title type="html">Obese Cat</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/10-points-for-reference.jpg" medium="image">
			<media:title type="html">Replicators</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/magic-happening.jpg?w=256" medium="image">
			<media:title type="html">Magic Happening</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/super-duper-programmer.jpg" medium="image">
			<media:title type="html">Super Duper Programmer</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/easypeasy.jpg" medium="image">
			<media:title type="html">Easy Peasy</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/scared-orangutan.jpg" medium="image">
			<media:title type="html">Scared Orangutan</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/good-news-everyone.png?w=150" medium="image">
			<media:title type="html">Good News Everyone</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/cons.jpg?w=150" medium="image">
			<media:title type="html">Bender</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/11/3-33outof5.gif" medium="image">
			<media:title type="html">3.33 Out Of 5</media:title>
		</media:content>
	</item>
		<item>
		<title>A Good Look at Android Location Data</title>
		<link>http://blog.shinetech.com/2011/10/14/a-good-look-at-android-location-data/</link>
		<comments>http://blog.shinetech.com/2011/10/14/a-good-look-at-android-location-data/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 00:28:38 +0000</pubDate>
		<dc:creator>Marc Fasel</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Location Data]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=1439</guid>
		<description><![CDATA[Getting started with the development of location-based services on Android is relatively easy thanks to the well documented location API. However, getting more serious shows there is still much uncharted territory. One such area concerns the accuracy of real-life location data, which &#8230; <a href="http://blog.shinetech.com/2011/10/14/a-good-look-at-android-location-data/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1439&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div style="float:left;"><img class="alignleft size-full wp-image-1457" title="android_logo" src="http://shinetechblog.files.wordpress.com/2011/10/android_logo.png?w=640" alt=""   /></div>
<p dir="ltr">Getting started with the development of location-based services on Android is relatively easy thanks to the <a href="http://developer.android.com/guide/topics/location/obtaining-user-location.html" target="_blank">well</a> <a href="http://android-developers.blogspot.com/2011/06/deep-dive-into-location.html" target="_blank">documented</a> <a href="http://www.vogella.de/articles/AndroidLocationAPI/article.html" target="_blank">location API</a>. However, getting more serious shows there is still much uncharted territory. One such area concerns the accuracy of real-life location data, which I have recently taken a close look at. In short, location data can be far more accurate than Google&#8217;s conservative estimates &#8211; at least with the phone that I used.</p>
<p dir="ltr"><span id="more-1439"></span>The Android developer documentation gives estimates on expected accuracy of the location data. This estimate varies according to the location provider used. Android distinguishes two location provider types with the following accuracy:</p>
<ul>
<li>Fine-grained location provider like the GPS provider with an accuracy of less than 100 m.</li>
<li>Coarse-grained location provider like the network location provider with an accuracy of 100 &#8211; 500 m</li>
</ul>
<p dir="ltr">One look at the Google Maps application makes it clear that the estimates for the accuracy are very conservative: in many cases the user location is shown on Google Maps with an accuracy of a few meters, much better than the estimates stated above.</p>
<p dir="ltr">My interest is in the individual accuracy of real-world data rather than an average accuracy estimate. Each time a location provider sends a location update, the accuracy of this individual location is given as well. In this article I look at this accuracy as reported by the location provider, and  compare the location accuracy of the two main location providers to actual locations.</p>
<h2 id="internal-source-marker_0.012480390258133411">Location Providers</h2>
<p dir="ltr">Location providers are the sources of location data in Android. Even though the Android API specifies location providers in a very generic way, in practice there are two main location providers: The GPS location provider and the network location provider. Because they use different ways to obtain location data they differ in accuracy, minimum notification interval, time to first fix (TTFF), and battery consumption.</p>
<p dir="ltr">The way you receive location information in Android is to register a Location Listener with the Location Manager. At registration the location provider, notification interval and notification distance have to be specified:</p>
<p><code>locationManager.requestLocationUpdates(provider, notificationInterval, notificationDistance, locationListener);</code></p>
<p dir="ltr">The Location Manager  will call the <code>onLocationChanged()</code> method of the listener if the distance since the last location update for the registered location provider is greater then the <code>notificationDistance</code>, or the time since last location update is greater than the <code>notificationInterval</code>.</p>
<div>
<h2 id="internal-source-marker_0.012480390258133411">GPS Location Provider</h2>
<p dir="ltr">The most obvious location provider is the GPS. GPS provides data with high accuracy: Less than 100 m is the official number, but real accuracy is often around 2 m &#8211; 20 m. Once it is connected to satellites it can provide location updates in intervals as short as a few seconds.</p>
<p dir="ltr">Sounds like an ideal location provider, but the GPS also has its draw-backs. For one, the initial connection to the satellites &#8211; Time to First Fix (TTFF) &#8211; can be quite slow. GPS traditionally needs to connect to at least three satellites for a 2D location, and initial transmission of so-called Ephemeris data takes a minimum of 30 seconds for a satellite. Once the Ephemeris data has been transmitted and connection to the satellite is made, location updates are very fast.</p>
<p dir="ltr">To speed up the TTFF, manufacturers have come up with a new way to deliver the initial Ephemeris data to the GPS: They use an Internet connection to deliver the data much faster than the transmission from the satellite. Android uses this so-called Assisted GPS (A-GPS) to speed up TTFF to 5-15 seconds, but only if you have an Internet connection.</p>
<p dir="ltr">Another draw-back of the GPS provider is that the battery consumption is quite high, and continued use of the the GPS will drain the battery. Even though GPS location updates can be received every few seconds, the Android developers guide recommends update intervals for the GPS of greater than 10 minutes. This limits the type of applications that can benefit from using the GPS.</p>
<p dir="ltr">Last but not least: Since GPS uses a radio signal, solid objects &#8211; especially those made from metal &#8211; will obstruct the signal. In practice, this means the GPS will not work in most buildings (GPS is not affected by clouds, rain, or snow, though).</p>
<p dir="ltr"><span class="Apple-style-span" style="color:#000000;font-size:17px;line-height:25px;">Accuracy</span></p>
<div>
<div>
<p dir="ltr">Each location update from a location provider comes with the accuracy of the data in meters. This accuracy is given for each location update. To visualise the location data and the accuracy for each location I wrote an Android application that records the location data in a database. Drawing the recorded data on a Google Map helps visualise the data. The following map shows the data recorded for the GPS provider during a walk through Melbourne.</p>
<div id="attachment_1444" class="wp-caption aligncenter" style="width: 650px"><a href="http://shinetechblog.files.wordpress.com/2011/10/walkaboutgps.png"><img class="size-full wp-image-1444" title="GPS Location Data" src="http://shinetechblog.files.wordpress.com/2011/10/walkaboutgps.png?w=640&h=541" alt="" width="640" height="541" /></a><p class="wp-caption-text">GPS provider data compared to actual location</p></div>
<div>
<p id="internal-source-marker_0.5163292873185128" dir="ltr">The black line is the actual path I took during the walk. The white dots are the locations recorded by the GPS provider, while the red circles around the dots indicate the accuracy per location as reported by the GPS provider.</p>
<p dir="ltr">As expected the accuracy of the GPS provider is quite good: Most of the time the accuracy is within 30 m, some times as good as 2 m. That is much better than the conservative estimate of less than 100 m stated in the documentation.</p>
<p dir="ltr">An interesting observation is that sometimes the actual location is not within the circle of accuracy given by the GPS provider. The location marked with 1 on the map is about 25 m off the actual location, with an accuracy radius of about 5 m. Even with the radius of accuracy the result is still 20 m off the actual location.</p>
<p dir="ltr">Another observation that shows the draw-back of the GPS: if we are indoors or have otherwise bad reception there may not be a GPS signal, which means the location is completely lost. Marker 2 shows a section of the walk without any GPS signal. First I walked through a building from the Flight Centre to the cafe “The Journal”. Even after I passed though this building and walked down down the narrow Flinders Lane the GPS reception didn’t improve, so there are no readings at all during this time.</p>
<div>
<h2 id="internal-source-marker_0.5163292873185128">Network Location Provider</h2>
<p dir="ltr">The network location provider uses both WiFi hotspots and cell towers known to the Android device to approximate a location of a user. When the location provider is polled, the IDs of the WiFi hotspots and cell towers in the area are sent via Internet to the Google Location Server, a database with location information on WiFi hotspots and cell towers. Google Location Server returns an approximate location of the user.</p>
<p dir="ltr">The data comes from a combination of cell and WiFi hotspot information, and can only be obtained when the device can access the Internet to query the Google Location Server. Accuracy of the data is specified somewhere between 100 m &#8211; 1000 m depending on the information available. WiFi hotspots allow an accuracy of 100 m &#8211; 500 m, while cell towers only allow for an accuracy greater 500 m. This means the network provider will be very inaccurate in areas without WiFi hotspots. Conversely, the more hotspots and cell towers are in the area the greater the accuracy.</p>
<p dir="ltr">The network provider can give first location results within seconds. This is much faster than the GPS location provider, which even using A-GPS may take up to a minute to give back first results.</p>
<div>
<h3>Accuracy</h3>
<p dir="ltr">The following map visualises data recorded for the network provider when walking through Melbourne.</p>
<div id="attachment_1447" class="wp-caption aligncenter" style="width: 650px"><a href="http://shinetechblog.files.wordpress.com/2011/10/walkaboutnetwork.png"><img class="size-full wp-image-1447" title="Network Provider Data" src="http://shinetechblog.files.wordpress.com/2011/10/walkaboutnetwork.png?w=640&h=521" alt="" width="640" height="521" /></a><p class="wp-caption-text">Network provider data compared to actual location</p></div>
<div>
<p dir="ltr">The black line again is the actual path taken, while the white dots are the locations recorded by the network provider. The turquoise circles indicate the accuracy reported by the network provider. The walk took about 30 minutes, during that time 16 points where within a reasonable accuracy (I discarded those points with an accuracy of greater than 100 m as too inaccurate, just to make the map clearer).</p>
<p dir="ltr">The map shows that at least in an urban area the network provider gives enough data with an accuracy of less than 100 m. Most of them were actually in the area of 50 m. This is not as good as the GPS, but still quite impressive. The network provider also has number of advantages over the GPS: It works both indoors and outdoors, starts up quickly, and doesn’t drain the battery.</p>
<h3>WiFi Hotspot Location Data</h3>
<p dir="ltr">During recording of the data I stumbled across an interesting anomaly: The network location provider put me in a totally different location than where I actually was. Curiously this happened every time I connected to my WiFi hotspot at home.</p>
<div id="attachment_1448" class="wp-caption aligncenter" style="width: 397px"><a href="http://shinetechblog.files.wordpress.com/2011/10/wrongnetworklocation.png"><img class="size-full wp-image-1448" title="Wrong WiFi Hotspot Location" src="http://shinetechblog.files.wordpress.com/2011/10/wrongnetworklocation.png?w=640" alt=""   /></a><p class="wp-caption-text">Wrong WiFi Hotspot Location</p></div>
<div>
<p id="internal-source-marker_0.5163292873185128" dir="ltr">The location marked with 1 is near my home, while the location marked with 2 is the place where I used to live. Once I arrived home the network provider placed me in location 2 instead of near location 1. Apparently Google thought I was in my old home once I logged into my home network, because it had previously registered the location of my WiFi hotspot in location 2.</p>
<p dir="ltr">This made me think about how Google actually obtains the location of a WiFi hotspot. It used to be possible to register the location of your WiFi hotspot with Google by hand. This option apparently does not exist anymore. As this <a href="http://android.stackexchange.com/questions/4715/how-may-i-submit-a-wifi-hotspot-to-androids-database-for-a-better-triangulation" target="_blank">discussion</a> shows, the data for the <strong>network provider</strong> actually comes from data Android <strong>GPS providers</strong> sent to the Google Location Server at some other time:</p>
<blockquote>
<p dir="ltr">“[...] before the GPS acquires a &#8220;fix&#8221;, Android will send the Wifi&#8217;s MAC/SSID and Cell Tower base stations CID/LAC around you to Google&#8217;s server and Google&#8217;s server will send back your location information; after the GPS acquires a &#8220;fix&#8221;, your device will send the Wifi MAC/SSID, Cell Tower CID/LAC, and your GPS location to Google&#8217;s server and Google&#8217;s server will collect this information to refine their own Wifi database.”</p>
</blockquote>
<p dir="ltr">The discussion also shows an Email reply from a Google employee stating that updating location information on WiFi hotspots is done automatically when a GPS provider sends new location data, but “<em>may require a significant amount of data from you and other users before changes are made to Google&#8217;s location database</em>”.  That explains why my WiFi hotspot is still registered at my old home in the Google Location Server.</p>
<div>
<h2 id="internal-source-marker_0.5163292873185128">Conclusion</h2>
<p dir="ltr">Comparing the location data received from the location providers with the actual location data shows that both location providers are much better in accuracy than the conservative estimates of the documentation.</p>
<p dir="ltr">For the hightest accuracy the GPS provider needs to be used, but is not suitable for all situations. The limitation of GPS to outdoor use is quite constraining, as is the battery consumption and TTFF, especially when used without A-GPS.</p>
<p id="internal-source-marker_0.5163292873185128" dir="ltr">The results of network provider for me came as a surprise: It is quite accurate while doing without the draw-backs of GPS like power-consumption,  TTFF, and restriction to outdoor use. It does lead to large inaccuracies in areas without WiFi hotspots.</p>
<p dir="ltr">Clearly a combination of both provides will yield the best results. How they are mixed depends on the application. A foreground application with emphasis on accuracy would use the GPS provider as the primary provider, with the network provider as a backup, while a background application with emphasis on low power consumption would use the network provider as its primary location provider with the GPS as a backup. Varying the update intervals allows fine-tuning the providers to a specific application.</p>
<p dir="ltr"><span class="Apple-style-span" style="color:#000000;font-size:22px;line-height:32px;">Code</span></p>
<p>If you want to have a look at the location data on your Android device I have uploaded the code to <a href="https://github.com/marcfasel/LocationMapper" target="_blank">GitHub</a>. It consists of an Android application that records the data as well as an HTML page that displays the data on Google Maps.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/1439/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/1439/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/1439/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/1439/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/1439/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/1439/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/1439/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/1439/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/1439/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/1439/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/1439/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/1439/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/1439/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/1439/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1439&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2011/10/14/a-good-look-at-android-location-data/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b6fce92508146cc8d095ed11ebacfbd7?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">marcfaselshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/10/android_logo.png" medium="image">
			<media:title type="html">android_logo</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/10/walkaboutgps.png" medium="image">
			<media:title type="html">GPS Location Data</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/10/walkaboutnetwork.png" medium="image">
			<media:title type="html">Network Provider Data</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/10/wrongnetworklocation.png" medium="image">
			<media:title type="html">Wrong WiFi Hotspot Location</media:title>
		</media:content>
	</item>
		<item>
		<title>Swipe Conference Highlights: Gamification</title>
		<link>http://blog.shinetech.com/2011/09/09/swipe-conference-highlights-gamification/</link>
		<comments>http://blog.shinetech.com/2011/09/09/swipe-conference-highlights-gamification/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 07:07:10 +0000</pubDate>
		<dc:creator>Michael Gillies</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Opinion]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=1384</guid>
		<description><![CDATA[Of the many excellent sessions at this week&#8217;s Swipe Conference, the one titled &#8220;Build Better Cocoa Apps Using Game Mechanics&#8221; by Paris Buttfield-Addison was unique in its topic. In it, Paris outlined how gamification is currently viewed as something that can be &#8230; <a href="http://blog.shinetech.com/2011/09/09/swipe-conference-highlights-gamification/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1384&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://shinetechblog.files.wordpress.com/2011/09/swipe.png?w=640&amp;h=213" alt="Swipe Conference" /></p>
<p>Of the many excellent sessions at this week&#8217;s <a href="http://swipeconference.com.au/">Swipe Conference</a>, the one titled &#8220;Build Better Cocoa Apps Using Game Mechanics&#8221; by Paris Buttfield-Addison was unique in its topic. In it, Paris outlined how gamification is currently viewed as something that can be quickly slapped onto an existing product in order to increase its appeal, whereas in reality, successful gamification requires carefully thought-out integration, for when done correctly it should form a core part of your app&#8217;s user experience.<br />
<span id="more-1384"></span><br />
In case you&#8217;re new to the concept, <a href="http://en.wikipedia.org/wiki/Gamification">gamification</a> is the application of game-like mechanics to non-game products in an effort to increase engagement with the user, motivating them to spend more time or money on your product.</p>
<p>The current trend in gamification is rather worrying, with seemingly everyone adding it to the list of things their product needs &#8211; as though it were a requirement for being successful. The reality of the situation is that these &#8216;gamification grafts&#8217; do nothing to enhance the user experience at all, providing mainly virtual badges for completing rather menial tasks &#8211; for example, pushing a button. This lack of challenge contributes to a failure to keep a user engaged, for they quickly become bored and move on.</p>
<p>A better approach to gamification would be to find a way to enhance the core functionality through the use of game-like mechanics. An example of successful gamification is <a href="http://stackoverflow.com/">Stack Overflow</a>. The core functionality is to provide people with a place to both ask and answer questions. However, game play elements come into it by rewarding users with a reputation system; the more you participate on the site, the more your reputation increases. Your reputation is then an indication of how helpful you are in the community. With higher reputation comes privileges that extend to helping with moderation of the site. This reputation system sets itself up in a unique way so that it encourages people to actively take part in the community and rewards them in the process.</p>
<p>Perhaps the most important point that was made during Paris&#8217; session was that not all products are suited to gamification. An app that displays the weather has no use for leader boards or an elaborate point system &#8211; they bring nothing meaningful to the user experience. However something like Foursquare, whose core functionality is to provide you with a means of sharing your location with others, benefits greatly from the addition of game play elements, effectively turning an otherwise dull concept into an engaging experience that rewards and encourages exploration of your surroundings.</p>
<p>In conclusion, the concept of gamification is definitely here to stay, but as developers and designers, we need to be vigilant and not give in to the urge to simply slap on a half-baked implementation. Instead we need to take the extra time to evaluate if it will actually enhance the existing user experience.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/1384/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1384&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2011/09/09/swipe-conference-highlights-gamification/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/088a5cf14ded31a969394544d7df1789?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">michaelgilliesshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/swipe.png?w=640&#38;h=213" medium="image">
			<media:title type="html">Swipe Conference</media:title>
		</media:content>
	</item>
		<item>
		<title>iOS Developers and Designers: Stickin&#8217; together is what good waffles do!</title>
		<link>http://blog.shinetech.com/2011/09/09/expanding-team-member%e2%80%99s-responsibilities-for-high-quality-iphone-experiences/</link>
		<comments>http://blog.shinetech.com/2011/09/09/expanding-team-member%e2%80%99s-responsibilities-for-high-quality-iphone-experiences/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 06:45:14 +0000</pubDate>
		<dc:creator>Chaise Hocking</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Opinion]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=1396</guid>
		<description><![CDATA[We’ve all heard developers say it: “I’m a terrible drawer” or “I’ve got no design skills”. Perhaps we’re even guilty of saying it ourselves &#8211; I know I am. But after attending this year’s Swipe Conference I now subscribe to &#8230; <a href="http://blog.shinetech.com/2011/09/09/expanding-team-member%e2%80%99s-responsibilities-for-high-quality-iphone-experiences/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1396&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://shinetechblog.files.wordpress.com/2011/09/simp01.jpg"><img class="alignnone size-full wp-image-1432" title="simp01" src="http://shinetechblog.files.wordpress.com/2011/09/simp01.jpg?w=640" alt=""   /></a></p>
<p>We’ve all heard developers say it: “I’m a terrible drawer” or “I’ve got no design skills”. Perhaps we’re even guilty of saying it ourselves &#8211; I know I am. But after attending this year’s <a href="http://swipeconference.com.au/">Swipe Conference</a> I now subscribe to the opinion that this is no longer acceptable. We are all responsible for the design of the app we are building; developer, designer, tester, or producer: every member of the team is accountable for helping shape the app’s design and interactions.<span id="more-1396"></span></p>
<div id="attachment_1411" class="wp-caption alignnone" style="width: 609px"><a href="http://shinetechblog.files.wordpress.com/2011/09/oldcollab.png"><img class="size-full wp-image-1411" title="The usual way of collaborating" src="http://shinetechblog.files.wordpress.com/2011/09/oldcollab.png?w=640" alt=""   /></a><p class="wp-caption-text">For far too long this has represented how teams have collaborated.</p></div>
<p><strong>Why must we all be accountable?</strong></p>
<p>We &#8211; as developers &#8211; are iPhone experts. We know what can and can’t be done technically. We have toyed with and tried building (with both successes and failures) many ideas before. But before that, we are users; in fact, not just users but experienced <em>super</em> users. Sure we know how to code, but this is really just a small part of creating an app with an amazing user experience.</p>
<p><strong>But I can&#8217;t draw</strong></p>
<p>During the Swipe Conference we had a 30-minute session that addressed this exact problem. But the fact is, that it’s not a problem at all. When talking about working together to help build an intuitive interactive app, I’m not talking about creating the entire visual representation of your app. I’m talking about presenting ideas, and thinking through them as a team.</p>
<p>This 30-minute session taught us such a simple lesson, how to use a pen, how to draw a basic shape, a square, a circle, and how to colour them in. This is all you need to do, in order to present your ideas to the team. Sketch some simple shapes that represent the objects in your app, shade the background to bring the elements to the front, and colour them in. It’s simpler than a picture you would have drawn in kindergarten. “I can’t draw” is not an excuse!</p>
<p><strong>So I’ve drawn my picture, now what?</strong></p>
<p>At the end of this session, we were all encouraged to hand in the sketches of the iPhone interfaces that we had created. The organisers then took these sketches and stuck them up on the wall. And guess what, with just a black pen, a grey texta, and an orange texta (the swipe conference colour), we had hundreds of ideas that both conveyed an idea and were immediately understandable.</p>
<p>Just as we were able to do at Swipe Conference, everyone in an iPhone team can and must spend time doing the same thing. Pin your ideas on a wall, tear them down, change them, evolve them, give feedback, and work together to evolve from an infinite number of ideas from each team member into one highly refined and fantastic experience.</p>
<p><strong>Brilliant apps with intuitive interactions</strong></p>
<div id="attachment_1412" class="wp-caption alignnone" style="width: 436px"><a href="http://shinetechblog.files.wordpress.com/2011/09/newcollab.png"><img class="size-full wp-image-1412" title="The Required Way of Collaborating" src="http://shinetechblog.files.wordpress.com/2011/09/newcollab.png?w=640" alt=""   /></a><p class="wp-caption-text">This is how we need to think about working</p></div>
<p>By having a team where everyone can provide input, we help to create an experience that can only be beneficial. I know from some of the projects I’ve worked on, that it can be increasingly frustrating when you&#8217;re involved building the inner workings of the app, but cannot influence its overall direction. With such a great device to work on, and the potential it provides to user and developers alike, it would be a gross injustice to continue working in a counter productive way.</p>
<p>Let the designers turn your ideas into beautiful pixel-perfect designs, and let the developers transform these designs into interactive working interfaces &#8211; but also work together with everyone to allow your app to become a masterful interactive experience.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/1396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/1396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/1396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/1396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/1396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/1396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/1396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/1396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/1396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/1396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/1396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/1396/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/1396/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/1396/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1396&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2011/09/09/expanding-team-member%e2%80%99s-responsibilities-for-high-quality-iphone-experiences/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b5c1dc68b3374b9754e81f4414340112?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">chaisehockingshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/simp01.jpg" medium="image">
			<media:title type="html">simp01</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/oldcollab.png" medium="image">
			<media:title type="html">The usual way of collaborating</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/newcollab.png" medium="image">
			<media:title type="html">The Required Way of Collaborating</media:title>
		</media:content>
	</item>
		<item>
		<title>Swipe Conference Highlights: Using gestures as shortcuts within iOS apps</title>
		<link>http://blog.shinetech.com/2011/09/07/swipe-conference-highlights-using-gestures-as-shortcuts-within-ios-apps/</link>
		<comments>http://blog.shinetech.com/2011/09/07/swipe-conference-highlights-using-gestures-as-shortcuts-within-ios-apps/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 00:48:20 +0000</pubDate>
		<dc:creator>Shaun Ervine</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[swipeconference]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=1362</guid>
		<description><![CDATA[Yesterday was the last day of Swipe Conference so I thought I would take this time to reiterate one of the points I took from the first presentation by Josh Clark.  Josh covered quite a few topics and if you &#8230; <a href="http://blog.shinetech.com/2011/09/07/swipe-conference-highlights-using-gestures-as-shortcuts-within-ios-apps/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1362&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://shinetechblog.files.wordpress.com/2011/09/swipe.png"><img src="http://shinetechblog.files.wordpress.com/2011/09/swipe.png?w=640&h=213" alt="" title="swipe" width="640" height="213" class="alignnone size-full wp-image-1379" /></a></p>
<p>Yesterday was the last day of <a href="http://swipeconference.com.au/">Swipe Conference</a> so I thought I would take this time to reiterate one of the points I took from the first presentation by Josh Clark.  Josh covered quite a few topics and if you haven&#8217;t already you should check out his book <a href="http://oreilly.com/catalog/0636920001133">Tapworthy: Designing Great iPhone Apps</a>. </p>
<p>In short:</p>
<ul>
<li>Gestures can be brilliant … if the context they are used in feels natural</li>
<li>If you&#8217;re using gestures make sure your users will find them</li>
<li>If you don&#8217;t think your users will figure out your gestures easily, don&#8217;t overload your users with lots of help hints all at once; instead, let them &#8220;unlock&#8221; them over time, like a reward for using your app</li>
<li>Downside though is that there is no consensus on what a 3 finger swipe gesture might do. Every iOS app that uses this gestures decides it for themselves.</li>
</ul>
<p>It was obvious from the way Josh presents that he has so much passion for touch / gesture based devices. What I personally took away from his presentation was that gestures can be awesome shortcuts within your app. In a lot of cases gestures are a natural progression with how we interact with real world items.<span id="more-1362"></span></p>
<p>So let&#8217;s drill in a little more to some of these points.</p>
<p><strong>Gestures are brilliant&#8230; if used in the correct context</strong></p>
<p>How cool are gestures?! As a developer I have the freedom to implement any gesture I want, to perform any actions I desire. But it&#8217;s not really that simple &#8211; you need to consider if the gesture you&#8217;re using makes sense for the functionally you&#8217;re tying it to. For example, do you believe your users will associate a cool 4 finger pinch gesture in your app with bringing up a feedback email form?</p>
<p>Bad example, I know &#8211; because of course you would say: thats just stupid; why would you do that?! But these are exactly the kind of questions we need to ask ourselves &#8211; not only as developers, but as UX designers.</p>
<p><strong>How will users learn your gestures?</strong></p>
<p>If you want to add a gesture to your app because it&#8217;s a cool shortcut, how are you going to let your users know those gestures exist within your app?</p>
<p>Take a look at Apple for example. Their iBook app allows a user to turn a page by swiping from right to left; and yet in Contacts app, performing this action will most likely prompt you to delete one of your contacts. This is just confusing to a user.</p>
<p>I highly recommend that you watch <a href="http://cathyshive.com/">Cathy Shive</a>&#8216;s presentation (when the Swipe Conference presentations are released &#8211; I will update this post when it happens). Cathy highlighted a lot of great reasons why it&#8217;s so important to get your metaphors right. If it looks like a book and doesn&#8217;t function at all like a book, then why are you making your app look like a book?</p>
<p>If the gesture you&#8217;re adding into your app is not something a user will instinctively know to try out, then you need to give them some hints to be able to find this shortcut.</p>
<p>There are a number ways you can do this:</p>
<ul>
<li>Possibly draw attention to the part of the app that has this gesture &#8211; maybe it could pulse for the first time to signify it is interactive</li>
<li>Perform an animation that hints to the type of gesture that may be used to replay something</li>
<li>If your app has quite a few shortcuts maybe only provide one hint each time the user starts up your app</li>
</ul>
<p>Don&#8217;t forget to give your users a chance to explore your app. Users love to explore. They may stumble upon your gestures themselves.</p>
<p><strong>Don&#8217;t overload your new users with &#8220;helpful&#8221; hint messages</strong></p>
<p>I really liked the example Josh highlighted, which was if you were to be given an in-depth explanation before you were to read a book, you would instantly feel like using a book was quite complicated. For example: you turn the page from left to right, you read from left to right (depending on culture) and when you reach the end of a line you jump down to the next line and continue; to bookmark you can fold over a page and return to it in the future; when done, simply close the book (there&#8217;s a funny explanatory diagram along similar lines that you can find <a href="http://www.subtraction.com/2011/03/28/an-illustration-for-stack-america">here</a>).</p>
<p>The same goes for an iOS app. Feel free to explore gestures; make use of them as shortcuts within your app, but if you need to explain to a user how to use your app, then don&#8217;t just throw up a big old welcome message that tells a user every gesture they can perform &#8211; I guarantee you they will glaze over it. If it looks and feels complicated, then you&#8217;re just putting off your users.</p>
<p>In short, ease your users into finding these hidden gems within your app.</p>
<p><strong>I hope swipeconf runs again next year!</strong></p>
<p>Swipe Conference was great! I had a great time and all the presenters were excellent. It was cool to see so many iOS developers / UX designers out there who are really trying to build the best iOS apps they can.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/1362/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/1362/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/1362/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/1362/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/1362/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/1362/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/1362/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/1362/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/1362/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/1362/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/1362/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/1362/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/1362/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/1362/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1362&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2011/09/07/swipe-conference-highlights-using-gestures-as-shortcuts-within-ios-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/c6bc2b8da920b22451e0c8c7a28f901b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">shaunervineshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/swipe.png" medium="image">
			<media:title type="html">swipe</media:title>
		</media:content>
	</item>
		<item>
		<title>Me Want Cookie: Session Handling with NetBiscuits Mobile Web Apps</title>
		<link>http://blog.shinetech.com/2011/09/06/me-want-cookie-session-handling-with-netbiscuits-mobile-web-apps/</link>
		<comments>http://blog.shinetech.com/2011/09/06/me-want-cookie-session-handling-with-netbiscuits-mobile-web-apps/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 06:55:26 +0000</pubDate>
		<dc:creator>Edward Calderon</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[netbiscuits]]></category>

		<guid isPermaLink="false">http://blog.shinetech.com/?p=1163</guid>
		<description><![CDATA[Shine was recently involved with helping a client bring an outsourced mobile web site in-house. The site was essentially a guide for browsing business and event information for cinemas, restaurants and bars in your area. Bringing this web site in-house &#8230; <a href="http://blog.shinetech.com/2011/09/06/me-want-cookie-session-handling-with-netbiscuits-mobile-web-apps/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1163&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://shinetechblog.files.wordpress.com/2011/09/cookie-monster.jpg"><img src="http://shinetechblog.files.wordpress.com/2011/09/cookie-monster.jpg?w=640" alt="" title="cookie-monster"   class="alignnone size-full wp-image-1357" /></a></p>
<p>Shine was recently involved with helping a client bring an outsourced mobile web site in-house. The site was essentially a guide for browsing business and event information for cinemas, restaurants and bars in your area. Bringing this web site in-house was mainly an exercise in re-writing the outsourced instance as a component to the client’s own internally developed <a title="http://nodejs.org" href="http://nodejs.org" target="_blank">NodeJS</a>/<a title="http://expressjs.com/" href="http://expressjs.com/" target="_blank">Express</a> app server (currently used to serve their main &#8211; non-mobile &#8211; web site). </p>
<p>The <a title="http://www.netbiscuits.com" href="http://www.netbiscuits.com" target="_blank">NetBiscuits</a> platform was used to handle all the device specific porting which allowed the development effort to focus almost entirely on business logic and backend data processing. The combined learning curve of NetBiscuit’s own markup language with Shine’s <a title="https://github.com/shinetech/jazz" href="https://github.com/shinetech/jazz" target="_blank">Jazz</a> template system was simple enough to make the presentation layer development a breeze. This blog will talk about the process involved in developing for NetBiscuits and some of the problems and solutions encountered on the way.<br />
<span id="more-1163"></span><br />
<strong>So what is NetBiscuits?</strong><br />
NetBiscuits is a hosted platform technology that enables web apps to reach mobile devices. It’s essentially a knowledge base that maps mobile devices and their browsers to a presentation profile, translating your mobile site into the format expected by whatever mobile client that is making the request.</p>
<p>It’s worth noting that the concept of porting web content to mobile devices and their browsers is big. Seriously. The impact of standardized mobile web development is perhaps lost on those of us who’ve never worked in it before. Where common web development concerns itself with compliance across 4 or 5 main browsers, mobile web development must cater to <a title="http://www.tera-wurfl.com/explore/" href="http://www.tera-wurfl.com/explore/" target="_blank">hundreds</a>. Even in the days when Nokia ruled the world the support and maintenance of mobile web apps for an ever-growing device list was not just for the final phase of a project but an ongoing full time job. </p>
<p>Maximizing your audience still means supporting the lowest denominator, but these days you can expect your low-end browsers to run javascript. This old school WAP and J2ME developer acknowledges that times have moved on but pays due credit to the people behind NetBiscuits and their mobile platform.</p>
<p><strong>Working with NetBiscuits</strong><br />
You develop your mobile web app in mostly the same way as any other web app with the difference that instead of dynamically generating HTML you’re generating <a title="http://www.netbiscuits.com/biscuitml-reference" href="http://www.netbiscuits.com/biscuitml-reference" target="_blank">BiscuitML</a>. Your production URL will point to your NetBiscuits account (hosted on their cloud) which in turn points to your app server.</p>
<div class="mceTemp mceIEcenter" style="text-align:center;">
<dl class="wp-caption aligncenter">
<dt class="wp-caption-dt"><a href="http://shinetechblog.files.wordpress.com/2011/09/simple_nb_flow.png"><img class="size-full wp-image-1165" title="simple_nb_flow" src="http://shinetechblog.files.wordpress.com/2011/09/simple_nb_flow.png?w=640&h=175" alt="simple_nb_flow" width="640" height="175" /></a></dt>
<dd class="wp-caption-dd">Simple Control Flow</dd>
</dl>
</div>
<p>For as long as your app server talks to the NetBiscuits platform in BML, NetBiscuits will talk fluently to all devices that hit your mobile site. This means your development efforts can focus purely on the business logic without the concern of tailoring content to multiple screen sizes and browser types.</p>
<div class="mceTemp mceIEcenter" style="text-align:center;">
<dl class="wp-caption aligncenter">
<dt class="wp-caption-dt"><a href="http://shinetechblog.files.wordpress.com/2011/09/detailed_nb_flow.png"><img class="size-full wp-image-1164" title="detailed_nb_flow" src="http://shinetechblog.files.wordpress.com/2011/09/detailed_nb_flow.png?w=640&h=192" alt="Detailed NetBiscuits Control Flow" width="640" height="192" /></a></dt>
<dd class="wp-caption-dd">Detailed Control Flow</dd>
</dl>
</div>
<p>So what can you do with BML? Pretty much everything you can do with HTML. For most of the devices hitting your mobile site NetBiscuits will convert your BML to HTML. Writing markup in BML is done with Biscuit tags that comprise of familiar page elements such as; list, table, form, image etc. More specialised tags are available to handle ad-banners, analytics, maps and media. A script tag exists to provide various levels of javascript support ranging from handling browser events completely within the markup to simply relying on an external js file.</p>
<p><strong>Challenges with Session Handling</strong><br />
Environmental constraints meant that client side session management was the only option available. This in turn meant that support for cookies and javascript was a requirement for any browser hitting the site. Cookies would store the user’s state code (see below) and the preferred list of cinema venues for returning movie times.</p>
<p><pre class="brush: xml;">
&lt;TEXT&gt;
    &lt;richtext&gt;
        Select your state:[br]
    &lt;/richtext&gt;
    ...
    &lt;richtext&gt;
        &lt;event type=&quot;onclick&quot;&gt;
            &lt;!-- Custom set cookie function --&gt;
            &lt;action eval=&quot;setStateCodeCookie('VIC');&quot; /&gt;
            &lt;action eval=&quot;return true;&quot; /&gt;
        &lt;/event&gt;
        [url=&quot;path/to/main/page/?{URLParams}&quot;]VIC[/url]
    &lt;/richtext&gt;
    ...
&lt;/TEXT&gt;

</pre></p>
<p>Maintaining sessions within cookies is certainly made easier in the Tomcat/JSP model where the HTTPSession interface provides easy access to user data. In such a scenario, session data are largely managed by the server and a user is identified by a cookie-stored session id. In our instance we ended up pulling session data directly from cookies after discovering some limitations with BML.</p>
<p>Amidst the wealth of documentation for BML and its rich internet features there were examples of how to get/set/delete cookies from script tags. This led us to the false belief that a cookie could be interrogated and manipulated fully from within the markup. Wrong. BML’s <code>getCookie</code> function exists only to test the presence of a cookie, not to read/extract its data. Cookie handling was therefore relegated to an external js file which also meant taking control away from the markup for certain browser events. Specifically, the <code>onclick</code> event had to be hijacked from certain anchor tags to implement redirects for re-written URLs.</p>
<p><pre class="brush: xml;">
&lt;TEXT&gt;
    &lt;richtext&gt;
        Find Movies:[br]
    &lt;/richtext&gt;
    ...
    &lt;richtext&gt;
        &lt;event type=&quot;onclick&quot;&gt;
            &lt;!-- Override default behaviour and use
                 an externally defined custom handler
                 to perform redirect --&gt;
            &lt;action eval=&quot;getPreferredCinemasForMovieSearch('{URLParams}');&quot; /&gt;
            &lt;action eval=&quot;return false;&quot; /&gt;
        &lt;/event&gt;
        [url=&quot;#&quot;]Browse by Cinemas[/url]
    &lt;/richtext&gt;
    ...
&lt;/TEXT&gt;
</pre></p>
<p><strong>Hijacking the Onclick Event</strong><br />
Retrieving a user’s cinema preferences (above) is one example of URL re-writing trickery. Retrieving their state code is another. A state code would populate all URLs presented to the user. New users would have their state code persisted in URL parameters for the duration of their session. Returning users would need their session initialised by extracting their state code from the cookie.</p>
<p>Since cookie data wasn’t available at BML generation time, extraction would have to happen at URL click time. So this meant triggering a javascript function on the browser using the anchor tag’s <code>onclick</code> event.</p>
<div class="mceTemp mceIEcenter" style="text-align:center;">
<dl class="wp-caption aligncenter">
<dt class="wp-caption-dt"><a href="http://shinetechblog.files.wordpress.com/2011/09/event_blackhole.png"><img class="size-full wp-image-1200" title="Cookie handling at onclick" src="http://shinetechblog.files.wordpress.com/2011/09/event_blackhole.png?w=640&h=181" alt="Cookie handling at onclick" width="640" height="181" /></a></dt>
<dd class="wp-caption-dd">Cookie handling at onclick</dd>
</dl>
</div>
<p>Performing cookie data extraction at ‘click time’ effectively turns the handler function into an event-swallowing black hole, since it must also perform the page redirect leaving no control to pass back to the browser and it’s anchor tags. A consequence is that any URL parameters normally processed within the markup must now be passed to the javascript function for re-writing to the URL.</p>
<p><strong>Ideals, Alternatives and Trade Offs</strong><br />
Relying on the BML to handle all things cookie/session related would have been the most ideal solution. URLs could have been re-written at BML generation time using cookie data without any javascript intervention. With the benefit of hindsight, the next best alternative would have been to utilize the <code>onload</code> event instead of hijacking the <code>onclick</code> event. This is because the <code>onload</code> event allows for the markup to retain control of its anchors – since re-writing happens well before URL click time.</p>
<p><a href="http://shinetechblog.files.wordpress.com/2011/09/session_handling1.png"><img class="aligncenter size-full wp-image-1193" title="session_handling" src="http://shinetechblog.files.wordpress.com/2011/09/session_handling1.png?w=640&h=402" alt="" width="640" height="402" /></a>This works fine for initialising a returning user’s state code since ALL URLs are modified with this data in the same way. However in situations where we needed to be more selective (extracting a user’s cinema preferences for only certain URLs), additional effort is required to identify/isolate the subset of URLs to operate on. Not all URLs need specific preference data appended to them. So the trade off is down to the assembly and redirect of URLs for a pre-determined anchor using the <code>onclick</code> method versus isolating a target set of anchors and appending data to an existing URL using the <code>onload</code> method.</p>
<p><pre class="brush: xml;">
&lt;page&gt;
    &lt;script&gt;
        &lt;event type=”onload”&gt;
            &lt;!-- Append cookie data to a
                 target set of anchor tags --&gt;
            &lt;action eval=&quot;appendCookieDataToTargetURLs('{cookieName}',
                                                       '{targetId}',
                                                       '{URLParams}');&quot; /&gt;
        &lt;/event&gt;
    &lt;/script&gt;
...
&lt;/page&gt;
</pre></p>
<p><strong>Conclusion</strong><br />
On the one hand it makes sense that BML can only provide superficial support for cookies given that its markup is never processed directly by the browser. On the other hand, if the NetBiscuits platform is communicating with client browsers and processing the BML on our behalf, could it not set its own session cookie and expose it through a set of functions within the markup? Where is NetBiscuit’s HTTPSession?! Perhaps the logistics of supporting potentially thousands of such sessions makes this concept infeasible.</p>
<p>To summarise, there may be further options available for enabling a mobile website that warrant a comparison but our experience with NetBiscuits was a happy and successful one. Cookie handling aside, the presentation layer development for our mobile app was super smooth. We also made use of a couple of the specialised tags for analytics and maps with relative ease.</p>
<p>The absence of full cookie support just means a little extra work. Perhaps we’ll see this built out in a future implementation of BML? In the meantime, its just old-school javascript know-how to enable cookie based sessions for your web apps. Of course, all this needs to be put in perspective with the main advantage provided by NetBiscuits: standardised mobile web development! Easy to overlook this significance when granted in such an accessible and ready-to-use format.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shinetechblog.wordpress.com/1163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shinetechblog.wordpress.com/1163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shinetechblog.wordpress.com/1163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/shinetechblog.wordpress.com/1163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/shinetechblog.wordpress.com/1163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/shinetechblog.wordpress.com/1163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/shinetechblog.wordpress.com/1163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/shinetechblog.wordpress.com/1163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/shinetechblog.wordpress.com/1163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/shinetechblog.wordpress.com/1163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/shinetechblog.wordpress.com/1163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/shinetechblog.wordpress.com/1163/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/shinetechblog.wordpress.com/1163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/shinetechblog.wordpress.com/1163/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shinetech.com&#038;blog=25494966&#038;post=1163&#038;subd=shinetechblog&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shinetech.com/2011/09/06/me-want-cookie-session-handling-with-netbiscuits-mobile-web-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e5c4cf41c760c1697460856b91db6a72?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">edwardcalderonshinetech</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/cookie-monster.jpg" medium="image">
			<media:title type="html">cookie-monster</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/simple_nb_flow.png" medium="image">
			<media:title type="html">simple_nb_flow</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/detailed_nb_flow.png" medium="image">
			<media:title type="html">detailed_nb_flow</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/event_blackhole.png" medium="image">
			<media:title type="html">Cookie handling at onclick</media:title>
		</media:content>

		<media:content url="http://shinetechblog.files.wordpress.com/2011/09/session_handling1.png" medium="image">
			<media:title type="html">session_handling</media:title>
		</media:content>
	</item>
	</channel>
</rss>
