<?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>Atomic Spin</title>
	<atom:link href="http://spin.atomicobject.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://spin.atomicobject.com</link>
	<description>Atomic Object&#039;s Blog On Software Design &#38; Development</description>
	<lastBuildDate>Wed, 22 Feb 2012 18:57:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Lessons from Startup Weekend Detroit</title>
		<link>http://spin.atomicobject.com/2012/02/22/lessons-from-startup-weekend-detroit/</link>
		<comments>http://spin.atomicobject.com/2012/02/22/lessons-from-startup-weekend-detroit/#comments</comments>
		<pubDate>Wed, 22 Feb 2012 17:41:10 +0000</pubDate>
		<dc:creator>Jason Porritt</dc:creator>
				<category><![CDATA[Process & Practices]]></category>
		<category><![CDATA[Startups]]></category>
		<category><![CDATA[detroit]]></category>
		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84500</guid>
		<description><![CDATA[	<p>What kind of business can you build in 54 hours? That&#8217;s the challenge at every Startup Weekend event and the group in attendance at the M@dison building for <a href="http://detroit.startupweekend.org/2012/02/21/startup-weekend-detroit-4-recap-video/">Startup Weekend Detroit</a> was more than up to the challenge. Six of us from Atomic Object made the trek out to the event to participate. We built, and learned, a lot.</p>

<p><a href="http://spin.atomicobject.com/2012/02/22/lessons-from-startup-weekend-detroit/" class="more-link">Read more on Lessons from Startup Weekend Detroit <span class="meta-nav">&#187;</span></a></p>]]></description>
			<content:encoded><![CDATA[	<p>What kind of business can you build in 54 hours? That&#8217;s the challenge at every Startup Weekend event and the group in attendance at the M@dison building for <a href="http://detroit.startupweekend.org/2012/02/21/startup-weekend-detroit-4-recap-video/">Startup Weekend Detroit</a> was more than up to the challenge. Six of us from Atomic Object made the trek out to the event to participate. We built, and learned, a lot.</p>

	<p><img src="http://spin.atomicobject.com/wp-content/uploads/6907024605_c60b7f7be7.jpeg" alt="Drew, Mike, Justin, and Jason in Detroit." title="AO in the D" width="500" height="333" class="size-full wp-image-84516" /></p>

	<p><a href="http://atomicobject.com/pages/Drew+Colthorp">Drew Colthorp</a> and I worked with <a href="http://www.peterbeaugard.com/">Peter Beaugard</a>, Kari, and Ben on <a href="http://turndetroit.com/">turnDetroit</a> for the weekend. In a nutshell, turnDetroit&#8217;s goal is to promote community involvement in identifying, funding, and pursuing opportunities to make productive use of vacant spaces. We were reminded of a few important lessons throughout the event, and our project in particular illustrated that the most important problems to solve are often not technical in nature.</p>

	<p><span id="more-84500"></span></p>

	<h2>The most important problems are frequently non-technical</h2>

	<p>Non-technical problems can be very interesting, challenging, and rewarding to take on. Still, as developers, it can be easy to jump into building software when a short deadline looms on the horizon. We spent a lot of time as a team working out exactly what problem we were trying to solve, how to engage communities, how to process incoming ideas, and how turnDetroit could make enough money to be self-sustaining. Peter had alreay put a lot of thinking into the concept of turnDetroit and that helped frame our minimum viable product discussions.</p>

	<p>Software was involved in our proposed solutions to the problems identified, but the type of software needed is not particularly challenging or unique. The approach to personal interactions was much more valuable to define.</p>

	<h2>Prioritize, prioritize, prioritize</h2>

	<p>It was critical to focus on the product we really needed from our limited time: the pitch. We prioritized tasks that would help build a good story for the pitch. Ben worked diligently on <a href="http://vimeo.com/37066604">a video to illustrate the concept</a>, Kari and Peter focused a lot of energy on the pitch slide deck, and Drew and I focused in on wireframes for the idea intake, discovery, and funding tasks. Keeping post-it notes hung on the wall identifying our high-value personas and stories helped keep us focused.</p>

	<p>Still, we found ourselves off in the woods for an hour or two. Of course Drew and I wanted to build some sort of software to show off during the pitch (we <em>are</em> software developers) and we gave it a brief try. But it came to an end as we were reminded of another lesson:</p>

	<h2>Frustration saps energy and motivation; success rejuvinates</h2>

	<p>The technology side of our mockup came together relatively quickly thanks to a combination of familiar and new tools (Staticmatic2, Twitter&#8217;s Bootstrap). We had a reasonably functional and flexible layout for the content we wanted to show, but it needed more design attention. Drew and I stated integrating aspects of the design aesthetic from a pre-existing slide deck but were struggling with adapting it to the needs of the web content.</p>

	<p>Combined with the already long day (9am to 7pm at that point), the frustration of striving for successful visual design without success left us both nearly ready to call it a day by 8pm. We felt exhausted and unmotivated.</p>

	<p>Amazingly, after we aborted that attempt, took a brief break, and then focused on putting together a few Balsamiq mockups  (something we&#8217;re quite good at) we regained our motivation and worked steadily until 11pm.</p>

	<p>We&#8217;ve seen this pattern before. It&#8217;s a big reason why we find it worthwhile to spend time crafting tools. The less we feel like we&#8217;re banging our heads against technology, the more energy we have to solve the problems our customers are more interested in. Good tools more than pay for themselves in the long run.</p>

	<h2>There&#8217;s a lot of positive energy in Detroit</h2>

	<p>We got to meet awesome people, work on a few great projects, and see first-hand the entrepreneurial spirit at work in Detroit. I hope we&#8217;ll see a few of the winners at the <a href="http://momentum-mi.com/events/lean-conference/">Michigan Lean Startup Conference</a> in Grand Rapids on May 17, and I expect We&#8217;ll be back to spend some time in Detroit again soon. Well done, everyone.</p>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/22/lessons-from-startup-weekend-detroit/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Usability Testing Summary Template</title>
		<link>http://spin.atomicobject.com/2012/02/21/usability-testing-summary-template/</link>
		<comments>http://spin.atomicobject.com/2012/02/21/usability-testing-summary-template/#comments</comments>
		<pubDate>Tue, 21 Feb 2012 21:41:41 +0000</pubDate>
		<dc:creator>Shawn Crowley</dc:creator>
				<category><![CDATA[Process & Practices]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[usability testing]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84433</guid>
		<description><![CDATA[<p><a href="http://atomicobject.com/pages/Brittany+Hunter">Brittany</a> and I recently created a usability test overview that aimed to summarize our test findings with clarity and brevity.</p>
<p>You can download the template <a href="http://spin.atomicobject.com/wp-content/uploads/UsabilityTestResultsTemplate.numbers.zip" title="Usability Testing Summary Template">here</a>.</p>
<p>We designed our test scenarios using our <a href="https://spin.atomicobject.com/2012/02/15/usability-testing-starter-kit/" title="Usability Starter Kit">usability starter kit templates</a>.</p>
<p><a href="http://spin.atomicobject.com/2012/02/21/usability-testing-summary-template/" class="more-link">Read more on Usability Testing Summary Template <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p><a href="http://atomicobject.com/pages/Brittany+Hunter">Brittany</a> and I recently created a usability test overview that aimed to summarize our test findings with clarity and brevity.</p>
<p>You can download the template <a href="http://spin.atomicobject.com/wp-content/uploads/UsabilityTestResultsTemplate.numbers.zip" title="Usability Testing Summary Template">here</a>.</p>
<p>We designed our test scenarios using our <a href="https://spin.atomicobject.com/2012/02/15/usability-testing-starter-kit/" title="Usability Starter Kit">usability starter kit templates</a>.</p>
<p>The starter kit templates made sure our testing session was organized and our tests were consistent.</p>
<p>Rather than present our test plan and comprehensive observer notes to the team, we preferred to create a summary that grouped each users&#8217; test step performance into a category that indicated confidence and overall success.</p>
<p>For each step, we categorized a user action to be:</p>
<ul>
<li>Immediate</li>
<li>Some Thought</li>
<li>Multiple Tries</li>
<li>Failed</li>
</ul>
<p>We then created color-coded tables of scenario steps and users to give a quick visual overview of smooth and troublesome points.</p>
<p><a href="http://spin.atomicobject.com/2012/02/21/usability-testing-summary-template/usabilitytestresultstemplate/" rel="attachment wp-att-84439"><img src="http://spin.atomicobject.com/wp-content/uploads/UsabilityTestResultsTemplate-590x464.png" alt="" title="Usability Test Results Template" width="590" height="464" class="aligncenter size-medium wp-image-84439" /></a></p>
<p>We used comments to call out interesting points from our observer notes.</p>
<p>We included three large comment notes to provide context and next steps:</p>
<ul>
<li><strong>Rationale</strong> &#8211; Includes a brief summary of the test plan. Includes test hypotheses.</li>
<li><strong>Observations</strong> &#8211; States if hypotheses were supported or contradicted.</li>
<li><strong>Recommendations</strong> &#8211; Makes clear recommendations for next steps (if any). Should state areas that will be addressed but doesn&#8217;t necessarily define how.
</li>
</ul>
<p>I like how the template turned out. It provides a quick reference of intent and results, an intuitive visual overview, and qualitative details that balance the discrete categorization of users&#8217; interactions.</p>
<p>Please <a href="http://spin.atomicobject.com/wp-content/uploads/UsabilityTestResultsTemplate.numbers.zip" title="Usability Testing Summary Template">try the template</a> if it can be useful to you and please feel free to contribute changes or additions.</p>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/21/usability-testing-summary-template/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Given I am signed in using capybara-webkit</title>
		<link>http://spin.atomicobject.com/2012/02/20/signed-in-with-capybara-webkit/</link>
		<comments>http://spin.atomicobject.com/2012/02/20/signed-in-with-capybara-webkit/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 20:00:55 +0000</pubDate>
		<dc:creator>Patrick Bacon</dc:creator>
				<category><![CDATA[Testing]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[capybara]]></category>
		<category><![CDATA[capybara-webkit]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84436</guid>
		<description><![CDATA[<p>Inspired by the blog post <a href="http://collectiveidea.com/blog/archives/2012/01/05/capybara-cucumber-and-how-the-cookie-crumbles/">Capybara, Cucumber and How the Cookie Crumbles</a>, I wanted to write a Cucumber step that signs a user directly into my application, without the need to navigate to a log-in page and submit a form. I am not thrilled about the stubbing and monkey patching discussed in that post, and I am also not concerned about doing something that is specific to the <a href="https://github.com/thoughtbot/capybara-webkit">capybara-webkit</a> driver used on my current project. The result is a capybara-webkit specific way of bypassing authentication from my Cucumber features.</p>
<p><a href="http://spin.atomicobject.com/2012/02/20/signed-in-with-capybara-webkit/" class="more-link">Read more on Given I am signed in using capybara-webkit <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>Inspired by the blog post <a href="http://collectiveidea.com/blog/archives/2012/01/05/capybara-cucumber-and-how-the-cookie-crumbles/">Capybara, Cucumber and How the Cookie Crumbles</a>, I wanted to write a Cucumber step that signs a user directly into my application, without the need to navigate to a log-in page and submit a form. I am not thrilled about the stubbing and monkey patching discussed in that post, and I am also not concerned about doing something that is specific to the <a href="https://github.com/thoughtbot/capybara-webkit">capybara-webkit</a> driver used on my current project. The result is a capybara-webkit specific way of bypassing authentication from my Cucumber features.</p>
<p><span id="more-84436"></span></p>
<p>The previously mentioned blog post sets a cookie with a token that identifies the logged in user. I decided to simply use the user&#8217;s ID instead:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> current_user
    <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0066ff; font-weight:bold;">@current_user</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#9966CC; font-weight:bold;">defined</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>@current_user<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">if</span> Rails.<span style="color:#9900CC;">env</span>.<span style="color:#9900CC;">test</span>? <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> cookies<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:test_user_id</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@current_user</span> = User.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span>cookies<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:test_user_id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Allowing a production user to be automatically signed into the application just by having their user ID in a cookie is an exceedingly poor idea; thus, the check to only allow this type of login to work in the <code>test</code> environment.</p>
<p>Now all the Cucumber step needs to do is to set a cookie with the appropriate user ID:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">When</span> <span style="color:#006600; font-weight:bold;">/</span>^I am signed <span style="color:#9966CC; font-weight:bold;">in</span> as <span style="color:#996600;">&quot;([^&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">*</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#996600;">&quot;$/ do |email|
    user_id = User.find_by_email!(email).id
    page.driver.browser.set_cookie(
      &quot;</span>test_user_id=<span style="color:#008000; font-style:italic;">#{user_id}; path=/; domain=localhost&quot;)</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now when the next request is made from the test, the specified user will be set in the <code>current_user</code> call.</p>
<h3>Notes</h3>
<ul>
<li>This particular test suite is configured to access the web server using <code>http://localhost:8888</code>. I first tried setting the domain in the cookie to be <code>127.0.0.1</code>, but it was not working. I am not sure what the default Capybara configuration is, but if you run into issues try both <code>127.0.0.1</code> and <code>localhost</code> as the domain in the cookie.</li>
<li>In addition to the user ID I also need to fake out several more cookies that the application sets when a user signs in using the normal form. I ran into some trouble setting these until I escaped the values with <code>CGI.escape</code>:</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  page.<span style="color:#9900CC;">driver</span>.<span style="color:#9900CC;">browser</span>.<span style="color:#9900CC;">set_cookie</span><span style="color:#006600; font-weight:bold;">&#40;</span>
    <span style="color:#996600;">&quot;#{key}=#{CGI.escape(value.to_s)}; path=/; domain=localhost&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<ul>
<li>The version of capybara-webkit I am using is a little older; it appears that a new interface for setting/getting cookies has been added in the form of a <code>cookies</code> method on the <a href="https://github.com/thoughtbot/capybara-webkit/blob/master/lib/capybara/driver/webkit.rb">Capybara::Driver::Webkit class</a>. I haven&#8217;t used this interface yet so I can&#8217;t speak to how it may differ the approach described above.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/20/signed-in-with-capybara-webkit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Software GR host Patrick Foley: &#8220;A Developer’s Guide to the Ever-Changing Cloud&#8221;</title>
		<link>http://spin.atomicobject.com/2012/02/20/software-gr-host-patrick-foley-a-developers-guide-to-the-ever-changing-cloud/</link>
		<comments>http://spin.atomicobject.com/2012/02/20/software-gr-host-patrick-foley-a-developers-guide-to-the-ever-changing-cloud/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 14:14:54 +0000</pubDate>
		<dc:creator>Mike Swieton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84487</guid>
		<description><![CDATA[<p>Recently Microsoft&#8217;s Patrick Foley visited <a href="http://softwaregr.org">Software GR.</a> Patrick is an <span class="caps">ISV</span> Architect Evangelist, which means he helps other software companies succeed building on the Microsoft platform. In addition to working with hundreds of partners, large and small, Patrick cohosts the Startup Success Podcast with Bob Walsh and produces Smart Bear Live with Jason Cohen.</p>
<p><a href="http://spin.atomicobject.com/2012/02/20/software-gr-host-patrick-foley-a-developers-guide-to-the-ever-changing-cloud/" class="more-link">Read more on Software GR host Patrick Foley: &#8220;A Developer’s Guide to the Ever-Changing Cloud&#8221; <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>Recently Microsoft&#8217;s Patrick Foley visited <a href="http://softwaregr.org">Software GR.</a> Patrick is an <span class="caps">ISV</span> Architect Evangelist, which means he helps other software companies succeed building on the Microsoft platform. In addition to working with hundreds of partners, large and small, Patrick cohosts the Startup Success Podcast with Bob Walsh and produces Smart Bear Live with Jason Cohen.</p>
<p>In this talk he shares his knowledge about what &#8220;cloud&#8221; is and what the technology might mean to your business.</p>
<p><!-- more --></p>
<p>This overview might be old news for some but if you&#8217;re looking to get a big picture view of the cloud world, <a href="http://vimeo.com/36369362">check out the video.</a></p>
<p>Next month Software GR will focus another of Grand Rapids&#8217; own great development talent, Traction Software&#8217;s Andy Keller:</p>
<blockquote>
<h2>When should you reinvent the wheel? </h2>
<p>When creating software, whether it be a small website or a large custom platform, you repeatedly face the build vs buy dilemma. Should you use raw sockets or a web framework that already speaks <span class="caps">HTTP</span>? Should you write javascript directly against the <span class="caps">DOM</span> or use a library like jQuery? Should you write a graphing library or find one on the web? Sometimes the answer seems obvious, but making the wrong decision can increase cost, time, complexity, maintenance and support.</p>
<p>In this talk I will start by framing the problem and will provide guidance for making the right decision while avoiding simple cliches like &#8220;don&#8217;t reinvent the wheel&#8221;. I will then go through specific examples from my experience working on a large mature codebase for a product that evolved considerably over more than 15 years. You&#8217;ll be surprised by some of our decisions and what we learned from them.</p>
</blockquote>
<p>Check <a href="http://softwaregr.org/2012/02/20/andy-keller-when-should-you-build-vs-buy/">the Software GR website</a> for the latest, and I&#8217;ll see you all there!</p>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/20/software-gr-host-patrick-foley-a-developers-guide-to-the-ever-changing-cloud/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Successful Demo Software Is Hard to Support</title>
		<link>http://spin.atomicobject.com/2012/02/20/successful-demo-software-is-hard-to-support/</link>
		<comments>http://spin.atomicobject.com/2012/02/20/successful-demo-software-is-hard-to-support/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 05:19:10 +0000</pubDate>
		<dc:creator>David Crosby</dc:creator>
				<category><![CDATA[Process & Practices]]></category>
		<category><![CDATA[agile]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84470</guid>
		<description><![CDATA[<p>We sometimes help customers build proof-of-concept products for internal demonstration, or better yet, run at a trade show in front of <em>their</em> customers and competitors.  We help define features, scope and budget, drive code with tests, and deliver continuously to provide as much control over the demo as possible. Sounds almost like production code.</p>
<p><a href="http://spin.atomicobject.com/2012/02/20/successful-demo-software-is-hard-to-support/" class="more-link">Read more on Successful Demo Software Is Hard to Support <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>We sometimes help customers build proof-of-concept products for internal demonstration, or better yet, run at a trade show in front of <em>their</em> customers and competitors.  We help define features, scope and budget, drive code with tests, and deliver continuously to provide as much control over the demo as possible. Sounds almost like production code.</p>
<p>Though it may not be a real product, the code we write is real software: it has purpose and value, and it <em>must work properly</em>. Why would we treat it differently than anything else?<br />
<span id="more-84470"></span></p>
<p>On the surface, it seems there are a few key differences in our approach to demo software as opposed to code we intend to launch into production.  For starters, we might worry less about cross-platform support, server up-time, security and so on if such things provide no value to the demo.  (Examples: selecting one specific smart phone for a mobile demo to reduce cross-device UI design and memory concerns, assuming a wifi network with preset addresses to avoid the need for a configuration screen.) We start to see how the phrase &#8220;must work properly&#8221; depends heavily on your definition of &#8220;proper,&#8221; on which we must carefully and continually maintain alignment with our customer. </p>
<p>But what we do build, we develop as we do everything else: working software that behaves as designed, without defects. We can&#8217;t ship a broken demo because we won&#8217;t get a second chance.</p>
<p>We&#8217;ve served our customers demo needs well with this careful balance of narrowing assumptions and quality software practices. In fact, a number of demos have lived long past their intended targets and taken on a life of their own.  Different groups in the customer&#8217;s organization demo the technology to a different audience, managers show their managers, VPs show potential clients. (Very cool!)</p>
<p>But as the stakes go up, the software is in increasing danger of failure.  Remember those carefully designed assumptions we made about environment and context? The new users might know very little about those.  They&#8217;re in a new location, maybe using some newly introduced hardware, maybe running the app on their personal cell phone. You might expect a production app to weather the changes, but our demo app probably won&#8217;t.  (Not very cool.)</p>
<p>So things start to break, and our original customers are getting stressful phone calls asking for help, and they ask for <em>our</em> help and we&#8217;re at a loss.  We&#8217;re annoyed that our software is misbehaving, we&#8217;re upset that it&#8217;s impacting somebody important on the customer side, and we&#8217;re pissed off that we can&#8217;t seem to help.  </p>
<p>Interesting puzzle, right?  We did a good job, the software is a hit, and everyone wants to see it, but the longer this goes on, the worse things seem to get.  </p>
<p>On the bright side, we have learned a few practical things that help us prepare for post-demo success, and the potential fall out:</p>
<ul>
<li>Deliver a single volume of all code, assets and tools related to the project, especially items produced by the customer&#8217;s team (if any)</li>
<li>Include very good documentation, geared toward someone who might be attempting a ground-up rebuild of the project</li>
<li>Automations: scripts and tools that enable quick build / deployment of the project</li>
</ul>
<p>Even though the source code belongs in source control, and documents belong in a document management system or wiki, and the customer&#8217;s firmware images are their own to manage, having everything in one place provides a common frame of reference.  On a phone call or emergency chat, we can refer back to this known good starting point, fast.  Capturing the customer&#8217;s artifacts along side our own will save them the trouble of going back in time to find a match for what we gave them.</p>
<p>&#8220;Good documentation&#8221; doesn&#8217;t mean exhaustive, repetitive, templated documentation.  Instead, strive for a <span class="caps">README</span>.txt that provides a list of simple steps to re-image a microprocessor, or upload a new config file, or access an error log.  Write these docs expecting that the reader is sweating, hurrying and unfamiliar with Ruby, CoffeeScript, awk, and all the other crazy stuff you used to build and deploy the project.</p>
<p>We strive to automate the build and deployment steps for all our projects, and this extends to uploading code to embedded controllers or executing <span class="caps">JAR</span> files on remote tablet PCs.  Why wouldn&#8217;t we share these tools with our customer?  (We might need to add a few links to describe the installation and setup of our automation tools.)</p>
<p>These three items are hardly new&#8212;they&#8217;re part of any reasonable project.  However, they can easily be overlooked in a proof-of-concept environment, where we&#8217;re making tradeoffs between traditional &#8220;production quality&#8221; and demo-time pragmatism.  But the reality is that even the initial demo can present some pretty stressful challenges, and over-delivering on artifacts, documentation and automation can help even at this early stage.</p>
<p>The last observation I&#8217;ll make speaks directly to the anxiety we feel at the outset of a demo project, when experience warns us to resist tradeoffs that might lead to future instability:  <strong>Remember not to second-guess the customer&#8217;s estimation of quality.</strong> Perhaps with the exception of the above three items, our customers must be trusted (and enabled) to make time-saving assumptions that can make the difference for their demo.  With our help, they can retain this flexibility without sacrificing the quality of the product we&#8217;re building for them.</p>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/20/successful-demo-software-is-hard-to-support/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Thoughts on Consolidation</title>
		<link>http://spin.atomicobject.com/2012/02/18/thoughts-on-consolidation/</link>
		<comments>http://spin.atomicobject.com/2012/02/18/thoughts-on-consolidation/#comments</comments>
		<pubDate>Sat, 18 Feb 2012 05:29:03 +0000</pubDate>
		<dc:creator>Scott Miller</dc:creator>
				<category><![CDATA[Business of Software]]></category>
		<category><![CDATA[Culture]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84421</guid>
		<description><![CDATA[<p>What do the following enterprises have in common:</p>
<ul>
<li>Automobile manufacturing</li>
<li>Banking</li>
<li>Garbage collection</li>
<li>Hardware sales</li>
<li>Video rentals</li>
</ul>
<p>Give up? Each of them, at one time, were nascent industries populated chiefly by small, local, mom &#38; pop style businesses. Also in common: they are all now dominated by a small handful of mega corporations<a title="" href="#_ftn1">[1]</a>.</p>
<p><a href="http://spin.atomicobject.com/2012/02/18/thoughts-on-consolidation/" class="more-link">Read more on Thoughts on Consolidation <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>What do the following enterprises have in common:</p>
<ul>
<li>Automobile manufacturing</li>
<li>Banking</li>
<li>Garbage collection</li>
<li>Hardware sales</li>
<li>Video rentals</li>
</ul>
<p>Give up? Each of them, at one time, were nascent industries populated chiefly by small, local, mom &amp; pop style businesses. Also in common: they are all now dominated by a small handful of mega corporations<a title="" href="#_ftn1">[1]</a>.</p>
<p>Is it possible that Atomic Object or the software industry in general could be headed down this same road?</p>
<p><span id="more-84421"></span>Early in the 20<sup>th</sup> century there were <a href="http://en.wikipedia.org/wiki/History_of_the_automobile#Veteran_era">hundreds of carmakers</a> throughout the western world, now the top 7 builders control nearly <a href="http://www.automotivedigest.com/content/displayArticle.aspx?a=56328">90% of the market</a>. Not that long ago there was a friendly neighborhood bank in nearly every neighborhood. After three decades of consolidation the likes of Bank of America, Chase &amp; Citigroup now reign over almost <a href="http://www.infoplease.com/toptens/usbanks.html">every region of the US</a>.  Waste Management, Home Depot &amp; Blockbuster head the list of modern goliaths in the other businesses.</p>
<p>With some recent events here in Grand Rapids and in our industry the question around the office these days is how does this trend apply to the custom software industry, or does it at all?</p>
<p>According to <a href="http://www.manta.com/mb_35_G217302S_000/custom_computer_programming_services">one collator</a> there are over 1600 custom software service companies in the United States. Over 60% of these companies had revenue of less than US$500,000, and about 85% with revenue below US$5,000,000. To put that in employee terms, nine out of ten firms in our industry employ fewer than 50 employees. We seem to still be in the &#8220;many small companies&#8221; stage of industry development.</p>
<p>The question of consolidation is an interesting subject at Atomic. We have been extremely cautious with the company’s growth plans. One of our <a href="http://www.atomicobject.com/pages/Working+at+Atomic+Object">core values</a> is maintaining the culture of excellence that began with the formation of Atomic Object in 2001. We are convinced that keeping a manageable office size is one of the keys to this philosophy. Our concern about growing our Grand Rapids office much beyond our current size has been one of the motivations to looking at expanding to <a href="http://spin.atomicobject.com/2011/12/09/reflections-on-2011-predictions-for-2012/#more-82475">Detroit</a>. It is inconceivable to most of us that we could be part of a company of hundreds or thousands and still be who we want to be.</p>
<p>Now, we think we’re getting pretty good at this innovation services game. And we think our culture and values have had as much to do with this as our technical prowess. Does this mean that the future of Atomic is sure to bring tempered or maybe no growth? In measurements limited to size, maybe it does. The bigger question is: is our industry headed the way of the mega corporation? I hope not. What do you think? Let me know in the comments.</p>
<div>
<hr align="left" size="1" width="33%" />
<div>
<p><a title="" href="#_ftnref1">[1]</a> Of course, video rental might be one the way out altogether</p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/18/thoughts-on-consolidation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How do you build a positively charged feedback loop?</title>
		<link>http://spin.atomicobject.com/2012/02/17/how-do-you-build-a-positively-charged-feedback-loop/</link>
		<comments>http://spin.atomicobject.com/2012/02/17/how-do-you-build-a-positively-charged-feedback-loop/#comments</comments>
		<pubDate>Fri, 17 Feb 2012 11:30:57 +0000</pubDate>
		<dc:creator>Micah Alles</dc:creator>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[Culture]]></category>
		<category><![CDATA[Startups]]></category>
		<category><![CDATA[feedback]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84411</guid>
		<description><![CDATA[<p>People like to hear they&#8217;re doing a good job. They don&#8217;t like to hear that they&#8217;re falling short. This conflict makes it difficult to implement an effective, comprehensive system for feedback in an organization. Another more difficult problem is leadership lacking data on the positive things an employee is contributing to the organization.</p>
<p><a href="http://spin.atomicobject.com/2012/02/17/how-do-you-build-a-positively-charged-feedback-loop/" class="more-link">Read more on How do you build a positively charged feedback loop? <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>People like to hear they&#8217;re doing a good job. They don&#8217;t like to hear that they&#8217;re falling short. This conflict makes it difficult to implement an effective, comprehensive system for feedback in an organization. Another more difficult problem is leadership lacking data on the positive things an employee is contributing to the organization.</p>
<p><span id="more-84411"></span></p>
<p>Recently I came across a blog post about Snippets, a system that facilitates scalable, asynchronous feedback from employees to management. Every employee reflects on what he accomplished over the past week, and what he plans to do the following week. This email is sent to the team leader, direct manager, <span class="caps">CEO</span> or made open to everyone. From the <a href="http://blog.idonethis.com/post/16736314554/silicon-valleys-productivity-secret">iDoneThis post:</a></p>
<blockquote>
<p>The Snippets process at any scale is a compelling productivity solution, and companies of all sizes have adopted it — some, like SV Angel, rich in Google <span class="caps">DNA</span>, do daily snippets. The process forces employees to reflect and to jot out a forward-looking plan for getting stuff done, all while requiring a minimal disruption in the employee’s actual work.</p>
</blockquote>
<blockquote>
<p>Setting aside time on a daily or weekly basis to reflect on the day is a powerful productivity hack. In The Progress Principle, Harvard Business School professor Teresa Amabile and Steven Kramer showed the counterintuitive conclusion that progress toward a meaningful goal is the #1 motivator for employees at work, not financial motivation or downward pressure. Professor Amabile prescribes 5 minutes per day of reflection, religiously protected by bosses, centered around the progress and the setbacks of the day. Simply put, employees connected to their work and its progress are happier and more productive.</p>
</blockquote>
<p>Techniques like this arm leaders with information that makes them proud of their employees while intrinsically motivating employees.</p>
<p>Have you tried to implemented or participated in a program like this? If so, how effective did you find it?</p>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/17/how-do-you-build-a-positively-charged-feedback-loop/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Leprechaun&#8217;s Pencil</title>
		<link>http://spin.atomicobject.com/2012/02/16/the-leprechauns-pencil/</link>
		<comments>http://spin.atomicobject.com/2012/02/16/the-leprechauns-pencil/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 17:13:46 +0000</pubDate>
		<dc:creator>Phil Kirkham</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[presentations]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84390</guid>
		<description><![CDATA[<p>Thanks to a recent tweet I ended up watching a video of a presentation about agile. Whilst the content of the talk could be an entire blog post in itself, the presentation was also poor. The presenter used Powerpoint slides with a paragraph of text that he would read out in its entirety, often followed by a &#8216;humorous&#8217; picture to illustrate his point.<br />
<span id="more-84390"></span> </p>
<p><a href="http://spin.atomicobject.com/2012/02/16/the-leprechauns-pencil/" class="more-link">Read more on The Leprechaun&#8217;s Pencil <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>Thanks to a recent tweet I ended up watching a video of a presentation about agile. Whilst the content of the talk could be an entire blog post in itself, the presentation was also poor. The presenter used Powerpoint slides with a paragraph of text that he would read out in its entirety, often followed by a &#8216;humorous&#8217; picture to illustrate his point.<br />
<span id="more-84390"></span> </p>
<p>He then moved onto how he kept things simple in his project and he decided to illustrate his point by using the example of NASA spending millions to develop a pen that worked in space whilst the Russians used a pencil.<br />
This has been debunked many times, a quick visit to <a href="http://www.snopes.com/business/genius/spacepen.asp" title="Snopes" target="_blank">Snopes</a> shows the story is false and that actually using a pencil would be dangerous with pieces of lead floating around the cabin. </p>
<p>( If you really want to buy a <a href="http://thewritersedge.com/fisher.astronaut.cfm" title="Space Pen" target="_blank">Space Pen</a> you can. )</p>
<p>Back to the presentation and the presenter had now lost some credibility. With <a href="http://leanpub.com/leprechauns" title="The Leprechauns of S/W Engineering" target="_blank">the Leprechauns of S/W Engineering</a> being hunted down, be careful when doing a presentation, writing an article or a blog post that you don&#8217;t lazily use &#8220;common truths&#8221; that don&#8217;t actually stand up to scrutiny.</p>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/16/the-leprechauns-pencil/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Usability Testing Starter Kit</title>
		<link>http://spin.atomicobject.com/2012/02/15/usability-testing-starter-kit/</link>
		<comments>http://spin.atomicobject.com/2012/02/15/usability-testing-starter-kit/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 18:37:32 +0000</pubDate>
		<dc:creator>Brittany Hunter</dc:creator>
				<category><![CDATA[Process & Practices]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84353</guid>
		<description><![CDATA[<p>Good usability testing takes a fair amount of planning. In order to get quality feedback from your test participants, it is essential to carefully craft your tasks ahead of time, make sure your software is ready for users to play with it, and make sure everyone on your team is in agreement when it comes to the goals, procedures, and desired outcomes of the testing.</p>
<p><a href="http://spin.atomicobject.com/2012/02/15/usability-testing-starter-kit/" class="more-link">Read more on Usability Testing Starter Kit <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>Good usability testing takes a fair amount of planning. In order to get quality feedback from your test participants, it is essential to carefully craft your tasks ahead of time, make sure your software is ready for users to play with it, and make sure everyone on your team is in agreement when it comes to the goals, procedures, and desired outcomes of the testing.</p>
<p>At Atomic Object, we&#8217;ve created a &#8220;Usability Test Starter Kit&#8221; to help bootstrap this planning process. The starter kit is a collection of documents with suggested procedures to follow including tried-and-true scheduling tactics, facilitator scripts, and a test plan overview document.</p>
<p>The kit has been very useful to us here, so <a href="http://spin.atomicobject.com/wp-content/uploads/atomic_usability_starter_kit.zip">we&#8217;re offering it as a free download</a>.</p>
<p><span id="more-84353"></span></p>
<p>The starter kit includes the following items:</p>
<ul>
<li><strong>Sample Consent Form</strong> &#8211; a sample consent form for recording the test.</li>
<li><strong>Sample Facilitator Script</strong> &#8211; a pretty generic script for facilitating a usability test. Modify as necessary for your project&#8217;s particular needs.
<li><strong>Sample Participant Script</strong> &#8211; includes the tasks that you will have your participants perform. you will need to extensively edit this document to reflect your particular testing goals and your project&#8217;s needs.
<li><strong>Observer Notes</strong> &#8211; Notes sheet for observers with reminders about how and what to observe. Useful to hand out to all team members who will be observing the test.</li>
<li><strong>Notes On Usability Testing</strong> &#8211; General notes compiled by designers at Atomic Object. Good to review while working on a usability test plan.</li>
<li><strong>Sample Usability Testing Plan</strong> &#8211; A Usability Testing Plan is a good document to distribute to all team members (both internal and client.) It is the place where you include a general overview of the procedure that will be followed, as well as logistical information such as dates, time, location, and computer needs. Augment and modify the usability testing plan as necessary for your usability test&#8217;s needs. </li>
<li><strong>Checklist.txt</strong> &#8211; A checklist of things to do and remember before and during the test. Review each day you are prepping or running the tests.
</li>
</ul>
<p>We keep the starter kit in a Git repository so that it&#8217;s accessible to every team in the company. When a team is ready to conduct a usability test, they can copy the kit and modify each part of it to reflect the details of their particular project. Additionally, if a team tries out something new or has tips to share, they can add updated artifacts to the repo. That way, the kit evolves and grows along with our usability testing process. </p>
<p><a href="http://spin.atomicobject.com/wp-content/uploads/atomic_usability_starter_kit.zip">Click here to download the Usability Testing Starter Kit.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/15/usability-testing-starter-kit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Avoid Putting Preprocessor Directives in .c Files</title>
		<link>http://spin.atomicobject.com/2012/02/15/avoid-putting-preprocessor-directives-in-c-files/</link>
		<comments>http://spin.atomicobject.com/2012/02/15/avoid-putting-preprocessor-directives-in-c-files/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 14:37:08 +0000</pubDate>
		<dc:creator>John Van Enk</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=84366</guid>
		<description><![CDATA[<p dir="ltr">The C Language has a heavy reliance on the <a href="http://en.wikipedia.org/wiki/C_preprocessor">C Preprocessor</a> (CPP)&#8211;a preprocessor is a program that runs over a set of text files replacing specific patterns as it goes. The more I use C, the more I’ve become convinced that the CPP should be used only very rarely in .c files (though limited use in a header file doesn’t bother me). A major exception to this is the use of the ‘#include’ statement to pull header files into .c files.</p>
<p>I have a couple main reasons to avoid the preprocessor in .c files:</p>
<p><a href="http://spin.atomicobject.com/2012/02/15/avoid-putting-preprocessor-directives-in-c-files/" class="more-link">Read more on Avoid Putting Preprocessor Directives in .c Files <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p dir="ltr">The C Language has a heavy reliance on the <a href="http://en.wikipedia.org/wiki/C_preprocessor">C Preprocessor</a> (CPP)&#8211;a preprocessor is a program that runs over a set of text files replacing specific patterns as it goes. The more I use C, the more I’ve become convinced that the CPP should be used only very rarely in .c files (though limited use in a header file doesn’t bother me). A major exception to this is the use of the ‘#include’ statement to pull header files into .c files.</p>
<p>I have a couple main reasons to avoid the preprocessor in .c files:</p>
<ul><span id="more-84366"></span></p>
<li>It’s easy to add preprocessor statements, but hard to take them out. They are the ultimate quick fix, but the longer you use them, the more of them you’ll need to fix the next problem. Eventually they will take your code hostage, and the project descends into Preprocessor Hell &#8212; a place where it’s hard to determine what code is active and, if it is, what it does.</li>
<li>I don’t normally have a compelling reason to put macro definitions inside .c files. Adding them there clutters up the more important aspects of my project. I end up putting these in one of my various header files.</li>
</ul>
<p>I want to point out one good way to avoid using preprocessor statements in .c files when dealing with multiple platforms. First, here’s a program that uses the preprocessor to differentiate between platform implementations:</p>
<p><div id="gist-1836072" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">#include &quot;interface.h&quot;</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="kt">void</span> <span class="nf">initialize</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC4'><span class="p">{</span></div><div class='line' id='LC5'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Common Initialize</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="cp">#if   defined(PLATFORM_A)</span></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Initialize A</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC9'><span class="cp">#elif defined(PLATFORM_B)</span></div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Initialize B</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC11'><span class="cp">#else</span></div><div class='line' id='LC12'><span class="cp">  #error &quot;Invalid platform.&quot;</span></div><div class='line' id='LC13'><span class="cp">#endif</span></div><div class='line' id='LC14'><span class="p">}</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="kt">void</span> <span class="nf">do_stuff</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC17'><span class="p">{</span></div><div class='line' id='LC18'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Common Do Stuff</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC19'><br/></div><div class='line' id='LC20'><span class="cp">#if   defined(PLATFORM_A)</span></div><div class='line' id='LC21'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Do Stuff A</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC22'><span class="cp">#elif defined(PLATFORM_B)</span></div><div class='line' id='LC23'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Do Stuff B</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC24'><span class="cp">#else</span></div><div class='line' id='LC25'><span class="cp">  #error &quot;Invalid platform.&quot;</span></div><div class='line' id='LC26'><span class="cp">#endif</span></div><div class='line' id='LC27'><span class="p">}</span></div><div class='line' id='LC28'><br/></div><div class='line' id='LC29'><span class="kt">void</span> <span class="nf">cleanup</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC30'><span class="p">{</span></div><div class='line' id='LC31'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Common Cleanup</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC32'><br/></div><div class='line' id='LC33'><span class="cp">#if   defined(PLATFORM_A)</span></div><div class='line' id='LC34'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Cleanup A</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC35'><span class="cp">#elif defined(PLATFORM_B)</span></div><div class='line' id='LC36'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Cleanup B</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC37'><span class="cp">#else</span></div><div class='line' id='LC38'><span class="cp">  #error &quot;Invalid platform.&quot;</span></div><div class='line' id='LC39'><span class="cp">#endif</span></div><div class='line' id='LC40'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1836072/0e9d33e592936011a2c9fe7feace6d310907b77f/bad_way.c" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1836072#file_bad_way.c" style="float:right;margin-right:10px;color:#666">bad_way.c</a>
            <a href="https://gist.github.com/1836072">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>In this example we can see that there’s common code in each of the three functions, but there are also sections specific to each of PLATFORM_A and PLATFORM_B. It’s not too hard to see how this becomes unmanageable with more than 2 platforms or more than a few functions.</p>
<p>Instead of using conditionals in .c files, I propose using a single header file that defines all of the interfaces each platform must implement. It might look something like this:</p>
<p><div id="gist-1836105" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">#ifndef __INTERFACE__</span></div><div class='line' id='LC2'><span class="cp">#define __INTERFACE__</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="kt">void</span> <span class="n">initialize</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span></div><div class='line' id='LC5'><span class="kt">void</span> <span class="n">do_stuff</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span></div><div class='line' id='LC6'><span class="kt">void</span> <span class="n">cleanup</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="cp">#endif </span><span class="cm">/* __INTERFACE__ */</span><span class="cp"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1836105/c8ad03a2d4ef931ddc4a14b554b4929615c509e1/interface.h" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1836105#file_interface.h" style="float:right;margin-right:10px;color:#666">interface.h</a>
            <a href="https://gist.github.com/1836105">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>Once we have this interface defined, we just need to implement it once for each different platform. Here’s the first implementation:</p>
<p><div id="gist-1836130" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">#include &lt;stdio.h&gt;</span></div><div class='line' id='LC2'><span class="cp">#include &quot;common.h&quot;</span></div><div class='line' id='LC3'><span class="cp">#include &quot;interface.h&quot;</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="kt">void</span> <span class="nf">initialize</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC6'><span class="p">{</span></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="n">common_initialize</span><span class="p">();</span></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Initialize A</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC9'><span class="p">}</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="kt">void</span> <span class="nf">do_stuff</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC12'><span class="p">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;<span class="n">common_do_stuff</span><span class="p">();</span></div><div class='line' id='LC14'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Do Stuff A</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC15'><span class="p">}</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'><span class="kt">void</span> <span class="nf">cleanup</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC18'><span class="p">{</span></div><div class='line' id='LC19'>&nbsp;&nbsp;<span class="n">common_cleanup</span><span class="p">();</span></div><div class='line' id='LC20'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Cleanup A</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC21'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1836130/8c7734dc70d1ecb3424c4487fa61604a60fa5e2b/platform_a.c" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1836130#file_platform_a.c" style="float:right;margin-right:10px;color:#666">platform_a.c</a>
            <a href="https://gist.github.com/1836130">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>… and here’s the second:</p>
<p><div id="gist-1836143" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">#include &lt;stdio.h&gt;</span></div><div class='line' id='LC2'><span class="cp">#include &quot;common.h&quot;</span></div><div class='line' id='LC3'><span class="cp">#include &quot;interface.h&quot;</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="kt">void</span> <span class="nf">initialize</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC6'><span class="p">{</span></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="n">common_initialize</span><span class="p">();</span></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Initialize B</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC9'><span class="p">}</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="kt">void</span> <span class="nf">do_stuff</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC12'><span class="p">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;<span class="n">common_do_stuff</span><span class="p">();</span></div><div class='line' id='LC14'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Do Stuff B</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC15'><span class="p">}</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'><span class="kt">void</span> <span class="nf">cleanup</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span></div><div class='line' id='LC18'><span class="p">{</span></div><div class='line' id='LC19'>&nbsp;&nbsp;<span class="n">common_cleanup</span><span class="p">();</span></div><div class='line' id='LC20'>&nbsp;&nbsp;<span class="n">puts</span><span class="p">(</span><span class="s">&quot;Cleanup B</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span></div><div class='line' id='LC21'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1836143/7ad99e5a4ef8ef135709ff6e05b6cc4bd44c55a8/platform_b.c" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1836143#file_platform_b.c" style="float:right;margin-right:10px;color:#666">platform_b.c</a>
            <a href="https://gist.github.com/1836143">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>Notice that the compiler will prevent us from compiling both implementations at once since the symbol names would clash. The preprocessor prevents this with a #error statement in the #else branch, but what if this piece was forgotten? I think it&#8217;s safer and cleaner to push this logic into the build system in order to simplify the code. This isn’t hard to do especially if each of the platforms have a directory for platform specific code.<br />
<strong><strong><br />
</strong></strong>Using a common interface with multiple platform implementations has several advantages:</p>
<ul>
<li>The compiler will help us catch missing portions or duplicate portions of the interface. A preprocessor-only implementation will not reliably help us catch these bugs.</li>
<li>The C files don’t need special analysis to figure out what code is active and what code isn’t active. This makes the code more maintainable in the future.</li>
<li>We completely avoid #ifdef hell.</li>
<li>The common interface header file serves as a template for adding new platforms.</li>
<li>Using different files for the platform-dependent code gives certain guarantees about independence. We can be confident we haven’t accidentally modified the code for the wrong platform.</li>
</ul>
<p><strong><strong><br />
</strong></strong>I’ve put together a complete example of this anti-CPP-pattern in <a href="https://gist.github.com/1833197">this GitHub gist</a>. It consists of the following files:</p>
<ul>
<li>main.c &#8211; the entry point which calls all three of the functions</li>
<li>common.h &#8211; some code that’s common to both platforms</li>
<li>common.c &#8211; implementation of common.h</li>
<li>interface.h &#8211; the interface file that defines the functions required by each platform</li>
<li>platform_a.c &#8211; the implementation of the interface for Platform A</li>
<li>platform_b.c &#8211; the implementation of the interface for Platform B</li>
<li>bad_way.c &#8211; both platforms implemented in a single file using the preprocessor to select which code to include</li>
</ul>
<p><strong><strong><br />
</strong></strong>If you have GCC installed and in your path&#8230;<br />
<strong><strong><br />
</strong></strong>You can build the code for Platform A by running:</p>
<pre style="padding-left: 30px;" dir="ltr">gcc main.c common.c platform_a.c -o platform_a</pre>
<p><strong><strong><br />
</strong></strong>Platform B can be built with:</p>
<pre style="padding-left: 30px;" dir="ltr">gcc main.c common.c platform_b.c -o platform_b</pre>
<p><strong id="internal-source-marker_0.20321377459913492"><br />
</strong>I’ve found build system and architectural changes preferable to the use of preprocessor statements in .c files.<br />
<strong id="internal-source-marker_0.20321377459913492"><br />
</strong>What other ways are there to avoid overusing the preprocessor?</p>
]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/02/15/avoid-putting-preprocessor-directives-in-c-files/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached

Served from: spin.atomicobject.com @ 2012-02-23 01:58:28 -->
