<?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>The Carbon Emitter &#187; Software Design</title>
	<atom:link href="http://blog.carbonfive.com/tag/software-design/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.carbonfive.com</link>
	<description>The blog of Carbon Five</description>
	<lastBuildDate>Thu, 19 Apr 2012 16:48:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Designing mobile APIs &#8211; dynamic content</title>
		<link>http://blog.carbonfive.com/2011/08/24/designing-mobile-apis-dynamic-content/</link>
		<comments>http://blog.carbonfive.com/2011/08/24/designing-mobile-apis-dynamic-content/#comments</comments>
		<pubDate>Wed, 24 Aug 2011 19:00:55 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=4601</guid>
		<description><![CDATA[On mobile devices native UIs offer superior responsiveness and performance but web views offer flexible layouts and data driven content. How can we combine the strengths of both to produce a highly responsive UI which can display dynamic data from &#8230; <a href="http://blog.carbonfive.com/2011/08/24/designing-mobile-apis-dynamic-content/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>On mobile devices native UIs offer superior responsiveness and performance but web views offer flexible layouts and data driven content. How can we combine the strengths of both to produce a highly responsive UI which can display dynamic data from a remote server?<br />
<span id="more-4601"></span><br />
On a recent project I needed to present dynamic forms to the app&#8217;s users. The number and content of these forms was certain to change over time and it wouldn&#8217;t be practical to attempt to distribute an app update every time a form changed. One possible solution would have been to render a html form in a web view. Web views often offer a convenient way to insert server-managed content into an app. However using web views can also have some disadvantages.</p>
<p>It can be difficult to extract user entered data from a web view. This in turn raises the cost of destroying the web view when it is not visible in order to save memory and recreating it on demand. Behavior which may be much easier with native views. The overall memory overhead of loading a web view and its content may also be greater than that of an equivalent native UI.</p>
<p>In my case I also wanted to serve these forms from a generic API which would support multiple clients. While rendering a HTML form would have been convenient it would require at least a unique stylesheet per client in order to match the rest of the client&#8217;s design. Even more difficult would have been identifying and supporting different forms of navigation, element selection, and input on different devices. Selecting a list option might be best served by an action sheet with a UIPickerView on iOS devices and a drill-down selection screen which respects the hardware back button on Android devices. Text entry requires different markup to support different keyboard types on different devices. Detecting external keyboards vs onscreen keypads of different sizes may not be possible within a web view so repositioning content to accomodate the keyboard is difficult. Similarly it would be difficult for a client to choose to display a custom keyboard tailored to the type of entry required. Web views also do not have access to all of the native features of a device so a client displaying an HTML form cannot present the user with an option to complete an email input by selecting an address from their contact list.</p>
<p>Given all of those limitation I wanted to push responsibility for displaying these input forms onto the clients who would render an appropriate UI using their native view elements. This introduced its own set of tradeoffs. Native views with custom layout rules can be more expensive to develop than comparable web views. The api implementation would be limited to only those form elements supported by the clients and that list would need to be well defined rather than being able to supply effectively arbitrary HTML. Client side validation would also be more difficult that executing some server provided javascript on form submission.</p>
<p>Ultimately I settled on a Ruby DSL to define a JSON payload representing a form which was sent to the clients by the API&#8217;s Rails backend. Using a DSL allowed me to both produce an expressive language for defining these forms as views in my Rails application and also provided a convenient way to enforce that the resulting JSON was limited to a well defined set of possible values the clients would all be able to respond to appropriately. The result was a platform agnostic API response which could be used to generate different UI elements on different clients while returning a well defined set of data back to the API when the form was submitted. It was also flexible enough to allow server side updates to the required input fields and support a growing set of data served by this API without requiring client updates.</p>
<p>A form in one of the Rails views looked something like the following:</p>
<pre class="brush: ruby; title: ; notranslate">data_form do
  fieldset &quot;Identity&quot; do
    field :first_name, :label =&gt; &quot;&quot;, :placeholder =&gt; &quot;First Name&quot;
    field :last_name, :label =&gt; &quot;&quot;, :placeholder =&gt; &quot;Last Name&quot;
  end
  fieldset &quot;Credentials&quot; do
    field :email, :label =&gt; &quot;&quot;, :placeholder =&gt; &quot;Email Address&quot;, :type =&gt; :email
    field :password, :label =&gt; &quot;&quot;, :placeholder =&gt; &quot;Password&quot;, :type =&gt; &quot;password&quot;
    field :security_question, :label =&gt; &quot;Security Question&quot;, :type =&gt; :select do
      User::security_questions.each { |q| option q, :label =&gt; q }
    end
    field :security_answer, :label =&gt; &quot;&quot;, :placeholder =&gt; &quot;Answer&quot;
  end
  fieldset &quot;Read &amp; Agree&quot; do
    field :terms_of_use, :label =&gt; &quot;I agree to the Terms &amp; Conditions.&quot;, :type =&gt; :checkbox do
      detail UserAgreement.current.terms, :label =&gt; &quot;Terms &amp; Conditions&quot;, :format =&gt; :html
    end
  end
  submit &quot;Submit&quot;
end</pre>
<p>On an iOS device that form was then rendered as UINavigationController displaying a grouped UITableView with a section for each fieldset and a cell for each field. Each select field would push an additional table view onto the navigation stack containing a list of the field&#8217;s option element. Android clients presented a completely different view of the same form tailored to the device they were running on.</p>
<p>This designed worked well for the application I was working on but it certainly falls somewhere in the middle of a spectrum from completely native UIs to purely web view based UIs and may not be reasonable for many other applications. Taken too far this could grow into a poor reimplementation of HTML. Underutilized and this would be an unnecessarily over-engineered solution. However for a domain which demanded a flexible interface which could be updated from the server, support multiple clients, and provided all the interaction of a native UI I found this to be a great solution. Would you use something similar or what alternatives have you tried for your applications?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/08/24/designing-mobile-apis-dynamic-content/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designing mobile APIs &#8211; error handling</title>
		<link>http://blog.carbonfive.com/2011/08/12/designing-mobile-apis-error-handling/</link>
		<comments>http://blog.carbonfive.com/2011/08/12/designing-mobile-apis-error-handling/#comments</comments>
		<pubDate>Fri, 12 Aug 2011 19:00:39 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=4599</guid>
		<description><![CDATA[While designing an api I need to provide reliable error responses to both protocol and application level errors. Here I&#8217;ll consider any error response generated outside our application stack to be a protocol error while those errors returned from my &#8230; <a href="http://blog.carbonfive.com/2011/08/12/designing-mobile-apis-error-handling/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>While designing an api I need to provide reliable error responses to both protocol and application level errors. Here I&#8217;ll consider any error response generated outside our application stack to be a protocol error while those errors returned from my application&#8217;s codebase are classified as application level errors. On a recent project I started to conflate these two categories which would have made the client implementation unnecessarily difficult if my pair had not intervened.<br />
<span id="more-4599"></span><br />
Before a request ever reaches my application it might timeout, it might be required to provide authentication, be redirected, hit a 404 &#8220;not found&#8221; response if my site is down for maintenance, or encounter a 5xx server error. These protocol level errors are handled well by HTTP status codes in the response header. In any of these cases there&#8217;s no need for the client to attempt to parse the response body.</p>
<p>Once a request reaches my Rack/Rails stack it might still result in an error response if no matching route exists or if it fails validation. Some of these application level errors might map to HTTP status codes but not all of them. For example in the case of validation errors I want to return relevant messages to the client. In these cases I want to send a 200 response code to indicate that the response body can be expected to be well formatted. The client can then attempt to parse the response as JSON, identify that there was a validation error, and notify the user appropriately.</p>
<p>In a recent project my api responses looked something like this:</p>
<p><code><br />
{<br />
  'error' : {<br />
    'type : "AStringDenotingTheErrorType",<br />
    'message' : "An error message appropriate for display to the user."<br />
  }<br />
  'data' : {<br />
    "attribute": value,<br />
    ...<br />
  }<br />
}<br />
</code></p>
<p>Mobile clients who maintain an offline cache of data might encounter validation errors as a result of being out of date with the server. I found it helpful to include an up to date representation of the model which failed validation in the error response. Much like rendering a form with validation errors, returning a model or other data along with a set of validation errors allows the client to make sure they are not submitting an out of date version of the resource.</p>
<p>For instance on an application which cached forms it received via an API submitting an old version of a form might result in a validation error. By returning the latest copy of the form with that validation error the client had an opportunity to update its cache and present the correct form the the user to make corrections and fill out new required fields.</p>
<p>A well designed API will communicate both application and protocol errors clearly to the client. It supplies the client with an appropriate level of information to correct errors when possible and saves the client from needing to guess what might have gone wrong with a failed request.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/08/12/designing-mobile-apis-error-handling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designing mobile APIs &#8211; basic behaviors</title>
		<link>http://blog.carbonfive.com/2011/08/10/designing-mobile-apis-basic-behaviors/</link>
		<comments>http://blog.carbonfive.com/2011/08/10/designing-mobile-apis-basic-behaviors/#comments</comments>
		<pubDate>Thu, 11 Aug 2011 02:00:38 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=4597</guid>
		<description><![CDATA[As Rails developers we design APIs on a regular basis: routes for browsers to interact with a web app, JSON apis and routes for client side javascript to build dynamic pages, payloads queued for background processing on a server, and &#8230; <a href="http://blog.carbonfive.com/2011/08/10/designing-mobile-apis-basic-behaviors/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As Rails developers we design APIs on a regular basis: routes for browsers to interact with a web app, JSON apis and routes for client side javascript to build dynamic pages, payloads queued for background processing on a server, and so on. As we move into mobile development we can benefit from many of the lessons we have learned about good API design, but also face some new problems and changing demands.<br />
<span id="more-4597"></span><br />
Many of our familiar practices from Rails development still apply. </p>
<ul>
<li>REST still provides a nice clean way to organize our routes.</li>
<li>XML and JSON are common data formats.</li>
<li>Clients create sessions, often identified by a session id returned in a cookie.</li>
<li>We can improve client performance and reduce server load by caching request responses, providing HTTP ETags and 304 responses, and appending asset ids to assets served via the rails stack.</li>
</ul>
<p>However we also find a number of cases where our conventions do not match well with the needs and behavior of mobile clients. </p>
<h2>Synchronous requests and redirects:</h2>
<p>Synchronous requests on high latency wireless networks lead to a poor user experience as clients must wait for a response from the server before they can proceed. Unfortunately for us, redirects create synchronous requests. When a client encounters a redirect response it has waited for one full round trip to the server and must now wait for another round trip before it will have the information it needs to proceed. Similarly references to other resources including stylesheets or child objects cannot be loaded until the client has received the initial response containing those references.</p>
<p>Whenever a client needs to make multiple requests there is a reasonable chance that some of them will fail. This can become problematic as the client then needs to determine what to do with the partial set of data it has received. Should the client retry only the failed requests and hope that the rest of the data set is still up to date by the time they finish? Should the entire set of data be discarded because one portion could not be loaded? Can an incremental or partial set of results be shown to the user and still be meaningful?</p>
<h3>For example</h3>
<p>We might allow a user to sign into our API via a <code>sessions/#create</code> route and expose an authenticated user&#8217;s profile via a <code>profile</code> route. If we want to allow users to sign in and then be greeted by name (retrieved from their profile) we are forcing clients to either make a pair of synchronous requests before a user can move past the sign in screen or to display a reasonable interface when the users profile has not yet been retrieved.<br />
If instead we were to return the user&#8217;s profile data as part of a successful <code>sessions/#create</code> response we could cut the perceived sign in time in half.</p>
<p>Returning deeply nested object graphs may present us with a new problem. Now we may need to join multiple models together to construct the response and generate an expensive query in the process. That&#8217;s not too bad, we&#8217;re pretty good at optimizing query times when they become a problem, but it also makes the resulting response harder to cache because we must invalidate that cache whenever any of the models included in that aggregate response change.</p>
<h2>Sessions</h2>
<p>On the web, sessions are well defined and we often use session cookies to store session identifiers. Mobile devices are not so simple; they are likely to gain and lose focus many times while a user is actively using the app. Every phone call, text message, switch to look at a mobile browser, and so on may force an iOS app into the background. As an app enters the background we could delete session identifiers and clear out any sensitive cached data, but we don&#8217;t know if the user will return immediately or in the far future. If we discard credentials aggressively we may force the user to re-authenticate after every interruption, a poor user experience, but if we do not we might expose those credentials to whomever next uses the app.<br />
We might be able to conditionally clear out data from expired sessions when an app resumes but may also need to store it encrypted in order to prevent access to sensitive data while the app is not running.</p>
<h2>Idempotent requests:</h2>
<p>Mobile clients operate on unreliable network connections. As a result many of their network requests will fail somewhere along their route to our servers. Retrying failed requests should be an obvious initial solution when a request never reaches the server but what about when the acknowledgement of a request is lost on its way back to the client? Suppose our server received a request to create a new user account with a unique username and responded with some kind of 201 (created) response. Unfortunately the response never reached the client device, it eventually considers the request to have timed out and dutifully sends it again, eventually successfully. Now our server receives a second request to create an account with the same unique username and returns a validation error because that username is already taken!</p>
<p>It might be a better user experience if our server could identify duplicate requests from the same client and return the same  response for all of them without applying duplicate changes to our model. In general it is beneficial for us if we can make all requests to our API idempotent, resulting in the same model state no matter how many times they are performed. Therefore we should prefer an update which sets a value to an update which increments that value or include enough information in each request (timestamps, sequence numbers, version numbers, and so on) to identify duplicate requests.</p>
<h2>Closing thoughts:</h2>
<p>Designing APIs for mobile clients presents some new problems which force us to reconsider some of our common practices as developers of web applications. Many of the conventions found in Rails are still valuable, but we need to respect the needs of our mobile clients and the network environment they operate in order to enable them to provide the best possible user experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/08/10/designing-mobile-apis-basic-behaviors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Abusing UIViewControllers</title>
		<link>http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/</link>
		<comments>http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 12:00:16 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1699</guid>
		<description><![CDATA[UIViewControllers are a fundamental building block of most iOS applications. Unfortunately many developers seem to use them in unintended and unsupported ways which leaves their apps vulnerable to bugs, rejections, unpredictable behavior under new iOS releases, and with controllers which &#8230; <a href="http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html">UIViewController</a>s are a fundamental building block of most iOS applications. Unfortunately many developers seem to use them in unintended and unsupported ways which leaves their apps vulnerable to bugs, rejections, unpredictable behavior under new iOS releases, and with controllers which are difficult to update or reuse. The core misconceptions behind this abuse of UIViewController are understandable. Apple presents UIViewControllers as a key element of an app&#8217;s navigation and interface stating &#8220;custom view controllers are the primary coordinating objects for your application’s content&#8221;. The basic application templates are defined in terms of their UIViewController behavior; &#8220;navigation-based&#8221;, &#8220;tab bar&#8221;, &#8220;split-view based&#8221;. From our first exposure to the platform developers are presented with UIViewControllers as classes for managing views and the transitions between them. Sadly those examples present a pattern which we, as iOS developers outside Apple, cannot follow or build on.</p>
<p>Any app which contains code like<br />
<code>[viewController.view addSubview:someOtherViewController.view];</code><br />
or<br />
<code>viewController.view.bounds = CGRectMake(50, 50, 100, 200);</code><br />
or which loads a nib doing the equivalent is abusing UIViewControllers. Given time this will emerge as bugs or at least pain for developers continuing to work on the app.</p>
<p><strong>What? How is that wrong?</strong><br />
<span id="more-1699"></span><br />
The core problem, and surprise for too many developers, is stated in the &#8220;View Controller Programing Guide for iOS&#8221; in &#8220;<a href="http://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/AboutViewControllers/AboutViewControllers.html#//apple_ref/doc/uid/TP40007457-CH112-SW12">About Custom View Controllers</a>&#8220;:</p>
<blockquote><p>Each custom view controller object you create is responsible for managing all of the views in a single view hierarchy. In iPhone applications, the views in a view hierarchy traditionally cover the entire screen, but in iPad applications they may cover only a portion of the screen. The one-to-one correspondence between a view controller and the views in its view hierarchy is the key design consideration. You should not use multiple custom view controllers to manage different portions of the same view hierarchy. Similarly, you should not use a single custom view controller object to manage multiple screens worth of content.
</p></blockquote>
<p>Essentially the <em><a href="http://developer.apple.com/library/ios/documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html#//apple_ref/doc/uid/TP40006817-CH3-SW33">rootViewController</a></em> of the current UIWindow should be the only UIViewController with a visible view.</p>
<p>With multiple UIViewController&#8217;s views visible at once some of those controllers may not receive important messages like <em>-viewWillAppear:</em> or <em>-didReceiveMemoryWarning</em>. Additionally some of their properties like <em>parentViewController</em> and <em>interfaceOrientation</em> may not be set or updated as expected.</p>
<p>&#8220;<a href="http://developer.apple.com/library/ios/#qa/qa1688/_index.html">Why won&#8217;t my UIViewController rotate with the device?</a>&#8221; states this even more explicitly.</p>
<blockquote><p> If you add an additional view controller&#8217;s UIView property to UIWindow (at the same level as your primary view controller) via the following:</p>
<p>[myWindow addSubview:anotherController.view];</p>
<p>this additional view controller will not receive rotation events and will never rotate. Only the first view controller added to UIWindow will rotate. </p></blockquote>
<p>Now Apple is able to provide &#8220;container view controllers&#8221; like UINavigationController and UITabBarController which manage the presentation of other UIViewController&#8217;s views. Unfortunately to do so requires the use of private API calls which are not available for any app seeking approval for distribution in the App Store (discussed in more detail here: <a href="https://devforums.apple.com/message/310806#310806">https://devforums.apple.com/message/310806#310806</a>). We can come close but without a supported path for implementing custom container view controllers nesting UIViewControllers&#8217; views will not give us all the behavior we expect from a UIViewController.</p>
<p><strong>Isn&#8217;t close good enough?</strong></p>
<p>Not really. We can implement a custom container view controller which sends messages like <em>-viewWillAppear</em> to its child view controllers but that only solves part of the problem. </p>
<ul>
<li>Without being able to rely on <em>interfaceOrientation</em> those child view controllers may never support rotation correctly.<br />
Since view controllers&#8217; views are expected to fill the window views &#8220;behind&#8221; modal view controllers may not be drawn or may be unloaded while visible.</li>
<li>Without properties like <em>parentViewController</em> or <em>navigationController</em> being set all of our child view controllers need to be aware of how they are being presented and the fact that they cannot rely on all the behavior they should be able to expect from inheriting from UIViewController.</li>
<li>Child view controllers may not be properly inserted into the responder chain so they may never see events passed up the chain from their views.</li>
</ul>
<p>With no public setters available for these properties or documentation of these behaviors there&#8217;s currently no way to resolve this situation (see this thread for further discussion: <a href="https://devforums.apple.com/message/365171#365171">https://devforums.apple.com/message/365171#365171</a>). Since there is currently no supported means of creating container view controllers those behaviors which do work now are not guaranteed to continue to function in future iOS updates and may vary between existing iOS versions.<br />
By nesting UIViewControllers we create a UIViewController instance which cannot rely on the entire contract offered by UIViewController. A non-obvious and context specific problem for any developer working on the app in the future.</p>
<p><strong>So what&#8217;s the alternative?</strong></p>
<p>The &#8220;<a href="http://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/AboutViewControllers/AboutViewControllers.html#//apple_ref/doc/uid/TP40007457-CH112-SW12">View Controller Programming Guide for iOS</a>&#8221; at least suggests an alternative:</p>
<blockquote><p>Note: If you want to divide a view hierarchy into multiple subareas and manage each one separately, use generic controller objects (custom objects descending from NSObject) instead of view controller objects to manage each subarea. Then use a single view controller object to manage the generic controller objects.
</p></blockquote>
<p>A controller does not necessarily have to be a subclass of UIViewController. We can create controller objects responsible for managing specific behaviors or portions of our view and have these controllers inherit from NSObject instead of from UIViewController. This allows you to break up your app&#8217;s controller logic into manageable classes with clear responsibilities while still following the limitations of UIViewController. This works well when you want to have different controllers manage different sections of a single view hierarchy. </p>
<p><code><br />
@interface SampleController : NSObject  {<br />
}<br />
@end<br />
</code></p>
<p>This is however an inadequate replacement for custom container view controllers which should be able to manage transitions between arbitrary UIViewControllers. Instead we have to either reinvent much of UIViewController&#8217;s behavior (<em>-viewWillAppear:</em> and <em>-viewDidDisappear:</em> style lifecycle methods, unloading and reloading of views on demand, transformation of views in response to device rotations) or abuse UIViewController and risk producing unstable apps.</p>
<p><code><br />
@protocol ViewController<br />
    - (void)viewDidAppear:(BOOL)animated;<br />
    - (void)viewDidDisappear:(BOOL)animated;<br />
    - (void)viewWillAppear:(BOOL)animated;<br />
    - (void)viewWillDisappear:(BOOL)animated;<br />
    -(UIView *)view;<br />
@end</p>
<p>@interface SampleController : NSObject  {<br />
}<br />
@end</p>
<p>@interface SampleContainerViewController : UIViewController {<br />
}<br />
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated;<br />
@property(nonatomic, copy) NSArray *viewControllers;<br />
@end<br />
</code></p>
<p>For now I have found that the best solution is to stay within the supported constraints of UIViewController and build custom non-UIViewController controllers as necessary. Have you found a better alternative, chosen to use UIViewControllers anyway, or avoided this problem entirely?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/feed/</wfw:commentRss>
		<slash:comments>59</slash:comments>
		</item>
		<item>
		<title>iPhone Distributed Computing Fallacy #8: the network is homogeneous</title>
		<link>http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/</link>
		<comments>http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/#comments</comments>
		<pubDate>Mon, 06 Dec 2010 17:23:32 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=2154</guid>
		<description><![CDATA[Reviewing the 8 classic &#8220;fallacies of distributed computing&#8221; and how we can avoid them when writing iOS applications. The fallacies of distributed computing The network is reliable. Latency is zero. Bandwidth is infinite. The network is secure. Topology doesn&#8217;t change. &#8230; <a href="http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Reviewing the 8 classic &#8220;<a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">fallacies of distributed computing</a>&#8221; and how we can avoid them when writing iOS applications.</p>
<p><em>The fallacies of distributed computing</em></p>
<ol>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-1-the-network-is-reliabl">The network is reliable.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-2-latency-is-zero">Latency is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite">Bandwidth is infinite.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-4-the-network-is-secure">The network is secure.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-5-topology-doesnt-change">Topology doesn&#8217;t change.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-6-there-is-one-administrator">There is one administrator.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/">Transport cost is zero.</a></li>
<li><strong>The network is homogeneous.</strong></li>
</ol>
<p><img title="More..." src="http://carbonfivecommunity.wordpress.com/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /><br />
Fallacy #8: &#8220;the network is homogeneous&#8221;.</p>
<p>Mobile devices are something of an exception compared to web development; it is possible for an app to have a largely homogeneous network of users. Unfortunately assuming that the network is homogeneous still leads to problems on several levels.</p>
<p>Similarly to fallacy #6 not all networks will have the same configuration. For example some wifi networks will allow peer to peer communication between devices and some will not. Allowing a mobile app to communicate with other devices (ie synch with a desktop app) can therefore be difficult even if both are on the same network. TN2152 &#8220;<a href="http://developer.apple.com/library/mac/#technotes/tn2009/tn2152.html">Document Transfer Strategies</a>&#8221; has an excellent overview of several techniques for communicating between devices or with remote services.</p>
<p>A web service might initially be designed for use only by iOS apps but it would be nice if adding apps for other device families later was not unnecessarily difficult. The service may therefore need to serve multiple data formats so its clients can choose to receive content as xml, json, or whatever they can easily parse. Binary and proprietary data formats may be difficult to parse on multiple devices.<br />
For services based around a central server this shouldn&#8217;t be a serious problem as the server can serve content in each client&#8217;s preferred format and translate between them. For applications with direct peer to peer communication (ie using GameKit) connecting an iOS app to an Android app, or just handling clients using multiple versions of the same app, is more difficult.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Distributed Computing Fallacy #7: transport cost is zero</title>
		<link>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/</link>
		<comments>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 19:00:18 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1702</guid>
		<description><![CDATA[Reviewing the 8 classic &#8220;fallacies of distributed computing&#8221; and how we can avoid them when writing iOS applications. The fallacies of distributed computing The network is reliable. Latency is zero. Bandwidth is infinite. The network is secure. Topology doesn&#8217;t change. &#8230; <a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Reviewing the 8 classic &#8220;<a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">fallacies of distributed computing</a>&#8221; and how we can avoid them when writing iOS applications.</p>
<p><em>The fallacies of distributed computing</em></p>
<ol>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-1-the-network-is-reliabl">The network is reliable.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-2-latency-is-zero">Latency is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite">Bandwidth is infinite.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-4-the-network-is-secure">The network is secure.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-5-topology-doesnt-change">Topology doesn&#8217;t change.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-6-there-is-one-administrator">There is one administrator.</a></li>
<li><strong>Transport cost is zero.</strong></li>
<li><a href="http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/">The network is homogeneous.</a></li>
</ol>
<p><span id="more-1702"></span><br />
Fallacy #7: &#8220;transport cost is zero&#8221;.</p>
<p>Arnon Rotem-Gal-Oz&#8217;s <a href="http://www.rgoarchitects.com/Files/fallacies.pdf">explanation</a> of this fallacy points out two possible interpretations, both of which can be problematic mistakes.</p>
<p>First you can consider the cost of moving data between your application and the network interface. The performance impact of serializing objects or parsing data add a cost above and beyond the limitations of bandwidth and latency. Apple&#8217;s <a href="http://developer.apple.com/videos/wwdc/2010/">2010 WWDC session 117</a> &#8220;building a server-driven user experience&#8221; for their comparison of the size and load time of data in xml, json, and plists (slide #40 &amp; 41 at ~27:30). While the size of each format was similar the time required to parse the result varied tremendously; 812ms for xml, 416ms for json, 140ms for an ascii plist and only 19ms for a binary plist.</p>
<p>Secondly you can consider the cost of maintaining network services and infrastructure. How much load does each user place on your servers and what do they cost to run? How many concurrent requests can your servers actually handle and what does it cost to scale those systems? What does using your app cost your users who live with monthly data limits or pay on a per-kilobyte basis?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Distributed Computing Fallacy #6: there is one administrator</title>
		<link>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-6-there-is-one-administrator/</link>
		<comments>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-6-there-is-one-administrator/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 16:00:15 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1697</guid>
		<description><![CDATA[Reviewing the 8 classic &#8220;fallacies of distributed computing&#8221; and how we can avoid them when writing iOS applications. The fallacies of distributed computing The network is reliable. Latency is zero. Bandwidth is infinite. The network is secure. Topology doesn&#8217;t change. &#8230; <a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-6-there-is-one-administrator/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Reviewing the 8 classic &#8220;<a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">fallacies of distributed computing</a>&#8221; and how we can avoid them when writing iOS applications.</p>
<p><em>The fallacies of distributed computing</em></p>
<ol>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-1-the-network-is-reliabl">The network is reliable.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-2-latency-is-zero">Latency is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite">Bandwidth is infinite.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-4-the-network-is-secure">The network is secure.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-5-topology-doesnt-change">Topology doesn&#8217;t change.</a></li>
<li><strong>There is one administrator.</strong></li>
<li><a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/">Transport cost is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/">The network is homogeneous.</a></li>
</ol>
<p><span id="more-1697"></span><br />
Fallacy #6: &#8220;there is one administrator&#8221;.</p>
<p>While you, as the developer, can control when your apps and servers are released and updated neither you nor anyone else can control the entire collection of devices which will be running your app. Your users will update their devices on different schedules or not at all. Leaving you with a range of different application version in the wild. For networked applications this may be problematic as you might have different application versions using different api versions to communicate with your server or with each other. I&#8217;ve found it helpful to introduce api versioning to a project as early as possible. There may not be any need to support multiple api versions immediately but having a strategy in place to move from api.example.com/1/ to api.example.com/2/ when you need to change an existing api call can make your next app release much smoother.<br />
In addition to supporting users of different api versions apps also need to be able to handle upgrades locally. If you change the format for storing data on disk, or in core data, or in the keychain between application versions have a plan for migrating user&#8217;s existing data when they upgrade (or at least don&#8217;t crash trying to read an old data format). Your application will also need to handle users who upgrade from version 1 directly to version 3 without failing because you lost track of what changed in version 2.</p>
<p>As the administrators of their devices your users can change many of the other restrictions on your application&#8217;s environment as well. Only some of them will allow you to access their location. Only some of them will permit push notifications. Some of them will use parental controls to block access to Safari, the app store, or other applications.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-6-there-is-one-administrator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Distributed Computing Fallacy #5: topology doesn&#8217;t change</title>
		<link>http://blog.carbonfive.com/2010/12/02/iphone-distributed-computing-fallacy-5-topology-doesnt-change/</link>
		<comments>http://blog.carbonfive.com/2010/12/02/iphone-distributed-computing-fallacy-5-topology-doesnt-change/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 22:00:09 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1691</guid>
		<description><![CDATA[Reviewing the 8 classic &#8220;fallacies of distributed computing&#8221; and how we can avoid them when writing iOS applications. The fallacies of distributed computing The network is reliable. Latency is zero. Bandwidth is infinite. The network is secure. Topology doesn&#8217;t change. &#8230; <a href="http://blog.carbonfive.com/2010/12/02/iphone-distributed-computing-fallacy-5-topology-doesnt-change/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Reviewing the 8 classic &#8220;<a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">fallacies of distributed computing</a>&#8221; and how we can avoid them when writing iOS applications.</p>
<p><em>The fallacies of distributed computing</em></p>
<ol>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-1-the-network-is-reliabl">The network is reliable.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-2-latency-is-zero">Latency is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite">Bandwidth is infinite.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-4-the-network-is-secure">The network is secure.</a></li>
<li><strong>Topology doesn&#8217;t change.</strong></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-6-there-is-one-administrator">There is one administrator.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/">Transport cost is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/">The network is homogeneous.</a></li>
</ol>
<p><span id="more-1691"></span><br />
Fallacy #5: &#8220;topology doesn&#8217;t change&#8221;.</p>
<p>WWAN connections use significantly more power than WiFi connections. This becomes important when working with long lived connections or streaming media. A connection established over the WWAN will keep that interface active even if a WiFi network becomes available. To avoid running both interfaces it is up to the app to close and re-establish any active connections on the newly available network interface. Use Apple&#8217;s Reachability example to monitor changes in available interfaces and react as necessary. Also take a look at Paul Danbold&#8217;s &#8220;<a href="http://developer.apple.com/videos/iphone/#video-advanced-networking">Advanced networking</a>&#8221; talk from the 2009 Tech Talk World Tour.</p>
<p>Those changes to the network are also likely to result in changes to the device&#8217;s available bandwidth and latency so apps which make decisions based on those characteristics may need to monitor their connections and adapt to changing conditions. Since apps which stream significant amounts of audio or video are required to use <a href="http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008332-CH1-DontLinkElementID_30">http live streaming</a> they can automatically switch between available streams designed for higher or lower bandwidth connections as network conditions change.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/12/02/iphone-distributed-computing-fallacy-5-topology-doesnt-change/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Distributed Computing Fallacy #4: the network is secure</title>
		<link>http://blog.carbonfive.com/2010/11/29/iphone-distributed-computing-fallacy-4-the-network-is-secure/</link>
		<comments>http://blog.carbonfive.com/2010/11/29/iphone-distributed-computing-fallacy-4-the-network-is-secure/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 06:34:24 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1679</guid>
		<description><![CDATA[Reviewing the 8 classic &#8220;fallacies of distributed computing&#8221; and how we can avoid them when writing iOS applications. The fallacies of distributed computing The network is reliable. Latency is zero. Bandwidth is infinite. The network is secure. Topology doesn&#8217;t change. &#8230; <a href="http://blog.carbonfive.com/2010/11/29/iphone-distributed-computing-fallacy-4-the-network-is-secure/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Reviewing the 8 classic &#8220;<a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">fallacies of distributed computing</a>&#8221; and how we can avoid them when writing iOS applications.</p>
<p><em>The fallacies of distributed computing</em></p>
<ol>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-1-the-network-is-reliabl">The network is reliable.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-2-latency-is-zero">Latency is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite">Bandwidth is infinite.</a></li>
<li><strong>The network is secure.</strong></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-5-topology-doesnt-change">Topology doesn&#8217;t change.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-6-there-is-one-administrator">There is one administrator.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/">Transport cost is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/">The network is homogeneous.</a></li>
</ol>
<p><span id="more-1679"></span><br />
Fallacy #4: &#8220;the network is secure&#8221;.</p>
<p>Any network service needs to consider security as part of its design and services built for use by iOS applications are no exception. All of the basic attacks a web service needs to consider still apply; session hijacking, stolen credentials, code injection, and so on. Securing a web service is a much larger topic but let&#8217;s consider a couple of areas specific to iOS client applications.</p>
<p>User&#8217;s devices are only as trustworthy as the users themselves. Anyone with a copy of your app can inspect both the contents of your application&#8217;s bundle and the traffic it sends. Don&#8217;t rely on your app storing a shared secret (credentials to access your web service, certificates, encryption keys, and so on) without revealing it to your users.</p>
<p>UDIDs are unfortunately a poor mechanism for user authentication. They are convenient as a unique identifier available without needing to walk users through any sort of account creation and I&#8217;ve worked on apps which use them as a temporary form of identification but they don&#8217;t work well as permanent identifiers. UDIDs are effectively user provided data and can be changed; either deliberately which might allow one user to masquerade as another or unintentionally when a user upgrades their device or installs an app on a second device.  A UDID identifies a device, not a user.</p>
<p>Mobile devices are even more likely than general web traffic to be used on public access points and networks which can easily include malicious users. Any data your app sends in the clear can be read by other members of the network. If you or your users consider that data sensitive it really needs to be sent over an encrypted connection. Apple provides the <a href="http://developer.apple.com/library/ios/#samplecode/AdvancedURLConnections/Introduction/Intro.html">Advanced URLConnection</a> sample application which demonstrates establishing connections using http basic auth, and certificates (including self-signed certificates if you want to issue your own for your web services).<br />
As a simplistic example a NSURLConnection can support https requests with the addition of just two additional delegate methods.</p>
<pre class="brush: objc; light: true; title: ; wrap-lines: false; notranslate">
- (void) httpsConnection {
    self.connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@&amp;quot;https://encrypted.google.com/&amp;quot;]] delegate:self];
    [self.connection start];
}

-(BOOL) connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
    return [protectionSpace authenticationMethod] == NSURLProtectionSpaceHTTPS;
}

-(void) connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    if ([challenge previousFailureCount] == 0) {
        if ([challenge proposedCredential] == nil) {
            NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
            SecTrustRef trust = [protectionSpace serverTrust];
            SecTrustResultType trustResult;
            SecTrustEvaluate(trust, &amp;amp;trustResult);
            if (trustResult == kSecTrustResultProceed) {
                NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
                [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
            }
            else {
                [[challenge sender] cancelAuthenticationChallenge:challenge];
            }
        }
        else {
            [[challenge sender] cancelAuthenticationChallenge:challenge];
        }
    }
    else {
        [[challenge sender] cancelAuthenticationChallenge:challenge];
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/11/29/iphone-distributed-computing-fallacy-4-the-network-is-secure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Distributed Computing Fallacy #3: bandwidth is infinite</title>
		<link>http://blog.carbonfive.com/2010/11/22/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite/</link>
		<comments>http://blog.carbonfive.com/2010/11/22/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 02:54:33 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1664</guid>
		<description><![CDATA[Reviewing the 8 classic &#8220;fallacies of distributed computing&#8221; and how we can avoid them when writing iOS applications. The fallacies of distributed computing The network is reliable. Latency is zero. Bandwidth is infinite. The network is secure. Topology doesn&#8217;t change. &#8230; <a href="http://blog.carbonfive.com/2010/11/22/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Reviewing the 8 classic &#8220;<a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">fallacies of distributed computing</a>&#8221; and how we can avoid them when writing iOS applications.</p>
<p><em>The fallacies of distributed computing</em></p>
<ol>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-1-the-network-is-reliabl">The network is reliable.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-2-latency-is-zero">Latency is zero.</a></li>
<li><strong>Bandwidth is infinite.</strong></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-4-the-network-is-secure">The network is secure.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-5-topology-doesnt-change">Topology doesn&#8217;t change.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-6-there-is-one-administrator">There is one administrator.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/">Transport cost is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/">The network is homogeneous.</a></li>
</ol>
<p><span id="more-1664"></span><br />
Fallacy #3: &#8220;bandwidth is infinite&#8221;.</p>
<p>Bandwidth is not unlimited and it is not free, this has implications beyond &#8220;downloading lots of data takes longer&#8221;.</p>
<ol>
<li>Apps over 20MB cannot be downloaded over cellular networks: see the <a href="https://developer.apple.com/appstore/resources/approval/guidelines.html">App store approval guidelines</a>.</li>
<li>
<blockquote>If your app delivers video over cellular networks, and the video exceeds either 10 minutes duration or 5 MB of data in a five minute period, you are required to use HTTP Live Streaming. (Progressive download may be used for smaller clips.)</p>
<p>If your app uses HTTP Live Streaming over cellular networks, you are required to provide at least one stream at 64 Kbps or lower bandwidth (the low-bandwidth stream may be audio-only or audio with a still image).</p></blockquote>
<p>From the <a href="http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/UsingHTTPLiveStreaming/UsingHTTPLiveStreaming.html#//apple_ref/doc/uid/TP40008332-CH102-DontLinkElementID_20">Streaming Media Guide</a>.</li>
<li>
<blockquote>Audio streaming content over a cellular network may not use more than 5MB over 5 minutes</p></blockquote>
<p>From the <a href="https://developer.apple.com/appstore/resources/approval/guidelines.html">App store approval guidelines</a>.</li>
</ol>
<p>Many users do not have unlimited data plans so your app&#8217;s total bandwidth use while on a mobile network may be a concern.</p>
<p>Since the network is not reliable large requests, which take longer to complete, are sometimes going to fail as a network connection is interrupted. If your app cannot resume those connections you risk always transferring the first 80% of the data, losing the connection, and starting again from the beginning.</p>
<p>Users are also unreliable; they will close or background the app while you are trying to transfer data for them.</p>
<p><strong>Testing bandwidth</strong><br />
I use Charles to <a href="http://www.charlesproxy.com/documentation/proxying/throttling/">throttle network bandwith</a> to test apps using low bandwith connections during development.<br />
The Settings app provides an easy tool for measuring cellular bandwidth use if your app behaves differently while using the WWAN; look in Settings -&gt; General -&gt; Usage.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/11/22/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

