<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feed.pivotallabs.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Pivotal Blabs</title>
    <link>http://www.pivotallabs.com/blabs</link>
    <description>The Pivotal Labs Blog</description>
    <language>en-us</language>
    <lastBuildDate>Wed, 16 May 2012 06:36:00 -0700</lastBuildDate>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feed.pivotallabs.com/pivotal-labs/blabs" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="pivotal-labs/blabs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
      <pubDate>Wed, 16 May 2012 06:36:00 -0700</pubDate>
      <title>git reset -p for fun and profit</title>
      <author>Kris Hicks</author>
      <link>http://www.pivotallabs.com/users/khicks/blog/articles/2114-git-reset-p-for-fun-and-profit</link>
      <guid>http://www.pivotallabs.com/users/khicks/blog/articles/2114-git-reset-p-for-fun-and-profit</guid>
      <description>&lt;p&gt;I've been using &lt;code&gt;git reset -p&lt;/code&gt; a lot recently and I think it makes sense to clarify what it is that it does because when I first started using it I found it a little confusing.&lt;/p&gt;

&lt;p&gt;I sometimes realize that an earlier commit contains some change that I don't want, so I want to remove it from the commit. This also works when not rebasing, so for simplicity I'll use an example where the commit to be modified is already HEAD. Previously I would have done:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git reset HEAD~1
git add -p
git commit -C &amp;lt;treeish&amp;gt;
git checkout .
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or, in English:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;take off the HEAD commit, adding it to the working directory&lt;/li&gt;
&lt;li&gt;add back the parts you want to keep&lt;/li&gt;
&lt;li&gt;make a new commit using the message from what used to be the HEAD commit&lt;/li&gt;
&lt;li&gt;throw away the changes you didn't want&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With git reset -p this process is a little different. Here's what it looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git reset -p HEAD~1
git commit --amend -C HEAD
git checkout .
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, in English:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;apply to the index the negations of certain parts of the HEAD commit&lt;/li&gt;
&lt;li&gt;amend the HEAD commit with the negations&lt;/li&gt;
&lt;li&gt;throw away the changes you don't want&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How does this work?&lt;/p&gt;

&lt;p&gt;In the second example you added &lt;code&gt;-p&lt;/code&gt; to the &lt;code&gt;reset&lt;/code&gt; command. This will reset only parts of the original commit, leaving it intact otherwise. That's worth stating a different way: When you &lt;code&gt;reset -p&lt;/code&gt;, &lt;strong&gt;the original commit remains unchanged&lt;/strong&gt;. The only changes are made to your working directory and index.&lt;/p&gt;

&lt;p&gt;The trick is to know what you're doing when you're saying "y" to a hunk git presents to you for resetting. Say you added a line to the commit originally:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;foo
+ bar
baz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But you want to get rid of it. When you git reset -p, git will ask you:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;foo
- bar
baz
Apply this hunk to index [y,n,q,a,d,/,e,?]?
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you say 'y', Git will apply that hunk to the index. What you also get, however, is the original hunk &amp;#40;that added "bar"&amp;#41; in your working directory.&lt;/p&gt;

&lt;p&gt;To summarize, your working directory will have:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;foo
+ bar
baz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While the index has:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;foo
- bar
baz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While the commit &amp;#40;unchanged, remember&amp;#41; has:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;foo
+ bar
baz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You now have a chance to tell git what you want to do, without having done anything to the original commit yet. In the example above, you wanted to get rid of the addition of the "bar" line. To do that, you want to take what's in the index &amp;#40;the negation of the addition of "bar"&amp;#41; and apply it to the commit, making it go away:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git commit --amend -C HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then you still have in your working directory the adding of "bar", which in this case you just want to get rid of, so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git checkout .
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I like using &lt;code&gt;reset -p&lt;/code&gt; because it makes it really easy to make small changes to a commit, removing something I added or putting back something I deleted.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reset -p&lt;/code&gt; allows you to more easily get a grip on the changes you've made and the ones you're about to make. It also makes much better use of Git, in that you can do even more interesting operations when in the resulting state, which I won't go into now as to avoid information overload.&lt;/p&gt;

&lt;p&gt;And there you have it.&lt;/p&gt;</description>
    </item>
    <item>
      <pubDate>Tue, 15 May 2012 06:41:00 -0700</pubDate>
      <title>FOWD Day 2: Notes On Design</title>
      <author>Jonathan Berger</author>
      <link>http://www.pivotallabs.com/users/jonathanpberger/blog/articles/2113-fowd-day-2-notes-on-design</link>
      <guid>http://www.pivotallabs.com/users/jonathanpberger/blog/articles/2113-fowd-day-2-notes-on-design</guid>
      <description>&lt;p&gt;&lt;a href="http://www.brendandawes.com/"&gt;Brendan Dawes&lt;/a&gt;, hacker and interaction designer, trawled through his sketchbook to deliver an inspiring opening talk about his work, what inspires him, and some Rules for making. Full notes after the jump.&lt;/p&gt;&lt;h2&gt;"It should remind you of something you've never seen before."&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;finding beauty in the mundane&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src="http://farm6.staticflickr.com/5249/5335045383_f6eb2fbba7_z.jpg" alt="Paper clips from several countries." /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BD collects paper clips: made from the same material, do the same job, but communicate different aesthetics&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Life's too short to own an ugly pencil&lt;/h2&gt;

&lt;h2&gt;Obsess about the tools you use&lt;/h2&gt;

&lt;p&gt;I hate that phrase "A poor craftsman blames his tools". I'd like to find who said that and bash him in the face with a beautifully-made hammer.&lt;/p&gt;

&lt;p&gt;Blackwing 602: L30 on ebay. Chuck Jones used these.
Palomino Blackwing
Dixon Ticonderoga. Rahl Dahl wrote with these.&lt;/p&gt;

&lt;p&gt;When you care at that level, you're going to care about the things that come forth from these tools.&lt;/p&gt;

&lt;h2&gt;Innovation / Iterinnovation&lt;/h2&gt;

&lt;p&gt;Iteration as a craft or as a way to see new things. Instagram was an iteration on photo sharing, not an innovation. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Saul Bass titles for &lt;a href="http://youtu.be/zMoo6LgcU4s"&gt;Vertigo in 1958&lt;/a&gt;. &lt;a href="http://en.wikipedia.org/wiki/John_Whitney_(animator"&gt;John Whitney&lt;/a&gt; created oscillating art that looked computer generated using &lt;a href="http://en.wikipedia.org/wiki/Lissajous_curve"&gt;Lissajous Curves&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BD started iterating on these. only 0.1 difference between each one. Sometimes you'll go from an ornate design to a circle in one step. &lt;img src="http://www.brendandawes.com/content/02-projects/lissajous/75_iteration000.jpg" alt="Lissajous Curves" /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Occasionally we'll make beautiful things out of this iterative process.&lt;/li&gt;
&lt;li&gt;This showed BD the importance of continuously making things.&lt;/li&gt;
&lt;li&gt;What about the n+1 iteration? You'll always run out of time and budget at some point. That's a design constraint; embrace it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Comma. Semicolon. Full stop.&lt;/h2&gt;

&lt;p&gt;Well designed objects are all imbued with good use of punctuation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This includes physical objects, apps, whatever.&lt;/li&gt;
&lt;li&gt;BD was designing packaging for a physical object. He got the box back and it opened too easily. By re-engineering the box so that there was a short pause in the opening, the experience of opening the box was enhanced. It was a 10mm engineering change.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Subtract to Add.&lt;/h2&gt;

&lt;blockquote&gt;
    &lt;p&gt;You know something's finished not when there's nothing left to add, but when there's nothing left to take away.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why can't things be perfect at version 1? Why are we never done with things?&lt;/p&gt;

&lt;p&gt;Created the accidental news explorer: search for a term, read an article, discover Related News, spiral out, end up somewhere you didn't expect to be.&lt;/p&gt;

&lt;p&gt;Spent two weeks adding a feature: suggested starting points &amp;#40;headlines&amp;#41;. Usage increased 2%. Was it worth it? BD felt compelled to do an update because people feel as if an app is dead if its not being updated.&lt;/p&gt;

&lt;h2&gt;Make [pencil]. Make better [eraser].&lt;/h2&gt;

&lt;h2&gt;I make for me.&lt;/h2&gt;

&lt;p&gt;Using lots of tools: altoids tins, keychain laser pointer, chumby, calipers, pencils, arduinos, breadboard.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.brendandawes.com/thumbs/cf5f1a9e812ff9cf0d289015dab50ac9.620.0.0.0.100.jpg" alt="Memory Box" /&gt;
His wife asked for L200 Christian Dior face cream for her birthday. He gave her a box that with an ardiuno and a small LCD screen that played back their text messages. Physical container for digital things.&lt;/p&gt;

&lt;h2&gt;Data by itself is not enough. Data needs poetry.&lt;/h2&gt;

&lt;p&gt;What if one button did one thing?
Laser-cut wooden box with an arduino and a display of the weather that peeks through the transparent button.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.brendandawes.com/thumbs/8fd08d06ab9e82a445813fb4518dfdbf.620.0.0.0.100.jpg" alt="happiness machine" /&gt;
&lt;a href="http://www.brendandawes.com/projects/happinessmachine"&gt;Device&lt;/a&gt; to print for happy thoughts on the internet.&lt;/p&gt;

&lt;h2&gt;Be Naive.&lt;/h2&gt;

&lt;p&gt;One of the makerbot founders said "If we were mechanical engineers, we would have known this was impossible and never tried it."&lt;/p&gt;

&lt;p&gt;BD has a makerbot and made a lot of crap. He also made some useful stuff: egg cups, headphone wrap to contain cord.&lt;/p&gt;

&lt;p&gt;He doesn't use a visual interface; it's done all in code: &lt;a href="http://www.brendandawes.com/"&gt;OpenScad&lt;/a&gt;. Write code and it spits out a model. &lt;/p&gt;

&lt;h2&gt;Own what it is that makes you different &amp;#40;Aimee Mullin&amp;#41;&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Aimee_Mullins"&gt;Aimee Mullin&lt;/a&gt;: fashion model, athlete, double amputee. Her story was featured on the &lt;a href="http://www.wnyc.org/shows/moth-radio-hour/2011/oct/22/"&gt;Moth&lt;/a&gt;, "True stories told live, without notes".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BD learned &lt;strong&gt;Bring to projects what makes you you, and celebrate that&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Watch this &amp;#40;don't read the author&amp;#41;: &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once you know who it is, it totally makes sense.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;It took me a long time to get to the top of the Empire State Building. I was uncomfortable. I wasn't happy. But all that was forgotten when I saw the view.&lt;/h2&gt;</description>
    </item>
    <item>
      <pubDate>Mon, 14 May 2012 18:03:00 -0700</pubDate>
      <title>Standup 5/14/12 - Watch your SafeBuffer</title>
      <author>Justin Richard</author>
      <link>http://www.pivotallabs.com/users/justin/blog/articles/2110-standup-5-14-12-watch-your-safebuffer</link>
      <guid>http://www.pivotallabs.com/users/justin/blog/articles/2110-standup-5-14-12-watch-your-safebuffer</guid>
      <description>&lt;h2&gt;Interesting Things&lt;/h2&gt;

&lt;p&gt;ActiveSupport::SafeBuffer do not work with all the features of #gsub.  Mind your strings, or fix this bug in ruby!&lt;/p&gt;

&lt;pre&gt;
# normal: 
1.9.3-p125 :004 &amp;gt; &amp;quot;foo&amp;quot;.gsub&amp;#40;/&amp;#40;?&amp;lt;my_string&amp;gt;.*&amp;#41;/&amp;#41; { $~[:my_string]*2 }
 =&amp;gt; &amp;quot;foofoo&amp;quot; 

# broken:
1.9.3-p125 :005 &amp;gt; &amp;quot;foo&amp;quot;.html_safe.gsub&amp;#40;/&amp;#40;?&amp;lt;my_string&amp;gt;.*&amp;#41;/&amp;#41; { $~[:my_string]*2 }
 =&amp;gt; &amp;quot;&amp;quot; 

# round trip, back to working
1.9.3-p125 :006 &amp;gt; &amp;quot;foo&amp;quot;.html_safe.to_str.gsub&amp;#40;/&amp;#40;?&amp;lt;my_string&amp;gt;.*&amp;#41;/&amp;#41; { $~[:my_string]*2 }
 =&amp;gt; &amp;quot;foofoo&amp;quot;
&amp;lt;/my_string&amp;gt;&amp;lt;/my_string&amp;gt;&amp;lt;/my_string&amp;gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <pubDate>Mon, 14 May 2012 15:14:00 -0700</pubDate>
      <title>Director of Product Management at Sharespost</title>
      <author>Ash Hogan</author>
      <link>http://www.pivotallabs.com/users/ahogan/blog/articles/2109-director-of-product-management-at-sharespost</link>
      <guid>http://www.pivotallabs.com/users/ahogan/blog/articles/2109-director-of-product-management-at-sharespost</guid>
      <description>&lt;p&gt;At Pivotal Labs, one of the services we provide our clients is helping them interview and hire. Pivotal Labs and our clients place a strong emphasis on Agile development and its many aspects: Pair Programming, Test-Driven Development, rapid iterations, and frequent refactoring.&lt;/p&gt;

&lt;p&gt;Below is the job description for a Director of Product Management with &lt;a href="http://www.sharespost.com"&gt;Sharespost&lt;/a&gt; which is the only online platform that efficiently connects forward-thinking investors with late-stage venture-backed companies and their shareholders. They have the largest online network of private company investors ever assembled and the broadest offering of independent, third-party research. It’s all designed to make the process of managing secondary liquidity and raising primary capital easier and more transparent than ever before.&lt;/p&gt;

&lt;p&gt;Sharespost is hiring - here's why you want to work there:&lt;/p&gt;&lt;h2&gt;Job Description&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://www.sharespost.com"&gt;Sharespost&lt;/a&gt;  is looking for a Director of Product Management to work closely with senior management &amp;#40;especially the CTO and President/Founder&amp;#41; and the engineering team to manage the definition, prioritization, and development of our web application.&lt;/p&gt;

&lt;h2&gt;Responsibilities:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Work closely with the founders to translate the product vision into an actionable Product Roadmap and development backlog&lt;/li&gt;
&lt;li&gt;Work hands-on with the development team to prioritize, plan, and deliver&lt;/li&gt;
&lt;li&gt;Ensure the product meets the needs of Sharespost customers and employees &amp;#40;including Sales/Brokers, Operations, and Finance&amp;#41;&lt;/li&gt;
&lt;li&gt;Work closely with outside design firm to shepherd the design effort and ensure timely deliver of designs and assets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Long term, the Director of Product Management will be based out of our San Bruno offices. We are currently engaged with Pivotal Labs for development services. The Director of Product Management will be based at Pivotal SF along with our CTO and dev team for the duration of the Pivotal engagement.&lt;/p&gt;

&lt;h2&gt;Desired Skills &amp;amp; Experience&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;4+ years of product management experience, especially with web products&lt;/li&gt;
&lt;li&gt;Skilled at defining and prioritizing product ideas&lt;/li&gt;
&lt;li&gt;Strong leadership and communication skills&lt;/li&gt;
&lt;li&gt;Ability to collaborate well with engineers&lt;/li&gt;
&lt;li&gt;Experience with Pivotal Tracker planning software&lt;/li&gt;
&lt;li&gt;Previous success working with an agile development team &lt;/li&gt;
&lt;li&gt;Domain expertise in financial markets is a plus&lt;/li&gt;
&lt;li&gt;Background in design or software development a plus&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re interested in helping us build a great company in the fast-growing private capital market, please &lt;a href="mailto:drew@road3.com"&gt;email&lt;/a&gt; your résumé and cover letter with the subject "Sharespost Director of Product Management."&lt;/p&gt;</description>
    </item>
    <item>
      <pubDate>Mon, 14 May 2012 09:42:00 -0700</pubDate>
      <title>Deploy strategies for HerokuSan</title>
      <author>Ken Mayer</author>
      <link>http://www.pivotallabs.com/users/ken/blog/articles/2108-deploy-strategies-for-herokusan</link>
      <guid>http://www.pivotallabs.com/users/ken/blog/articles/2108-deploy-strategies-for-herokusan</guid>
      <description>&lt;h1&gt;Deploy Strategies&lt;/h1&gt;

&lt;p&gt;If you look at the network graphs of &lt;code&gt;heroku_san&lt;/code&gt; on github, you'll see a number of branches where the only change is the deletion of the following line from the &lt;code&gt;deploy&lt;/code&gt; task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stage.migrate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If more than a few people are willing to take the effort to fork a gem just so they can delete 1 line, something smells. The reason is that these forkers were using something other than Rails+ActiveRecord+SQL in their project. Some were using Sinatra, others were using Rails, but with CouchDB. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;raison d'être&lt;/em&gt; for the &lt;code&gt;heroku_san&lt;/code&gt; gem is to make Heroku deploys dirt simple. So, if people are making whole forks to customize the deploy task, we should make it less painful.&lt;/p&gt;&lt;h2&gt;Enter strategies&lt;/h2&gt;

&lt;p&gt;&lt;a href="need_ref"&gt;Strategies&lt;/a&gt; are an object oriented programming pattern for creating pluggable execution control. There's is now a new class of objects that inherit from &lt;code&gt;HerokuSan::Deploy::Base&lt;/code&gt;. These objects now control how deploys are executed for you. The Rails strategy, &lt;code&gt;HerokuSan::Deploy::Rails&lt;/code&gt; does exactly what HerokuSan has always done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;push to git@heroku.com&lt;/li&gt;
&lt;li&gt;call rake db:migrate&lt;/li&gt;
&lt;li&gt;restart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, the Sinatra strategy, &lt;code&gt;HerokuSan::Deploy::Sinatra&lt;/code&gt; does nothing more than the base strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;push to git@heroku.com&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can create your own strategies and then configure HerokuSan to use it instead of its default:&lt;/p&gt;

&lt;h2&gt;Rails 3 projects&lt;/h2&gt;

&lt;p&gt;Amend your &lt;code&gt;Rakefile&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'heroku_san'

class MyStrategy &amp;lt; HerokuSan::Deploy::Base
  def deploy
    super
    # call my own code to do something unique
  end
end

HerokuSan.project = HerokuSan::Project.new&amp;#40;Rails.root.join&amp;#40;"config","heroku.yml"&amp;#41;, :deploy =&amp;gt; MyStrategy&amp;#41;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Sinatra &amp;#40;and other Rack based apps&amp;#41;&lt;/h2&gt;

&lt;p&gt;Amend your &lt;code&gt;Rakefile&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'heroku_san'

class MyStrategy &amp;lt; HerokuSan::Deploy::Base
  def deploy
    super
    # call my own code to do something unique
  end
end

config_file = File.join&amp;#40;File.expand_path&amp;#40;File.dirname&amp;#40;__FILE__&amp;#41;&amp;#41;, 'config', 'heroku.yml'&amp;#41;
HerokuSan.project = HerokuSan::Project.new&amp;#40;config_file, :deploy =&amp;gt; MyStrategy&amp;#41;

load "heroku_san/tasks.rb"
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <pubDate>Mon, 14 May 2012 05:56:00 -0700</pubDate>
      <title>FOWD Day 1: Tapworthy Mobile Design</title>
      <author>Jonathan Berger</author>
      <link>http://www.pivotallabs.com/users/jonathanpberger/blog/articles/2111-fowd-day-1-tapworthy-mobile-design-</link>
      <guid>http://www.pivotallabs.com/users/jonathanpberger/blog/articles/2111-fowd-day-1-tapworthy-mobile-design-</guid>
      <description>&lt;p&gt;&lt;img src="http://assets.pivotallabs.com/1395/original/josh_clark.jpg" alt="Designing for Touch with Josh Clark" /&gt;&lt;/p&gt;

&lt;p&gt;Day 1 of the &lt;a href="futureofwebdesign.com"&gt;Future of Web Design&lt;/a&gt; was a fantastic workshop on designing for mobile with &lt;a href="http://globalmoxie.com/"&gt;Josh Clark&lt;/a&gt; aka &lt;a href="http://twitter.com/globalmoxie"&gt;@globalmoxie&lt;/a&gt;, fellow Brooklynite and author of &lt;a href="http://shop.oreilly.com/product/0636920001133.do"&gt;Tapworthy&lt;/a&gt;, a sharp guy, and a great speaker. Hop below the fold for the full notes.&lt;/p&gt;&lt;h1&gt;§1: Mobile Context&lt;/h1&gt;

&lt;h2&gt;Intro&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Early assumptions about designing for mobile may not have been right&lt;/li&gt;
&lt;li&gt;JC wrote "TapWorthy: Designing great iPhone Apps". More of a general touch-ui specific book than exclusively iPhone.&lt;/li&gt;
&lt;li&gt;Q: "What's your favorite app?" A: uhhhhh...they all drive me crazy? Maybe &lt;a href="http://www.mindsnacks.com/"&gt;MindSnacks&lt;/a&gt;. Discuss w/ yr neighbor.&lt;/li&gt;
&lt;li&gt;Software used to be very grey and dry, but it's tough to get you to stop talking about your favorite app. It's an engaging question. First the web, and now especially mobile, have made software much more human and lovable and fun.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Anthropology&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We're all anthropologists here.&lt;/li&gt;
&lt;li&gt;Though we design monolithically, there're lots of mobile cultures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Myths&lt;/h2&gt;

&lt;h3&gt;Myth 1: Mobile users are rushed and distracted&lt;/h3&gt;

&lt;p&gt;Mobile isn't actually mobile anymore. It's on the couch, in the kitchen, on the 3 hour layover. We &lt;em&gt;have&lt;/em&gt; time. Mobile != Desktop Lite&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: alibris &amp;#40;amazon competitor&amp;#41; left its main differentiating feature &amp;#40;rare book sales&amp;#41; off the mobile app.&lt;/li&gt;
&lt;li&gt;28% of US mobile web users mostly use the web on mobile&lt;/li&gt;
&lt;li&gt;25mm people only see the web via a phone&lt;/li&gt;
&lt;li&gt;Making all content and features is a "civic responsibility". Mmm...&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Myth 2: Mobile == Less&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Jacob Nielson recently advised a separate, feature-reduced site for mobile. JC does not agree.&lt;/li&gt;
&lt;li&gt;Don't confuse &lt;strong&gt;context&lt;/strong&gt; with &lt;strong&gt;intent&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Myth 3: Complexity is a dirty word&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Complexity is good. It's powerful.&lt;/li&gt;
&lt;li&gt;Mitigate confusion, not complexity.&lt;/li&gt;
&lt;li&gt;Figure out what the user needs.&lt;/li&gt;
&lt;li&gt;Example: "Do I need an umbrella"? app is perfect for JC. For his Weather-Channel-watching father in law, it's condescending.&lt;/li&gt;
&lt;li&gt;It's not that 'less is more'; it's that 'just enough is more'.&lt;/li&gt;
&lt;li&gt;Original Facebook iOS app was desktop-lite; users were incensed. "No comments?! No photos?!" It's since grown to include ~90% of the desktop feature set, and it the most-used FB interface.&lt;/li&gt;
&lt;li&gt;Don't manage complexity all at once; manage it through give-and-take.&lt;/li&gt;
&lt;li&gt;Don't confuse &lt;strong&gt;clarity&lt;/strong&gt; and &lt;strong&gt;density&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Every screen should have a primary task".&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Myth 4: Extra taps and clicks are evil&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We're not on dial-up modems anymore. A lot of "minimize clicks" ethos had to do with mitigating the effects of latency.&lt;/li&gt;
&lt;li&gt;"Every tap should deliver satisfaction": more information, a smile, whatever.&lt;/li&gt;
&lt;li&gt;"Progressive disclosure": give a little bit at a time, as its asked for.&lt;/li&gt;
&lt;li&gt;An interesting opportunity for phones is that there's probably only one user; you can train a specific user. E.g., twitter was hiding some controls. To educate the user, they opened the screen w/ hidden controls visible, and then hid them after 250ms. Later, they turned off the animation once the user triggered the "Show more controls" button.&lt;/li&gt;
&lt;li&gt;"&lt;strong&gt;Mobile == More&lt;/strong&gt;"&lt;/li&gt;
&lt;li&gt;How can mobile do more? It's got cameras, microphones, gyroscopes.&lt;/li&gt;
&lt;li&gt;Start with a basic site, use feature-sniffing javascript to discover what the client can do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Myth 5: Gotta have a mobile website&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need a great mobile experience, but a mobile website? Maybe not.&lt;/li&gt;
&lt;li&gt;There is no 'mobile web'. Don't silo by device.&lt;/li&gt;
&lt;li&gt;if "www.mysite.com" redirects to "mobile.mysite.com", you're doing it wrong. URL == &lt;strong&gt;Uniform&lt;/strong&gt; resource locator.&lt;/li&gt;
&lt;li&gt;We only know &lt;em&gt;device&lt;/em&gt; context, not &lt;em&gt;user&lt;/em&gt; context.&lt;/li&gt;
&lt;li&gt;Ideally, there should be One Web.&lt;/li&gt;
&lt;li&gt;The mobile site shouldn't have less stuff than desktop because there's a smaller screen. It should have less stuff because most of the stuff on desktop is crap.&lt;/li&gt;
&lt;li&gt;Luke W.'s whole "mobile first" point is that small-screen design constraints are a useful filter for &lt;em&gt;everything&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Content runs the show. Your interface is a collection of apps plugging into the wellspring of content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Myth 6: Mobile is about apps &amp;#40;or websites&amp;#41;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We tend to focus on a single container &amp;#40;e.g. apps or websites&amp;#41;&lt;/li&gt;
&lt;li&gt;An app isn't a strategy; it's an app.&lt;/li&gt;
&lt;li&gt;Your product isn't an app, or a website, or a feed, etc. These are all containers. You're product is your content.&lt;/li&gt;
&lt;li&gt;We have to pull back from our obsession with presentation and think about content.&lt;/li&gt;
&lt;li&gt;Civilians &amp;#40;not just geeks&amp;#41; are beginning to expect their content to be available on every device.&lt;/li&gt;
&lt;li&gt;Some people have all the devices &amp;#40;laptop, tablet, phone&amp;#41;, others only have one.&lt;/li&gt;
&lt;li&gt;We're also beginning to expect that this content is integrated: when I put down my Kindle and start reading on my phone, or I pause a Netflix movie on the TV and pick it up in bed on my iPad, it picks up where I left off. With iCloud, this is happening with the content &lt;em&gt;we&lt;/em&gt; create.&lt;/li&gt;
&lt;li&gt;We're all iCloud developers now.&lt;/li&gt;
&lt;li&gt;Every native app should be a web client. The browser's a native app, btw.&lt;/li&gt;
&lt;li&gt;Some thoughts on this stuff: &lt;a href="http:futurefriend.ly"&gt;http:futurefriend.ly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Myth 7: CMS and API are for database nerds&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We all need to think about this stuff.&lt;/li&gt;
&lt;li&gt;Structured content is going to allow us to design for multiple platforms.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;"Metadata is the new art direction."&lt;/strong&gt; &lt;a href="http://www.ethanresnick.com/"&gt;Ethan Resnick&lt;/a&gt;, &lt;a href="https://twitter.com/erd_ux"&gt;@erd_ux&lt;/a&gt; 19-yo NYU student&amp;#40;!&amp;#41;&lt;/li&gt;
&lt;li&gt;Ergo, we have to drive our design skills further down the stack.&lt;/li&gt;
&lt;li&gt;Traditional editorial judgement often disappears when we go mobile, e.g. newspaper layout &amp;#40;reflects editorial judgement about what's important&amp;#41; vs. many digital interfaces &amp;#40;often simply reverse-chronological order&amp;#41;.&lt;/li&gt;
&lt;li&gt;Let the robots do it: e.g., the Guardian parses InDesign .indd files to gauge importance and reflect that on the web.&lt;/li&gt;
&lt;li&gt;Repurpose design content.&lt;/li&gt;
&lt;li&gt;Create content and design strategies that aren't tied to a particular container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Mobile != rushed&lt;/li&gt;
&lt;li&gt;Mobile != less&lt;/li&gt;
&lt;li&gt;Complex != complicated&lt;/li&gt;
&lt;li&gt;Tap quality &gt; tap quantity&lt;/li&gt;
&lt;li&gt;No such thing as 'mobile web'&lt;/li&gt;
&lt;li&gt;Focus for all platforms&lt;/li&gt;
&lt;li&gt;Don't think 'app'; think 'service'.&lt;/li&gt;
&lt;li&gt;Metadata is the new art direction&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Everywhereness is a design nightmare&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It suggests infinite possibilities and therefore infinite priorities.&lt;/li&gt;
&lt;li&gt;"Simplify before we suppress." - Ethan Marcotte&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Contexts we tend to design mobile against:&lt;/h2&gt;

&lt;h3&gt;Context #1: I'm microtasking:&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Capture lost time: waiting on line, when your dining companion leaves for the bathroom, etc.&lt;/li&gt;
&lt;li&gt;identify lost tasks&lt;/li&gt;
&lt;li&gt;Find the primary task for an app and make it available everywhere &amp;#40;e.g. todo apps should have an 'add task' icon on every screen&amp;#41;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Context #2: I'm local&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Mobile is the primary device not because it's always with you &amp;#40;though that's important&amp;#41;, but because it knows the most about you: sensors, personal data&lt;/li&gt;
&lt;li&gt;change &lt;em&gt;context&lt;/em&gt;, not &lt;em&gt;content&lt;/em&gt;:
&lt;ul&gt;
&lt;li&gt;Shopper: shuffles your shopping list depending on where your geolocated in the store, e.g. produce aisle, dairy, etc.&lt;/li&gt;
&lt;li&gt;Word Lens: point camera at a word in a foreign language, see translation.&lt;/li&gt;
&lt;li&gt;IntoNow: foursquare for TV that listens &amp;#40;like Shazam&amp;#41; to identify season and episode.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Save input effort on these devices because they're not that good at traditional input.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.tabledrum.com/"&gt;Table Drum&lt;/a&gt;: map table taps to drum kit sounds. WANT! Transforms your environment into an interface.&lt;/li&gt;
&lt;li&gt;How can we use the superpowers of the device for input?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Context #3: I'm bored&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It's not so much "i'm bored" as "i have attention to spend".&lt;/li&gt;
&lt;li&gt;Software isn't just for work anymore: fart-apps might be frivolous, but they represents a shift from software-as-business-tool to software-as-distraction and entertainment for civilians &amp;#40;not just geeks&amp;#41;.&lt;/li&gt;
&lt;li&gt;Exploration is a common theme for escape apps &amp;#40;reading, games, etc&amp;#41;.&lt;/li&gt;
&lt;li&gt;Work apps have a lot of untapped potential for exploration; &lt;strong&gt;quantified life apps are video games for narcissists.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Don't just optimize for the fastest interaction; give them a chance to slow down and explore.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;How do we use these?&lt;/h2&gt;

&lt;p&gt;&lt;img src="http://txt4ever.files.wordpress.com/2012/02/tablet-time-usage.png" alt="CHART: usage of device (mobile, tablet, desktop) vs hour-of-day" /&gt; usage of device &amp;#40;mobile, tablet, desktop&amp;#41; vs hour-of-day.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;iPad use explodes after 6pm or so; &lt;strong&gt;it's the return of the evening newspaper&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Phone is &lt;em&gt;mobile&lt;/em&gt;, tablet is &lt;em&gt;portable&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;iPhone: very active browsers, more willing to buy, skew older, wealthier, more educated, have more sex than other mobile users.&lt;/li&gt;
&lt;li&gt;NB: eBay == 25% of US mobile commerce&lt;/li&gt;
&lt;li&gt;Ads are a good proxy for how companies think of themselves and their customers&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=yatSAEqNL7k"&gt;Apple ads for Facetime&lt;/a&gt;: Louis Armstrong, parent seeing child, grandparents seeing graduate. Sentimental.&lt;/li&gt;
&lt;li&gt;When people get these devices for the first time, they're surprised at how emotionally attached they are&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=tiaRAcpIJmw"&gt;Verizon droid ad&lt;/a&gt;: sci-fi alien cyborg. It's about the technology.&lt;/li&gt;
&lt;li&gt;Android skews techy, users customize their phones more &amp;#40;wallpaper, ringtones&amp;#41;, skews more to straight communication. Apps are tools, not media. Skews younger, less affluent. &lt;/li&gt;
&lt;li&gt;Windows mobile: formerly MS + Symbian were 80% of market. Slaughtered by iPhone.&lt;/li&gt;
&lt;li&gt;Metro interface is helping MSFT come back. Very interesting UI. Aiming for a specific user &amp;#40;young, mobile couple, very plugged into social media&amp;#41;. Incorporates personalization.&lt;/li&gt;
&lt;li&gt;No clear winner right now.&lt;/li&gt;
&lt;li&gt;46% of US adults have smartphones. There're still a lot of people on feature phones.&lt;/li&gt;
&lt;li&gt;75% of US adults use text message. Teens do about 8 texts / waking hour&amp;#40;!&amp;#41;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;§2: Finger-Friendly Design&lt;/h1&gt;

&lt;h2&gt;What do you wish your phone could do?&lt;/h2&gt;

&lt;p&gt;Brainstorm a quick list of apps to work on.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collate tour recommendations into an offline touring app&lt;/li&gt;
&lt;li&gt;Allow me to make calendar appointments / decisions and communicate them via email in a non-shitty way&lt;/li&gt;
&lt;li&gt;Turn objects on the table into a drum machine&lt;/li&gt;
&lt;li&gt;capture 3D panoramas&lt;/li&gt;
&lt;li&gt;capture panoramic workspaces, eg capture my whiteboards and foamcores in virtual space and let me view windows into them&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Group suggestions&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Family intercom app so I don't have to shout to my kids acorss the house&lt;/li&gt;
&lt;li&gt;Find the nearest open burger king; the Junk App aka Junkfinder&lt;/li&gt;
&lt;li&gt;dictophone that translates into mini notes for music&lt;/li&gt;
&lt;li&gt;universal remote for home&lt;/li&gt;
&lt;li&gt;on-the go IDE&lt;/li&gt;
&lt;li&gt;customize your phone&lt;/li&gt;
&lt;li&gt;home automation app&lt;/li&gt;
&lt;li&gt;integrated augmented reality app&lt;/li&gt;
&lt;li&gt;organize work by client or project on the go&lt;/li&gt;
&lt;li&gt;touring recommendations&lt;/li&gt;
&lt;li&gt;calendar &amp;amp; comms on a single screen&lt;/li&gt;
&lt;li&gt;aug-reality whiteboard&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Winner: integrated home automation &amp;#40;coffee, lights&amp;#41;&lt;/h4&gt;

&lt;h2&gt;Consider the physical affordances of the device&lt;/h2&gt;

&lt;p&gt;&lt;img src="http://www.wengerna.com/stuff/contentmgr/files/0/a45137daa224e9531cb3050458faee64/image/wenger_giant_knife.png" alt="giant swiss army knife" /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Huge physical load, but also huge cognitive load&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;clarity trumps density&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;handheld =&gt; industrial design. how do your pixels feel? In one hand?
&lt;ul&gt;
&lt;li&gt;one hand, tapping with thumb&lt;/li&gt;
&lt;li&gt;two-handed, tapping with thumbs&lt;/li&gt;
&lt;li&gt;hold with one hand, tap with the other&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Thumbs are awesome&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;one-handed, tapping w/ thumb is the most common&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src="http://answers.oreilly.com/uploads/monthly_07_2010/post-1510-127991438964.png" alt="Thumb Tapping Hot Zone" /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Top-vs-bottom is the main axis of emphasis&lt;/strong&gt;; don't worry about left vs right.&lt;/li&gt;
&lt;li&gt;In iOS, edit buttons tend to go top-right; available, but not risking accidental taps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Occlusion&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Traditional physical design tends towards control at bottom, content at the top.&lt;/li&gt;
&lt;li&gt;How to keep fingers from occluding content?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Placing Controls&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It's a bad idea to stack controls on touch devices, especially on the bottom of the screen. Lots of opportunity for mis-taps.&lt;/li&gt;
&lt;li&gt;Primary system controls are good at the bottom.&lt;/li&gt;
&lt;li&gt;Tabbing works a little better at the top for Android, bottom for iOS.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Position:fixed&lt;/code&gt; is &lt;strong&gt;really&lt;/strong&gt; poorly implemented on mobile browsers, especially for Android. It's hard to get &lt;code&gt;position:fixed&lt;/code&gt; to work right.&lt;/li&gt;
&lt;li&gt;Apps like LinkedIn overwrite native scrolling in javascript to do things like pinning controls to the bottom.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://m.adage.com"&gt;Ad Age&lt;/a&gt; uses a "MENU" button on the top right, which is an anchor link to the full-screen nav located at the bottom. HTML 1.0. Quick, clean, DRY, universally implemented.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Placing Navigation&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;iPhone: screen bottom&lt;/li&gt;
&lt;li&gt;Android: screen top &amp;#40;don't compete w/ primary hardware buttons&amp;#41;&lt;/li&gt;
&lt;li&gt;Native web: page bottom&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Tablets&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Avoid putting controls on top-middle of screen.&lt;/li&gt;
&lt;li&gt;Put controls in the top-corners.&lt;/li&gt;
&lt;li&gt;UNLESS you need to preview the effects in the main window above, in which case controls need to be on the bottom.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Targets&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Apple suggests 44pt is the minimum target size for tap targets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;INTERLUDE: Pixels vs points&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Now that screen density varies widely, measure in points: 1/96th of an inch.
&lt;img src="http://a53.idata.over-blog.com/5/76/72/34/pipe.gif" alt="Ceci n'est pas un pixel" /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Android: "Density-independent pixel &amp;#40;dp&amp;#41;"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;iOS: Point &amp;#40;not to be confused w/ typography points&amp;#41;&lt;/li&gt;
&lt;li&gt;CSS: "Pixel". D'oh!&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;iPhone&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Originally 320x480.&lt;/li&gt;
&lt;li&gt;Retina doubled it to 640x960. How to deal w/ legacy screens?&lt;/li&gt;
&lt;li&gt;Introduce points: Retina: 2px == 1pt.&lt;/li&gt;
&lt;li&gt;Other displays: 1px == 1pt.&lt;/li&gt;
&lt;li&gt;iOS knows that image@2x.png &amp;#40;100x100&amp;#41; is the retina version of image.png &amp;#40;50x50&amp;#41;.&lt;/li&gt;
&lt;li&gt;Design in vector, beware half-pixel divisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Back to Pixels vs Points&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;On the web, its a little uglier: &lt;code&gt;&amp;lt;img width='50' height ='50' src='image@2x.png'&amp;gt;&lt;/code&gt;. Now we're shoving hi-res images down the pipe even for screens that can't handle it.&lt;/li&gt;
&lt;li&gt;Responsive image serving is a hard problem w/in the context of HTML.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.cloudfour.com/responsive-imgs/"&gt;grigsby responsive images&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.alistapart.com/articles/responsive-images-how-they-almost-worked-and-what-we-need/"&gt;argument for changing HTML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CSS
&lt;code&gt;.className { background-image: url&amp;#40;image.png&amp;#41;; /*50 px square */ }&lt;/code&gt;
&lt;code&gt;@media only screen and &amp;#40;-webkit-min-device-pixel-ratio: 2&amp;#41;
.className { background-image: url&amp;#40;image@2x.png&amp;#41;; /*100 px square */ }
.className { background-size: 50%; /*50 px square */ }&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Targets!&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Mobile touch is not only an interface for the hand, but &lt;em&gt;of&lt;/em&gt; the hand.&lt;/li&gt;
&lt;li&gt;44pts &amp;#40;~7mm&amp;#41; is a useful touch target &amp;#40;size of the fingertip&amp;#41;&lt;/li&gt;
&lt;li&gt;44px is close enough on the web.&lt;/li&gt;
&lt;li&gt;e.g. iPhone keyboard is 44pt high.&lt;/li&gt;
&lt;li&gt;You can squeeze the other dimension as low as 29pt and it'll still work, so 44x29 or 29x44 are ok.&lt;/li&gt;
&lt;li&gt;iOS uses 44pt heights all over the place &amp;#40;key size, row height, top and bottom nav&amp;#41;; it becomes a regular element of the graphic system, almost like a grid. Home icons are 88pts.&lt;/li&gt;
&lt;li&gt;Android standardizes on 48dp &amp;#40;~10mm&amp;#41;, because there's enough variability in the hardware that they need a little margin for error.&lt;/li&gt;
&lt;li&gt;The closer the buttons are together, the larger they have to be.&lt;/li&gt;
&lt;li&gt;Hardware detection area accounts for occlusion &amp;#40;the target is a little below the visual&amp;#41;, so smaller targets where you're really concentrating and trying to be precise are actually &lt;strong&gt;harder&lt;/strong&gt; to hit!&lt;/li&gt;
&lt;li&gt;Touch targets tend to be larger than the visual area implies.&lt;/li&gt;
&lt;li&gt;If you do have to take tap-risks and jam things together at the bottom of the screen, do the extra work and rebuild the bottom nav so the touch area isn't that huge.&lt;/li&gt;
&lt;li&gt;It's ok / desirable to make your tap targets larger than they appear.&lt;/li&gt;
&lt;li&gt;Don't just make it easy to read; make it easy to touch. &lt;strong&gt;Clarity trumps density.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Don't just design in Photoshop; put it on the app and test.&lt;/li&gt;
&lt;li&gt;Glance test: put it on the phone, hold at arms length, and see if it makes sense.&lt;/li&gt;
&lt;li&gt;Bite-size content &amp;#40;e.g. a weather app&amp;#41; should eschew scrolling when possible. Single-screen makes the app feel more solid, almost like a physical object.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Review&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You're designing a &lt;em&gt;physical&lt;/em&gt; device.&lt;/li&gt;
&lt;li&gt;Where do fingers and thumbs sit? &amp;#40;hot zones&amp;#41;.&lt;/li&gt;
&lt;li&gt;Varied rules for phones &amp;#40;iOS: controls at bottom. Android: controls at top&amp;#41;.&lt;/li&gt;
&lt;li&gt;Tablet: push to edges and corners.&lt;/li&gt;
&lt;li&gt;Big fat touch targets: at least 44pt.&lt;/li&gt;
&lt;li&gt;Progressive disclosure: &lt;strong&gt;clarity trumps density&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Building: Layout&lt;/h3&gt;

&lt;h4&gt;Design the main screen&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Featured content&lt;/li&gt;
&lt;li&gt;Primary Tasks&lt;/li&gt;
&lt;li&gt;Secondary Tasks&lt;/li&gt;
&lt;li&gt;Navigation to other views&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Remember&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Make use of the sensors&lt;/li&gt;
&lt;li&gt;Create room for exploration&lt;/li&gt;
&lt;li&gt;Capture lost time&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Design w/ team!&lt;/h4&gt;

&lt;h1&gt;§3: Navigation&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Remember &lt;em&gt;Choose Your Own Adventure&lt;/em&gt; books? Tangled navigation paths.&lt;/li&gt;
&lt;li&gt;Paths should not cross.&lt;/li&gt;
&lt;li&gt;Paths should be predictable and unique.&lt;/li&gt;
&lt;li&gt;It may seem that multiple paths give more convenience, but they're harder to model mentally.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;3 models:&lt;/h2&gt;

&lt;h3&gt;Flat Pages:&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Good for casual browsing, focused content, or discovery. &lt;/li&gt;
&lt;li&gt;Good for variable screens, custom content.&lt;/li&gt;
&lt;li&gt;Easy to swipe between pages. &lt;/li&gt;
&lt;li&gt;Very little interface chrome; good for saving space, but not a lot of inference.&lt;/li&gt;
&lt;li&gt;It's flexible: typically let ppl change order, add cards. &lt;/li&gt;
&lt;li&gt;Downside: can't jump to a specific screen.&lt;/li&gt;
&lt;li&gt;Limited to 20 &amp;#40;practically, ~10&amp;#41; cards; past that, there's no more room for the navigation!&lt;/li&gt;
&lt;li&gt;Works best for homogenous content; when the cards are different, it's tough to remember which screen is which.&lt;/li&gt;
&lt;li&gt;Works best for no-scroll screens. It feels like a card, like something physical. We're not that good at scrolling in two directions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Tab Bar&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Very familiar; this is where people start to design by default.&lt;/li&gt;
&lt;li&gt;Easily allows for heterogeneous content.&lt;/li&gt;
&lt;li&gt;Constant advertisement / reminder for what the app can do.&lt;/li&gt;
&lt;li&gt;iPhone is limited to 5 tabs; add more and you'll automatically get the "More" tab.&lt;/li&gt;
&lt;li&gt;DO NOT use the 'More' as a junk drawer.&lt;/li&gt;
&lt;li&gt;Have the discipline to leave things at 5 tabs on iOS; if you need more, go to Tree Structure.&lt;/li&gt;
&lt;li&gt;If you're on Android, drop to 4 tabs.&lt;/li&gt;
&lt;li&gt;Android Ice Cream Sandwich introduces the Action Bar: show one tab, with 1 or more tools &amp;#40;depending on screen size and orientation&amp;#41;.&lt;/li&gt;
&lt;li&gt;Order: righties will have the leftmost tab in prime tab position, vice versa for lefties. New convention is to have the prime action being the center. How to draw attention? Make it a little bigger &amp;#40;a la old instagram or new foursquare&amp;#41;.&lt;/li&gt;
&lt;li&gt;Path: interesting vertical tab structure with invoked tabs, but a little weird and tough to discover.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Toolbar vs Tab bar&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Toolbar: usually light background. Act locally &amp;#40;on the content on the individual screen&amp;#41;.&lt;/li&gt;
&lt;li&gt;Tab bar: usually dark background. Think globally. &amp;#40;change to show whatever tools you need to affect that content.&amp;#41;&lt;/li&gt;
&lt;li&gt;Don't show both at once.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Tab Bar Pro's:&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One tap access to all main features.&lt;/li&gt;
&lt;li&gt;Clearly labeled menu advertises features.&lt;/li&gt;
&lt;li&gt;It's always there.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Tab Bar Cons:&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Limited to four &amp;#40;five?&amp;#41; buttons.&lt;/li&gt;
&lt;li&gt;Committing a lot of screen space. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Tree Structures&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Scales to a ton of content.&lt;/li&gt;
&lt;li&gt;Familiar mental model.&lt;/li&gt;
&lt;li&gt;Direct interaction w/ content: the word or picture you want to use; it removes abstractions.&lt;/li&gt;
&lt;li&gt;Nested folders, a lot like column view in Finder.&lt;/li&gt;
&lt;li&gt;Allows longer and more customizable menu options.&lt;/li&gt;
&lt;li&gt;Often a list.&lt;/li&gt;
&lt;li&gt;But sometimes you'll see springboards &amp;#40;facebook&amp;#41; or galleries &amp;#40;photo albums&amp;#41;.&lt;/li&gt;
&lt;li&gt;Not much room for a way out or 'back to home'. Leads to a lot of 'back back back' garbage taps. It's not easy to switch branches.&lt;/li&gt;
&lt;li&gt;Work-around: combine w/ tab bar.&lt;/li&gt;
&lt;li&gt;It would be nice to have a gesture to go back. "Swipe across the top" is becoming the norm.&lt;/li&gt;
&lt;li&gt;As designers, we need to protect users from actions that will do them harm. Gesture Jiujitsu can help, e.g. using swipes &amp;#40;easy to do, hard to do accidentally&amp;#41; for undo or Return To Home.&lt;/li&gt;
&lt;li&gt;One of the great things about touch is that it removes mediation; you deal directly w/ what you want.&lt;/li&gt;
&lt;li&gt;Cons: 
&lt;ul&gt;
&lt;li&gt;Main categories available only from top.&lt;/li&gt;
&lt;li&gt;Inefficient to switch branches.&lt;/li&gt;
&lt;li&gt;No standard for returning to top level.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Popovers&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;iPad is a monster in the tablet space &amp;#40;although Kindle Fire is coming on strong in the US&amp;#41;.&lt;/li&gt;
&lt;li&gt;It's too big a screen to be switching pages all the time. Often the phone's "card-flipping" model doesn't work as well.&lt;/li&gt;
&lt;li&gt;Long-hold is the right-click of gestural interfaces.&lt;/li&gt;
&lt;li&gt;Pop-overs are ok for quick interactions.&lt;/li&gt;
&lt;li&gt;Use popovers to act on content.&lt;/li&gt;
&lt;li&gt;Use popovers for quick peaks.&lt;/li&gt;
&lt;li&gt;Avoid popovers for exploration or navigation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;None of the above: new interfaces&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Design the personality of your app at the outset.&lt;/li&gt;
&lt;li&gt;A personality will emerge no matter what; if you don't design it, you'll be at its mercy.&lt;/li&gt;
&lt;li&gt;Simple things like backgrounds can change the personality greatly, even while sticking to the same design patterns.&lt;/li&gt;
&lt;li&gt;Emotion is a design element.&lt;/li&gt;
&lt;li&gt;Q: do you like skeumorphism? At worst, it can be kitschy, but at best it can show you how to use the app. What does your metaphor propose? and what does it promise? If it looks like a book, I should be able to turn the page &amp;#40;I'm looking at you, iPad contacts&amp;#41;. Be true to your metaphor when you go skeuomorphic.&lt;/li&gt;
&lt;li&gt;Skeumorphism often takes a strong point of view, which can be good or bad.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Metaphorically speaking&lt;/h3&gt;

&lt;p&gt;The Dark Art of Aping Real Objects&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Some clones are the same size: Guitar tuner, apple remote. Sounds and animation can enhance that illusion. You're absorbing all the industrial design thought that went into the original, though you may  lose some ergonomic affordances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Minitures &amp;#40;Chess, GarageBand's piano&amp;#41; are a bit different. The interface loses its ergonomics.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src="http://www.radiootd.com/wp-content/uploads/2011/12/apple-voice-memos-voice-recorder-iphone.jpg" alt="Voice capture app is eye candy, but not functional." /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sometimes it's just eye-candy. &amp;#40;E.g. voice capture app w/ its microphone&amp;#41;.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lots of shelves these days. Its just a dressed-up tree structure, but &lt;strong&gt;we love collections&lt;/strong&gt;. It's fine for things that belong on a shelf &amp;#40;e.g. books&amp;#41;, but you'll lose emotional resonance when the objects can't really be on shelves and the metaphors break.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When contemplating metaphors: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this a problem that can be solved with built-in, native tools?&lt;/li&gt;
&lt;li&gt;Are you being too clever? Is the metaphor complicating the mental model?&lt;/li&gt;
&lt;li&gt;Is your metaphor appropriate to the device? Phone OS's are card-based; bringing windows in gets weird.&lt;/li&gt;
&lt;li&gt;Do you have more interface than you need?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don't be different to be different, be different to be better. Different means I have to learn something new.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Creative interfaces can be joyful. See: &lt;a href="http://www.normalware.com/"&gt;BeBot&lt;/a&gt; &amp;#40;robot synth app&amp;#41;.&lt;/li&gt;
&lt;li&gt;Ask: am I going too far? Am I going far enough?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Gimmicky presentation&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;"The sin of pridefully obvious presentation": Ed Tufte.&lt;/li&gt;
&lt;li&gt;The NYT app quacks a lot like a newspaper. Why so boring?&lt;/li&gt;
&lt;li&gt;Apple asked NYT to build a demo for the iPad, just before the iPad was announced. Three young designers / developers were brought in: two weeks to do it, no contact with home base, no cell phones. "You'll be demo'ing to Steve, make us proud." Eep!&lt;/li&gt;
&lt;li&gt;After 2 days, they built a Deck-based version. Realized it was wrong; went back to what became "NYT Editors Choice". "Strong if conservative first effort".&lt;/li&gt;
&lt;li&gt;Sometimes you can impress most by doing it quietly.&lt;/li&gt;
&lt;li&gt;NYT App: "Yawn. It looks like the NYT". Flipboard: "HOLY CRAP! It looks like the NYT!!!"&lt;/li&gt;
&lt;li&gt;Old conventions aren't necessarily old-fashioned.&lt;/li&gt;
&lt;li&gt;Feature the content, not the interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Gestures&lt;/h1&gt;

&lt;h2&gt;Multitouch with Two Hands&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Uzu app for iPad: multitouch manipulation of particle generators.&lt;/li&gt;
&lt;li&gt;The utility of keyboard shortcuts comes from being able to do them w/o looking. Gestures provide a similar opportunity.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gestures that begin at the edge should be OS-level gestures: android, WebOS, Meego all did this. Apple used to, but recently has been breaking edge gestures by taking them over.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Buttons require cognitive and physical effort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Gestures ~= keyboard shortcuts.&lt;/li&gt;
&lt;li&gt;Use entires screen as a controls.&lt;/li&gt;
&lt;li&gt;Standards are emerging: tap, swipe, pinch/spread, long tap.&lt;/li&gt;
&lt;li&gt;Model content as physical objects.&lt;/li&gt;
&lt;li&gt;Explore multitouch gestures.&lt;/li&gt;
&lt;li&gt;Follow the toddlers; they're better at this than we are. They haven't been spoiled by 20 years of desktop interactions.&lt;/li&gt;
&lt;li&gt;Make a 3 yr old your beta tester. She won't understand the content of the app, but she can use the interface and navigate.&lt;/li&gt;
&lt;li&gt;"NUI": Natural User Interface&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Haptics&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Shake is a powerful gesture, but can be gimmicky. It takes the focus off the app, and onto the device.&lt;/li&gt;
&lt;li&gt;Younger people are more inclined to rotate the phone; older folks stay with portrait.&lt;/li&gt;
&lt;li&gt;Landscape tends to be more engaging: both hands are occupied, and the aspect ration is closer to our biological field of view. &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The more backward-compatible &amp;#40;accessible&amp;#41; your app is, the more forward-compatible &amp;#40;future-proof&amp;#41; it'll be.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Mobile's a great wedge, because it's got everyone in a panic right now. We've been building websites the wrong way for 15 years.&lt;/li&gt;
&lt;li&gt;We've got the most exciting job in the world!&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Tweets&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;When designing for mobile, don't confuse &lt;strong&gt;context&lt;/strong&gt; with &lt;strong&gt;intent&lt;/strong&gt;. - Josh Clark&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;clarity trumps density&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <pubDate>Sun, 13 May 2012 11:42:00 -0700</pubDate>
      <title>From customer requirements to releasable gem</title>
      <author>Ken Mayer</author>
      <link>http://www.pivotallabs.com/users/ken/blog/articles/2107-from-customer-requirements-to-releasable-gem</link>
      <guid>http://www.pivotallabs.com/users/ken/blog/articles/2107-from-customer-requirements-to-releasable-gem</guid>
      <description>&lt;p&gt;One of the many pleasures of working at Pivotal Labs is that we are encouraged to release some of our work as open source. Often during the course of our engagements, we write code that might have wide-spread use. Due to the nature of our contracts, we can not unilaterally release such code. Those rights belong to the client. And rightly so. So, it is an even greater pleasure when one of our clients believes in "giving back" to the community, as well. &lt;/p&gt;

&lt;p&gt;One such example is this modest gem, &lt;code&gt;attribute_access_controllable&lt;/code&gt; which allows you to set read-only access at the &lt;em&gt;attribute&lt;/em&gt; level, on a per-instance basis. For example, let's say that you have a model &lt;code&gt;Person&lt;/code&gt; with an attribute &lt;code&gt;birthday&lt;/code&gt;, which, for security purposes, cannot be changed once this attribute is set &amp;#40;except, perhaps, by an administrator with extraordinary privileges&amp;#41;. Any future attempts to change this attribute will result in a validation error.&lt;/p&gt;

&lt;p&gt;e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; alice = Person.new&amp;#40;:birthday =&amp;gt; '12/12/12'&amp;#41;
=&amp;gt; #&amp;lt;Person id: nil, attr1: nil, created_at: nil, updated_at: nil, read_only_attributes: nil, birthday: "0012-12-12"&amp;gt; 
&amp;gt; alice.attr_read_only&amp;#40;:birthday&amp;#41;
=&amp;gt; #&amp;lt;Set: {"birthday"}&amp;gt; 
&amp;gt; alice.save!
=&amp;gt; true
&amp;gt; alice.birthday = "2012-12-12"
=&amp;gt; "2012-12-12" 
&amp;gt; alice.save!
ActiveRecord::RecordInvalid: Validation failed: Birthday is invalid, Birthday is read_only
&amp;gt; alice.save!&amp;#40;:skip_read_only =&amp;gt; true&amp;#41;
=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Setting this up is trivial, thanks to a Rails generator which does most of the heavy lifting for you.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rails generate attribute_access Person
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After that, you need only know about one new method added to your class:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#attr_read_only&amp;#40;*attributes&amp;#41; # Marks attributes as read-only
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are a few others, but this one, plus the new functionality added to &lt;code&gt;#save&lt;/code&gt; and &lt;code&gt;#save!&lt;/code&gt; will get you quite far.&lt;/p&gt;

&lt;p&gt;And if that's all that you were looking for when you stumbled across this article, then there's no need to read any further. Go install the gem and have fun &amp;#40;and may your tests be green when you expect them to be&amp;#41;.&lt;/p&gt;&lt;h2&gt;From customer requirements to releasable gem&lt;/h2&gt;

&lt;p&gt;On the other hand, if you are interested in how we got from the original customer story to a releasable open sourced gem, read on. The source code for the module is a &lt;a href="https://github.com/halogenguides/Attribute-Access-Controllable/blob/master/lib/attribute_access_controllable.rb"&gt;mere 34 lines long&lt;/a&gt;. It implements 2 new methods, a validator and &amp;#40;gently&amp;#41; overrides &lt;code&gt;#save&lt;/code&gt; and &lt;code&gt;#save!&lt;/code&gt;. Being good Test Driven Developers, we wrote our specs first, and since we wanted this behavior to be included in several models, we wrote our specs as a &lt;a href="https://github.com/halogenguides/Attribute-Access-Controllable/blob/master/lib/attribute_access_controllable/spec_support/shared_examples.rb"&gt;&lt;em&gt;shared behavior&lt;/em&gt;&lt;/a&gt; as well. The spec clocks in at 44 lines, slightly longer than our implementation. All in all, tiny. The whole commit was less than 100 lines of code.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;AttributeAccessControllable
  it should behave like it has AttributeAccessControllable
    #attr_read_only&amp;#40;:attribute, ...&amp;#41; marks an attribute as read-only
    #read_only_attribute?&amp;#40;:attribute&amp;#41; returns true when marked read-only
    #read_only_attribute?&amp;#40;:attribute&amp;#41; returns false when not marked read-only &amp;#40;or not marked at all&amp;#41;
    #save! raises error when :attribute is read-only
    #save!&amp;#40;:context =&amp;gt; :skip_read_only&amp;#41; is okay
    #save is invalid when :attribute is read-only
    #save&amp;#40;:context =&amp;gt; :skip_read_only&amp;#41; is okay
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In order to get to something "releasable" we needed a few more things, which we put on our To-Do list:&lt;/p&gt;

&lt;h4&gt;To do&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;MIT License&lt;/li&gt;
&lt;li&gt;A gem specification&lt;/li&gt;
&lt;li&gt;Basic documentation in a README file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The list got longer as we fleshed out both the documentation and the integration tests, as you'll see in a moment, but first, let's talk about&lt;/p&gt;

&lt;h3&gt;Getting the legal issues resolved&lt;/h3&gt;

&lt;p&gt;Pivotal's open sourcing policy is straightforward and simple to execute; We don't touch it. We write code for our clients, it's their code to do with as they please. My particular client liked the work we did for them and thought it would make a great open source gem. The Director of Engineering signed off on the idea and I paired with him to create the github repository during a lunch break. The first commit was tiny, just a basic directory structure and the existing code. I don't think the tests passed because they lacked a proper RSpec infrastructure.&lt;/p&gt;

&lt;h3&gt;Creating the gem&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;bundler gem DIRECTORY
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;is your best friend. It set up the layout for us, including an MIT License and a gem specification. It had a boilerplate README, too.&lt;/p&gt;

&lt;h3&gt;Writing the documentation for the code you wished you had&lt;/h3&gt;

&lt;p&gt;Next, we wrote a draft of the README file which documented what we knew: You needed a migration to create a column called &lt;code&gt;:read_only_attributes&lt;/code&gt; and you needed to include the module into the class. Then we started thinking about the pain points of using our code as is. Wouldn't it be nice if we could create the migration automatically? Rails generators do that sort of thing, how hard could it be? &amp;#40;Famous last words...&amp;#41; It became clear that we needed to test drive out some new features of the &lt;em&gt;gem&lt;/em&gt; that supported the actual &lt;em&gt;module&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;To do&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strike&gt;MIT License&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;A gem specification&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Basic documentation in a README file&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;Integration test&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;I am not a big cucumber fan, but...&lt;/h3&gt;

&lt;p&gt;Really, I'm not. I used to write Cucumber features all the time, but nowadays, I use a combination of RSpec and Capybara to get most of my day-to-day integration testing done. There is, however, one sweet spot for Cucumber that I'm finding more and more useful; A very high-level document that describes essential features in a way that a reader will say, "Ahhh, so &lt;em&gt;that&lt;/em&gt; is how it is supposed to work!" Here's a copy of the spec I wrote:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Feature: Read only attributes

Scenario: In a simple rails application
  Given a new rails application
  And I generate a new migration for the class "Person"
  And I generate an attribute access migration for the class "Person"
  And I have a test that exercises read-only
  When I run `rake spec`
  Then the output should contain "7 examples, 0 failures"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You probably won't find any web-steps out there to handle these lines. I use &lt;a href="https://github.com/cucumber/aruba"&gt;Aruba&lt;/a&gt; to handle the dirty work of executing shell commands in a safe sandbox-y way. The &lt;a href="https://github.com/halogenguides/Attribute-Access-Controllable/blob/master/features/step_definitions/steps.rb"&gt;step definition file&lt;/a&gt; hides most of the ugliness. Even so, most readers could figure out what to do, by hand, for each step.&lt;/p&gt;

&lt;h4&gt;To do&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strike&gt;MIT License&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;A gem specification&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Basic documentation in a README file&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Integration test&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;Generator&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Big generators&lt;/h3&gt;

&lt;p&gt;This gem was my first attempt at writing a generator, so it was awkward. I still don't understand &lt;a href="https://github.com/wycats/thor"&gt;Thor&lt;/a&gt; properly. Fortunately, I happened upon &lt;a href="https://github.com/alexrothenberg/ammeter"&gt;Ammeter&lt;/a&gt;, which helped me write out test specs for the generator. If you've got good specs, then you can sometimes stumble along until you learn enough to get it right. Alex Rothenberg's original &lt;a href="http://www.alexrothenberg.com/2011/10/10/ammeter-the-way-to-write-specs-for-your-rails-generators.html"&gt;blog post&lt;/a&gt; about the gem was quite informative, as were the test cases from the &lt;a href="https://github.com/plataformatec/devise/tree/master/test/generators"&gt;Devise&lt;/a&gt; gem.&lt;/p&gt;

&lt;p&gt;I have to admit; constructing the generator was more complex than the original module! There are more "moving parts;" templates, usage files, specs, in addition to the generator itself. So there is a certain amount of overhead that might overwhelm the original content. On the other hand, I learned quite a bit, and the gem is far more useful.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require "spec_helper"
require 'generators/attribute_access/attribute_access_generator'

describe AttributeAccessGenerator do
  before do
    prepare_destination
    Rails::Generators.options[:rails][:orm] = :active_record
  end

  describe "the migration" do
    before { run_generator w&amp;#40;Person&amp;#41; }
    subject { migration_file&amp;#40;'db/migrate/create_people.rb'&amp;#41; }
    it { should exist }
    it { should be_a_migration }
    it { should contain 'class CreatePeople &amp;lt; ActiveRecord::Migration' }
    it { should contain 'create_table :people do |t|'}
    it { should contain 't.text :read_only_attributes'}
  end

  describe "the class" do
    before { run_generator w&amp;#40;Person&amp;#41; }
    subject { file&amp;#40;'app/models/person.rb'&amp;#41; }
    it { should exist }
    it { should contain 'include AttributeAccessControllable' }
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some interesting things to note; you must &lt;code&gt;require&lt;/code&gt; the generator, since it is not pulled in by default. The subject of each suite is a &lt;em&gt;file&lt;/em&gt;, not the class &lt;code&gt;AttributeAccessGenerator&lt;/code&gt;. The &lt;code&gt;migration_file&lt;/code&gt; helper prepends the TIMESTAMP onto the migration file for you. If you need to set up more things for your test, &lt;code&gt;destination_root&lt;/code&gt; is a helper with a path to the temporary directory. It remains after the tests have run, which makes it useful when debugging.&lt;/p&gt;

&lt;p&gt;Here's something else that I did not know, but it might help new generator writers; the order in which you define your methods in the generator class is &lt;em&gt;significant&lt;/em&gt;. I don't know how this is done, but each "method" in the generator class is executed in turn. This is important for my generator; the model class definition &lt;em&gt;must&lt;/em&gt; exist before I inject the new content that mixes in the module, so I had to write the &lt;code&gt;generate_model&lt;/code&gt; method before the &lt;code&gt;inject_attribute_access_content&lt;/code&gt; method. I was scratching my head over that one for quite awhile.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require "rails/generators/active_record"

class AttributeAccessGenerator &amp;lt; ActiveRecord::Generators::Base
  source_root File.expand_path&amp;#40;'../templates', __FILE__&amp;#41;

  def create_migration_file
    if &amp;#40;behavior == :invoke &amp;amp;&amp;amp; model_exists?&amp;#41;
      migration_template "migration.rb", "db/migrate/add_read_only_attributes_to_#{table_name}"
    else
      migration_template "migration_create.rb", "db/migrate/create_#{table_name}"
    end
  end

  def generate_model
    invoke "active_record:model", [name], :migration =&amp;gt; false unless model_exists? &amp;amp;&amp;amp; behavior == :invoke
  end

  def inject_attribute_access_content
    class_path = class_name.to_s.split&amp;#40;'::'&amp;#41;

    indent_depth = class_path.size
    content = "  " * indent_depth + 'include AttributeAccessControllable' + "\n"

    inject_into_class&amp;#40;model_path, class_path.last, content&amp;#41;
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;To do&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strike&gt;MIT License&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;A gem specification&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Basic documentation in a README file&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Integration test&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Generator&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;Shareable tests&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Yo, I hear you like tests in your tests&lt;/h2&gt;

&lt;p&gt;Lastly, we want to share the testing love. The gem consumer should not have to &lt;em&gt;write&lt;/em&gt; tests to drive out the same feature that we have already tested. That would not be very DRY. So, in order to make our shared behavior, er, um, &lt;em&gt;shareable&lt;/em&gt;, we moved it into &lt;code&gt;lib&lt;/code&gt; with a few wrappers, namely, the &lt;code&gt;spec_support.rb&lt;/code&gt; file, which you can include in your own spec files to test drive adding the module to your own classes.&lt;/p&gt;

&lt;p&gt;Which is where &lt;code&gt;And I have a test that exercises read-only&lt;/code&gt; comes in. You can see this in the &lt;code&gt;steps.rb&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'spec_helper'
require 'attribute_access_controllable/spec_support'

describe Person do
  it_should_behave_like "it has AttributeAccessControllable", :attr1
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;To do&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strike&gt;MIT License&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;A gem specification&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Basic documentation in a README file&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Integration test&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Generator&lt;/strike&gt;&lt;/li&gt;
&lt;li&gt;&lt;strike&gt;Shareable tests&lt;/strike&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Don't be afraid to release v1.0.0&lt;/h2&gt;

&lt;p&gt;I am a strong believer in &lt;a href="http://semver.org/"&gt;semantic versioning&lt;/a&gt;. I simply can not understand why some core ruby tools are still living in version zero land, even after years and years of development and use. So, after a couple of internal commits, we released v1.0.0 of the gem, and less than a day later released v1.1.0 and then v1.1.1! &amp;#40;You probably shouldn't use anything less than v1.1.1&amp;#41;&lt;/p&gt;

&lt;h2&gt;An interesting mix&lt;/h2&gt;

&lt;p&gt;In summary, we used a lot of tools and techniques to go from a simple commit to a shareable gem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rails generators&lt;/li&gt;
&lt;li&gt;Cucumber&lt;/li&gt;
&lt;li&gt;Aruba&lt;/li&gt;
&lt;li&gt;Ammeter&lt;/li&gt;
&lt;li&gt;RSpec shared behaviors&lt;/li&gt;
&lt;li&gt;Integration tests&lt;/li&gt;
&lt;li&gt;Generator tests&lt;/li&gt;
&lt;li&gt;Module tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I encourage everyone to release as much of their work as possible because it raises the state of the art for us all. There are limits, of course, but that still affords lots of wiggle room. Small gems like &lt;code&gt;attribute_access_controllable&lt;/code&gt; won't change the world, but they ease the pain of staying DRY and we all get to learn a little something.&lt;/p&gt;

&lt;h3&gt;Thanks&lt;/h3&gt;

&lt;p&gt;To Social Chorus for choosing to open source this code. And to Pivotal Labs for encouraging a better way to do software engineering.&lt;/p&gt;</description>
    </item>
    <item>
      <pubDate>Fri, 11 May 2012 11:04:00 -0700</pubDate>
      <title>The Future of Web Design in London</title>
      <author>Jonathan Berger</author>
      <link>http://www.pivotallabs.com/users/jonathanpberger/blog/articles/2106-the-future-of-web-design-in-london</link>
      <guid>http://www.pivotallabs.com/users/jonathanpberger/blog/articles/2106-the-future-of-web-design-in-london</guid>
      <description>&lt;p&gt;I'm very excited to head to London next week to speak &lt;a href="http://futureofwebdesign.com/london-2012/schedule#code-literacy-for-designers-session"&gt;Code Literacy for Designers&lt;/a&gt; at the always-excellent Future of Web Design Conference. Working at Pivotal Labs, I've learned a lot over the last few years about how Agile software development and design interact, and I'm really looking forward to engaging in the conversation in one of my favorite cities. If you'll be at FOWD, please come check it out at 11:15 on Wed! And if you're in London and want to talk UX, drop me a line!&lt;/p&gt;

&lt;p&gt;From the talk description:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;Do you spend half your day on mockups in Illustrator and the other half on Javascript in a text editor? Know anyone who does? The way we work is changing. Rigid, traditionally defined roles like "Designer" and "Developer" are being displaced by interdisciplinary skillsets and a culture of collective product ownership. In this talk, we’ll investigate how treating Coding as Literacy can affect the way decisions are made and work gets done, describe how varying levels of literacy among teammates facilitate effective agile design and development, and discuss how designers can get literate in technical topics.&lt;/p&gt;
&lt;/blockquote&gt;</description>
    </item>
    <item>
      <pubDate>Thu, 10 May 2012 12:43:00 -0700</pubDate>
      <title>Getting image data from a CarrierWave uploader into RMagick</title>
      <author>Mark Rushakoff</author>
      <link>http://www.pivotallabs.com/users/mrushakoff/blog/articles/2105-getting-image-data-from-a-carrierwave-uploader-into-rmagick</link>
      <guid>http://www.pivotallabs.com/users/mrushakoff/blog/articles/2105-getting-image-data-from-a-carrierwave-uploader-into-rmagick</guid>
      <description>&lt;p&gt;Carrierwave has an RMagick module that offers a handy &lt;a href="http://rdoc.info:8080/github/jnicklas/carrierwave/master/CarrierWave/RMagick#manipulate21-instance_method"&gt;&lt;code&gt;manipulate!&lt;/code&gt; method&lt;/a&gt; that takes a block where you can modify the image, and then it saves the changes to the image.&lt;/p&gt;

&lt;p&gt;But sometimes you only want to interrogate the image, and there's no need to save any changes.&lt;/p&gt;

&lt;p&gt;After spending probably 30-45 minutes trying to figure out how to read an image that may not necessarily exist on your local disk, the simplest solution we found was to call &lt;a href="http://rdoc.info:8080/github/jnicklas/carrierwave/master/CarrierWave/Uploader/Proxy#read-instance_method"&gt;&lt;code&gt;uploader#read&lt;/code&gt;&lt;/a&gt; to get the contents of the file as a string, and then pass that into &lt;a href="http://www.imagemagick.org/RMagick/doc/image1.html#from_blob"&gt;&lt;code&gt;Magick::Image.from_blob&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <pubDate>Wed, 09 May 2012 11:50:00 -0700</pubDate>
      <title>How GOV.UK keeps calm and carries on with Tracker</title>
      <author>Ronan Dunlop</author>
      <link>http://www.pivotallabs.com/users/rdunlop/blog/articles/2103-how-gov-uk-keeps-calm-and-carries-on-with-tracker</link>
      <guid>http://www.pivotallabs.com/users/rdunlop/blog/articles/2103-how-gov-uk-keeps-calm-and-carries-on-with-tracker</guid>
      <description>&lt;p&gt;&lt;/p&gt;
&lt;/p&gt;&lt;a href="http://assets.pivotallabs.com/1394/original/carry_on_gov.png" alt="Trackerati at the watering hole"&gt;&lt;img src="http://assets.pivotallabs.com/1394/original/carry_on_gov.png" width="100" /&gt;&lt;/a&gt;
&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;The courageous folk working on the GOV.UK website &amp;#40;an experimental ‘beta’ replacement for Directgov and the first step towards a single government website&amp;#41; have regularly written about their experience and their &lt;a href="http://digital.cabinetoffice.gov.uk/archives/"&gt;blog&lt;/a&gt; is a worthwhile read. &lt;/p&gt;

&lt;p&gt;Their most recent article &lt;a href="http://digital.cabinetoffice.gov.uk/2012/04/30/delivering-inside-government/"&gt;Delivering Inside Government&lt;/a&gt;, posted by Peter Herlihy, offers great insights and advice for agile teams. &lt;/p&gt;

&lt;p&gt;Below is an outline of their article with point six detailing their use of Tracker and how making their stories &lt;a href="https://www.pivotaltracker.com/projects/367813/stories"&gt;public&lt;/a&gt; while scary at first proved to be a good move.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If it's hard to write a story, it's probably not as important as you think&lt;/li&gt;
&lt;li&gt;If it's important you will remember it&lt;/li&gt;
&lt;li&gt;Investing time preparing stories before sprint planning paid big dividends&lt;/li&gt;
&lt;li&gt;Avoid the temptation to make the newest story the most important&lt;/li&gt;
&lt;li&gt;Make sure you can tell when your objectives are met&lt;/li&gt;
&lt;li&gt;Running our project in the open wasn't a scary thing.
&lt;/p&gt;
&lt;a href="http://digital.cabinetoffice.gov.uk/2012/04/30/delivering-inside-government/"&gt;Read the full blog post here&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
  </channel>
</rss>

