<?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://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Atomic Spin</title>
	
	<link>http://spin.atomicobject.com</link>
	<description>Atomic Object's Blog On Software Design &amp; Development</description>
	<lastBuildDate>Tue, 29 May 2012 22:17:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/atomic_spin" /><feedburner:info uri="atomic_spin" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>42.955944</geo:lat><geo:long>-85.644983</geo:long><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/atomic_spin" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><item>
		<title>Jim Weirich, live: Connascence Explained</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/e8wH4pQSbsw/</link>
		<comments>http://spin.atomicobject.com/2012/05/29/jim-weirich-live-connascence-explained/#comments</comments>
		<pubDate>Tue, 29 May 2012 21:53:01 +0000</pubDate>
		<dc:creator>Drew Colthorp</dc:creator>
				<category><![CDATA[Design & Development]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86506</guid>
		<description><![CDATA[	<p>Tonight&#8217;s SoftwareGR features Jim Weirich from <a href="http://edgecase.com">EdgeCase</a>. Jim is a pillar of the Ruby community and the original author of both <a href="http://rake.rubyforge.org/">Rake</a> and <a href="http://builder.rubyforge.org/">Builder</a>. Jim will be speaking about connascence, a measurement of coupling in a software system. This talk was originally given at <span class="caps">SCNA</span>, and was such a hit with those of us at Atomic that saw it, we decided to invite him to SoftwareGR.</p>

<p><a href="http://spin.atomicobject.com/2012/05/29/jim-weirich-live-connascence-explained/" class="more-link">Read more on Jim Weirich, live: Connascence Explained <span class="meta-nav">&#187;</span></a></p>]]></description>
			<content:encoded><![CDATA[	<p>Tonight&#8217;s SoftwareGR features Jim Weirich from <a href="http://edgecase.com">EdgeCase</a>. Jim is a pillar of the Ruby community and the original author of both <a href="http://rake.rubyforge.org/">Rake</a> and <a href="http://builder.rubyforge.org/">Builder</a>. Jim will be speaking about connascence, a measurement of coupling in a software system. This talk was originally given at <span class="caps">SCNA</span>, and was such a hit with those of us at Atomic that saw it, we decided to invite him to SoftwareGR.</p>

	<p>This event will be streamed live starting at 6:00. Tune in at <a href="http://www.ustream.tv/channel/software-gr-live">ustream</a>.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=e8wH4pQSbsw:ggSlVWmk2J8:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=e8wH4pQSbsw:ggSlVWmk2J8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=e8wH4pQSbsw:ggSlVWmk2J8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=e8wH4pQSbsw:ggSlVWmk2J8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=e8wH4pQSbsw:ggSlVWmk2J8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=e8wH4pQSbsw:ggSlVWmk2J8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=e8wH4pQSbsw:ggSlVWmk2J8:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=e8wH4pQSbsw:ggSlVWmk2J8:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/e8wH4pQSbsw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/29/jim-weirich-live-connascence-explained/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/29/jim-weirich-live-connascence-explained/</feedburner:origLink></item>
		<item>
		<title>The perspective of great developers</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/p0iPE5h6Uuk/</link>
		<comments>http://spin.atomicobject.com/2012/05/25/the-perspective-of-great-developers/#comments</comments>
		<pubDate>Fri, 25 May 2012 19:32:01 +0000</pubDate>
		<dc:creator>Shawn Crowley</dc:creator>
				<category><![CDATA[Design & Development]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[great]]></category>
		<category><![CDATA[kicking ass]]></category>
		<category><![CDATA[owning it]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86480</guid>
		<description><![CDATA[<p>
I&#8217;ve noticed a perspective that differentiates great developers from good developers.
</p>
<p>
Most projects consist of code that the team writes and third-party code that the team purchases or obtains from an open source provider.
</p>
<p><a href="http://spin.atomicobject.com/2012/05/25/the-perspective-of-great-developers/" class="more-link">Read more on The perspective of great developers <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;ve noticed a perspective that differentiates great developers from good developers.
</p>
<p>
Most projects consist of code that the team writes and third-party code that the team purchases or obtains from an open source provider.
</p>
<p>
Average developers conceptualize third-party code as a fixed entity to call upon and use. Good developers usually become experts with the third-party components they use.
</p>
<p><a href="http://spin.atomicobject.com/2012/05/25/the-perspective-of-great-developers/micah_and_matt/" rel="attachment wp-att-86481"><img src="http://spin.atomicobject.com/wp-content/uploads/micah_and_matt.jpg" alt="Micah and Matt" title="micah_and_matt" width="500" height="333" class="size-full wp-image-86481" /></a></p>
<p>
Great developers view code they didn&#8217;t write as an open and modifiable resource (assuming the code is open source). Great developers aren&#8217;t reluctant to look behind interfaces and fully understand, or even modify, the implementation.
</p>
<p><span id="more-86480"></span></p>
<p>
The perspective difference is elegantly described by Robert M. Pirsig in <a href="http://www.design.caltech.edu/Misc/pirsig.html"><u>Zen and the Art of Motorcycle Maintenance</u></a>.
</p>
<blockquote><p>
I&#8217;ve noticed that people who have never worked with steel have trouble seeing this&#8230; that the motorcycle is primarily a mental phenomenon. They associate metal with given shapes&#8230; pipes, rods, girders, tools, parts&#8230; all of them fixed and inviolable, and think of it as primarily physical.</p>
<p>But a person who does machining or foundry work or forge work or welding sees &#8220;steel&#8221; as having no shape at all. Steel can be any shape you want if you are skilled enough, and any shape but the one you want if you are not. Shapes, like this tappet, are what you arrive at, what you give to the steel. Steel has no more shape than this old pile of dirt on the engine here. These shapes are all out of someone&#8217;s mind.
</p></blockquote>
<p>
I was pleased when Andy Keller&#8217;s <a href="http://spin.atomicobject.com/2012/03/06/andy-keller-build-vs-buy-software-gr/">recent Software GR</a> talk hit upon the mindset of ownership for the code you buy or use from a third-party provider. When something goes wrong with your product, your customers don&#8217;t care if you wrote the code or got it from someone else. As a steward of your product, you have the responsibility to expediently fix issues that occur.
</p>
<p>
When issues do occur with a third-party component, great developers are worth their weight in gold.
</p>
<p>
A great developer will expose third-party bugs with automated tests and then create and submit a patch back to the provider.
</p>
<p>
Anecdotal forum browsing will show that average developers post questions and wait for an expert to do the thinking. Average developers may be blocked for days while they wait for an expert to investigate the issue and provide a solution.
</p>
<p>
Even though open-source resources allow average teams to be greatly productive, when quality and dependability matter, there is no substitute for great teams.
</p>
<p>
Average developers can become great developers by adopting the mindset of ownership and a perspective of fluidity towards third-party code. Don&#8217;t look at code you work with as a fixed entity. Understand the ideas and intent behind the code and craft it back into shape when necessary.
</p>
<p>
Do you have a story to share where you or your team stepped up to solve a problem with third-party code?</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=p0iPE5h6Uuk:c0gVPrFMCXs:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=p0iPE5h6Uuk:c0gVPrFMCXs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=p0iPE5h6Uuk:c0gVPrFMCXs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=p0iPE5h6Uuk:c0gVPrFMCXs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=p0iPE5h6Uuk:c0gVPrFMCXs:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=p0iPE5h6Uuk:c0gVPrFMCXs:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=p0iPE5h6Uuk:c0gVPrFMCXs:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=p0iPE5h6Uuk:c0gVPrFMCXs:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/p0iPE5h6Uuk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/25/the-perspective-of-great-developers/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/25/the-perspective-of-great-developers/</feedburner:origLink></item>
		<item>
		<title>Using Backbone.js Support</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/4P3tLQSOu3o/</link>
		<comments>http://spin.atomicobject.com/2012/05/24/backbone-js-support/#comments</comments>
		<pubDate>Thu, 24 May 2012 13:12:36 +0000</pubDate>
		<dc:creator>Jared Sartin</dc:creator>
				<category><![CDATA[Design & Development]]></category>
		<category><![CDATA[Languages]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[backbone.js]]></category>
		<category><![CDATA[coffeescript]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86456</guid>
		<description><![CDATA[<p>Backbone.js is a powerful framework. If you&#8217;ve been following our blog, you have most likely noticed that we use it a lot. If you don&#8217;t have much background in it, take a look at the <a href="http://documentcloud.github.com/backbone/">Backbone.js homepage</a> or some of <a href="http://spin.atomicobject.com/?s=backbone.js&#038;searchsubmit=Search">our articles</a> to get you started. Although Backbone.js is powerful it lacks an automated way to clear views and unbind event bindings for garbage collection. With the help of a an extension known as <a href="https://github.com/thoughtbot/backbone-support">Backbone Support</a>, it&#8217;s easy to build views that automatically clean themselves up.</p>
<p><a href="http://spin.atomicobject.com/2012/05/24/backbone-js-support/" class="more-link">Read more on Using Backbone.js Support <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>Backbone.js is a powerful framework. If you&#8217;ve been following our blog, you have most likely noticed that we use it a lot. If you don&#8217;t have much background in it, take a look at the <a href="http://documentcloud.github.com/backbone/">Backbone.js homepage</a> or some of <a href="http://spin.atomicobject.com/?s=backbone.js&#038;searchsubmit=Search">our articles</a> to get you started. Although Backbone.js is powerful it lacks an automated way to clear views and unbind event bindings for garbage collection. With the help of a an extension known as <a href="https://github.com/thoughtbot/backbone-support">Backbone Support</a>, it&#8217;s easy to build views that automatically clean themselves up.</p>
<p><span id="more-86456"></span></p>
<p>The first step of bringing Backbone Support into your project (after including the JavaScript file) is to extend the <code>SwappingRouter</code> in all of your routers. The <code>SwappingRouter</code> needs to know an element to grab hold of to place rendered views into. Whenever you want the router to show a new view, all you have to do is to <code>new</code> one up and pass it to <code>@swap()</code> for display. When <code>@swap()</code> is used, it unbinds and removes the previous view, to allow for garbage collection. Here is a sample:</p>
<p><div id="gist-2779246" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="nv">TestApp = </span><span class="nx">Support</span><span class="p">.</span><span class="nx">SwappingRouter</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="nv">initialize: </span><span class="nf">(options) -&gt;</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@el = </span><span class="nx">$</span><span class="p">(</span><span class="s">&quot;.random_element&quot;</span><span class="p">)</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>&nbsp;&nbsp;<span class="nv">routes:</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">foo: </span><span class="s">&quot;index&quot;</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">bar: </span><span class="s">&quot;bar&quot;</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="nv">index: </span><span class="o">-&gt;</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">view = </span><span class="k">new</span> <span class="nx">TestApp</span><span class="p">.</span><span class="nx">Views</span><span class="p">.</span><span class="nx">FooIndex</span><span class="p">()</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">@swap</span> <span class="nx">view</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'>&nbsp;&nbsp;<span class="nv">bar: </span><span class="o">-&gt;</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">view = </span><span class="k">new</span> <span class="nx">TestApp</span><span class="p">.</span><span class="nx">Views</span><span class="p">.</span><span class="nx">Bar</span><span class="p">(</span><span class="nv">model: </span><span class="k">new</span> <span class="nx">Baz</span><span class="p">())</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">@swap</span> <span class="nx">view</span></div><div class='line' id='LC16'><span class="p">)</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2779246/735bbf440c45e8d272af3abb8d9da736dc8f6445/SwappingRouter.coffee" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2779246#file_swapping_router.coffee" style="float:right;margin-right:10px;color:#666">SwappingRouter.coffee</a>
            <a href="https://gist.github.com/2779246">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>The example uses <a href="http://coffeescript.org/">CoffeeScript</a>. You can see a little more about using <a href="http://spin.atomicobject.com/2011/05/06/using-backbone-js-with-coffeescript/">Backbone.js and CoffeeScript</a> in a previous post.</p>
<p>The next step is to extend <code>Support.CompositeView</code> to your views to provide supporting methods for managing child views. The methods provided help render and append child views to an element on the page via <code>@renderChildInto()</code> or appending it to the view&#8217;s element itself with <code>@appendChild()</code>. It also provides a <code>@leave()</code> method to allow the view to unbind and remove itself from the page.</p>
<p>For more information, give the Backbone Support <a href="https://github.com/thoughtbot/backbone-support">github page</a> a read. If you are in need of a more in-depth set of functionality, like <code>@appendChildTo()</code> or <code>@prependChildTo()</code> to place children within a specific element in the view, take a look at the <a href="https://github.com/domchristie/backbone-support">fork from GitHub user domchristie</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=4P3tLQSOu3o:9W22txdL2NE:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=4P3tLQSOu3o:9W22txdL2NE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=4P3tLQSOu3o:9W22txdL2NE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=4P3tLQSOu3o:9W22txdL2NE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=4P3tLQSOu3o:9W22txdL2NE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=4P3tLQSOu3o:9W22txdL2NE:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=4P3tLQSOu3o:9W22txdL2NE:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=4P3tLQSOu3o:9W22txdL2NE:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/4P3tLQSOu3o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/24/backbone-js-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/24/backbone-js-support/</feedburner:origLink></item>
		<item>
		<title>The Case for Agile in Healthcare Software</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/HbZoBOCrI_Y/</link>
		<comments>http://spin.atomicobject.com/2012/05/24/the-case-for-agile-in-healthcare-software/#comments</comments>
		<pubDate>Thu, 24 May 2012 12:53:23 +0000</pubDate>
		<dc:creator>Will Ryan</dc:creator>
				<category><![CDATA[Pairing]]></category>
		<category><![CDATA[Process & Practices]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[healthcare]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86405</guid>
		<description><![CDATA[<p><a href="http://www.flickr.com/photos/67272961@N03/6123892769/" class="alignleft" title="laptop and stethoscope by jfcherry, on Flickr"><img src="http://farm7.staticflickr.com/6079/6123892769_9fd6451484_n.jpg" width="320" height="212" alt="laptop and stethoscope"/></a>Before I joined Atomic and learned the ways of agile and TDD, I spent several years working in the software industry. So from time to time I reflect on the other industries where I have experience, and I consider how the techniques we use might benefit development in those domains.</p>
<p><a href="http://spin.atomicobject.com/2012/05/24/the-case-for-agile-in-healthcare-software/" class="more-link">Read more on The Case for Agile in Healthcare Software <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/67272961@N03/6123892769/" class="alignleft" title="laptop and stethoscope by jfcherry, on Flickr"><img src="http://farm7.staticflickr.com/6079/6123892769_9fd6451484_n.jpg" width="320" height="212" alt="laptop and stethoscope"></a>Before I joined Atomic and learned the ways of agile and TDD, I spent several years working in the software industry. So from time to time I reflect on the other industries where I have experience, and I consider how the techniques we use might benefit development in those domains.</p>
<p>One area I have quite a bit of exposure to is healthcare software. The more I think about it, the more the distinctive traits of healthcare lend themselves to agile methodology.<br />
<span id="more-86405"></span><br />
Healthcare has a critical need for their software to work flawlessly. Every time a bug is discovered that may affect patient care, a tremendous amount of time and energy must go into fixing the bug for all affected versions of the software. This is to say nothing of the risk to health and safety that such bugs may inflict. So the software better work. Given the mammoth size and incredible configurability of enterprise-scale healthcare software products, the only way to have a prayer of accomplishing this is through tests.</p>
<p>Within testing, of course I would advocate the usual battery of unit, integration, and system tests. I want to make specific mention of continuous integration testing, or regression testing. A software product that touches every aspect of the healthcare industry is inherently huge. Even with the fastest machines on the market, running every test locally is probably impractical. So it falls to the continuous integration server to catch regressions and cases where seemingly unrelated code changes interfere with each other. Furthermore, the QA on staff at a company big enough to write and maintain this software always has their hands full. Any time and mental energy wasted testing a feature that clearly doesn&#8217;t work is a big loss for the company.</p>
<p>Just having a huge array of tests is not sufficient, though. They also have to be the right tests. One of the most valuable traits of a successful developer working on large-scale software is the ability to understand the business domain. This gets put to use in feature design, in meetings with the customer, and of course while actually writing code. How much better to also use this knowledge in unison with test driven development! If developers start by asking &#8220;What could go wrong with patient care if we mess this code up?&#8221; and then write those tests, then those errors will never happen.</p>
<p>Of course, no one person could be expected to predict every possible bug or issue with the code &#8211; which is why it would be quite helpful to have another expert in both the domain and the code sitting there. Keeping track of how the code might inadvertently affect patient care is really just another hat for the non-typing pair to wear, and it meshes well with keeping an eye on the 30,000 foot view.</p>
<p>In my opinion, those are the big ticket items where Agile process would help improve the way complex, safety-critical software like healthcare software is written.</p>
<p>Where have you seen a need for Agile in an industry where it isn&#8217;t generally applied?</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=HbZoBOCrI_Y:927nOJ-lpw8:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=HbZoBOCrI_Y:927nOJ-lpw8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=HbZoBOCrI_Y:927nOJ-lpw8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=HbZoBOCrI_Y:927nOJ-lpw8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=HbZoBOCrI_Y:927nOJ-lpw8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=HbZoBOCrI_Y:927nOJ-lpw8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=HbZoBOCrI_Y:927nOJ-lpw8:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=HbZoBOCrI_Y:927nOJ-lpw8:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/HbZoBOCrI_Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/24/the-case-for-agile-in-healthcare-software/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/24/the-case-for-agile-in-healthcare-software/</feedburner:origLink></item>
		<item>
		<title>Acceptance Testing C++ with Cucumber and the Wire Protocol</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/hcRtVd4cKo4/</link>
		<comments>http://spin.atomicobject.com/2012/05/23/acceptance-testing-c-with-cucumber-and-the-wire-protocol/#comments</comments>
		<pubDate>Wed, 23 May 2012 12:15:03 +0000</pubDate>
		<dc:creator>Greg Williams</dc:creator>
				<category><![CDATA[Languages]]></category>
		<category><![CDATA[Process & Practices]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86422</guid>
		<description><![CDATA[<p dir="ltr">Acceptance Test Driven Development has become a popular practice for establishing and validating what done means for a feature. <a title="Cucumber Info Site" href="http://cukes.info/" target="_blank">Cucumber</a> has gained much popularity in validating Ruby code, especially for Ruby on Rails web applications. The <a title="Cucumber Wire Protocol" href="https://github.com/cucumber/cucumber/wiki/Wire-Protocol" target="_blank">Wire Protocol</a> was added to Cucumber to support testing different languages by implementing a simple Wire Server in the target language. The Wire support allows step definitions to be written in an arbitrary language with communication over a TCP socket.</p>
<p><a href="http://spin.atomicobject.com/2012/05/23/acceptance-testing-c-with-cucumber-and-the-wire-protocol/" class="more-link">Read more on Acceptance Testing C++ with Cucumber and the Wire Protocol <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p dir="ltr">Acceptance Test Driven Development has become a popular practice for establishing and validating what done means for a feature. <a title="Cucumber Info Site" href="http://cukes.info/" target="_blank">Cucumber</a> has gained much popularity in validating Ruby code, especially for Ruby on Rails web applications. The <a title="Cucumber Wire Protocol" href="https://github.com/cucumber/cucumber/wiki/Wire-Protocol" target="_blank">Wire Protocol</a> was added to Cucumber to support testing different languages by implementing a simple Wire Server in the target language. The Wire support allows step definitions to be written in an arbitrary language with communication over a TCP socket.</p>
<p dir="ltr"><span id="more-86422"></span>The following example shows how this works with C++ using <a title="cucumber-cpp" href="https://github.com/paoloambrosio/cucumber-cpp/" target="_blank">Cucumber-Cpp</a> (thanks <a title="Paolo Ambrosio" href="https://github.com/paoloambrosio" target="_blank">Paolo Ambrusio</a>) and an example that comes bundled with it.</p>
<p>Features are written in <a title="Gherkin" href="https://github.com/cucumber/cucumber/wiki/Gherkin" target="_blank">Gherkin</a>, just like standard Cucumber tests. Gherkin is a business-level DSL (Domain-Specific Language) that allows test to be written in high level terminology. This allows tests to be written and understood by non-developers, thus facilitating the conversion of what done should mean for a given feature. Below is a feature definition and scenario for a simple calculator application to validate division:</p>
<p><div id="gist-2773463" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">Feature:</span><span class="nf"> Division</span></div><div class='line' id='LC2'><span class="nf">  In order to avoid silly mistakes</span></div><div class='line' id='LC3'><span class="nf">  Cashiers must be able to calculate a fraction</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="nf">  </span><span class="k">Scenario:</span><span class="nf"> Regular numbers</span></div><div class='line' id='LC6'><span class="k">    Given </span><span class="nf">I have entered </span><span class="s">3</span><span class="nf"> into the calculator</span></div><div class='line' id='LC7'><span class="nf">    </span><span class="k">And </span><span class="nf">I have entered </span><span class="s">2</span><span class="nf"> into the calculator</span></div><div class='line' id='LC8'><span class="nf">    </span><span class="k">When </span><span class="nf">I press divide</span></div><div class='line' id='LC9'><span class="nf">    </span><span class="k">Then </span><span class="nf">the result should be </span><span class="s">1.5</span><span class="nf"> on the screen</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2773463/0049b7b100caae2c31fa6999a0d6d6ecf2d6c6e1/division.feature" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2773463#file_division.feature" style="float:right;margin-right:10px;color:#666">division.feature</a>
            <a href="https://gist.github.com/2773463">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>The implementation of the step definitions for all features and the corresponding support for setting up the test fixture are contained in a C++ file. Below is the source file that implements all the needed step definitions for the feature file above, though it also includes step definitions for the rest of the feature files in the test suite. At the top of the file is the implementation of the Context class that is instantiated prior to executing each feature scenario, and is destroyed when the scenario terminates. In the current implementation of Cucumber-Cpp, exceptions (including those in test assertion frameworks) cannot occur in the Context constructor nor destructor. There is a request to in to resolve this limitation.</p>
<p><div id="gist-2781482" 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;gtest/gtest.h&gt;</span></div><div class='line' id='LC2'><span class="cp">#include &lt;cucumber-cpp/defs.hpp&gt;</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="cp">#include &lt;Calculator.h&gt;</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><span class="k">struct</span> <span class="n">CalcCtx</span> <span class="p">{</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">Calculator</span> <span class="n">calc</span><span class="p">;</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">result</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="n">GIVEN</span><span class="p">(</span><span class="s">&quot;^I have entered (</span><span class="se">\\</span><span class="s">d+) into the calculator$&quot;</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">REGEX_PARAM</span><span class="p">(</span><span class="kt">double</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">USING_CONTEXT</span><span class="p">(</span><span class="n">CalcCtx</span><span class="p">,</span> <span class="n">context</span><span class="p">);</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">context</span><span class="o">-&gt;</span><span class="n">calc</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">n</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="n">WHEN</span><span class="p">(</span><span class="s">&quot;^I press add&quot;</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">USING_CONTEXT</span><span class="p">(</span><span class="n">CalcCtx</span><span class="p">,</span> <span class="n">context</span><span class="p">);</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">context</span><span class="o">-&gt;</span><span class="n">result</span> <span class="o">=</span> <span class="n">context</span><span class="o">-&gt;</span><span class="n">calc</span><span class="p">.</span><span class="n">add</span><span class="p">();</span></div><div class='line' id='LC20'><span class="p">}</span></div><div class='line' id='LC21'><br/></div><div class='line' id='LC22'><span class="n">WHEN</span><span class="p">(</span><span class="s">&quot;^I press divide&quot;</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">USING_CONTEXT</span><span class="p">(</span><span class="n">CalcCtx</span><span class="p">,</span> <span class="n">context</span><span class="p">);</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">context</span><span class="o">-&gt;</span><span class="n">result</span> <span class="o">=</span> <span class="n">context</span><span class="o">-&gt;</span><span class="n">calc</span><span class="p">.</span><span class="n">divide</span><span class="p">();</span></div><div class='line' id='LC25'><span class="p">}</span></div><div class='line' id='LC26'><br/></div><div class='line' id='LC27'><span class="n">THEN</span><span class="p">(</span><span class="s">&quot;^the result should be (.*) on the screen$&quot;</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">REGEX_PARAM</span><span class="p">(</span><span class="kt">double</span><span class="p">,</span> <span class="n">expected</span><span class="p">);</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">USING_CONTEXT</span><span class="p">(</span><span class="n">CalcCtx</span><span class="p">,</span> <span class="n">context</span><span class="p">);</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">EXPECT_EQ</span><span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="n">context</span><span class="o">-&gt;</span><span class="n">result</span><span class="p">);</span></div><div class='line' id='LC31'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2781482/ee764b8f27443d4c1ea9c6d61905ff70c51c82c7/CalculatorSteps.cpp" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2781482#file_calculator_steps.cpp" style="float:right;margin-right:10px;color:#666">CalculatorSteps.cpp</a>
            <a href="https://gist.github.com/2781482">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p dir="ltr">Wire communication is done via a simple protocol encoded in <a title="JSON" href="http://www.json.org/" target="_blank">JSON</a>. Executing the feature file above yields the output below, which is the same output you would get from a true Cucumber test. Although, the C++ step definitions  get annotated with the source file and line number for cross referencing.</p>
<p dir="ltr"><div id="gist-2773442" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">Feature:</span><span class="nf"> Division</span></div><div class='line' id='LC2'><span class="nf">  In order to avoid silly mistakes</span></div><div class='line' id='LC3'><span class="nf">  Cashiers must be able to calculate a fraction</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="nf">  </span><span class="k">Scenario:</span><span class="nf"> Regular numbers                     # division.feature:6</span></div><div class='line' id='LC6'><span class="k">    Given </span><span class="nf">I have entered </span><span class="s">3</span><span class="nf"> into the calculator  </span><span class="c"># CalculatorSteps.cpp:11</span><span class="nf"></span></div><div class='line' id='LC7'><span class="nf">    </span><span class="k">And </span><span class="nf">I have entered </span><span class="s">2</span><span class="nf"> into the calculator    </span><span class="c"># CalculatorSteps.cpp:11</span><span class="nf"></span></div><div class='line' id='LC8'><span class="nf">    </span><span class="k">When </span><span class="nf">I press divide                         </span><span class="c"># CalculatorSteps.cpp:22</span><span class="nf"></span></div><div class='line' id='LC9'><span class="nf">    </span><span class="k">Then </span><span class="nf">the result should be </span><span class="s">1.5</span><span class="nf"> on the screen </span><span class="c"># CalculatorSteps.cpp:27</span><span class="nf"></span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="s">4</span><span class="nf"> scenarios (</span><span class="s">4</span><span class="nf"> passed)</span></div><div class='line' id='LC12'><span class="s">16</span><span class="nf"> steps (</span><span class="s">16</span><span class="nf"> passed)</span></div><div class='line' id='LC13'><span class="s">0</span><span class="nf">m</span><span class="s">0.073</span><span class="nf">s</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2773442/9b2cd8c10292772a7dc7496f6f499e524fcb85e9/division.feature" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2773442#file_division.feature" style="float:right;margin-right:10px;color:#666">division.feature</a>
            <a href="https://gist.github.com/2773442">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p dir="ltr">Adding some debug output to Cucumber shows how the execution happens across The Wire:</p>
<p dir="ltr"><div id="gist-2773486" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">Scenario:</span><span class="nf"> Regular numbers # division.feature:6</span></div><div class='line' id='LC2'><span class="nf">&gt; [&quot;begin_scenario&quot;] </span><span class="c"># Cucumber sends this message to the Wire server to start the scenario</span><span class="nf"></span></div><div class='line' id='LC3'><span class="nf">&lt; [&quot;success&quot;] </span><span class="c"># Each message sent to the Wire server is acknowledged, and may include response data as well</span><span class="nf"></span></div><div class='line' id='LC4'><span class="nf">&gt; [&quot;step_matches&quot;, </span><span class="c"># Cucumber sends the first step of the scenario</span><span class="nf"></span></div><div class='line' id='LC5'><span class="nf">    {</span></div><div class='line' id='LC6'><span class="nf">      &quot;name_to_match&quot;:&quot;I have entered 3 into the calculator&quot;</span></div><div class='line' id='LC7'><span class="nf">    }</span></div><div class='line' id='LC8'><span class="nf">  ]</span></div><div class='line' id='LC9'><span class="nf">&lt; [&quot;success&quot;, </span><span class="c"># The Wire server responds with the regular expression that matches the specified step, including the extracted parameter and location of the step definition</span><span class="nf"></span></div><div class='line' id='LC10'><span class="nf">    [</span></div><div class='line' id='LC11'><span class="nf">      {</span></div><div class='line' id='LC12'><span class="nf">        &quot;regexp&quot;:&quot;^I have entered (\\d+) into the calculator$&quot;,</span></div><div class='line' id='LC13'><span class="nf">        &quot;args&quot;:[{&quot;val&quot;:&quot;3&quot;,&quot;pos&quot;:15}],</span></div><div class='line' id='LC14'><span class="nf">        &quot;id&quot;:&quot;1&quot;,</span></div><div class='line' id='LC15'><span class="nf">        &quot;source&quot;:&quot;CalculatorSteps.cpp:11&quot;</span></div><div class='line' id='LC16'><span class="nf">      }</span></div><div class='line' id='LC17'><span class="nf">    ]</span></div><div class='line' id='LC18'><span class="nf">  ]</span></div><div class='line' id='LC19'><span class="nf">&gt; [&quot;invoke&quot;, </span><span class="c"># Cucumber now tells the server to go ahead and execute the step</span><span class="nf"></span></div><div class='line' id='LC20'><span class="nf">    {</span></div><div class='line' id='LC21'><span class="nf">      &quot;args&quot;:[&quot;3&quot;],</span></div><div class='line' id='LC22'><span class="nf">      &quot;id&quot;:&quot;1&quot;</span></div><div class='line' id='LC23'><span class="nf">    }</span></div><div class='line' id='LC24'><span class="nf">  ]</span></div><div class='line' id='LC25'><span class="nf">&lt; [&quot;success&quot;] </span><span class="c"># The server responds with the result</span><span class="nf"></span></div><div class='line' id='LC26'><span class="k"> Given </span><span class="nf">I have entered </span><span class="s">3</span><span class="nf"> into the calculator </span><span class="c"># CalculatorSteps.cpp:11 (This is the normal formatted output that appears on the console after a step is executed)</span><span class="nf"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2773486/df7b32649c10c37813a01c39681d5bdf1a72d5d8/division.feature" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2773486#file_division.feature" style="float:right;margin-right:10px;color:#666">division.feature</a>
            <a href="https://gist.github.com/2773486">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>As you can see, the protocol and data exchange is pretty straight-forward. In addition to Cucumber-Cpp, there are Wire implementations <a title="Cucumber Wire Protocol" href="https://github.com/cucumber/cucumber/wiki/Wire-Protocol" target="_blank">for other languages</a> as well.</p>
<pre></pre>
<pre dir="ltr"></pre>
<p dir="ltr"><strong><br />
</strong></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=hcRtVd4cKo4:DTDzohSyZV8:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=hcRtVd4cKo4:DTDzohSyZV8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=hcRtVd4cKo4:DTDzohSyZV8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=hcRtVd4cKo4:DTDzohSyZV8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=hcRtVd4cKo4:DTDzohSyZV8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=hcRtVd4cKo4:DTDzohSyZV8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=hcRtVd4cKo4:DTDzohSyZV8:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=hcRtVd4cKo4:DTDzohSyZV8:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/hcRtVd4cKo4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/23/acceptance-testing-c-with-cucumber-and-the-wire-protocol/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/23/acceptance-testing-c-with-cucumber-and-the-wire-protocol/</feedburner:origLink></item>
		<item>
		<title>Being a generalist makes me happy</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/qzkFY4RXksA/</link>
		<comments>http://spin.atomicobject.com/2012/05/22/being-a-generalist/#comments</comments>
		<pubDate>Wed, 23 May 2012 03:59:49 +0000</pubDate>
		<dc:creator>Chris Farber</dc:creator>
				<category><![CDATA[Culture]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86416</guid>
		<description><![CDATA[<p>What motivates you to work and create? If you were to ask me a year ago, I would have said that my motivation lies in the pride of making polished and elegant products. That&#8217;s still true for me today, but I realize that I had forgotten an important source of motivation and happiness: learning new ways to think about programming and solving problems.</p>
<p><a href="http://spin.atomicobject.com/2012/05/22/being-a-generalist/" class="more-link">Read more on Being a generalist makes me happy <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>What motivates you to work and create? If you were to ask me a year ago, I would have said that my motivation lies in the pride of making polished and elegant products. That&#8217;s still true for me today, but I realize that I had forgotten an important source of motivation and happiness: learning new ways to think about programming and solving problems.</p>
<p><span id="more-86416"></span></p>
<p>This was, in fact, what had led me to become a developer. Growing up, the sense of joy and accomplishment I felt as I wrapped mind around concepts like recursion or object-oriented programming was good enough to be a drug. Coupled with my attention to detail and proclivity to idealism, I found myself focusing intensely on learning a particular language and set of frameworks that I found most elegant.</p>
<p>Eventually, I found myself well-versed in the idioms and practices of the language. This was the goal, after all. I wanted to master the tools I had chosen with a deep, technical understanding and a solid grasp of their design philosophies.</p>
<p>However, it turned out that the journey was more satisfying than the destination. I found that, over time, programming became less thrilling and intrinsically motivating. This was because, by effectively living in a monoculture, I had inadvertently isolated myself from exploring new idioms and ideas from other languages and environments. I was accidentally limiting my ability to discover and learn.</p>
<p>I&#8217;m proud that, at Atomic Object, we are generalists. By using many different technologies, and picking up new ones regularly, we keep the passion for development alive because we never stop learning. And the cross-pollination of ideas from the variety of tools we use inevitably leads to the improvement of not only ourselves as developers, but our craft as a whole.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=qzkFY4RXksA:g3Z3q4jF0YA:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=qzkFY4RXksA:g3Z3q4jF0YA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=qzkFY4RXksA:g3Z3q4jF0YA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=qzkFY4RXksA:g3Z3q4jF0YA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=qzkFY4RXksA:g3Z3q4jF0YA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=qzkFY4RXksA:g3Z3q4jF0YA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=qzkFY4RXksA:g3Z3q4jF0YA:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=qzkFY4RXksA:g3Z3q4jF0YA:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/qzkFY4RXksA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/22/being-a-generalist/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/22/being-a-generalist/</feedburner:origLink></item>
		<item>
		<title>Hanging Out for Work</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/sEAyCNLrBGQ/</link>
		<comments>http://spin.atomicobject.com/2012/05/22/hanging-out-for-work/#comments</comments>
		<pubDate>Tue, 22 May 2012 12:44:34 +0000</pubDate>
		<dc:creator>Kedron Rhodes</dc:creator>
				<category><![CDATA[Workplace]]></category>
		<category><![CDATA[collaboration]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86399</guid>
		<description><![CDATA[<p>Most of the time our project teams share a physical desk and workspace, but occasionally we need to share a desk and workspace with someone miles apart. The distances makes sharing ideas and collaborating with team members harder to do.<br />
<span id="more-86399"></span><br />
As an effort to bridge the physical distance between teams, we&#8217;ve been exploring the use of <a href="http://www.google.com/+/learnmore/hangouts/" title="Catch up in a hangout - Google+">Google Hangouts</a>. </p>
<p><a href="http://spin.atomicobject.com/2012/05/22/hanging-out-for-work/" class="more-link">Read more on Hanging Out for Work <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>Most of the time our project teams share a physical desk and workspace, but occasionally we need to share a desk and workspace with someone miles apart. The distances makes sharing ideas and collaborating with team members harder to do.<br />
<span id="more-86399"></span><br />
As an effort to bridge the physical distance between teams, we&#8217;ve been exploring the use of <a href="http://www.google.com/+/learnmore/hangouts/" title="Catch up in a hangout - Google+">Google Hangouts</a>. </p>
<p>One of the first things I do in the morning is plug in an <a href="http://www.logitech.com/en-us/webcam-communications/webcams/devices/hd-pro-webcam-c920" title="Logitech® HD Pro Webcam C920">external video camera</a> and join our project specific Hangout. Once the team has joined, we leave a live video stream going throughout the day. This makes it easy to share thoughts and ideas, as well as reinforce the sense of team across the miles. Google Hangouts also makes it easy to share a screen, online documents and other collaborative tools.</p>
<p>We&#8217;ve weathered some of the early adopter pain (UI changes, feature changes, etc), and made the Hangout a daily part of showing up at the office. What tools and resources do you use to help connect with remote teammates? </p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/7qlunRCjZ2U?rel=0" frameborder="0" allowfullscreen></iframe></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=sEAyCNLrBGQ:peO5Ez49abg:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=sEAyCNLrBGQ:peO5Ez49abg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=sEAyCNLrBGQ:peO5Ez49abg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=sEAyCNLrBGQ:peO5Ez49abg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=sEAyCNLrBGQ:peO5Ez49abg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=sEAyCNLrBGQ:peO5Ez49abg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=sEAyCNLrBGQ:peO5Ez49abg:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=sEAyCNLrBGQ:peO5Ez49abg:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/sEAyCNLrBGQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/22/hanging-out-for-work/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/22/hanging-out-for-work/</feedburner:origLink></item>
		<item>
		<title>RapidXml – A lightweight xml library for C++</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/asqs50Y1rX8/</link>
		<comments>http://spin.atomicobject.com/2012/05/20/rapidxml-a-lightweight-xml-library-for-c/#comments</comments>
		<pubDate>Mon, 21 May 2012 03:14:02 +0000</pubDate>
		<dc:creator>Jordan Schaenzle</dc:creator>
				<category><![CDATA[Design & Development]]></category>
		<category><![CDATA[Embedded Software]]></category>
		<category><![CDATA[Project Stories]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[RapidXml]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86294</guid>
		<description><![CDATA[<p>I don’t write in C++ frequently and I can’t say that I am sad about that. However, we all have those projects where, for some reason or another, we must use a tool that wouldn’t normally be our first choice. In one particular case, just recently, I was given a library written in C++ that I needed to use to perform a specific action on some data. The front end of the application that I was working on was written in Ruby and it basically collected information from different sources and stuffed the data into an XML file. I needed to write a simple shim, in C++, that could read in the data from the XML file and then call the correct functions in the library based on the data contained within.</p>
<p><a href="http://spin.atomicobject.com/2012/05/20/rapidxml-a-lightweight-xml-library-for-c/" class="more-link">Read more on RapidXml &#8211; A lightweight xml library for C++ <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>I don’t write in C++ frequently and I can’t say that I am sad about that. However, we all have those projects where, for some reason or another, we must use a tool that wouldn’t normally be our first choice. In one particular case, just recently, I was given a library written in C++ that I needed to use to perform a specific action on some data. The front end of the application that I was working on was written in Ruby and it basically collected information from different sources and stuffed the data into an XML file. I needed to write a simple shim, in C++, that could read in the data from the XML file and then call the correct functions in the library based on the data contained within.</p>
<p>C++ does not have support for parsing XML data in the standard libraries. I started with a typical Google search, “C++ XML Parsing”, which returned a large number of results&#8230; of course. My goal was to find something really lightweight and simple to use. All I wanted to do was iterate over the tree, identify nodes and read attributes. I skimmed through several README files, downloaded a couple libraries and finally stumbled upon <a title="RapidXml" href="http://rapidxml.sourceforge.net/index.htm" target="_blank">RapidXml</a>.</p>
<p>As stated in the project documentation, “RapidXml is an attempt to create the fastest XML parser possible, while retaining usability, portability and reasonable W3C compatibility.” Sounded great to me! I gave it a try and the results were very positive. The library is composed of 4 files, the total size of which is 141KB.<span id="more-86294"></span></p>
<h2>Demonstration</h2>
<p>To demonstrate its functionality, I created a sample XML file which contains information about a few breweries that I have visited. It looks like this:</p>
<p><div id="gist-2726944" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span></div><div class='line' id='LC2'><span class="nt">&lt;MyBeerJournal&gt;</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Brewery</span> <span class="na">name=</span><span class="s">&quot;Founders Brewing Company&quot;</span> <span class="na">location=</span><span class="s">&quot;Grand Rapids, MI&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Beer</span> <span class="na">name=</span><span class="s">&quot;Centennial&quot;</span> <span class="na">description=</span><span class="s">&quot;IPA&quot;</span> <span class="na">rating=</span><span class="s">&quot;A+&quot;</span> <span class="na">dateSampled=</span><span class="s">&quot;01/02/2011&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;What an excellent IPA. This is the most delicious beer I have ever tasted!&quot;</div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Beer&gt;</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Brewery&gt;</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Brewery</span> <span class="na">name=</span><span class="s">&quot;Brewery Vivant&quot;</span> <span class="na">location=</span><span class="s">&quot;Grand Rapids, MI&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Beer</span> <span class="na">name=</span><span class="s">&quot;Farmhouse Ale&quot;</span> <span class="na">description=</span><span class="s">&quot;Belgian Ale&quot;</span> <span class="na">rating=</span><span class="s">&quot;B&quot;</span> <span class="na">dateSampled=</span><span class="s">&quot;02/07/2015&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;This beer is not so good... but I am not that big of a fan of english style ales.</div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Beer&gt;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Brewery&gt;</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Brewery</span> <span class="na">name=</span><span class="s">&quot;Bells Brewery&quot;</span> <span class="na">location=</span><span class="s">&quot;Kalamazoo, MI&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Beer</span> <span class="na">name=</span><span class="s">&quot;Two Hearted Ale&quot;</span> <span class="na">description=</span><span class="s">&quot;IPA&quot;</span> <span class="na">rating=</span><span class="s">&quot;A&quot;</span> <span class="na">dateSampled=</span><span class="s">&quot;03/15/2012&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Another execllent brew. Two Hearted gives Founders Centennial a run for it&#39;s money.</div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Beer&gt;</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Brewery&gt;</span></div><div class='line' id='LC18'><span class="nt">&lt;/MyBeerJournal&gt;</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2726944/9838435dc7e3838ffaf2c417b3eb92afacefdb97/beerJournal.xml" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2726944#file_beer_journal.xml" style="float:right;margin-right:10px;color:#666">beerJournal.xml</a>
            <a href="https://gist.github.com/2726944">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>The code below simply reads in the data from the XML file and outputs easily readable text describing the data.</p>
<p><div id="gist-2726944" 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;string.h&gt;</span></div><div class='line' id='LC2'><span class="cp">#include &lt;stdio.h&gt;</span></div><div class='line' id='LC3'><span class="cp">#include &lt;iostream&gt;</span></div><div class='line' id='LC4'><span class="cp">#include &lt;fstream&gt;</span></div><div class='line' id='LC5'><span class="cp">#include &lt;vector&gt;</span></div><div class='line' id='LC6'><span class="cp">#include &quot;rapidxml-1.13/rapidxml.hpp&quot;</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="n">using</span> <span class="n">namespace</span> <span class="n">rapidxml</span><span class="p">;</span></div><div class='line' id='LC9'><span class="n">using</span> <span class="n">namespace</span> <span class="n">std</span><span class="p">;</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="kt">int</span> <span class="nf">main</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'>	<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;Parsing my beer journal...&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span></div><div class='line' id='LC14'>	<span class="n">xml_document</span><span class="o">&lt;&gt;</span> <span class="n">doc</span><span class="p">;</span></div><div class='line' id='LC15'>	<span class="n">xml_node</span><span class="o">&lt;&gt;</span> <span class="o">*</span> <span class="n">root_node</span><span class="p">;</span></div><div class='line' id='LC16'>	<span class="c1">// Read the xml file into a vector</span></div><div class='line' id='LC17'>	<span class="n">ifstream</span> <span class="n">theFile</span> <span class="p">(</span><span class="s">&quot;beerJournal.xml&quot;</span><span class="p">);</span></div><div class='line' id='LC18'>	<span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="n">buffer</span><span class="p">((</span><span class="n">istreambuf_iterator</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">(</span><span class="n">theFile</span><span class="p">)),</span> <span class="n">istreambuf_iterator</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">());</span></div><div class='line' id='LC19'>	<span class="n">buffer</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="sc">&#39;\0&#39;</span><span class="p">);</span></div><div class='line' id='LC20'>	<span class="c1">// Parse the buffer using the xml file parsing library into doc </span></div><div class='line' id='LC21'>	<span class="n">doc</span><span class="p">.</span><span class="n">parse</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buffer</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span></div><div class='line' id='LC22'>	<span class="c1">// Find our root node</span></div><div class='line' id='LC23'>	<span class="n">root_node</span> <span class="o">=</span> <span class="n">doc</span><span class="p">.</span><span class="n">first_node</span><span class="p">(</span><span class="s">&quot;MyBeerJournal&quot;</span><span class="p">);</span></div><div class='line' id='LC24'>	<span class="c1">// Iterate over the brewerys</span></div><div class='line' id='LC25'>	<span class="k">for</span> <span class="p">(</span><span class="n">xml_node</span><span class="o">&lt;&gt;</span> <span class="o">*</span> <span class="n">brewery_node</span> <span class="o">=</span> <span class="n">root_node</span><span class="o">-&gt;</span><span class="n">first_node</span><span class="p">(</span><span class="s">&quot;Brewery&quot;</span><span class="p">);</span> <span class="n">brewery_node</span><span class="p">;</span> <span class="n">brewery_node</span> <span class="o">=</span> <span class="n">brewery_node</span><span class="o">-&gt;</span><span class="n">next_sibling</span><span class="p">())</span></div><div class='line' id='LC26'>	<span class="p">{</span></div><div class='line' id='LC27'>	    <span class="n">printf</span><span class="p">(</span><span class="s">&quot;I have visited %s in %s. &quot;</span><span class="p">,</span> </div><div class='line' id='LC28'>	    	<span class="n">brewery_node</span><span class="o">-&gt;</span><span class="n">first_attribute</span><span class="p">(</span><span class="s">&quot;name&quot;</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">(),</span></div><div class='line' id='LC29'>	    	<span class="n">brewery_node</span><span class="o">-&gt;</span><span class="n">first_attribute</span><span class="p">(</span><span class="s">&quot;location&quot;</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">());</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// Interate over the beers</span></div><div class='line' id='LC31'>	    <span class="k">for</span><span class="p">(</span><span class="n">xml_node</span><span class="o">&lt;&gt;</span> <span class="o">*</span> <span class="n">beer_node</span> <span class="o">=</span> <span class="n">brewery_node</span><span class="o">-&gt;</span><span class="n">first_node</span><span class="p">(</span><span class="s">&quot;Beer&quot;</span><span class="p">);</span> <span class="n">beer_node</span><span class="p">;</span> <span class="n">beer_node</span> <span class="o">=</span> <span class="n">beer_node</span><span class="o">-&gt;</span><span class="n">next_sibling</span><span class="p">())</span></div><div class='line' id='LC32'>	    <span class="p">{</span></div><div class='line' id='LC33'>	    	<span class="n">printf</span><span class="p">(</span><span class="s">&quot;On %s, I tried their %s which is a %s. &quot;</span><span class="p">,</span> </div><div class='line' id='LC34'>	    		<span class="n">beer_node</span><span class="o">-&gt;</span><span class="n">first_attribute</span><span class="p">(</span><span class="s">&quot;dateSampled&quot;</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">(),</span></div><div class='line' id='LC35'>	    		<span class="n">beer_node</span><span class="o">-&gt;</span><span class="n">first_attribute</span><span class="p">(</span><span class="s">&quot;name&quot;</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">(),</span> </div><div class='line' id='LC36'>	    		<span class="n">beer_node</span><span class="o">-&gt;</span><span class="n">first_attribute</span><span class="p">(</span><span class="s">&quot;description&quot;</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">());</span></div><div class='line' id='LC37'>	    	<span class="n">printf</span><span class="p">(</span><span class="s">&quot;I gave it the following review: %s&quot;</span><span class="p">,</span> <span class="n">beer_node</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">());</span></div><div class='line' id='LC38'>	    <span class="p">}</span></div><div class='line' id='LC39'>	    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span></div><div class='line' id='LC40'>	<span class="p">}</span></div><div class='line' id='LC41'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2726944/1b1b5c18e8864dc195e5c318e367cb51f46ef749/RapidXmlExample.c" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2726944#file_rapid_xml_example.c" style="float:right;margin-right:10px;color:#666">RapidXmlExample.c</a>
            <a href="https://gist.github.com/2726944">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>and here is the output:</p>
<blockquote><p><em>I have visited Founders Brewing Company in Grand Rapids, MI. On 01/02/2011, I tried their Centennial which is a IPA. I gave it the following review:</em><br />
<em> &#8220;What an excellent IPA. This is the most delicious beer I have ever tasted!&#8221;</em></p>
<p><em>I have visited Brewery Vivant in Grand Rapids, MI. On 02/07/2015, I tried their Farmhouse Ale which is a Belgian Ale. I gave it the following review:</em><br />
<em> This beer is not so good&#8230; but I am not that big of a fan of english style ales.</em></p>
<p><em>I have visited Bells Brewery in Kalamazoo, MI. On 03/15/2012, I tried their Two Hearted Ale which is a IPA. I gave it the following review:</em><br />
<em> Another execllent brew. Two Hearted gives Founders Centennial a run for it&#8217;s money.</em></p></blockquote>
<p>Overall, I found that RapidXml works very well and is simple to use. One complaint is that if there is a syntax error in the XML file, it doesn&#8217;t give you much indication as to what the problem is. But, I suppose that is one of the tradeoffs of using a lightweight tool. The next time you need to parse some XML, from C++, you should give RapidXml a try!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=asqs50Y1rX8:XUa79CNAn-w:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=asqs50Y1rX8:XUa79CNAn-w:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=asqs50Y1rX8:XUa79CNAn-w:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=asqs50Y1rX8:XUa79CNAn-w:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=asqs50Y1rX8:XUa79CNAn-w:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=asqs50Y1rX8:XUa79CNAn-w:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=asqs50Y1rX8:XUa79CNAn-w:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=asqs50Y1rX8:XUa79CNAn-w:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/asqs50Y1rX8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/20/rapidxml-a-lightweight-xml-library-for-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/20/rapidxml-a-lightweight-xml-library-for-c/</feedburner:origLink></item>
		<item>
		<title>A craftsman exchange, part 2</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/LCV1iVmVABY/</link>
		<comments>http://spin.atomicobject.com/2012/05/20/a-craftsman-exchange-part-2/#comments</comments>
		<pubDate>Sun, 20 May 2012 17:36:03 +0000</pubDate>
		<dc:creator>Matt Fletcher</dc:creator>
				<category><![CDATA[Culture]]></category>
		<category><![CDATA[professional development]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86253</guid>
		<description><![CDATA[<p>Right now I&#8217;m writing this blog post like I write most of my posts: I&#8217;m sitting in a coffee shop, on one of my days off, enjoying a nice cup of kaffe. This time, though, things are a bit different, as this coffee shop is in Uppsala, Sweden.</p>
<p><a href="http://spin.atomicobject.com/2012/05/20/a-craftsman-exchange-part-2/" class="more-link">Read more on A craftsman exchange, part 2 <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>Right now I&#8217;m writing this blog post like I write most of my posts: I&#8217;m sitting in a coffee shop, on one of my days off, enjoying a nice cup of kaffe. This time, though, things are a bit different, as this coffee shop is in Uppsala, Sweden.</p>
<p>Wait. What? Why am I writing this from Sweden? It&#8217;s because I&#8217;m fortunate enough to be wrapping up the first <a href="http://www.citerus.se/">Citerus</a> &#8211; Atomic Object craftsman exchange.</p>
<p>	<a href="http://spin.atomicobject.com/2012/05/20/a-craftsman-exchange-part-2/citerus-2518/" rel="attachment wp-att-86269"><img src="http://spin.atomicobject.com/wp-content/uploads/citerus-2518-590x393.jpg" alt="Håkan, Matt, Patrik, and Mattias at the Uppsala Citerus office" title="Håkan, Matt, Patrik, and Mattias at the Uppsala Citerus office" width="590" height="393" class="size-medium wp-image-86269" /></a></p>
<p><span id="more-86253"></span></p>
<h4>Why?</h4>
<p>I already wrote about the why of the craftsman exchange in <a href="http://spin.atomicobject.com/2012/04/22/a-craftsman-exchange-part-1/">my part 1 blog post,</a> but the gist is this: Citerus and Atomic Object are two innovation services firms that value their employees&#8217; professional development. Programming on the side, researching new technologies, and participating in conferences are all great ways to grow. And I&#8217;ve done plenty of that. The craftsman exchange is a more interesting and exotic opportunity for growth and to and follow through on my passion for software product development.</p>
<p>Last month we began the exchange by having one of Citerus&#8217;s consultants, <a href="http://www.citerus.se/profile/204070-mattias-holmqvist">Mattias Holmqvist</a>, visit us in Grand Rapids; Mattias <a href="http://www.citerus.se/post/815552-craftsmanship-exchange-en-vecka-i">wrote about his experience</a> after he got home.</p>
<h4>Crafting software</h4>
<p>The exchange began with four days working on a customer project with <a href="http://www.citerus.se/profile/204074-patrik-fredriksson">Patrik Fredriksson</a> and <a href="http://www.citerus.se/profile/502306-h-kan-jonson">Håkan Jonson</a>. Patrik met me early on Monday and showed me to the customer&#8217;s office, located in the <a href="http://en.wikipedia.org/wiki/Gamla_stan">Gamla Stan region of Stockholm</a>, with a beautiful view over the water.</p>
<p><a href="http://www.globeimages.net/img-gamla-stan-stockholm-sweden-381.htm"><img src="http://www.globeimages.net/data/media/207/Gamla_Stan_Stockholm_Sweden.jpg" border="0" alt="Gamla_Stan_Stockholm_Sweden.jpg"></a></p>
<p>Toward the beginning of the week we focused on tightening up the application for an important demo to the customer&#8217;s board of directors. The project is relatively new, and this was the first demo, so we wanted to make it as best as we could. We didn&#8217;t need to put a lot of work into it &#8211; the application was already in a good state &#8211; but we still invested a little time in tweaking the colors, logos, presentation, etc.</p>
<p>Later in the week we started working through a thorny user experience problem. I feel pretty good about user experience now that I&#8217;ve had a lot of experience with it on Atomic projects, but I must say that this particular problem is going to be quite difficult to solve! Without getting into details, the problem is this: sometimes the user wants to completely invest themselves into thinking as one role, while sometimes the user needs to back up a bit and evaluate across a dozen or more roles.</p>
<p>Thankfully the team is composed of people who want to collaborate and solve problems, as opposed to people who want to bunker into their own world and throw work over the wall. After some discussion and confusion, we got together and did some quick <a href="http://spin.atomicobject.com/2010/09/28/drawing-with-your-customer/">team sketching</a> and <a href="http://en.wikipedia.org/wiki/Paper_prototyping">paper prototyping</a> exercises. This was good in that it brought out some new ways of thinking about the problem. And even for those of us who didn&#8217;t generate amazing sketches, the visualizations allowed us to understand how the others were thinking and then provide more insights and feedback.</p>
<p><a href="http://www.flickr.com/photos/collylogic/4971094116"><img src="http://spin.atomicobject.com/wp-content/uploads/4971094116_9b41aa738a_o-590x442.jpg" alt="an anonymous paper prototype" title="an anonymous paper prototype" width="590" height="442" class="size-medium wp-image-86329" /></a> <em>Photo credit: <a href='http://www.flickr.com/photos/collylogic/4971094116'>Simon Collison</a></em></p>
<p>We did not reveal the <em>best</em> solution (is there one?), but the team is now well positioned to continually iterate over <em>better</em> and <em>better</em> solutions. Best wishes on your problem, Håkan and Patrik!</p>
<h4>Meeting Citerus</h4>
<p>Working on challenging problems is good, but the exchange isn&#8217;t only about work &#8211; it&#8217;s about also meeting new craftspeople and trading ideas. Citerus is a company full of craftsman and craftswomen, and I&#8217;m glad I got to meet most of them throughout the week.</p>
<p>Tuesday evening Karin, Citerus&#8217;s <span class="caps">CEO</span>, graciously hosted me for dinner at her beautiful home on <a href="http://g.co/maps/ks3ux">Tranholmen</a>. Then, after work on Wednesday, several of us met up for beers, where I got to meet <a href="http://www.citerus.se/profile/664017-anton-gravestam">Anton</a> and <a href="http://www.citerus.se/profile/204071-mikael-boman">Mikael</a>. Beyond beers and dinner, we had an excellent conversation about Android testing; in particular, we discussed tactics for code design that avoid the need for <a href="http://code.google.com/p/powermock/">PowerMock</a> to mock Android <span class="caps">SDK</span> methods in unit tests.</p>
<p>But for me, the big event of the week was Friday&#8217;s Citerus Day. Most Citerus employees are working at a variety of customer sites, so about once a month they take the time to gather in either the Stockholm or Uppsala office. Thankfully my trip coincided with May&#8217;s Citerus Day in Uppsala and I got to meet most of the company.</p>
<p><a href="http://spin.atomicobject.com/2012/05/20/a-craftsman-exchange-part-2/citerus-2457/" rel="attachment wp-att-86346"><img src="http://spin.atomicobject.com/wp-content/uploads/citerus-2457-590x393.jpg" alt="" title="Håkan and Patrik&#039;s update" width="590" height="393" class="alignnone size-medium wp-image-86346" /></a></p>
<p>Citerus Day begins with everyone taking a few to talk about how their project is going. This was an effective way to learn about what everyone is working on, what technologies they are using, identify opportunities for sharing, and, in my case, meet the people in the company. We then moved onto several short talks, including a presentation by Håkan and Patrik about their project. I also gave a talk, which I plan on presenting at Atomic next and then reformulating as a blog post.</p>
<p><a href="http://spin.atomicobject.com/2012/05/20/a-craftsman-exchange-part-2/citerus-2465/" rel="attachment wp-att-86345"><img src="http://spin.atomicobject.com/wp-content/uploads/citerus-2465-590x393.jpg" alt="" title="My brown bag" width="590" height="393" class="alignnone size-medium wp-image-86345" /></a></p>
<p>After lunch we broke into a number of open spaces. Throughout the afternoon I participated in about three different conversations &#8211; continuations of thoughts that had come up in the morning status update, some technology demos, and other related topics. We concluded the day with some final remarks from Karin and myself about what I&#8217;d observed over the week.</p>
<p>The most striking thing I noticed over the course of the week, and especially during Citerus day, is how much Citerus&#8217;s and Atomic&#8217;s attitudes overlap with respect to Atomic&#8217;s four core values: <em>give a shit</em>, <em>teach and learn</em>, <em>own it</em>, and <em>share the pain</em><sup id="fnrev702844154fc54afcc6b8c" class="footnote"><a href="#fn702844154fc54afcc6b8c">1</a></sup>. In particular, when everyone was describing how their projects were going and how they felt about things, overall, it was evident that they all <strong>give a shit.</strong> They are not unhappy and demotivated butts-in-seats contractors. Citerus <strong>gives a shit.</strong></p>
<h4>Vacation</h4>
<p>It&#8217;s not often (or until now, ever) that I&#8217;m in Sweden, so what better time to take a week vacation? It&#8217;s nice to finally visit Uppsala, the city I&#8217;ve heard so much about from Mary, Carl, Karlin, Mike, and Dave. I may be becoming addicted to trips like this, whether it&#8217;s visiting Bill in Ireland, picking up my new car with Carl in Germany, or participating in a craftsman exchange with a company in Sweden. I suppose the gentle encouragement to get out of North America is another unseen benefit of working with the great people at Atomic.</p>
<p><a href="http://spin.atomicobject.com/2012/05/20/a-craftsman-exchange-part-2/img_1332/" rel="attachment wp-att-86340"><img src="http://spin.atomicobject.com/wp-content/uploads/IMG_1332-590x442.jpg" alt="" title="Uppsala before sunset" width="590" height="442" class="alignnone size-medium wp-image-86340" /></a></p>
<p>In conclusion, the first Citerus &#8211; Atomic Object craftsman exchange has been a great professional development opportunity for myself and Mattias. Outside of working on a project together, I can think of no better way for our two companies to build a strong relationship of mutual respect and learning. I hope further opportunities arise for us collaborate in the future.</p>
<p>I&#8217;d like to extend another huge thanks to Atomic and Citerus for providing this opportunity. And, Mattias, thank you so much for meeting me at the airport, helping me get around town, and connecting me with other helpful individuals. It made my two weeks in Sweden easy and enjoyable.</p>
<p id="fn702844154fc54afcc6b8c" class="footnote"><sup>1</sup> I&#8217;ve found our four core values are <a href="http://detroit.atomicobject.com">best documented on our Detroit hiring microsite</a> if you&#8217;d like to read more.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=LCV1iVmVABY:c6jnjcm7kOM:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=LCV1iVmVABY:c6jnjcm7kOM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=LCV1iVmVABY:c6jnjcm7kOM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=LCV1iVmVABY:c6jnjcm7kOM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=LCV1iVmVABY:c6jnjcm7kOM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=LCV1iVmVABY:c6jnjcm7kOM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=LCV1iVmVABY:c6jnjcm7kOM:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=LCV1iVmVABY:c6jnjcm7kOM:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/LCV1iVmVABY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/20/a-craftsman-exchange-part-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/20/a-craftsman-exchange-part-2/</feedburner:origLink></item>
		<item>
		<title>Acceptance tests, my hero!</title>
		<link>http://feedproxy.google.com/~r/atomic_spin/~3/ATxgA-XzdXM/</link>
		<comments>http://spin.atomicobject.com/2012/05/18/acceptance-tests-my-hero/#comments</comments>
		<pubDate>Fri, 18 May 2012 19:27:31 +0000</pubDate>
		<dc:creator>Shawn Anderson</dc:creator>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[Culture]]></category>
		<category><![CDATA[Process & Practices]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[acceptance testing]]></category>

		<guid isPermaLink="false">http://spin.atomicobject.com/?p=86287</guid>
		<description><![CDATA[<p>I believe strongly in behavior driven development (<span class="caps">BDD</span>) and acceptance testing. My standard AO workflow looks something like:</p>
<ol>
<li>write high-level acceptance test</li>
<li>write unit test for a component</li>
<li>make unit test pass</li>
</ol>
<p><a href="http://spin.atomicobject.com/2012/05/18/acceptance-tests-my-hero/" class="more-link">Read more on Acceptance tests, my hero! <span class="meta-nav">&#187;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>I believe strongly in behavior driven development (<span class="caps">BDD</span>) and acceptance testing. My standard AO workflow looks something like:</p>
<ol>
<li>write high-level acceptance test</li>
<li>write unit test for a component</li>
<li>make unit test pass</li>
<li>go to 2 until acceptance test passes</li>
</ol>
<p>This pattern has served me very well in the professional realm. However, when I sit down to play with personal game development project, <a href="https://github.com/shawn42/gamebox">gamebox</a>, acceptance testing and <span class="caps">BDD</span> tend to go out the window.</p>
<p><span id="more-86287"></span></p>
<p><img src="http://spin.atomicobject.com/wp-content/uploads/acceptance_testing_diagram.png" alt="" title="Acceptance Testing Loop" width="579" height="331" class="aligncenter size-full wp-image-86295" /></p>
<p>I go into &#8220;let&#8217;s get a dragon in the game&#8221; mode. With two kids, a wife, and a home to maintain, my time is always fleeting. Naively optimizing for short-term results, I tend to write unit tests only for interesting code and rarely ever write acceptance tests. </p>
<p>As gamebox grew in complexity, I hit a point where a large refactor was required. I started using David Crosby&#8217;s <a href="http://spin.atomicobject.com/2012/05/01/conject-modern-dependency-injection-in-ruby/">conject</a> gem. Conject takes over all of my dependency management and object construction, essentially touching every piece of the framework. I realized that in the current system, the only way I&#8217;d know that I had hooked up all the pieces correctly was to slowly update all the games that I had built using gamebox and see if they work. That approach sounded like a fail-train waiting to leave the station.</p>
<p>I finally sat down in the working system and wrote an acceptance test. The first test was the hardest. After writing a few helpers and moving things around I had a test that proved that a game object could be created, added, drawn, and receive keyboard input. The great thing about the testing harness that I had to write is that games built with gamebox can use them to acceptance test their games, as well. Double win!</p>
<p>	<div id="gist-2725203" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>&nbsp;&nbsp;<span class="n">it</span> <span class="s1">&#39;creates an actor from within stage with the correct behaviors and updates&#39;</span> <span class="k">do</span></div><div class='line' id='LC2'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">game</span><span class="o">.</span><span class="n">stage</span> <span class="k">do</span> <span class="o">|</span><span class="n">stage</span><span class="o">|</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">create_actor</span> <span class="ss">:mc_bane</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="mi">250</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mi">400</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">see_actor_attrs</span> <span class="ss">:mc_bane</span><span class="p">,</span> <span class="n">bullets</span><span class="p">:</span> <span class="mi">50</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">update</span> <span class="mi">10</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">see_image_not_drawn</span> <span class="n">mc_bane_png</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">draw</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">see_image_drawn</span> <span class="n">mc_bane_png</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">see_actor_attrs</span> <span class="ss">:mc_bane</span><span class="p">,</span> <span class="n">bullets</span><span class="p">:</span> <span class="mi">40</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">game</span><span class="o">.</span><span class="n">should</span> <span class="n">have_actor</span><span class="p">(</span><span class="ss">:mc_bane</span><span class="p">)</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">release_key</span> <span class="no">KbD</span></div><div class='line' id='LC17'><br/></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1"># should have removed himself</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">game</span><span class="o">.</span><span class="n">should_not</span> <span class="n">have_actor</span><span class="p">(</span><span class="ss">:mc_bane</span><span class="p">)</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC22'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/ee582984e4a29f4a3ae5/31099576bde0843658c754f82cfa3167ab0b2f1d/basic_actor_usage.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/ee582984e4a29f4a3ae5#file_basic_actor_usage.rb" style="float:right;margin-right:10px;color:#666">basic_actor_usage.rb</a>
            <a href="https://gist.github.com/ee582984e4a29f4a3ae5">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>Save yourself the headache. Start with the acceptance tests and drive from there. They improve your design and let you know when you&#8217;re done. I use them every day in the office, and now I play the home version, too. They can be real life savers. </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/atomic_spin?a=ATxgA-XzdXM:FA22m08YbwQ:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=ATxgA-XzdXM:FA22m08YbwQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=ATxgA-XzdXM:FA22m08YbwQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=ATxgA-XzdXM:FA22m08YbwQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=ATxgA-XzdXM:FA22m08YbwQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=ATxgA-XzdXM:FA22m08YbwQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/atomic_spin?i=ATxgA-XzdXM:FA22m08YbwQ:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/atomic_spin?a=ATxgA-XzdXM:FA22m08YbwQ:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/atomic_spin/~4/ATxgA-XzdXM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://spin.atomicobject.com/2012/05/18/acceptance-tests-my-hero/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://spin.atomicobject.com/2012/05/18/acceptance-tests-my-hero/</feedburner:origLink></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-05-29 18:17:36 -->

