<?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>migrant studios</title>
	<atom:link href="http://blog.migrantstudios.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.migrantstudios.com</link>
	<description>The latest news about our products and services</description>
	<lastBuildDate>Fri, 29 Mar 2013 15:04:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='blog.migrantstudios.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>migrant studios</title>
		<link>http://blog.migrantstudios.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://blog.migrantstudios.com/osd.xml" title="migrant studios" />
	<atom:link rel='hub' href='http://blog.migrantstudios.com/?pushpress=hub'/>
		<item>
		<title>RESTful Web Services for your Oven</title>
		<link>http://blog.migrantstudios.com/2013/03/13/restful-web-services-for-your-oven/</link>
		<comments>http://blog.migrantstudios.com/2013/03/13/restful-web-services-for-your-oven/#comments</comments>
		<pubDate>Thu, 14 Mar 2013 01:25:43 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[API Design Patterns]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[information architecture]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=322</guid>
		<description><![CDATA[There has been much discussion surrounding RESTful web services as a means of defining architectural best practices. Rails (http://rubyonrails.org) was a strong catalyst for the convergence of a specific naming standard, choosing convention over configuration. By creating classes with specific names, we can match instances of these classes to records in similarly named tables. The [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=322&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>There has been much discussion surrounding RESTful web services as a means of defining architectural best practices. Rails (<a href="http://rubyonrails.org" rel="nofollow">http://rubyonrails.org</a>) was a strong catalyst for the convergence of a specific naming standard, choosing convention over configuration. By creating classes with specific names, we can match instances of these classes to records in similarly named tables. The Device model can be automatically mapped to rows in the devices table, and as long as the names follow the convention exactly, everything just magically works. This decision to adopt what is known as the ActiveRecord pattern has influenced the best practice for object modeling and serialization. However, it may not always be the best strategy. As we build web services, it&#8217;s important to consider the architectural implications of one design over another. Let&#8217;s explore some options.</p>
<h1>Case Study: Web Service for Oven</h1>
<p>If we&#8217;re to consider a web service, let&#8217;s push the envelope a bit to include a real world example that might arise in the next few years. As of this writing, there are light bulbs on the market that can be controlled by web service requests over wifi. Philips has published the Hue API, which allows developers to build apps that interact with the light fixtures to change things like color and brightness. It won&#8217;t be long before there will be a product on the market that allows a web service client to adjust the temperature of the oven in your home via wifi. You&#8217;ll probably open an app on your mobile device to monitor data from the oven, adjust cooking temperature and time, and maybe even define a temperature profile to cook at 250F for 15min and then 450F for 1min. For ovens that support it, we could enable or disable the convection system to turn on/off at specific times during the baking cycle.</p>
<p>So, what does that look like in web service parlance?</p>
<h1>Strategies</h1>
<p>There are several distinct approaches to achieving the desired result. The one we choose in any given situation must be dictated by the relative merits of applying the technique to its unique scenario.</p>
<h2>1. Action-Based GET Command</h2>
<pre>GET /bake?temp=350&amp;time=30&amp;preheat=true</pre>
<p>What we&#8217;re saying here is that <strong>bake</strong> is a special action, that the target temperature is 350 (presumably Fahrenheit), cook time is 30 (presumably minutes), and the oven should preheat to target temperature before starting the cook timer. That&#8217;s a lot of assumptions, but these parameters are typically well documented in the provider&#8217;s API specification. For standards that find their way into consumer electronics, there is a document somewhere on the web that explains the options and their possible values, if any.</p>
<p>This sort of strategy works well for tasks that are simple enough as to be explained in a small number of input parameters. It is expected that the task will begin right away. No response value is expected. When the task completes, the oven will return to its idle state. Note that this strategy works only when the oven behaves like a sequential queue. There is one oven and it can cook one thing at a time. A separate task opens the door, removes the cake, and loads the pan for the next cake into the oven. In all likelihood, that would be a human task.</p>
<h2>2. Timer-Based Request Sequence</h2>
<pre>After 0sec PUT /ovens/1.json {"oven":{"target_temperature":350}}
After 1800sec PUT /ovens/1.json {"oven":{"target_temperature":nil}}</pre>
<p>This more closely follows the Rails style. We define a specific instance of an Oven with <strong>/ovens/1</strong>. We specify the communication language with the format extension, in this case <strong>json</strong>. We send a namespaced attribute hash, so the service can easily map the content body to an object in the service&#8217;s object model. With the class name matching the root key in the hash, the deserializer can magically find the actual oven for the given id (defined in the path, in this case 1) and update its state with the given attributes.</p>
<p>Observant readers will note that this strategy eliminates the possibility of a preheat period. This illustrates a deficiency in the architecture of this strategy. It lacks the ability to react to changes in the state of the systems being controlled. More specifically, this system requires frequent polling to achieve the preheat feature. Attempts to closely approximate this feature would likely result in a log like this:</p>
<pre>PUT /ovens/1.json {"oven":{"temperature":250}}
GET /ovens/1.json -&gt; {"oven":{"actual_temperature":75}}
GET /ovens/1.json -&gt; {"oven":{"actual_temperature":125}}
GET /ovens/1.json -&gt; {"oven":{"actual_temperature":175}}
GET /ovens/1.json -&gt; {"oven":{"actual_temperature":225}}
GET /ovens/1.json -&gt; {"oven":{"actual_temperature":250}}
PUT /ovens/1.json {"oven":{...}}</pre>
<h2>3. Task-Based Approach</h2>
<pre>POST /profiles.json {"profile":{"oven_id":1}} -&gt; {"profile":{"id":123,"oven_id":1,"started_at":nil,"ended_at":nil}}
POST /profiles/123/items.json {"item":{"temperature":250,"delay":0}}
POST /profiles/123/items.json {"item":{"temperature":nil,"delay":1800}, "condition":{"min_temperature":250}}
GET /profiles/123/start.json -&gt; {"profile":{"id":123,"oven_id":1,"started_at":"201303131234.567Z","ended_at":nil}}</pre>
<p>This is a nice approach when you need to schedule things in advance or if you have complex sequences involving many set points over time. The inclusion of the condition parameter enables the preheat feature. It&#8217;s worth mention here that this approach implies a sophisticated web service interface to the oven.</p>
<h1>In Stores Soon!</h1>
<p>In order to support the kind of command capabilities described here, the appliance manufacturers will rely on industry standards. That means the commercial sector will largely dictate the direction and evolution of these standards. We need to build some rather sophisticated command and control systems, following RESTful best practices, so the appliance manufacturers can have something to integrate into their products. If there is no clear standard, they&#8217;ll lose their way. Worst case, we end up with a widely adopted system no one can actually use; or we have the Bluray vs HD DVD battle.</p>
<p>Inevitably, what will most likely happen is there will be a handful of home automation control system manufacturers that emerge with smart appliance controls that integrate with &#8220;smart appliances&#8221; (those that support early drafts of a standard). These home automation companies will drive the development of a standard architecture, in much the same way that web browser companies drive the evolution of the HTML and CSS standards. In any case, it&#8217;s an interesting way to think about configuring the settings on your oven.</p>
<p><em><strong>Endnote:</strong></em> a quick shout out to Justin Davis (@jwd2a), founder of Madera Labs (<a href="http://maderalabs.com" rel="nofollow">http://maderalabs.com</a>), for the topic. His tweet about RESTful web services to control household appliances is what inspired this post.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/322/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/322/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=322&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2013/03/13/restful-web-services-for-your-oven/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>Threshold Dynamics: Supply-Driven vs Demand-Driven</title>
		<link>http://blog.migrantstudios.com/2012/12/17/threshold-dynamics-supply-driven-vs-demand-driven/</link>
		<comments>http://blog.migrantstudios.com/2012/12/17/threshold-dynamics-supply-driven-vs-demand-driven/#comments</comments>
		<pubDate>Mon, 17 Dec 2012 16:02:31 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[information architecture]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=318</guid>
		<description><![CDATA[In a perfect world, we design for an isolated set of conditions, call it the &#8220;equilibrium state,&#8221; and use linear first order system response as an approximation to model the actual system behavior. That works for many systems, where a single effect dominates the force balance. However, many systems can not be adequately described with [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=318&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>In a perfect world, we design for an isolated set of conditions, call it the &#8220;equilibrium state,&#8221; and use linear first order system response as an approximation to model the actual system behavior. That works for many systems, where a single effect dominates the force balance. However, many systems can not be adequately described with a linear first order model. <a title="bus+ web site - opens in new window" href="http://buspl.us" target="_blank">bus+</a> is one such system, as it requires many vehicles to provide infrastructure support for many passengers, additionally requiring location-based matching.</p>
<p>Consider three cases from the passenger&#8217;s perspective:</p>
<ul>
<li><span style="line-height:13px;">Multiple candidate vehicles available</span></li>
<li>One  candidate vehicle available</li>
<li>Zero candidate vehicles available</li>
</ul>
<p>In the first scenario (multiple candidate vehicles), the primary challenge is filtering candidates and matching them to passengers efficiently. This system is driven by supply dynamics. For any one passenger (consumer), several candidate vehicles (producers) must compete for the fare (fee for service). bus+ defines a mechanism to govern the matching process fairly and effectively compensates for scale. This solution works well for this scenario, but it is overkill for the second scenario.</p>
<p>The second scenario (one candidate vehicle) is the simplest case. The matcher found a single candidate vehicle, so the standard bidding process is skipped. The passenger is assigned to the vehicle immediately.</p>
<p>In the third scenario (zero candidate vehicles), the system is inverted, instead driven by demand. As passenger demand surpasses vehicle availability, some process must govern the assignment of passengers that are waiting for vehicles to become available. This means introducing a location-sensitive queueing system to manage passengers. It also means adding a real-time human resources paging system to enable automated demand-driven notification of &#8220;on call&#8221; drivers &#8211; those who are not &#8220;on duty&#8221; but also not in a &#8220;do not disturb&#8221; state.</p>
<p>All three scenarios serve similar goals &#8211; matching passengers to vehicles. Each scenario represents a unique puzzle, governed by very different rules. The system as a whole must be able to satisfy all of its operating parameters, spanning all three scenarios. As the design and architecture of bus+ matures, we&#8217;re delighted to find elegant and compelling solutions to these evolving challenges. I&#8217;m pleased to share those solutions with others, in hopes that we might all benefit and contribute positively to this universal problem.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/318/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/318/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=318&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/12/17/threshold-dynamics-supply-driven-vs-demand-driven/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>Device Testing for Complex Geo-Sensitive Systems</title>
		<link>http://blog.migrantstudios.com/2012/12/02/device-testing-for-complex-geo-sensitive-systems/</link>
		<comments>http://blog.migrantstudios.com/2012/12/02/device-testing-for-complex-geo-sensitive-systems/#comments</comments>
		<pubDate>Mon, 03 Dec 2012 00:05:29 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[device testing]]></category>
		<category><![CDATA[ghost town]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[launch]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=314</guid>
		<description><![CDATA[I was demonstrating bus+ at a party this weekend, and I encountered a problem that only really comes up in special cases. Since I specialize in solving hard problems, special cases are the norm in my daily work. In the case of bus+, there is a passenger app and a driver app. Passengers request point-to-point [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=314&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I was demonstrating <a title="bus+ website - Opens in new window" href="http://buspl.us" target="_blank">bus+</a> at a party this weekend, and I encountered a problem that only really comes up in special cases. Since I specialize in solving hard problems, special cases are the norm in my daily work. In the case of bus+, there is a <a title="bus+ passenger app - opens in new window" href="https://github.com/agoodman/busplus-ios" target="_blank">passenger app</a> and a <a title="bus+ driver app - opens in new window" href="https://github.com/agoodman/busplus-driver-ios" target="_blank">driver app</a>. Passengers request point-to-point transport. Automated dispatch matches passengers to drivers. Drivers pick up and drop off passengers. When there are multiple apps for different kinds of users, all coordinating together within a system, it can be tricky to do device testing. If, for example, one app must be in the foreground at the time a message is received in order to function correctly, it can be a challenge to test two or more of those apps on the same device. One app is foregrounded to initiate the producer action. Then, the other app must be quickly brought to the foreground to handle the message from the producer. The consumer app must then be backgrounded in favor of the producer app, where the response message from the consumer is handled. This makes for an ultimately ineffective demo.</p>
<p>There is also a bigger problem of geo-sensitivity. It is physically impossible to test all the bus+ features on a single device. Once a passenger is assigned to a vehicle, we use geo-fencing to detect pickup and drop-off and to notify the passenger of the arrival time of their ride. As the vehicle moves, it eventually crosses a virtual boundary in geo space, which triggers an alert to the passenger, saying &#8220;i&#8217;m 5mins away.&#8221; If the driver app is running on the same device as the passenger app, the vehicle will be detected as &#8220;arrived&#8221; immediately upon assignment, resulting in a flurry of messages that are not representative of real world app behavior. The only way to test the full behavior is to use separate devices. Then, the problem changes from a technical one to a social one.</p>
<p>So far, the best solution I&#8217;ve found to multiple device testing is to reach out to developer communities or friends and family to find willing participants. Realistically, if you can&#8217;t find ten people willing to test your system, you&#8217;re probably not addressing an urgent market need. If you can find people who are your target market who are also willing to participate in a private ad hoc beta, you&#8217;ll be that much closer to proving your concept and taking it to market. Regardless of your audience during private testing, you&#8217;ll need to coordinate with your test users to make sure they know what you expect of them. If, as in the case of bus+, your system involves user actions outside the app (driving somewhere to pick up someone they may not know), you need to be very clear up front that you need more from them than just a few minutes messing around on their mobile device. We&#8217;re nearly to this point with bus+, so I&#8217;ll need to design a coordination plan for my test users, so they&#8217;re all working together. If someone is testing passenger workflow when no one is actively on duty with the driver app, the passenger is doomed to disappointment. By communicating with the test team, we can minimize the total wall clock time we need to find the broken bits and fix them.</p>
<p>Ultimately, there&#8217;s a leap of faith the developer must take when publishing this kind of app. The first day we sell our driver app, we expect to see a lot of email traffic from drivers wondering why the app doesn&#8217;t do anything after they set it up. For this app, the driver and passenger apps will hit the App Store at the same time. However, there will definitely be a period of time when passengers are disappointed because there are no vehicles in their area yet. We&#8217;ll use email campaigns to mitigate as much of the disappointment as we can, but we expect to see low ratings and bad reviews until the early adopters populate the ghost town. We can also counter the ghost town effect with targeted marketing and strategic partnerships. My hope is to approach Super Shuttle, Yellow Cab, and county transit officials to join as pre-launch partners, so we have sufficient user base on the driver side to meet the sustained demand we&#8217;ll see from the passenger side.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/314/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/314/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=314&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/12/02/device-testing-for-complex-geo-sensitive-systems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>Information Architecture Diagrams</title>
		<link>http://blog.migrantstudios.com/2012/11/25/information-architecture-diagrams/</link>
		<comments>http://blog.migrantstudios.com/2012/11/25/information-architecture-diagrams/#comments</comments>
		<pubDate>Sun, 25 Nov 2012 20:50:37 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[diagram]]></category>
		<category><![CDATA[information architecture]]></category>
		<category><![CDATA[interactivity]]></category>
		<category><![CDATA[user experience]]></category>
		<category><![CDATA[visualization]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=304</guid>
		<description><![CDATA[I&#8217;m a huge fan of UML. While I haven&#8217;t really written much about it, I have used UML for many years to visualize complex interactions between systems in time and space. UML provides a set of diagrams that encapsulate key perspectives of a system. Use case diagrams illustrate the ways a user might interact with [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=304&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m a huge fan of UML. While I haven&#8217;t really written much about it, I have used UML for many years to visualize complex interactions between systems in time and space. UML provides a set of diagrams that encapsulate key perspectives of a system. Use case diagrams illustrate the ways a user might interact with the various components that make up a system. Object diagrams show a detailed definition of the information being manipulated and how it relates to other information. It&#8217;s nice to see a visual representation of time and sequence in activity diagrams. These graphical reminders give people an anchor to stabilize their understanding of a system described in words elsewhere. However, none of the diagrams in the UML toolkit shows how everything fits together. For that, we need a new format, which I call an information architecture (IA) diagram.</p>
<p>This is not a new term, but I believe it is new in this context. There are three key aspects of an IA diagram &#8211; object model, user stories, sequence. When systems have multiple actors, all working together to achieve some task, it is essential that the architect maintain a keen awareness of choreography. In dance, someone must coordinate all the dancers to work in harmony, or the lead ballerina may take an embarrassing fall, kicked in the face by her partner&#8217;s badly timed arabesque. Similarly in a producer-consumer model, we normally pay for goods before we transport them home. I doubt many retailers would be fond of a business model where the purchase was made on delivery, especially since most shoppers do not have point-of-sale card swipe equipment in their homes. Order matters. It&#8217;s important that each actor take appropriate action at appropriate time along a sequence. The goal of an IA diagram is to distill the critical interactivity idioms into one representation, illustrating the point in time of each action, the actor, and the information being manipulated.</p>
<p>Actions (CRUD operations on RESTful endpoints) originate from the actor timeline and point to their appropriate object. The single and double arrows in the object model represent belongs-to and has-many relationships, respectively. An envelope symbol pointing to an actor timeline is used to denote asynchronous notification, optionally with a label. Notifications stemming from an object represent on-create, on-update, etc, event triggers. As with the systems represented in an IA diagram, a text description of the diagram itself can not do justice to the glory that is a well-executed example. Without further ado, I present the following <a href="https://github.com/agoodman/bus_plus/wiki/Passenger-Workflow-Sketch" target="_blank">sketch of the passenger workflow from BusPlus</a> as self-evident.</p>
<p>My most significant inspiration for developing this diagram technique comes from Edward Tufte, a master craftsman in the art of visualization. His book, The Visual Display of Quantitative Information, is <a title="The Visual Display of Quantitative Information - Amazon" href="http://www.amazon.com/gp/product/0961392142/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0961392142&amp;linkCode=as2&amp;tag=migrastudi-20" target="_blank">available on Amazon</a>. It is well respected as one of the most influential texts in the field.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/304/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/304/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=304&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/11/25/information-architecture-diagrams/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>Geospatial Visualization &amp; Interactivity Techniques</title>
		<link>http://blog.migrantstudios.com/2012/10/27/geospatial-visualization-interactivity-techniques/</link>
		<comments>http://blog.migrantstudios.com/2012/10/27/geospatial-visualization-interactivity-techniques/#comments</comments>
		<pubDate>Sat, 27 Oct 2012 22:10:41 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[geospatial]]></category>
		<category><![CDATA[interactivity]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Rakiteer]]></category>
		<category><![CDATA[Tour Wrist]]></category>
		<category><![CDATA[user experience]]></category>
		<category><![CDATA[visualization]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=310</guid>
		<description><![CDATA[Lots of apps use search and browse features to expose large catalogs of useful information. In recent evolution of the market, this information has begun to include geospatial content, joining the location and time stamps along with other data. It could be a location-tagged picture or status update. It could be some traffic data, alerting [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=310&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Lots of apps use search and browse features to expose large catalogs of useful information. In recent evolution of the market, this information has begun to include geospatial content, joining the location and time stamps along with other data. It could be a location-tagged picture or status update. It could be some traffic data, alerting you of specific roads to avoid at specific times. In the retail space, we&#8217;ve encountered a challenging intersection of technology, interactivity, and human behavior.</p>
<h2>Background</h2>
<p>I&#8217;ve been developing the infrastructure and mobile and web apps for <a href="http://rakiteer.com" target="_blank">Rakiteer</a> off and on for about a year and full-time for the last three months. In a nutshell, we tag sale items with a location and time stamp, along with details about the product and make them available to consumers for purchase through their mobile device. You can also think of this as a real-time feed, ordered by time stamp, giving consumers a stream of deals as they&#8217;re discovered. Remember, these are deep discount deals on scarce items, usually no more than a few units in stock, not a product line available everywhere in abundance. The challenge: organizing data by relevance in time and space.</p>
<h2>Solution 1</h2>
<p>At first, we believed there were only two modes people might want to use &#8211; nearby and worldwide. We know that the majority of users will want to see things nearby their current location. Shopping is a largely impulse-driven emotional decision process. People are far more interested in deals in local shops than they are in deals across the country. A sure-fire way to guarantee user disappointment is to show them awesome deals on things they love in stores thousands of miles away. Fortunately, the nearby filter is pretty easy. We use a bounding quadrangle (four lat/lng points or a center point and grid size) to constrain in space, and the results are ordered in time and paginated in groups of a hundred or less. Small result sets can even be ordered by point-to-point distance, as the square root required to compute the distance is manageable if you only need to calculate fifty values, but that sort action happens on the device, not on the server. For the worldwide mode, though, we found ourselves questioning the relevance and value to the consumer. We didn&#8217;t see any meaningful use of data from all over the world, ordered in time. That seems like watching the global twitter feed &#8211; useless information overload.</p>
<p>Let&#8217;s take a step back for a moment. What does nearby mean? Well, we normally think it means near our current location, but it can also mean near a different location. As we fold that into our understanding of the user&#8217;s needs, we begin to appreciate something else. Maybe the user will want to look for items near a place they plan to be at some later point in time. Let&#8217;s say I&#8217;m planning to visit my family in Maryland for the holidays. I know that Delaware has no sales tax, so I might want to discover deals within an hour&#8217;s drive of my grandparents&#8217; house, so I can take advantage of the tax haven. With the nearby/worldwide toggle, I can&#8217;t find this information until I&#8217;m already there, and by the time I get there, I&#8217;ve probably forgotten I was going to go shopping.</p>
<h2>Solution 2</h2>
<p>After realizing the nearby/worldwide mode switch doesn&#8217;t really work as well as we thought, I set out to find a new interactivity idiom to meet our needs. Ironically, it was a user complaint that crystallized the direction we took. Someone complained that the app was not showing them any results. As we walked through the guide questions to help us understand what the user&#8217;s expectations were, it became clear that the user had declined to grant our app access to read their current location. It had simply never occurred to us that someone might decline that service. By design, the app is pretty much useless if you don&#8217;t allow location services. After this experience, I knew we had to find a solution that worked even when the user declines location services. In the end, I discovered a far superior solution that does so much more to help the user find value than we ever could have achieved with the previous solution.</p>
<p>Now, the user selects the search region by navigating the visible bounds of a map. This provides a simple, intuitive control that clearly defines the geospatial bounds of the search, while also providing immediate feedback about whether the current region contains any results. At all map scales, we display a translucent solid color overlay indicating rectangular areas of the map where there are deals. At small scales, we display the locations of deals as pins, telling you exactly where those items are relative to your current location. With this design, the user never needs to guess an area where there might be some valuable data. They simply zoom the map out a bit and look for red regions. At the moment, we&#8217;re only using a single color, but the goal of a heat map is to indicate a continuum of content, where bright spots are highly active data-rich areas and dark spots are areas with stale data. We&#8217;ll eventually use shades of color to represent relative densities between grid cells, but thanks to our architecture, we&#8217;ll have a lot more options for visualizing the information in a compelling and useful overlay.</p>
<h2>Infrastructure &amp; Performance</h2>
<p>This innovation has dramatically improved the usability and development of user confidence in our brand and largely eliminates the &#8220;ghost town&#8221; effect of location-sensitive apps, showing no data for your area because you&#8217;re the first to use the app there. But, observant readers will probably be saying &#8220;uh, you can&#8217;t index the internet on your user&#8217;s device, so how are you distributing that data?&#8221; Let&#8217;s dig into how we&#8217;ve achieved our scalable heat map solution.</p>
<p>My first foray into heat maps was in building one for <a href="http://tourwrist.com" target="_blank">Tour Wrist</a>. We encountered much the same problem with Tour Wrist as we do with Rakiteer. How do we help users find results they want, especially when the data itself is not easily searchable? Sure, we used tagging and schema-defined meta data to describe each tour, but there is a lot of unsearchable image data there. More importantly, the location problem persists. If you&#8217;re looking at a nationwide map view, you can&#8217;t show all the pins for all the locations in the country, and paginating the list means cutting out a lot of data. A heat map is the answer.</p>
<p>Heat maps visualize density information. By slicing the world up into a discrete grid, we can easily represent aggregated data density information with colored overlays. When I built the heat map for Tour Wrist, I naively chopped up the world into a 1deg grid by latitude and longitude. That makes a 180&#215;360 grid, or 64,800 cells. The heat map aggregation system is simple. Any time a record is created, we check to see which grid cell contains the location stamped on the record. We increment a counter on that grid cell. If a record is destroyed, we decrement the counter. Tour Wrist hosts 3D panoramic photos, called tours, from photographers all over the world, so the grid needed to span the entire globe. For Rakiteer, we&#8217;re focusing on America for now, so we didn&#8217;t need the global grid. Also, for Tour Wrist, we used an eager loading approach, where we create all the cells for the whole world up front and then update the records as data flows through the system. For Rakiteer, we use a revised lazy loading approach, only creating a grid cell when there&#8217;s data to represent there. This is an important distinction, as it eliminates the need to filter out records with zero values when rendering the overlay.</p>
<p>So, now we have all this wonderful elegant data structure for storing the information efficiently on the web service side. We still need to convey that data to every wireless client in our app&#8217;s ecosystem. We can have the map overlay render based on a web service call, allowing us to construct the overlay showing only data for the selected region. That would seem to make sense, since you&#8217;d want to minimize the information you need to send from server to client in order to have sufficient data to render the overlay. However, it really makes more sense to sync the entire heat map data set to the device, so you can render the map without needing to make a slow web service call in the process. If you already have all the data locally, you can render quickly.</p>
<p>We sync the heat map using a progressive sync technique. The first time a user launches the app, we sync the entire collection of grid cells and store the time stamp of the request. Then, every subsequent time the heat map syncs, it only requests grid cells that have changed since the last sync. We can do this because each grid cell maintains a record of its creation date and last update date. This allows the web service to maintain current copies of a large sparse data set on every user&#8217;s device efficiently. Since the heat map data is updated in real-time with the creation/destruction of the data being aggregated, the user&#8217;s heat map data is always kept current.</p>
<p>By considering the big picture of how the data is consumed, how the user interacts with it, and the performance impact of distribution, we were able to find an elegant, scalable, high performance heat map solution that integrates very easily with any web service and/or MapKit app. We are planning to package the heat map code into a gem and publish it sometime this year, so other Rails developers can leverage our work to bring value to their users.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/310/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=310&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/10/27/geospatial-visualization-interactivity-techniques/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>What Does Mitt Mean? A Social Experiment</title>
		<link>http://blog.migrantstudios.com/2012/10/17/what-does-mitt-mean-a-social-experiment/</link>
		<comments>http://blog.migrantstudios.com/2012/10/17/what-does-mitt-mean-a-social-experiment/#comments</comments>
		<pubDate>Wed, 17 Oct 2012 19:55:54 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[Editorial]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=307</guid>
		<description><![CDATA[I&#8217;d like to preface all of this with a simple assertion. My political beliefs have no influence over the content of this post. I merely provided a tool for others to share their feelings. The entire experiment was done anonymously, despite substantial additional data mining opportunities with authenticated sessions. At around 10:30am this morning, I [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=307&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;d like to preface all of this with a simple assertion. My political beliefs have no influence over the content of this post. I merely provided a tool for others to share their feelings. The entire experiment was done anonymously, despite substantial additional data mining opportunities with authenticated sessions.</p>
<p>At around 10:30am this morning, I had an idea. There&#8217;s been so much conversation in news and talk shows in America about the vagueness and lack of specificity in Mitt Romney&#8217;s campaign rhetoric. I thought to myself, what does he mean? Then, because my brain is highly susceptible to tangential effects, I thought about what the word &#8220;mitt&#8221; means, how many possible interpretations there are, just of that word alone. As I sat there, expanding on all the various words that came to mind when thinking of this one word, I began to realize that lots of other people must be having similar thoughts. I especially enjoyed <a href="http://romneytaxplan.com" target="_blank">http://romneytaxplan.com</a>, so I thought I&#8217;d try my hand at achieving a similar goal, but collecting interesting data about people&#8217;s raw emotional reaction to the word &#8220;mitt.&#8221;</p>
<p>And thus, <a href="http://whatdoesmittmean.com" target="_blank">http://whatdoesmittmean.com</a> was born. I checked on the domain. It was available. I bought it immediately, and set about to build an app that would capture the gut reactions people have. It is designed simply, with the intention to minimize bias in the user&#8217;s response. I considered showing pictures of Mitt Romney or oven mitts or baseball gloves or kittens or cute little girls playing in the snow. In the end, though, I concluded that any visual cue would result in a strong perceptual bias. Given the point of the experiment &#8211; a measurement of unfiltered reaction to a word &#8211; it felt best to bound the perceptual model with a short and highly vague prompt.</p>
<p><strong>What Does Mitt Mean?</strong></p>
<p>With just that one prompt, we invite users to enter some things that come to mind when they think of that sentence. We even give a placeholder in the text field, saying &#8220;first thing that comes to mind,&#8221; hoping to inspire a more visceral experience. No time to think, just say the first thing that comes to you.</p>
<p>Right now, we still have only a small data set from the few dozen folks who have visited the app and contributed. As time passes and I continue to promote the experiment in social media over the next few weeks, I expect to improve on the presentation of data. There will be a word cloud and maybe a top ten words list. I&#8217;m open to suggestion, too, so if anyone has an idea for different interesting ways to represent the information we&#8217;re collecting, please comment on this post. Also, please tell your friends. I&#8217;ll be adding social media sharing widgets to the app shortly to make it easier to share it. If you care about the answer to that question, please spread the word. As more people see the question, we have more opportunity to collect answers. Those answers help us better understand each other and our general impression of Mitt Romney.</p>
<p>Endnote: I love the fact that I can go from absolutely nothing, through concept, to an app running on a new domain in under 2hrs. That&#8217;s the power of Rails and Heroku.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/307/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/307/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=307&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/10/17/what-does-mitt-mean-a-social-experiment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>Cost-Efficient Web Service Hosting with Heroku, A Case Study</title>
		<link>http://blog.migrantstudios.com/2012/09/20/cost-efficient-web-service-hosting-with-heroku-a-case-study/</link>
		<comments>http://blog.migrantstudios.com/2012/09/20/cost-efficient-web-service-hosting-with-heroku-a-case-study/#comments</comments>
		<pubDate>Fri, 21 Sep 2012 02:12:18 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[analytics]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[uptimetry]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=299</guid>
		<description><![CDATA[We use Heroku for all web service hosting for our projects. It&#8217;s free to get started, and the free service level offers substantial performance. One of the most common concerns I hear from clients and venture partners is the fear that hosting costs will eventually be prohibitively expensive, as the system scales. I&#8217;d like to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=299&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>We use Heroku for all web service hosting for our projects. It&#8217;s free to get started, and the free service level offers substantial performance. One of the most common concerns I hear from clients and venture partners is the fear that hosting costs will eventually be prohibitively expensive, as the system scales. I&#8217;d like to offer the following case study as evidence of the actual cost per performance.</p>
<h3>Case Study: Uptimetry</h3>
<p>We&#8217;re very proud of our URL monitoring service, <a title="Uptimetry website" href="http://uptimetry.com" target="_blank">Uptimetry</a>, which we&#8217;ve been operating for about 18mo. It provides a simple service of polling web resources regularly to verify availability and validate content. Last month, the Uptimetry system processed a little over two million requests. Using the New Relic performance monitoring tool (a free addon), I can gain visibility into all sorts of interesting metrics. For the purposes of this study, we&#8217;ll focus on the web transaction reporting features. Using this tool, I was able to determine the average request response time and the average CPU usage required to process all the requests. Uptimetry has an average response time of about 100ms and uses about 10% CPU. This is with a single server instance &#8211; what Heroku calls a &#8220;dyno.&#8221; The first dyno is free, and you can scale up to a max of 100.</p>
<p>It follows logically that a single dyno could handle twenty million requests per month, assuming the average response time remains constant at 100ms. If we stretch our assumption to maintain the response time as the system scales, the upper bound of capacity would be 100 dynos running 100% CPU. That works out to two billion requests per month for a price of about $3600/mo, or about <strong>$1.80/mo per million requests</strong>. Of course, this number is based largely on the 100ms response time, which is fairly aggressive, even by 2012 standards. Our conservative target is typically 500ms. I can&#8217;t exaggerate how happy I am to be able to claim actual performance that is 5x better than our target. I&#8217;m even happier to say it costs us nothing to deliver that.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/299/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/299/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=299&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/09/20/cost-efficient-web-service-hosting-with-heroku-a-case-study/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>Effortless Push Messaging with Grocer</title>
		<link>http://blog.migrantstudios.com/2012/09/11/effortless-push-messaging-with-grocer/</link>
		<comments>http://blog.migrantstudios.com/2012/09/11/effortless-push-messaging-with-grocer/#comments</comments>
		<pubDate>Tue, 11 Sep 2012 15:06:29 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[push messaging]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=278</guid>
		<description><![CDATA[I had the distinct privilege of discovering Grocer last Thursday. Frequent readers will know that I&#8217;m a huge fan of simple APIs and improving the developer experience (DX). Anyone who has built a web service can tell you there&#8217;s a whole lot of common ground that every app must offer. That means a lot of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=278&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I had the distinct privilege of discovering <a title="Grocer on github - opens in new window" href="https://github.com/highgroove/grocer" target="_blank">Grocer</a> last Thursday. Frequent readers will know that I&#8217;m a huge fan of simple APIs and improving the developer experience (DX). Anyone who has built a web service can tell you there&#8217;s a whole lot of common ground that every app must offer. That means a lot of reused code (if you&#8217;re smart) or a lot of copy and paste (if you&#8217;re not), especially if your business is building APIs for clients. Grocer is a magnificent example of code that does what it needs to do and then gets out of the way.</p>
<p>One thing I like about Grocer that stands above all the other options for push messaging in a ruby environment is its simplicity. It doesn&#8217;t assume anything about how you acquire the device token or how many different apps you&#8217;re supporting. You tell it where to send the payload and give it a certificate, and it gets there in short order. It&#8217;s as simple as that. It&#8217;s so simple, in fact, that there is literally nothing in their documentation that I could distill into some more refined form. It&#8217;s already as easy as it can get. Other gems, like apn_on_rails, aim too high attempting to offer a turnkey gem alternative to paid services like <a title="Urban Airship website - opens in new window" href="http://urbanairship.com" target="_blank">Urban Airship</a>. They hopelessly clutter the space with consideration for devices and apps and foolishly attempt to divine which key to use based on context and associations in the object model. By letting the developer inject all the configuration at runtime, all that hardship can be avoided.</p>
<p>At the end of the day, the job is to push messages as efficiently as possible to an unknown number of devices. If you&#8217;re working with ruby, you can do no better than Grocer.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/278/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=278&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/09/11/effortless-push-messaging-with-grocer/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>Resolving Ambiguity in Complex API Design</title>
		<link>http://blog.migrantstudios.com/2012/08/18/resolving-ambiguity-in-complex-api-design/</link>
		<comments>http://blog.migrantstudios.com/2012/08/18/resolving-ambiguity-in-complex-api-design/#comments</comments>
		<pubDate>Sat, 18 Aug 2012 16:25:50 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[API Design Patterns]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[information architecture]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=288</guid>
		<description><![CDATA[Twice I&#8217;ve encountered these issues, and twice I&#8217;ve cobbled together something that works. Still, I don&#8217;t feel like the solutions were elegant or developer-friendly. Problem 1: Object Model Ambiguity In systems with user models that involve multiple roles, especially when some users (producers) are curating collections of objects and others (consumers) are interacting with these [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=288&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Twice I&#8217;ve encountered these issues, and twice I&#8217;ve cobbled together something that works. Still, I don&#8217;t feel like the solutions were elegant or developer-friendly.</p>
<h2>Problem 1: Object Model Ambiguity</h2>
<p>In systems with user models that involve multiple roles, especially when some users (producers) are curating collections of objects and others (consumers) are interacting with these objects, it can be challenging to define the relationships. If a producer is curating a set of playlists, one might assume that user.playlists would contain the playlist objects the producer owns. On the other end, the consumer might want to follow a set of playlists curated by others. From the consumer&#8217;s perspective, user.playlists might contain playlists the consumer is following.</p>
<h2>Solution 1: Functional Relationships</h2>
<p>In the example given above, the ambiguity lies in the naming of the relationships between User and Playlist. Instead of trying to combine the relationships into a conditional model, where the relationship means one thing in one situation and another thing in another situation, we simply separate the relationships into distinct associations. We further clarify the relationships by choosing names that more precisely describe the functional relationship between the objects. For playlists curated by a producer, we define user.curated_playlists. For playlists followed by a consumer, we define user.followed_playlists.</p>
<h2>Problem 2: Single vs Multiple Requests</h2>
<p>When interacting with an API, there are different ways to specify the focus of client requests. RESTful design patterns recommend representing the relationship of objects in their resource paths. Requesting /user may return only the user attributes, or it may return a set of nested collections or objects. Requesting /user/playlists returns playlists for the current user.</p>
<pre>GET /user
{
 user: {
  first_name: '...', 
  last_name: '...', 
  email: '...',
  playlists: [{id: 1, name: '...'}, {id: 2, name: '...'}]
 }
}</pre>
<p>or</p>
<pre>GET /user
{
 user: {
  first_name: '...',
  last_name: '...',
  email: '...'
 }
}

GET /user/playlists
[
 {playlist: {id: 1, name: '...'}},
 {playlist: {id: 2, name: '...'}}
]</pre>
<h2>Solution 2: Offer Both and Let Client Decide</h2>
<p>API design focuses on meeting the needs of many. Some clients will want to make a single request to sync content. Others will want to interact with specific collections in the object model hierarchy. By providing both mechanisms, the client can choose the endpoint(s) that best fit their specific needs.</p>
<h3>Bonus Points</h3>
<p>In a perfect world, the client can configure the response content at the interface level. Using the example given above, we might design the endpoint controller to respond to query string params to specify which fields to include.</p>
<pre>GET /user?only=id,email&amp;includes[playlists][only]=id,name&amp;includes[playlists][methods]=follower_ids
{
 user: {
  id: 1,
  email: '...',
  playlists: [{id: 1, name: '...', follower_ids: [2,3,4]}, {id: 2, name: '...', follower_ids: [4]}]
 }
}

</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/288/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/288/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=288&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/08/18/resolving-ambiguity-in-complex-api-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
		<item>
		<title>iOS Design Patterns, Part 3 &#8211; Navigation</title>
		<link>http://blog.migrantstudios.com/2012/07/16/ios-design-patterns-part-3-navigation/</link>
		<comments>http://blog.migrantstudios.com/2012/07/16/ios-design-patterns-part-3-navigation/#comments</comments>
		<pubDate>Mon, 16 Jul 2012 16:43:30 +0000</pubDate>
		<dc:creator>aubreygoodman</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[iOS Design Patterns]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[user experience]]></category>

		<guid isPermaLink="false">http://blog.migrantstudios.com/?p=240</guid>
		<description><![CDATA[This is the third of a series on design patterns. This chapter will focus on view dynamics and user experience. Navigation The iOS SDK offers an excellent set of tools for providing your users with a familiar and usable interactivity idiom. Two very common components are UINavigationController and UITabBarController. This section covers some useful patterns [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=240&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>This is the third of a series on design patterns. This chapter will focus on view dynamics and user experience.</p>
<h2>Navigation</h2>
<p>The iOS SDK offers an excellent set of tools for providing your users with a familiar and usable interactivity idiom. Two very common components are UINavigationController and UITabBarController. This section covers some useful patterns for working with a navigation controller nested within a tab bar.</p>
<h3>Prefer shallow stack structure</h3>
<p>Users can easily find themselves lost in the stack. The back button in the navigation bar, also know as a bread crumb, only allows the user to step one level up on the stack. They have no context of how many times they might need to &#8220;go back&#8221; in order to get to the top.</p>
<h3>Maintain narrow workflow focus (eliminate distractions)</h3>
<p>Unlike the web, where every page has a SEO-friendly footer and some kind of high level navigation, mobile development is much more sensitive to user distraction. Use high level navigation to organize your users&#8217; actions into narrow workflows. Limited screen real estate dictates the breakup of complex tasks into simpler components. After they have chosen a workflow path, make sure there are no interactive components on screen that take the user out of the workflow, except a single &#8220;cancel&#8221; or &#8220;discard&#8221; button.</p>
<p>Note: when using a tab bar with a navigation controller, it is often necessary to wrap workflow views in a navigation controller and present the result modally. The key is to obscure the tab bar for the duration of the workflow. If the tab bar is not obscured, users can easily select other tabs (intentionally or accidentally), which often leads to context confusion.</p>
<h3>Use a center button in a tab bar to highlight the most important use case</h3>
<p>Tab bars are great for grouping similar and/or related use cases together. Often, tasks can be organized within the context of a single tab. Sometimes, though, there is one task or workflow that is more important than all the others in the app. In that case, consider using a UIButton superimposed over the middle tab of the tab bar to trigger a modal presentation of the primary task or workflow. By introducing a modal workflow, this guarantees the user will be back where they were once the task is complete and the modal view dismisses. The UIButton approach allows you to make a component that stands out above the other tabs. It also allows you to set the bounds to whatever you like, allowing the button to be larger than the tab bar for extra effect.</p>
<h3>Maintain consistent context</h3>
<p>With a touch-based interactivity idiom, there is a strong time component in the user experience. Interface designers can not simply focus on the current view. It&#8217;s important to maintain a context of the previous view when designing the experience. If the user is browsing a collection and they select an item from that summary view, the subsequent detail view should include controls to traverse the set. Otherwise, the user is forced to go back to the summary view, scroll to another item, and select that in order to see its details. It is far better to offer a cursor control to allow the user to cycle through the collection in both views. More information about this topic is available in this post on <a href="http://blog.migrantstudios.com/2012/05/30/bifocal-collection-navigation/">Bifocal Collection Navigation</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/migrantstudios.wordpress.com/240/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/migrantstudios.wordpress.com/240/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.migrantstudios.com&#038;blog=17643073&#038;post=240&#038;subd=migrantstudios&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.migrantstudios.com/2012/07/16/ios-design-patterns-part-3-navigation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/eb9bc9e8dad3b5b5942f68b012d77ff5?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">aubreygoodman</media:title>
		</media:content>
	</item>
	</channel>
</rss>
