<?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/"
	>

<channel>
	<title>Mark Kirby - Mobile Developer</title>
	<atom:link href="http://mark-kirby.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>http://mark-kirby.co.uk</link>
	<description>I&#039;m a user focused mobile developer, here is where I publish advice and thoughts on building great mobile apps</description>
	<lastBuildDate>Fri, 08 Mar 2013 10:46:28 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>2 &#8211; Learning the Ruby Basics, the right way &#124; From PHP hobbyist to pro Ruby developer course</title>
		<link>http://mark-kirby.co.uk/2013/2-learning-the-ruby-basics-the-right-way-from-php-hobbyist-to-pro-ruby-developer-course/</link>
		<comments>http://mark-kirby.co.uk/2013/2-learning-the-ruby-basics-the-right-way-from-php-hobbyist-to-pro-ruby-developer-course/#comments</comments>
		<pubDate>Thu, 28 Feb 2013 12:18:57 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=1216</guid>
		<description><![CDATA[This forms part of my &#8220;From PHP hobbyist to pro Ruby developer&#8221; course which I&#8217;m trialling at the moment with Remi. The purpose of this unit is to learn Ruby, and a little about professional code construction. The two books you will need are: The Well Grounded Rubyist, David A Black Clean Code, A handbook...]]></description>
				<content:encoded><![CDATA[<p>This forms part of my &#8220;From PHP hobbyist to pro Ruby developer&#8221; course which I&#8217;m trialling at the moment with <a href="http://rshergold.github.com">Remi</a>.</p>
<p>The purpose of this unit is to learn Ruby, and a little about professional code construction.</p>
<p>The two books you will need are:</p>
<ul>
<li>The Well Grounded Rubyist, David A Black</li>
<li>Clean Code, A handbook of Agile Software Craftsmanship, Robert C. Martin (Uncle Bob)</li>
</ul>
<h2>Read the books</h2>
<p>Don&#8217;t worry about code at this point, begin by reading the books and working through the examples. Ensure at a minimum you read the following chapters:</p>
<ul>
<li>The Well Grounded Rubyist, <strong>every chapter</strong></li>
<li>Clean code, chapters 1 &#8211; 7 + 1o</li>
</ul>
<p>Don&#8217;t be tempted to work through your own code at this point, just follow along with the examples. Don&#8217;t worry about committing everything to memory, or even understanding it all. This won&#8217;t be the last time you read these books, but will give you an overview and remind you where to look when you encounter problems these books can help with in the future.</p>
<h2>Devise your sample code project</h2>
<p>After reading the books, come up with a simple project that will test the code you&#8217;ve learnt, under the following constraints.</p>
<ul>
<li><span style="line-height: 13px;">It should be a command line app</span></li>
<li>It should collect some input from the user</li>
<li>It should process that input, perhaps along with some data collected from the web and stored in a flat file</li>
<li>It should return some data back</li>
<li>It should be simple enough to code within a day or so</li>
</ul>
<p>Discuss the project with me at this point if you wish.</p>
<h2>Implement the project, using the best practices you&#8217;ve learnt</h2>
<ul>
<li>Create a new public github project to store the code in.</li>
<li>Write the code using the best practices you&#8217;ve picked up from Clean Code, and the skills in the Ruby Book.</li>
<li>Use git as you go, committing each change using the process learnt in unit 1. Stick to master for now.</li>
</ul>
<p>Notify me when you are done, and I&#8217;ll review your code in git and set up a code review ready for you to move on to the next step.</p>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2013/2-learning-the-ruby-basics-the-right-way-from-php-hobbyist-to-pro-ruby-developer-course/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>From PHP hobbyist to pro Ruby developer course &#8211; 1, Setting up the hipster blog</title>
		<link>http://mark-kirby.co.uk/2013/from-php-hobbyist-to-pro-ruby-developer-course-1-setting-up-the-hipster-blog/</link>
		<comments>http://mark-kirby.co.uk/2013/from-php-hobbyist-to-pro-ruby-developer-course-1-setting-up-the-hipster-blog/#comments</comments>
		<pubDate>Fri, 22 Feb 2013 12:12:18 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=1209</guid>
		<description><![CDATA[This is the first part of a longer course I&#8217;m developing for an Intern I&#8217;ve hired who we are guiding through the process of becoming a &#8216;pro developer&#8217;. In time these notes will form part of a larger post. Ensure you are on a Mac or Linux machine None of this is going to work...]]></description>
				<content:encoded><![CDATA[<p>This is the first part of a longer course I&#8217;m developing for an Intern I&#8217;ve hired who we are guiding through the process of becoming a &#8216;pro developer&#8217;. In time these notes will form part of a larger post.</p>
<h2>Ensure you are on a Mac or Linux machine</h2>
<p>None of this is going to work if you are using Windows, so the first step is to install Linux. <a href="http://www.ubuntu.com/">Download the latest version of Ubuntu</a>, and get it installed on your PC.</p>
<h2>Setup a GitHub account</h2>
<p>If you don&#8217;t have one, <a href="https://github.com/">set up your GitHub account</a>, where you can store your code and show it off!</p>
<p>Ensure you have set up your .ssh public/private keys, there is <a href="https://help.github.com/articles/generating-ssh-keys">good documentation on GitHub</a>.</p>
<h2>Learn the basics of Git</h2>
<p><a href="http://try.github.com/levels/1/challenges/1">Working through this tutorial</a> will get you up and running, and handily, it focuses on Octopress as an example!</p>
<p><em>Use the <a href="http://www.codeschool.com/courses/try-git">Code School tutorial</a> after for a second perspective if you wish.</em></p>
<h2>Read the first chapter of The Well-Grounded Rubyist</h2>
<p>It helps to have an understanding of where Ruby stores files to enable you to happily install Octopress and its dependencies, so reading the first chapter of our core course text &#8211; The Well Grounded Rubyist will give you that grounding.</p>
<h2>Set up RVM</h2>
<p>Next you need to set up RVM to manage your gemsets and ruby versions. <a href="http://net.tutsplus.com/tutorials/why-you-should-use-rvm/">First follow this tutorial</a> which will explain why RVM is so useful and how to get started.</p>
<h2>Install and setup Octopress</h2>
<p>Octopress is blogging platform of choice for the cool kids. It lets you store all your posts in MarkDown and uses Git to keep them versioned. You can host it on Github Pages, Heroku or your own choice of platform.</p>
<ul>
<li><a href="http://octopress.org/docs/">Follow the standard guide</a>s &#8211; don&#8217;t forget to use RVM to set your gemset location and Ruby version.</li>
<li>Consider using <a href="http://pow.cx/">POW</a> if you haven&#8217;t already</li>
</ul>
<h2>Set up your plugins</h2>
<p>I recommend (sign up for an account if you haven&#8217;t already) hooking into:</p>
<ul>
<li><span style="line-height: 13px;">Twitter</span></li>
<li>Delicious</li>
<li>Github</li>
</ul>
<p>Get some content on them all first!</p>
<h2>Write your first blog post and publish</h2>
<p>Write your first post, on your starting point and current experience, and what your goals are after completing the course.</p>
<p>Write your second post on the process of setting up Octopress and RVM and your thoughts on the platforms so far.</p>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2013/from-php-hobbyist-to-pro-ruby-developer-course-1-setting-up-the-hipster-blog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby hosting in the cloud &#8211; Elastic Beanstalk vs Heroku vs EngineYard</title>
		<link>http://mark-kirby.co.uk/2013/hosting-in-the-cloud-elastic-beanstalk-vs-heroku-vs-engineyard/</link>
		<comments>http://mark-kirby.co.uk/2013/hosting-in-the-cloud-elastic-beanstalk-vs-heroku-vs-engineyard/#comments</comments>
		<pubDate>Thu, 24 Jan 2013 12:58:21 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=1184</guid>
		<description><![CDATA[Three platforms stand out for cloud based hosting &#8211; Elastic Beanstalk, Heroku and EngineYard. Here I present my experiences with the three, and thoughts on which might be best to use under various factors. To cut to the chase &#8211; Elastic Beanstalk wins, but as usual it depends on your situation. Common features All the...]]></description>
				<content:encoded><![CDATA[<p>Three platforms stand out for cloud based hosting &#8211; Elastic Beanstalk, Heroku and EngineYard. Here I present my experiences with the three, and thoughts on which might be best to use under various factors.</p>
<p>To cut to the chase &#8211; Elastic Beanstalk wins, but as usual it depends on your situation.</p>
<h2>Common features</h2>
<p>All the below services feature:</p>
<ul>
<li>Deploy from the command line with git</li>
<li>Full support for Ruby/Rails apps</li>
<li>Gems installed and updated automatically on each push</li>
<li>Comprehensive settings to handle db:migrate</li>
<li>Integrated database support (no need to set up separate instance)</li>
</ul>
<p>Note that none of these features came with Elastic Beanstalk when it first launched &#8211; its come a long way, so may be worth reconsidering if you&#8217;d previously disregarded it.</p>
<h2>Heroku</h2>
<h3>Pros</h3>
<ul>
<li>Heroku <strong>very easy to get started</strong>, you just install the toolkit and your away</li>
<li>Documentation is <strong>simple and straightforward</strong></li>
<li>Heroku is the cheapest option for a low traffic site &#8211; you can run a site with a basic (less than 10k rows) database for <strong>free</strong>, although it will be <strong>quite slow</strong> if you have a lot of traffic</li>
<li>You <strong>don&#8217;t have to add a credit card</strong>, so you will go up in price only as and when you choose to &#8211; no nasty shocks</li>
<li><strong>Backups are handled automatically</strong></li>
<li>A <strong>number of addons are provided</strong>, making it easier to integrate with systems such as NewRelic for monitoring and SendGrid for emails</li>
<li>Database integration is simple with Postgres support out of the box</li>
</ul>
<h3>Cons</h3>
<ul>
<li>Once you need to add power and handle more traffic the <strong><a href="http://www.smashingboxes.com/heroku-vs-amazon-web-services/">price goes up quickly</a></strong></li>
<li>You need to <strong>manually scale your application</strong> by adding dynos &#8211; <a href="https://devcenter.heroku.com/articles/dynos">a vague and somewhat confusing concept Heroku have come up with themselves</a> - this gives you *some* control over price, but ultimately means your site <strong>won&#8217;t cope well with unexpected spikes in traffic</strong></li>
<li>Customer support is <strong><a href="http://www.smashingboxes.com/heroku-vs-aws-revisited/">reported to be</a> poor</strong>, but I haven&#8217;t needed to use it personally</li>
<li>Heroku is <strong>owned by Sales Force</strong>, which means it could be sold at any point or deprioritised</li>
<li>Unlike the others, you <strong>can&#8217;t log into your server via SSH</strong></li>
<li>After deploying an update the <strong>first hit to the server takes ages</strong></li>
</ul>
<p>We use Heroku for all our test applications, and for little pet projects that might grow. I wouldn&#8217;t use it for actual scaling though, its too expensive and you don&#8217;t get enough for your money.</p>
<h2>EngineYard</h2>
<h3>Pros</h3>
<ul>
<li><strong>Scaling happens automatically</strong>, so you can handle that spike (<em><strong>although</strong></em> this can lead to a suprisingly <strong>large bill</strong>)</li>
<li>You can <strong>SSH </strong>into the server and change things</li>
<li><strong>Backups are handled automatically</strong></li>
<li>A <strong>number of addons are provided</strong>, making it easier to integrate with systems such as NewRelic for monitoring and SendGrid for emails</li>
<li><strong>Database integration is simple</strong> with Postgres and MySQL support out of the box</li>
<li><strong>Support is excellent</strong> &#8211; I&#8217;ve had much first hand experience of this</li>
</ul>
<h3>Cons</h3>
<ul>
<li>Its a <strong>little more work to deploy than heroku</strong>, but not much, and after the first live publish it takes no longer to update</li>
<li><span style="line-height: 13px;">Its <strong>incredibly expensive</strong>, we once spent $100 on a month for a server without any traffic</span></li>
<li>EngineYard applies a <a href="https://www.engineyard.com/products/cloud/pricing">20% surcharge</a> on all of Amazons prices, as it uses Amazon for storage, IP Addresses and backup, so it will almost always be <strong>more expensive</strong></li>
</ul>
<p>I would recommend EngineYard for production products where money is no issue, and support and absolute minimal interaction with setting up addons is required.</p>
<h2>Elastic Beanstalk</h2>
<h3>Pros</h3>
<ul>
<li>New users can <a href="http://aws.amazon.com/pricing/elasticbeanstalk/">use Elastic Beanstalk free and underlying services</a> up to a certain amount <strong>free for a year</strong>, making it competitive with Heroku, certainly for the first year</li>
<li>A sample low traffic site on Elastic Beanstalk <strong>after the free period is $35 per month</strong>. To run that same site on <a href="https://www.engineyard.com/products/cloud/pricing">EngineYard would cost at least $86</a></li>
<li><strong>Scaling happens automatically</strong>, so you can handle that spike (<em><strong>although</strong></em> this can lead to a suprisingly <strong>large bill</strong>)</li>
<li>You can <strong>SSH </strong>into the server and change things</li>
<li><strong>Backups are handled automatically</strong></li>
</ul>
<h3>Cons</h3>
<ul>
<li>Its a little more work to set up and deploy for the first time than Heroku and even EngineYard (the toolkit needs installing manually, you can&#8217;t do it as a gem), but it only takes a few mins extra</li>
<li><span style="line-height: 13px;">In order to use a database to get the same ease you would with Heroku and EngineYard you need to use <a href="http://aws.amazon.com/rds/">Amazons RDS service</a> (which provides a MySQL, Oracle or SQL Server database) which comes with <strong>variable additional charges</strong></span></li>
<li><strong>Addons aren&#8217;t provided</strong>, so its a <a href="http://blog.newrelic.com/2012/12/05/deploying-a-scalable-application-with-aws-elastic-beanstalk-and-new-relic/?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+NewRelic+%28New+Relic+Blog%29">tiny tiny bit more complex</a> to integrate with essential monitoring tool New Relic (although it is free for AWS users), and SendGrid. Its not much more work though.</li>
<li>Its <strong>hard to work out how much you will pay</strong>, although it <strong>should always be cheaper than EngineYard</strong> since they use AWS and add on top. Elastic Beanstalk itself is free, but you pay for bandwidth, storage, database, backups etc.</li>
<li>You don&#8217;t get as much feedback from the server when pushing as you do for Heroku and EngineYard</li>
</ul>
<p>Elastic Beanstalk is where I would recommend hosting production products to get a balance of service and price. You could even start a pet project on there right away due to the free storage tier. There are more cons, but I feel these are offset by the price for many situations.</p>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2013/hosting-in-the-cloud-elastic-beanstalk-vs-heroku-vs-engineyard/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How to authenticate APIs &#8211; HTTP Basic vs HTTP Digest</title>
		<link>http://mark-kirby.co.uk/2013/how-to-authenticate-apis-http-basic-vs-http-digest/</link>
		<comments>http://mark-kirby.co.uk/2013/how-to-authenticate-apis-http-basic-vs-http-digest/#comments</comments>
		<pubDate>Fri, 18 Jan 2013 15:44:43 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=1173</guid>
		<description><![CDATA[A comparison of the pros and cons of the three main secure ways of authenticating an API, in plain business terms. We cover: HTTP Basic Access Authentication over SSL HTTP Digest The answer, as usual, is it depends, but if you can force the server to use SSL, or are creating a private API, then...]]></description>
				<content:encoded><![CDATA[<p>A comparison of the pros and cons of the three main secure ways of authenticating an API, in plain business terms. We cover:</p>
<ul>
<li>HTTP Basic Access Authentication over SSL</li>
<li>HTTP Digest</li>
</ul>
<p>The answer, <a href="http://adactio.com/journal/4437/">as usual</a>, is it depends, but if you can force the server to use SSL, or are creating a private API, then its Basic.</p>
<h2>HTTP Basic Access Authentication over SSL</h2>
<p><a href="http://en.wikipedia.org/wiki/Basic_access_authentication">HTTP Basic</a> is a simple form of authentication where:</p>
<ul>
<li>STEP 1 &#8211; the client makes a request for information, sending a username and password to the server in plain text</li>
<li>STEP 2 &#8211; the server responds with the desired information or an error</li>
</ul>
<p>HTTP Basic doesn&#8217;t need to be implemented over SSL, but if you don&#8217;t, it isn&#8217;t secure at all. So I&#8217;m not even going to entertain the idea of using it without.</p>
<h3>Pros</h3>
<ul>
<li><span style="line-height: 13px;">Its <strong>simple to implement</strong>, so your client developers will have <strong>less work to do</strong> and take <strong>less time to deliver</strong>, so developers could be <strong>more likely to want to use your API </strong></span></li>
<li>Unlike Digest, you can store the passwords on the server in whatever encryption method you like, such as <a href="http://en.wikipedia.org/wiki/Bcrypt">bcrypt</a>, making the <strong>passwords more secure</strong></li>
<li>Just one call to the server is needed to get the information, making the client <strong>slightly faster</strong> than more complex authentication methods might be</li>
</ul>
<h3>Cons</h3>
<ul>
<li>SSL is slower to run than basic HTTP so this <strong>causes the clients to be slightly slower</strong></li>
<li>If you <strong>don&#8217;t have control of the clients</strong>, and can&#8217;t <a href="http://stackoverflow.com/questions/567434/force-https-for-entire-server-domain">force the server to use SSL</a>, a developer might not use SSL, causing a <strong>security risk</strong></li>
</ul>
<p>In summary &#8211; if you have control of the clients, or can ensure they use SSL, HTTP Basic is a good choice. The slowness of the SSL can be cancelled out by the speed of only making one request.</p>
<h2>HTTP Digest Access Authentication</h2>
<p>HTTP Digest access authentication is a more complex form of authentication that works as follows:</p>
<ul>
<li>STEP 1 &#8211; a client sends a request to a server</li>
<li>STEP 2 -the server responds with a special code (called a nonce), another string representing the &#8216;realm&#8217; and asks the client to authenticate</li>
<li>STEP 3 - the client responds with this nonce and an encrypted version of the username, password and realm (a hash)</li>
<li>STEP 4 - the server responds with the requested information if the client hash matches their own hash of the username, password and realm, or an error if not</li>
</ul>
<h3>Pros</h3>
<ul>
<li><span style="line-height: 13px;">No usernames or passwords are sent to the server in plaintext, making a non-SSL connection more secure than an HTTP Basic request that isn&#8217;t sent over SSL. This means SSL isn&#8217;t required, which makes each call <strong>slightly faster</strong></span></li>
</ul>
<h3>Cons</h3>
<ul>
<li><span style="line-height: 13px;">For every call needed, the client must make 2, making the process <strong>slightly slower </strong>than HTTP Basic</span></li>
<li>HTTP Digest is <strong>vulnerable</strong> to a man-in-the-middle security attack which basically means it <strong>could be hacked</strong></li>
<li>HTTP Digest prevents use of the strong password encryption, meaning the passwords stored on the server <strong>could be hacked</strong></li>
</ul>
<p>In summary, HTTP Digest is vulnerable to at least 2 methods of hacking, where a server using strong encryption for passwords with HTTP Basic over SSL is not.</p>
<p>If you don&#8217;t have control over your clients however they could attempt to perform Basic authentication without SSL, which is much less secure than Digest.</p>
<h2>The answer &#8211; it depends, but probably HTTP Basic</h2>
<p>Ideal:</p>
<ul>
<li>Use HTTP Basic with SSL, slower than non-SSL, but only one call needed per information request</li>
<li>Store passwords on the server encrypted with a strong password hash such as bcrypt, making it harder for hackers to extract them from the server</li>
<li>Force the server to serve the API over SSL</li>
</ul>
<p>If you can&#8217;t force the server to server the API over SSL, and don&#8217;t have control over all the clients being built (i.e. you are creating a public API):</p>
<ul>
<li><span style="line-height: 13px;">Use HTTP digest</span></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2013/how-to-authenticate-apis-http-basic-vs-http-digest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating an efficient REST API with HTTP</title>
		<link>http://mark-kirby.co.uk/2013/creating-a-true-rest-api/</link>
		<comments>http://mark-kirby.co.uk/2013/creating-a-true-rest-api/#comments</comments>
		<pubDate>Wed, 16 Jan 2013 18:51:47 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=1107</guid>
		<description><![CDATA[A guide to creating a REST API, which will enable you to build API's in a cost and resource effective way that follows clear standards. I take you through the core principles you need to know to build a REST API.]]></description>
				<content:encoded><![CDATA[<p>Many API&#8217;s produced call themselves <strong>RESTful</strong>, but barely cover any of the core principles of REST. REST is a standard you can choose to follow, and many (but not all) will help you to build an API that is efficient, easy to use and highly understandable. Here I highlight all the core principles, and how using them can help you to build an excellent API, which is a rare thing indeed.</p>
<p><a href="http://mark-kirby.co.uk/2013/principles-of-a-true-rest-api/image_print/" rel="attachment wp-att-1151"><img class="alignnone size-full wp-image-1151" alt="image_print" src="http://mark-kirby.co.uk/wp-content/uploads/2013/01/image_print.jpeg" width="400" height="388" /></a></p>
<h2>Why bother</h2>
<p>A REST API follows standards, and these standards take into account many of the gotchas you would encounter if you just made up your own rules, as many choose to.</p>
<p>It is likely <strong>you will also be creating the clients</strong> (for example, you may be making mobile apps that the API supports), and the better the API, the easier it is to create those clients.</p>
<p>Following these standards means:</p>
<ul>
<li>Documentation will make more sense and so developers will <strong>understand your API quicker</strong></li>
<li>Developers who have used other REST API&#8217;s will <strong>already understand</strong> how to use yours</li>
<li>Developers will therefore be able to integrate quicker and therefore <strong>deliver products faster and at lower cost</strong></li>
<li>The API will handle common issues out of the box so clients should contain <strong>less bugs</strong></li>
<li>Many of the principles will make your clients faster, <strong>improving product quality</strong></li>
<li>These principles help to ensure as much as possible is managed by the server, so you <strong>don&#8217;t have to repeat as much code</strong> in each client</li>
</ul>
<h2>Create a uniform interface by mapping HTTP methods to CRUD</h2>
<p>CRUD = Create, Read, Update, Delete</p>
<p>HTTP methods = POST, GET, PUT, DELETE</p>
<ul>
<li>Create = POST</li>
<li>Read = GET</li>
<li>Update = PUT</li>
<li>Delete = DELETE</li>
</ul>
<p>So instead of API calls such as:</p>
<ul>
<li>Create &#8211; GET: /user/new?name=Mark</li>
<li>Read &#8211; GET: /user/1</li>
<li>Update &#8211; GET: /user/1/update?name=John</li>
<li>Delete &#8211; GET: /user/1/delete</li>
</ul>
<p>Simply:</p>
<ul>
<li>Create &#8211; POST: /user (with the variables in the entity-body)</li>
<li>Read &#8211; GET: /user/1</li>
<li>Update &#8211; PUT: /user/1 (with the variables in the entity-body)</li>
<li>Delete &#8211; DELETE: /user/1</li>
</ul>
<p>See <a href="https://www.ibm.com/developerworks/webservices/library/ws-restful/">IBM &#8211; RESTful Web Services: The Basics</a> for more justifications on this.</p>
<p>Following this means everyone can understand how to use your API in a common way and <strong>keeps the API simple</strong>.</p>
<h2>Understand the difference between a URI and a Resource</h2>
<p>Consider the following:</p>
<ul>
<li>POST: http:/test.com/user</li>
<li>GET: http:/test.com/user/1</li>
<li>PUT: http:/test.com/user/1</li>
<li>DELETE: http:/test.com/user/1</li>
</ul>
<p>POST, GET, PUT, DELETE are the methods</p>
<p>http:/test.com/user, http:/test.com/user/1 are URI&#8217;s</p>
<p><strong>user/1 </strong>is a user, which is a resource</p>
<h2>Understand the difference between a resource and a representation</h2>
<p>From the above example calling GET: http:/test.com/user/1 will return a representation of the resource user:1.</p>
<p>A representation is a set of attributes related to the resource, e.g.</p>
<ul>
<li>name: mark</li>
<li>city: brighton</li>
</ul>
<p>A representation will have a format (XML, JSON , XHTML etc), and a language.</p>
<h2>Keep the number of resources low</h2>
<p>The resource names <strong>should often</strong> map conceptual domain entities. They should map to objects, not actions on the objects.</p>
<p>If you want to <strong>declare a user as a subscriber</strong>, you <strong>don&#8217;t need to add a resource called subscribe</strong>. Just pass the following representation:</p>
<ul>
<li>name: mark</li>
<li>city: brighton</li>
<li>subscriber: YES</li>
</ul>
<p>This <strong>keeps documentation and coding simpler.</strong></p>
<h2>Create addressability by mapping a URI to each resource, possibly each representation</h2>
<p>A URI should map to only one resource.</p>
<ul>
<li>test.com/user maps only to user</li>
</ul>
<p>There should be URI mapping to each representation of the resource</p>
<ul>
<li>test.com/user.xml maps to the xml representation of the user</li>
<li>test.com/user.json maps to the json representation of the user</li>
</ul>
<p>This enables URI&#8217;s to be shared in a consistent way, which <strong>keeps things simple</strong>.</p>
<h2>Name resources and representations carefully</h2>
<p>Follow simple rules for naming resources. I recommend:</p>
<p>Use forward slashes to show child objects, with a resource for each item.</p>
<ul>
<li>/events &#8211; exposes all events</li>
<li>/events/concerts &#8211; exposes all concerts</li>
<li>/events/concerts/1 &#8211; exposes concert with id of 1</li>
</ul>
<p>Use semi-colons where there is no obvious sequence:</p>
<ul>
<li>/events/locations/the-concorde-2;the-brighton-dome &#8211; is a search for 2 event locations</li>
</ul>
<p>Use comma&#8217;s when the order matters but they are not child items:</p>
<ul>
<li><span style="line-height: 13px;">/events/locations/25.9,22.5 &#8211; is a lat/long search</span></li>
</ul>
<p>This keeps API&#8217;s consistent, making it <strong>easier to interact with them</strong>.</p>
<h2>Use POST for creating, not editing</h2>
<p>When you POST you POST to an unknown resource.</p>
<ul>
<li>POST: /user</li>
</ul>
<p>How should you handle the following situation:</p>
<ul>
<li>POST: /user/1</li>
</ul>
<p>You could update it with the new data, or you could respond with a already created code, and force the use of PUT.</p>
<p>I recommend keeping things simple, and refusing to update.</p>
<h2>Consider the use of overloaded POST only to handle situations where PUT and DELETE are unavailable</h2>
<p>If you want to allow your API to support clients without PUT and DELETE (in reality a rare situation these days), use overloaded POST. A true REST API wouldn&#8217;t do this, but sometimes you need to be flexible.</p>
<p>One way of doing this is to define in the API the actual call you want to use to replace POST:</p>
<ul>
<li>POST: /user/1?method=put</li>
<li>POST: /user/1?method=delete</li>
</ul>
<p>The API can then convert the POST call into the appropriate method, and funnel it into the same route.</p>
<h2>GET and HEAD should only ever fetch data, never alter or delete it</h2>
<p>If you manipulate or delete data using GET, you put your data at risk.</p>
<p>It is possible a web crawler or browser call could delete your data.</p>
<p><strong>GET should only ever fetch data.</strong></p>
<h2>Allow for multiple identical PUT or DELETE requests, without side effects</h2>
<p>If you are updating the price of a widget in a PUT request, don&#8217;t allow anything like:</p>
<ul>
<li>price: +1</li>
<li>price: -2</li>
</ul>
<p>Instead, only accept a new price:</p>
<ul>
<li>price: 3.99</li>
</ul>
<p>This is because an app could submit a PUT multiple times, without realising the negative effects. In the first example this would result in the price going up by 1 (or down by 2) on each submit.</p>
<p>In the second, the price would always remain at 3.99, there would be no ill effects.</p>
<h2>Use HTTP Response Codes</h2>
<p>HTTP provides response codes to inform clients of the status of their request. <strong>Use them! </strong>Don&#8217;t just return a 200 response with an error description if something is wrong.</p>
<p>These are the main ones used:</p>
<h3>2xx &#8211; Success codes</h3>
<ul>
<li><strong>200 &#8211; OK</strong>, all is fine. <em>Entity-body </em>contains the resource requested in its current state</li>
<li><strong>201 &#8211; Created</strong>, a new resource has been created. <em>Location</em> header contains the address of the new resource. <em>Entity-body</em> contains the representation of the new resource as it is on the server</li>
<li><strong>202 &#8211; Accepted</strong>, a clients request is pending and will be completed later. <em>Location</em> header contains the expected address of the new resource so it can be checked later.</li>
</ul>
<h3>3xx &#8211; Redirection codes</h3>
<ul>
<li><strong>301 &#8211; Moved Permanently</strong>, the API has moved a resource in response to the request, or an old resource is requested. <em>Location</em> contains the new URI.</li>
<li><strong>304 &#8211; Not Modified</strong>, the client already has this data, used when the client provided a <em>If-Modified-Since</em> header and the data hasn&#8217;t been modified. <em>Date </em>header is required, <em>ETag</em> and <em>Content-Location</em> should be same as a 200, <em>Expires, Cache-Control</em> and <em>Vary</em> are required if they&#8217;ve changed since last sent.</li>
</ul>
<h3>4xx &#8211; Client side error</h3>
<ul>
<li><strong>400 &#8211; Bad Request</strong>, there is a client-side problem, the document in the entity-body should contain more info on the problem</li>
<li><strong>401 &#8211; Unauthorized</strong>, wrong credentials provided, or no credentials provided. <em>WWW-Authenticate</em> header should describe the authentication methods accepted. <em>Entity-body</em> could contain more details about the error.</li>
<li><strong>404 &#8211; Not Found</strong>, no resource matches the requested URI, there is no reference to it on the server</li>
<li><strong>409 &#8211; Conflict</strong>, client attempted to do something which would leave a resource in an inconsistent state, such as create a user with an already taken name. <em>Location </em>could point to the source of the conflict. <em>Entity-body</em> to describe the conflict.</li>
<li><strong>412 &#8211; Precondition failed</strong>, client wanted to modify a resource using a If-Unmodified-Since/If-Match header, the resource had been modified by someone else.</li>
</ul>
<h3>5xx &#8211; Server side error</h3>
<ul>
<li><strong>500 &#8211; Internal Server Error</strong>, there is an error on the server</li>
</ul>
<p>More codes can be found in the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10">HTTP/1.1 Status Code Definitions guide</a></p>
<h2>Handle and use meta-data in HTTP Headers</h2>
<p>Implementing these will make your API more flexible and keep information in standard locations rather than URI&#8217;s.</p>
<p>These are common request headers (from client to server)</p>
<ul>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3">Accept-Encoding</a> - asks the server to use compression of responses</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.8">Authorization</a> - enables authentication via any method</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23">Host</a> - <strong>required</strong> - domain name of the URI, e.g. www.test.com</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24">If-Match</a> - value of a previous calls ETag response used with a PUT or DELETE. Server should only act if nobody else has modified the resource since you last fetched it. Otherwise provides a 412.</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25">If-Modified-Since</a> - value of a previous Last-Modified response used with a GET. Server should only provide a response if the resource was modified since the timestamp submitted. Use in conjunction with If-None-Match in case the change occurred within the same second. Otherwise provide a 304.</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25">If-None-Match</a> - value of a previous calls ETag response used with a GET. Server should only provide a response if the ETag doesn&#8217;t match, i.e. the resource has been altered. Otherwise provide a 304.</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.28">If-Unmodified-Since</a> - value of a previous Last-Modified response used with a PUT or DELETE. Server should only act if nobody else has modified the resource since you last fetched it. Otherwise provides a 412.</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43">User-Agent</a> - information on your client, useful for gathering statistics</li>
</ul>
<p>These are common response headers (from server to client)</p>
<ul>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11">Content-Encoding</a> - tells the client what compression is being used</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">Content-Length</a> - tells the client how many bytes the content body contains</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> - tells the client the media type the entity-body is, e.g. text/html</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19">ETag</a> - a string representing a version of a representation of a resource, useful in detecting if a resource has changed with If-Match or If-None-Match</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.29">Last-Modified</a> - the <strong>time the representation changed</strong>, useful in detecting if a resource has changed with If-Modified-Since and If-Unmodified-Since</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30">Location</a> - URI relating to the request, varies according to the HTTP status</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.47">WWW-Authenticate</a> - tells the client the expected authentication type when responding with a 401</li>
</ul>
<p>These are common request and response headers (bi-directional)</p>
<ul>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18">Date</a> - time on the client the request was made, time on the server request was responded too. The server must provide this unless is is responding with a 100, 101, 500, 503</li>
</ul>
<h2>REST is stateless &#8211; so don&#8217;t handle state in your API</h2>
<p>REST API&#8217;s must be stateless. Every call requiring authentication should provide the authentication and never a session key.</p>
<p>When you attempt to handle state in your API you create a nightmare of sessions and session handling on the API side, and create lots of repetitive work for each service connecting to your API who has to potentially always handle the case where the session has expired. <strong>Handling state will slow down your API</strong> and all clients using it.</p>
<p>Stateless API&#8217;s are <strong>easier to scale</strong>, <strong>more reliable </strong>and <strong>simpler to use</strong>.</p>
<h2>REST is cacheable 1 &#8211; allow clients to GET only updated resources via HTTP</h2>
<p>If your clients are repeatedly requesting the same data you are <strong>unnecessarily slowing all applications down</strong>, increasing bandwidth from the server to the clients and wasting computation power. Instead, use HTTP to handle this.</p>
<h3>The easy way with Last-Modified</h3>
<ul>
<li>Server provides a <em>Last-Modified </em>header with each GET call, the date the resource was last modified.</li>
<li>Clients can now GET with the header <em>If-Unmodified-Since</em> containing the latest Last-Modified value</li>
<li>The server either updates the resource if the Last-Modified value for the resource matches the one in If-Unmodified-Since, or respond with a 304 Not Modified.</li>
</ul>
<h3>Get more precise with ETags</h3>
<p>There is a risk here where more than one person can update data, that the data updated again within the same second. This is why you can also use ETags.</p>
<ul>
<li>Server provides an ETag (<a href="http://bitworking.org/news/150/REST-Tip-Deep-etags-give-you-more-benefits">more on how to create ETags</a>) which represents the resources current state, with each GET call</li>
<li>Clients can now GET with the header If-None-Match containing the latest ETag value</li>
<li>The server either responds with the resource if the ETags differ, or respond with a 304 Not Modified.</li>
</ul>
<p>However, ETags are more costly to generate than Last-Modified, and should be considered carefully.</p>
<h2>REST is cacheable 2 &#8211; prevent accidental simultaneous updates of the same resource via HTTP</h2>
<p>A common issue when more than one client can access the same resource is having one client do an update, and then another client overwrite that update because they didn&#8217;t know it had occurred.</p>
<h3>The basic way with Last-Modified</h3>
<ul>
<li>Server provides a <em>Last-Modified </em>header with each GET call, the date the resource was last modified.</li>
<li>Clients can now PUT with the header <em>If-Modified-Since</em> containing the latest Last-Modified value</li>
<li>The server either responds with the resource if the dates differ, or respond with a 412 PreCondition Failed.</li>
</ul>
<h3>Get more precise with ETags</h3>
<ul>
<li>Server provides an ETag (<a href="http://bitworking.org/news/150/REST-Tip-Deep-etags-give-you-more-benefits">more on how to create ETags</a>) which represents the resources current state, with each GET call</li>
<li>Clients can now GET with the header If-Match containing the latest ETag value</li>
<li>The server either responds with the resource if the ETags differ, or respond with a 412 PreCondition Failed.</li>
</ul>
<p><a href="http://blog.m.artins.net/restful-web-services-preventing-race-conditions/">Read more about preventing race conditions</a>.</p>
<h2>Use the HEAD method to allow the client to manage its bandwidth better</h2>
<p>The HEAD method for an resource should return a meta-data only representation of the resource.</p>
<p><em>HEAD: /user</em> should return everything <em>GET: /user</em> would except the entity-body.</p>
<p>This could be useful for a number of reasons, e.g. the Content-Length header might tell the client it doesn&#8217;t want to fetch this particular entity-body if its too large.</p>
<h2>Version your API, and never change released features</h2>
<p>Each URI should begin with a version number.</p>
<ul>
<li><span style="line-height: 13px;">/v1/user</span></li>
</ul>
<p>Returns:</p>
<ul>
<li><span style="line-height: 13px;">name</span></li>
<li>phonenumber</li>
</ul>
<p>If you remove anything from the representation being returned for user, or change the rules about what you accept, you need to increase the version number &#8211; don&#8217;t just change the current representation.</p>
<ul>
<li><span style="line-height: 13px;">/v2/user</span></li>
</ul>
<p>Returns</p>
<ul>
<li><span style="line-height: 13px;">name</span></li>
</ul>
<p><strong>This prevents your clients from breaking!</strong></p>
<p>&nbsp;</p>
<h2>Understand Hypermedia application state and why you probably shouldn&#8217;t use it</h2>
<p>Hypermedia Application State (also known as HATEOAS) is a concept wherein the client uses just one URI, and from that URI is able to deduce how to interact with the API by following links, as one would when using a website. What this means in theory is that the client need not know how to use the API in a certain way, which enables the API to evolve without updating all the clients. <a href="http://oredev.org/2010/sessions/hypermedia-apis">This talk explains it well</a>.</p>
<p>This is one part of REST I don&#8217;t agree with for most situations, although it is <a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">technically part of having a true REST API</a>.</p>
<p>The concept is great in theory, but it poses the following issues:</p>
<ul>
<li>At least 2 API calls are needed to perform any task, one to identify how to perform the task, and then the one to actually do it &#8211; which means <strong>more data being transferred</strong>, and <strong>more time taken</strong> to get the data. This is <strong>terrible for mobile</strong>, especially as the signal could be lost in between asking how to perform the task, and actually doing it.</li>
<li>You should not use JSON to run this type of API, and JSON is the most efficient way of passing information to clients</li>
<li>This is not a common way of consuming an API, so it creates complexity for the client developers, which could cause the development to <strong>take longer</strong>, or <strong>put people off</strong> using the API</li>
<li>There is still lots of information the client needs to know about the API in order to respond to it and navigate it, so its not true separation of concerns anyway</li>
</ul>
<p>Ultimately what this does is put the needs of the developers over that of the users. It places <strong>theory over practicality</strong>. No other aspect of REST does this, and that is why this is the one thing I don&#8217;t recommend, and <a href="http://37signals.com/svn/posts/3373-getting-hyper-about-hypermedia-apis">neither does the creator of Ruby on Rails</a>, <a href="http://www.intridea.com/blog/2010/4/29/rest-isnt-what-you-think-it-is">nor Michael Bleigh</a>. <a href="http://opensoul.org/blog/archives/2012/10/29/why-hypermedia-apis-matter/">Others do</a>, and its a big debate area. Understand it and make your own choices.</p>
<h2>Next steps</h2>
<h3>Learn more about API&#8217;s</h3>
<p>The best book you can read on this subject is the REST bible: <a href="http://www.amazon.co.uk/gp/product/0596529260/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;camp=1634&amp;creative=6738&amp;creativeASIN=0596529260&amp;linkCode=as2&amp;tag=tobloggle0e-21">RESTful Web Services, by Leonard Richards</a>, a <a href="http://www.amazon.co.uk/gp/product/B0043D2ED6/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;camp=1634&amp;creative=6738&amp;creativeASIN=B0043D2ED6&amp;linkCode=as2&amp;tag=tobloggle0e-21">Kindle edition is also available</a>.</p>
<h3>Get outside help with your API&#8217;s</h3>
<p>If you&#8217;ve enjoyed this article and have an API project you&#8217;d like help with, I may be available as a consultant on your project. I&#8217;ve built REST API&#8217;s for mobile apps, and worked with Tesco on the early versions of their (non REST) API as a mobile developer. I learned much from this experience, and have both made, and seen, many of the issues that can occur from not following the above guidelines. My business partner and our CTO <a href="http://www.linkedin.com/in/jamesmccarthy">James McCarthy</a> has over 20 years experience building back-end systems and API&#8217;s for organisations such as AMEX and may also be available.</p>
<p>To hire one of us, <a href="http://mark-kirby.co.uk/about">check out the contact page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2013/creating-a-true-rest-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why multivariate testing isn&#8217;t always a good thing</title>
		<link>http://mark-kirby.co.uk/2013/why-multivariate-testing-isnt-always-a-good-thing/</link>
		<comments>http://mark-kirby.co.uk/2013/why-multivariate-testing-isnt-always-a-good-thing/#comments</comments>
		<pubDate>Wed, 02 Jan 2013 17:25:19 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=1089</guid>
		<description><![CDATA[Multivariate testing isn't always a good thing. It comes with many pitfalls and risks I've laid out here.]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been thinking about multivariate testing lately, and have decided to collate my thoughts on why it&#8217;s no silver bullet, comes with many risks and should be used only in the right circumstances.</p>
<h2>Why test at all?</h2>
<p>If you have a site resulting in a <em><strong>call to action</strong></em> there are many things you can alter that might increase take-up.</p>
<p>If you just change things without testing you run the risk of making things worse, or lack a true understanding of what helped to create an uptake.</p>
<p>Create a hypothesis, a series of design suggestions, and test them on real users by using multivariate or split testing.</p>
<h2>What is the alternative to multivariate testing? (its split testing)</h2>
<p>Split testing allows you to test users on completely different versions of the page, where you could change one or more items, or run an entire redesign. You can test one, two or more variations of the page. A/B testing is term used to describe split testing of 2 alternatives.</p>
<p>Once you have completed the testing, you have a winner and you can make it live.</p>
<h2>What is multivariate testing?</h2>
<p>Multivariate testing allows you to change a number of elements on the page, and run tests to see which of those elements are more likely to result in improvements to the call to action.</p>
<p>Visitors to the site will see different element combinations each time, and the system you use will attempt to calculate which items are proving more successful over time.</p>
<p>Once you have completed the testing, you need to create a new design based on your learning.</p>
<h2>The primary benefit of multivariate testing over split testing</h2>
<p>Multivariate testing has a lot of fans, <a href="http://visualwebsiteoptimizer.com/split-testing-blog/9-award-winning-ab-tests/">large companies have seen increases in profits</a> thanks to its use. You will find many avid proponents of its use, <a href="http://www.smashingmagazine.com/2010/11/24/multivariate-testing-in-action-five-simple-steps-to-increase-conversion-rates/">especially from those who own companies that sell it as a service</a>.</p>
<p>The primary benefit of multivariate testing over split testing is you can try a number of changes all at once, run the tests, and find out approximately which were most successful, <strong>growing your knowledge of what triggers your customers to complete a task</strong>. If you are going to put this knowledge to good use in the future, then it is good to know. This is one of the principles of the lean startup movement.</p>
<p>To achieve this in a split test, you would need to change one thing at a time, see if it worked, and then if not, roll back and start again, so <em><strong>it would take longer to gain that knowledge</strong>.</em></p>
<p>However, you could also make a lot of changes in a split test, see your profits increase</p>
<h2>The downsides of multivariate testing</h2>
<h3>It is complex to set the tests up, whatever the blurb may say</h3>
<p>The tools such as market leaders <a href="http://visualwebsiteoptimizer.com/">Visual Website Optimizer</a> and <a href="https://www.optimizely.com/">Optimizely</a> both work by allowing you to edit the HTML and CSS inside their apps. Then they roll the changes out onto your site using JavaScript.</p>
<p><strong>Setting up the changes is fiddly</strong> and requires some <strong>HTML and CSS knowledge</strong> anyway. It should be easier for a skilled front-end developer to set up experiments in a split testing environment where you just upload an alternative file. If you aren&#8217;t a skilled developer you probably shouldn&#8217;t be making the changes anyway.</p>
<h3>You need to plan very carefully</h3>
<p>You need to think about how all the various combinations of changed elements could look together. You don&#8217;t want your site looking like a mess, as that will put people off anyway and skew the data.</p>
<h3>It could harm your search engine rankings</h3>
<p>Any split or multivariate testing can impact negatively on your search engine rankings as you run the risk of being penalised for duplicate content, lost backlink equity and page slowdown. <a href="http://padicode.com/blog/analytics/the-impact-of-ab-or-multivariate-testing-on-seo/">This SEO company explains it all in more detail</a>.</p>
<p>Whats concerning is that whilst there is plenty you can do if you are running split tests to mitigate the risk, with multivariate you are powerless to do anything. You just have to assume the risk, and take the hit if it occurs. For this reason alone,<strong> I wouldn&#8217;t use multivariate testing on a site that wasn&#8217;t extremely well linked to and established.</strong></p>
<h3>You can easily destroy cross browser and multiple platform consistency</h3>
<p>When setting up the multivariate tests you have no way of easily testing the changes across multiple browsers and platforms. It certainly needs to be done, but it will take you much longer to do when running multivariate tests than split tests. In a split test you can simply load the 2 pages, and test them manually. With multivariate tests you will need to hope your chosen software makes it easy to force certain scenarios and then work through them all.</p>
<p>Multivariate testing also gives you the potential power to destroy your site, so make sure you trust the HTML and CSS knowledge of whoever has control of the tests.</p>
<h3>Its takes a long time to find a potentially inaccurate answer</h3>
<p>Multivariate testing doesn&#8217;t ever truly prove that a certain element was responsible for the conversion rate increasing. It can only strongly suggest it. Since every user sees a different combination of elements, you can&#8217;t be 100% sure it was the element in question which convinced them.</p>
<p>To be even mostly sure as <a href="http://www.smashingmagazine.com/2010/11/24/multivariate-testing-in-action-five-simple-steps-to-increase-conversion-rates/">Paras points out</a> you need to see a large increase in conversion rates when a particular element is present, have a large number of visitors and ideally be starting with a page with an already high conversion rate of around 50%-60%. This takes a long time, <a href="https://www.optimizely.com/resources/multivariate-test-vs-ab-test">according to Optimizely</a> &#8220;Even a site with fairly high traffic might have trouble completing a test with more than 25 combinations in a feasible amount of time.&#8221;</p>
<h3>You still need to do a design at the end of the tests</h3>
<p>Multivariate testing will produce some pointers, but then you need to create a new design with the results taken into account. There will be more coding to be done, and you might not be happy with the hodgepodge design that will be produced. Plus, that particular combination of elements <strong>might not even work together</strong>&#8230;so&#8230;</p>
<h3>You still ought to do A/B testing of the new design vs the old</h3>
<p>Otherwise, you aren&#8217;t testing the final release &#8211; the most important of all. Expect to wait around 2 &#8211; 4 weeks for that to be completed.</p>
<h3>The software isn&#8217;t cheap</h3>
<p>Expect to pay between $100 and $400 per month to run multivariate tests.</p>
<h2><strong>If you trust your redesign ideas, or have an under performing site you could profit quicker using</strong> split<strong> testing</strong></h2>
<p>If your site has obvious issues, that you can see based on intuition and studying more successful competitors, such as:</p>
<ul>
<li>an outdated design</li>
<li>contains quickly drafted copy, that you wrote without outside help</li>
<li>has not been built on solid design principles and sales ideas</li>
</ul>
<p>Then <strong><em>it is likely that changing these things will result in higher sales</em>. </strong></p>
<p>You don&#8217;t need to know which of your individual improvements lead to the higher sales straight away, you just need a stronger bedrock to build on.</p>
<p>Why spend lots of time and money running multivariate tests when you can clearly see the improvements are there to be made.</p>
<p>Make them, ensure through A/B testing that you won&#8217;t actually see a drop in profits, and get there faster.</p>
<h2><strong>If you</strong> doubt<strong> your redesign ideas, or have no clear redesign in mind, you can increase profits slowly over time with multivariate testing</strong></h2>
<p>If any of the following apply:</p>
<ul>
<li>you can&#8217;t see immediately where you would improve the site</li>
<li>your site is built on solid design principles</li>
<li>you and others perceive your site is as good or better than your competitors</li>
<li>you have range of ideas you might implement but are unsure of</li>
<li>you have strong current conversion rates</li>
</ul>
<p>Then multivariate testing could be for you, especially if you have a solid knowledge of CSS and HTML.</p>
<p>Try some ideas, and see if any of them make a difference. If they do, update the site, if not, it&#8217;s no problem.</p>
<p>You won&#8217;t save a failing business this way &#8211; it&#8217;s too long-winded, but <em><strong>you might improve upon the already successful</strong></em>.</p>
<h2>However if you don&#8217;t have an abundance of time, visitors or money, beware of multivariate testing</h2>
<p>This sums it up for me:</p>
<p><em>&#8230;A/B testing is so speedy and easy to interpret that some large sites use it as their primary testing method, running cycles of tests one after another rather than more complex multivariate tests.</em></p>
<p><a href="http://www.smashingmagazine.com/2010/11/24/multivariate-testing-in-action-five-simple-steps-to-increase-conversion-rates/">Optimizely &#8211; sellers of multivariate testing software</a></p>
<h2>Conclusion</h2>
<p>You need to choose the right tool for the job. Each are valuable:</p>
<p>Multivariate testing requires more work, takes longer, carries more risk, but can provide arguably more accurate results.</p>
<p>A/B testing is simpler, quicker, less risky but you won&#8217;t always know whats worked unless you test one thing at a time.</p>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2013/why-multivariate-testing-isnt-always-a-good-thing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing FlexSlider2 manual direction controls extension</title>
		<link>http://mark-kirby.co.uk/2012/flexslider-manual-direction-controls-jquery-plugin/</link>
		<comments>http://mark-kirby.co.uk/2012/flexslider-manual-direction-controls-jquery-plugin/#comments</comments>
		<pubDate>Fri, 20 Jul 2012 14:20:07 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=1048</guid>
		<description><![CDATA[Update &#8211; Nov 2012 &#8211; Thankfully due to a recent update this plugin is no longer needed.  FlexSlider2 is a jQuery plugin that allows you to easily insert rotating banners, image galleries and app examples. They also automatically become responsive. The problem with FlexSlider2 Out of the box however it doesn&#8217;t allow you to use...]]></description>
				<content:encoded><![CDATA[<p><em>Update &#8211; Nov 2012 &#8211; Thankfully due to a recent update this plugin is no longer needed. </em></p>
<p>FlexSlider2 is a jQuery plugin that allows you to easily insert rotating banners, image galleries and app examples. They also automatically become responsive.</p>
<h2>The problem with FlexSlider2</h2>
<p>Out of the box however it doesn&#8217;t allow you to use custom HTML elements for the direction controls.</p>
<p>The default appears as you mouse over the gallery, looking like this:</p>
<p><a href="http://mark-kirby.co.uk/wp-content/uploads/2012/07/Screen-Shot-2012-07-20-at-14.55.18.png"><img class="alignnone size-medium wp-image-1049" title="Screen Shot 2012-07-20 at 14.55.18" src="http://mark-kirby.co.uk/wp-content/uploads/2012/07/Screen-Shot-2012-07-20-at-14.55.18-300x219.png" alt="" width="300" height="219" /></a></p>
<p>I had a need to use permanent navigation, always appearing, and with custom HTML which differed from the default.</p>
<p>Although FlexSlider2 allows you to set custom tabs (those dots at the bottom), there is no easy way of setting custom directional navigation.</p>
<p>So to fix the issue I wrote an extension to FlexSlider2</p>
<h2>My extension &#8211; Flexslider2+ManualDirectionalControls</h2>
<p><a href="https://github.com/markirby/FlexSlider-ManualDirectionControls">Download the extension here</a>, you can start using it straight away, following the instructions on github.</p>
<p>In a nutshell, to add the functionality, all you need to do is include the javascript and do the following:</p>
<div class="codesnip-container" >
<div class="javascript codesnip" style="font-family:monospace;">$<span class="br0">&#40;</span><span class="st0">&#8216;.flexslider&#8217;</span><span class="br0">&#41;</span>.<span class="me1">flexslider</span><span class="br0">&#40;</span><span class="br0">&#123;</span><br />
&nbsp;directionNav<span class="sy0">:</span> <span class="kw2">false</span><br />
&nbsp;<span class="br0">&#125;</span><span class="br0">&#41;</span>.<span class="me1">flexsliderManualDirectionControls</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</div>
<p>There are options you can pass, but this keeps it easy by looking for HTML elements named &#8216;next&#8217; or &#8216;previous&#8217; inside the &#8216;.flexslider&#8217; element and takes care of everything.</p>
<h2>Why didn&#8217;t I just send an updated version of FlexSlider to github?</h2>
<p>There was a discussion at <a href="http://thisishatch.co.uk">Hatch</a> of simply adapting FlexSlider2 to add the functionality and submit a pull request. I gave it some thought, but since the project currently has 55 issues, 4 pull requests and a great deal of discussion around features, I decided to take the law into my own hands.</p>
<ul>
<li>The extension works by overriding a single aspect of the existing plugin, and then continuing with the original flow, so it doesn&#8217;t break anything.</li>
<li>Its easy to use, with just one line of code needed to set it up</li>
<li>It can be used today, without having to worry about being unable to upgrade FlexSlider2 for fear of losing functionality (if you built using my flexslider branch, you could be stuck having to choose between versions)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2012/flexslider-manual-direction-controls-jquery-plugin/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Running a local webserver from a Dropbox folder on OS X</title>
		<link>http://mark-kirby.co.uk/2012/running-a-local-webserver-from-a-dropbox-folder-on-os-x/</link>
		<comments>http://mark-kirby.co.uk/2012/running-a-local-webserver-from-a-dropbox-folder-on-os-x/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 12:19:18 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=996</guid>
		<description><![CDATA[I wrote a article a few years back on setting up virtual hosts on OS X so you can have lots of urls pointing to different folders on your mac, for testing websites. A good practice I have found is to run this folder out of Dropbox, so even if you haven&#8217;t committed changes to...]]></description>
				<content:encoded><![CDATA[<p>I wrote a article a few years back on <a href="http://mark-kirby.co.uk/2008/setting-up-virtual-hosts-on-os-x-leopard/">setting up virtual hosts on OS X</a> so you can have lots of urls pointing to different folders on your mac, for testing websites. A good practice I have found is to run this folder out of Dropbox, so even if you haven&#8217;t committed changes to a remote repository your work is always saved and backed up. To do this, there are a couple of extra steps you need to take, so I am writing this article here, do read the old one first to get the basics set up, and then come here for the updates.</p>
<h2>Preparation</h2>
<p>Follow the instructions on <a href="http://mark-kirby.co.uk/2008/setting-up-virtual-hosts-on-os-x-leopard/">setting up virtual hosts on OS X</a>.</p>
<p>Your httpd-vhosts.conf should look something like this:</p>
<pre class="brush: bash; title: ; notranslate">
NameVirtualHost *:80

&lt;VirtualHost *:80&gt;
	DocumentRoot &quot;/Users/markirby/Sites&quot; 
	ServerName localhost
&lt;/VirtualHost&gt;

&lt;Directory /Users/*/Sites/&gt;
    Options Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    AllowOverride All
    Order allow,deny
    Allow from all
&lt;/Directory&gt;
</pre>
<p>Make sure you have set &#8216;/private/etc/hosts&#8217;, &#8216;/private/etc/apache2/httpd.conf&#8217; and restarted apache, as per the instructions.</p>
<h2>Create a symlink to link the sites folder to dropbox</h2>
<p>Enter the following to create a symlink which will enable you to edit files in either location and have the changes backed up as you work.</p>
<pre class="brush: bash; title: ; notranslate">
ln -s ~/Sites ~/Dropbox/Sites
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2012/running-a-local-webserver-from-a-dropbox-folder-on-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to install static frameworks on Xcode 4</title>
		<link>http://mark-kirby.co.uk/2012/how-to-install-static-frameworks-on-xcode-4/</link>
		<comments>http://mark-kirby.co.uk/2012/how-to-install-static-frameworks-on-xcode-4/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 13:11:33 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=971</guid>
		<description><![CDATA[I had some issues installing OCMock on Xcode 4, and found the method to be documented differently in a number of places. Fortunately I&#8217;ve worked out how to do it and it can be applied to any static framework, so I&#8217;m sharing it here, using OCMock as an example. Download the framework and locate the...]]></description>
				<content:encoded><![CDATA[<p>I had some issues installing OCMock on Xcode 4, and found the method to be documented differently in a number of places. Fortunately I&#8217;ve worked out how to do it and it can be applied to any static framework, so I&#8217;m sharing it here, using OCMock as an example.</p>
<h2>Download the framework and locate the .a and header files</h2>
<p>Download the distribution files for the framework (for OCMock it comes as a dmg) and locate the .a and header files.</p>
<p>Here&#8217;s mine on my desktop:</p>
<p><a href="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-01-11-at-11.48.28.png"><img class="alignnone size-full wp-image-972" title="Files in desktop" src="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-01-11-at-11.48.28.png" alt="" width="618" height="311" /></a></p>
<h2>Copy these files into your source folder for your Xcode project</h2>
<ul>
<li>Make a subfolder in the root of your project folder named &#8216;Libraries&#8217; (or place it where you wish &#8211; I&#8217;ll refer to this as {LIBRARIES FOLDER})</li>
<li>Make a subfolder in this with the name of your Framework, e.g. OCMock &#8211; I&#8217;ll call this {FRAMEWORK FOLDER}</li>
<li>Copy the contents of your static framework in here, preserving the original folder structure</li>
</ul>
<p>When you are done your structure should look something like this:</p>
<p><a href="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-03-01-at-16.43.08.png"><img class="alignnone size-full wp-image-1000" title="Screen Shot 2012-03-01 at 16.43.08" src="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-03-01-at-16.43.08.png" alt="" width="600" height="281" /></a></p>
<p>&nbsp;</p>
<h2>Create references to the files in Xcode 4</h2>
<p>To set up references to these new files:</p>
<ul>
<li>Create a new folder in Frameworks called the same as {FRAMEWORK FOLDER}</li>
<li>Drag all the files inside your actual {FRAMEWORK FOLDER} into this one</li>
<li>Deselect &#8220;Copy items to your destination folder&#8221;</li>
<li>Select the targets you need &#8211; in OCMock case it will be the Unit Tests, but generally it will be the main target</li>
</ul>
<div><a href="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-01-11-at-12.19.45.png"><img class="alignnone size-full wp-image-979" title="Adding framework" src="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-01-11-at-12.19.45.png" alt="" width="600" height="319" /></a></div>
<p>You should now see the framework listed.</p>
<p>My project folder now looks like this:</p>
<p><a href="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-03-01-at-16.47.42.png"><img class="alignnone size-full wp-image-1001" title="Screen Shot 2012-03-01 at 16.47.42" src="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-03-01-at-16.47.42.png" alt="" width="260" height="293" /></a></p>
<p><em>I&#8217;ll add any more headers from other Frameworks  in subgroups with the name of the framework.</em></p>
<h2>Add your header search path to the target build settings</h2>
<ul>
<li>Select the target you added the framework for, in my case, &#8220;FrameworkInstallTests&#8221;.</li>
<li>Select the &#8220;Build Settings&#8221; tab</li>
<li>Search for &#8220;header search paths&#8221;</li>
<li>Locate &#8220;Header Search Paths&#8221; field</li>
<li>Double click the field</li>
<li>Check the &#8220;recursive&#8221; box</li>
<li>Add this to the settings:</li>
<li>$(PROJECT_DIR)/Libraries</li>
</ul>
<div><a href="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-01-11-at-12.56.31.png"><img class="alignnone size-full wp-image-981" title="Adding the header setting" src="http://mark-kirby.co.uk/wp-content/uploads/2012/01/Screen-Shot-2012-01-11-at-12.56.31.png" alt="" width="600" height="339" /></a></div>
<div></div>
<div><em>Note: if you didn&#8217;t place your framework files into the Libraries folder, it should point to whatever {LIBRARIES_FOLDER} is. Because you selected recursive, it will search down until it locates the headers.</em></div>
<h2>Add linker flag</h2>
<ul>
<li>Select the target you added the framework for, in my case, &#8220;FrameworkInstallTests&#8221;.</li>
<li>Select the &#8220;Build Settings&#8221; tab</li>
<li>Search for &#8220;linker flags&#8221;</li>
<li>Locate &#8220;Other Linker Flags&#8221; field</li>
<li>Double click the field</li>
<li>Add this:</li>
<li>-force_load $(PROJECT_DIR)/Libraries/{FRAMEWORK FOLDER}/{YOUR FRAMEWORK NAME}.a</li>
<li>Which should be the full path to the .a file for the framework, e.g. &#8220;$(PROJECT_DIR)/Libraries/libOCMock.a&#8221;</li>
</ul>
<h2>Restart Xcode and you should be done!</h2>
<p>Restart Xcode.</p>
<p>Leave any issues in the comments and I&#8217;ll see what I can do.</p>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2012/how-to-install-static-frameworks-on-xcode-4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Native vs Web with PhoneGap &#8211; which to use</title>
		<link>http://mark-kirby.co.uk/2011/native-app-vs-packaged-web-app-which-to-use/</link>
		<comments>http://mark-kirby.co.uk/2011/native-app-vs-packaged-web-app-which-to-use/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 12:55:59 +0000</pubDate>
		<dc:creator>Mark Kirby</dc:creator>
				<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://mark-kirby.co.uk/?p=954</guid>
		<description><![CDATA[I&#8217;ve been talking to people about native vs web for years, and don&#8217;t fall down on one single answer. I thought it was time to get these thoughts down on paper. I&#8217;ve framed the discussion around a series of questions you might ask about an app you are developing. Are you designing an app which...]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been talking to people about native vs web for years, and don&#8217;t fall down on one single answer. I thought it was time to get these thoughts down on paper. I&#8217;ve framed the discussion around a series of questions you might ask about an app you are developing.</p>
<h2>Are you designing an app which could be composed of native interface elements?</h2>
<p>If you are designing an app for a phone, I would strongly consider <strong>using</strong> <strong>native UI components where possible</strong>.</p>
<ul>
<li>Native UI components provide a unified experience</li>
<li>The user should already know how to use your app as it features recognisable interface elements</li>
<li>Time spent redesigning existing components is time that could be spent better on the overall experience and areas that really are specific to your domain</li>
</ul>
<p><a href="http://itunes.apple.com/us/app/metar-reader/id465765574?mt=8">METAR reader for iPhone</a> was built as a packaged web app, and does not use standard UI elements.</p>
<p><a href="http://mark-kirby.co.uk/wp-content/uploads/2011/12/mzl.epwurhsn.jpeg"><img class="alignnone size-medium wp-image-955" title="mzl.epwurhsn" src="http://mark-kirby.co.uk/wp-content/uploads/2011/12/mzl.epwurhsn-200x300.jpg" alt="" width="200" height="300" /></a></p>
<p>It looks very nice, it could be for Android as much as iPhone, but could also easily be created using well styled native UI elements which would make it easier for users to know what to do and give the app a more familiar feel. What are those bottom 3 tabs for?</p>
<p>Some apps don&#8217;t really need to use native interface elements&#8230;</p>
<h2>Apps with neutral designs</h2>
<p>If you are designing a tablet app you may find yourself designing something which is neutral, more like a website, which doesn&#8217;t use native UI components. On tablet devices apps tend to follow less of a standard UI look, so there is less consistency anyway.</p>
<p>The <a href="http://apps.ft.com/ftwebapp/">FT web app</a> looks the same on all devices, and doesn&#8217;t lend itself to using native UI elements.</p>
<p><img class="alignnone size-medium wp-image-961" title="FT-app" src="http://mark-kirby.co.uk/wp-content/uploads/2011/12/FT-app-300x205.jpg" alt="" width="300" height="205" /></p>
<p>This app can look like this on any device, it uses no common interface elements.</p>
<h2>Recreating native interface elements with web technologies is a bad idea</h2>
<p>Recreating standard UI components in web can lead to the &#8216;<strong>uncanny valley</strong>&#8216; effect, where the app looks native but doesn&#8217;t feel quite right, as <a href="http://hackerne.ws/item?id=2982224">this discussion</a> describes.</p>
<p>At the moment you will never get a PhoneGap app with fake UI elements working as well as a native app with real UI components. There is an unobtainable final 5% of performance that can&#8217;t be gained.</p>
<p>A <strong>native app</strong> can work as well any on the device and <strong>feels solid and well produced</strong>.</p>
<h2>Native interface elements differ between platforms</h2>
<p>Each platform has a different standard look and feel.</p>
<p>Facebook on iPhone:</p>
<p><img class="alignnone size-medium wp-image-962" title="facebook-for-iphone-13" src="http://mark-kirby.co.uk/wp-content/uploads/2011/12/facebook-for-iphone-13-200x300.jpg" alt="" width="200" height="300" /></p>
<p>Facebook on Android:</p>
<p><img class="alignnone size-medium wp-image-963" title="Foreman_11657656_1024_38814_424516450908_74769995908_4660025_5606091_n_257x380" src="http://mark-kirby.co.uk/wp-content/uploads/2011/12/Foreman_11657656_1024_38814_424516450908_74769995908_4660025_5606091_n_257x380-202x300.jpg" alt="" width="202" height="300" /></p>
<p>Facebook on Windows Phone:</p>
<p><img class="alignnone size-medium wp-image-964" title="Facebook-Windows-Phone-7" src="http://mark-kirby.co.uk/wp-content/uploads/2011/12/Facebook-Windows-Phone-7-189x300.jpg" alt="" width="189" height="300" /></p>
<p>Each version of the app is consistent with the platform running it, and facebook lends itself to this. You certainly couldn&#8217;t put the iPhone design onto an Android device without it looking fake.</p>
<p>If you want to develop an app with a consistent UI on the platform running it (and in most cases you should), you need to <strong>redesign the app for every platform</strong>.</p>
<p>There will therefore be <strong>additional CSS work to do on every platform</strong> you want the app to run on, but with web you can share the core code. Even if you don&#8217;t redesign the app for other devices, browser differences mean you may have inconsistencies which will need to be tested for and worked out.</p>
<h2>Neutral designs work well as packaged web apps</h2>
<p>If your app doesn&#8217;t contain any native UI elements (like the FT app) it can easily be produced with web technologies without feeling fake.</p>
<p>The user has no expectations related to the UI elements you are using, so performance issues are reduced.</p>
<p>It will be easier to create custom UI elements with web technologies than using native tools to do so, so the project can be delivered quicker.</p>
<p>No redesign will be needed when putting the app on other devices, so minimal effort will be needed to target multiple platforms.</p>
<h2>To conclude&#8230;</h2>
<p>Don&#8217;t recreate native experiences with packaged web apps.</p>
<p>Use packaged web apps to create platform neutral experiences that can run across many platforms, none of which resemble the native experience on any single platform.</p>
]]></content:encoded>
			<wfw:commentRss>http://mark-kirby.co.uk/2011/native-app-vs-packaged-web-app-which-to-use/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
