<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Carbon Five Community &#187; Agile</title>
	<atom:link href="http://blog.carbonfive.com/tag/agile/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.carbonfive.com</link>
	<description></description>
	<lastBuildDate>Fri, 27 Aug 2010 00:24:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Alon at Web 2.0 in SF May 5 on &#8220;Blurring the Lines&#8221;</title>
		<link>http://blog.carbonfive.com/2010/04/speaking/alon-at-web-2-0-in-sf-may-5-on-blurring-the-lines</link>
		<comments>http://blog.carbonfive.com/2010/04/speaking/alon-at-web-2-0-in-sf-may-5-on-blurring-the-lines#comments</comments>
		<pubDate>Wed, 28 Apr 2010 19:19:54 +0000</pubDate>
		<dc:creator>alon</dc:creator>
				<category><![CDATA[Speaking]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[customer development]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[lean startups]]></category>
		<category><![CDATA[user experience]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=992</guid>
		<description><![CDATA[I&#8217;m excited about our panel next Wed at Web 2.0 Expo in San Francisco Blurring the Lines: From Human Centered Design to Customer Driven Development. We&#8217;re planning to share real world practices that help multi-disciplinary teams collaborate on creating great products. We&#8217;ve got a good range of perspective and experience to draw from. Maria Giudice [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m excited about our panel next Wed at Web 2.0 Expo in San Francisco <a href="http://www.web2expo.com/webexsf2010/public/schedule/detail/11837">Blurring the Lines: From Human Centered Design to Customer Driven Development</a>. We&#8217;re planning to share real world practices that help multi-disciplinary teams collaborate on creating great products.</p>
<p>We&#8217;ve got a good range of perspective and experience to draw from. <a href="http://www.web2expo.com/webexsf2010/public/schedule/speaker/10279">Maria Giudice</a> from <a href="http://www.hotstudio.com">Hot Studio</a> is our user-centered designer, <a href="http://www.web2expo.com/webexsf2010/public/schedule/speaker/52400">Rob Spiro</a> from <a href="http://aardvark.im">Aardvark</a> is our user-centered product entrepreneur, <a href="http://www.web2expo.com/webexsf2010/public/schedule/speaker/55939">Darren David</a> from <a href="http://stimulant.io">Stimulant</a> is our multi-touch and <a href="http://stimulant.io/wp/index.php/blog/2009/07/nathan-talks-nui-at-interaction09/">NUI</a> innovator, and I am our Agile software developer.</p>
<p>This event seems to have really caught on to the growing energy in the entrepreneurial community around strategies and techniques for creating products that people really want. <a href="http://www.web2expo.com/webexsf2010/public/schedule/speaker/45691">Eric Ries</a> is giving the <a href="http://www.web2expo.com/webexsf2010/public/schedule/detail/13317">keynote on Tuesday</a> just one year after his first big conference presentation at Web 2.0 2009 and <a href="http://www.steveblank.com/">Steve Blank</a> is giving the <a href="http://www.web2expo.com/webexsf2010/public/schedule/detail/12875">keynote Thursday</a>. Both of these guys and the growing community around them have been inspiration to me and our work at Carbon Five over the last year for the answers they provide about how software development serves the goal of creating successful businesses and products.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/04/speaking/alon-at-web-2-0-in-sf-may-5-on-blurring-the-lines/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Story Mapper is Release Planning for Pivotal Tracker</title>
		<link>http://blog.carbonfive.com/2010/03/agile/story-mapper-is-release-planning-for-pivotal-tracker</link>
		<comments>http://blog.carbonfive.com/2010/03/agile/story-mapper-is-release-planning-for-pivotal-tracker#comments</comments>
		<pubDate>Thu, 25 Mar 2010 22:42:03 +0000</pubDate>
		<dc:creator>alon</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[patton]]></category>
		<category><![CDATA[story map]]></category>
		<category><![CDATA[tracker]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=930</guid>
		<description><![CDATA[We&#8217;re proud to announce the release of Story Mapper, a project we have been working on at Carbon Five to support an Agile project planning technique called story mapping. We use Pivotal Tracker to manage our feature backlog and the day-to-day activities of tracking a feature from estimation through delivery and acceptance. However, we find [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re proud to announce the release of <a href="http://www.trackerstorymaps.com">Story Mapper</a>, a project we have been working on at Carbon Five to support an Agile project planning technique called <a href="http://www.agileproductdesign.com/blog/the_new_backlog.html">story mapping</a>.</p>
<p>We use <a href="http://www.pivotaltracker.com">Pivotal Tracker</a> to manage our feature backlog and the day-to-day activities of tracking a feature from estimation through delivery and acceptance. However, we find it easy to lose the big picture in the detail-oriented view Tracker provides.</p>
<p>Story Mapper uses your project data from Tracker to provide a higher level view geared toward release and milestone planning. This view is based on Jeff Patton&#8217;s <a href="http://www.agileproductdesign.com/blog/the_new_backlog.html">story mapping</a> techniques and provides the ability to see how the different components of your project will evolve across successive milestone.</p>
<p><a href="http://www.trackerstorymaps.com"><img src="http://blog.carbonfive.com/wp-content/uploads/2010/03/screenshot1.png" alt="Story Mapper Screenshot" title="Story Mapper Screenshot" width="500" height="347" class="aligncenter size-full wp-image-931" style="border:1px solid #303030;"/></a></p>
<p>All you need in order to use Story Mapper is a Tracker project with a backlog of stories and a subset of labels that represent user activities or components of your system. If you have a large project and have not been using labels in this way, you may have some work to do in Story Mapper before you have a story map that makes sense.</p>
<p><a href="http://www.trackerstorymaps.com">Try it out</a>, let us know what you think, and tell us how to make it better. Comment here so others can see your thoughts or by <a href="mailto:storymapper@carbonfive.com">contacting us directly</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/03/agile/story-mapper-is-release-planning-for-pivotal-tracker/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Recipe for 5 Whys with an Agile Software Team</title>
		<link>http://blog.carbonfive.com/2010/01/agile/recipe-for-5-whys-with-an-agile-software-team</link>
		<comments>http://blog.carbonfive.com/2010/01/agile/recipe-for-5-whys-with-an-agile-software-team#comments</comments>
		<pubDate>Wed, 27 Jan 2010 04:53:33 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[rapid development]]></category>
		<category><![CDATA[xp]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=818</guid>
		<description><![CDATA[5 Whys is a great way to get at the root of quality problems. On my last three projects, when I felt like code quality was dropping, I ran a &#8220;5 Whys&#8221; session. I have found it adds variety, solves a very specific problem, and plugs right in as an alternative to an agile reflection. [...]]]></description>
			<content:encoded><![CDATA[<p>5 Whys is a great way to get at the root of quality problems. On my last three projects, when I felt like code quality was dropping, I ran a &#8220;5 Whys&#8221; session. I have found it adds variety, solves a very specific problem, and plugs right in as an alternative to an <a href="http://blog.carbonfive.com/2009/12/agile/recipe-for-simple-agile-retrospectives">agile reflection</a>.</p>
<p>It&#8217;s not in every agile software team&#8217;s bag of tricks. Asking around our fairy savvy office, I discovered it&#8217;s far from universal. In the <a href="http://www.versionone.com/whitepapers.asp">&#8220;State of Agile&#8221; report from Version One</a>, which includes survey results from 2500 software developers, it wasn&#8217;t mentioned. Since I haven&#8217;t seen it show up that much in other agile writings, I thought I&#8217;d share my experiences here.<span id="more-818"></span></p>
<p><strong>What is &#8220;5 Whys&#8221;?</strong> I picked up &#8220;5 Whys&#8221; from the lean software movement, which sprang from Toyota manufacturing.  You can read about its history on <a href="http://en.wikipedia.org/wiki/5_Whys">wikipedia</a>, but it&#8217;s pretty simple: at the end of the assembly line, when a widget comes out with a problem, you stop the line and ask &#8220;Why?&#8221; Whatever the reason, you ask the &#8220;Why?&#8221; again. Repeat at least 5 times. The goal is to discover the &#8220;root cause&#8221; of the defect, and fix the root cause, not just some symptom. Wikipedia has a good example around car repair. Here&#8217;s a software example:</p>
<blockquote><p>1. Why did Sheryl say the sign-up flow was broken?<br />
<em>A: Because she was trying to sign up a second time. Duh.</em><br />
2. Yeah, but why did the flow break if the user is already signed up?<br />
<em>A: It&#8217;s a bug. We didn&#8217;t have a test case for that.</em><br />
3. Why didn&#8217;t we have a test case for it?<br />
<em>A: I just didn&#8217;t think of it.</em><br />
4. Why didn&#8217;t you think about it?<br />
<em>A: The story seemed easy&#8211; I guess I didn&#8217;t think it through.</em><br />
5. Why do you think you didn&#8217;t think it through?&#8221;<br />
<em>A: I guess I was working alone and was in a hurry.</em><br />
&#8230;</p></blockquote>
<p>Obviously you don&#8217;t have ask &#8220;Why?&#8221; exactly five times, but that does seem to be a pretty good number. The point is you start articulating the behaviors and procedures that cause the problems.</p>
<p><strong>Taking It for a Spin. </strong> I&#8217;ve come up with exercise for agile software teams.  Like I mentioned, when quality drops below your comfort level, give it a try:</p>
<ol>
<li>(2 minutes) Make a list of the most recent bugs you&#8217;ve uncovered. I&#8217;ve found that the last 10 is usually enough&#8211; if not too much. You can put these on a white board, index cards or a wiki page&#8211; all will work.</li>
<li>(2 minutes) Prioritize them based on the ones you want to talk about. Which caused the most embarrassment or cost? You usually only have energy to talk about 5 or 6 of them.</li>
<li>(15 minutes) For each bug, ask &#8220;Why did this happen?&#8221; Then, probe deeper until you can&#8217;t get much further. Write the answers down where everyone can see.</li>
<li>(5 minutes) When you&#8217;re done with all the bugs (or out of time), circle common root causes.</li>
<li>(10 minutes) Brainstorm ways to mitigate or eliminate the root causes. Come of with one or two SMART goals for the team.</li>
</ol>
<p>Some of the root causes we&#8217;ve gotten to recently:</p>
<ul>
<li> we didn&#8217;t pair on hard features</li>
<li> we didn&#8217;t ask for clarifications on the requirements</li>
<li> one engineer didn&#8217;t understand the intent behind the code</li>
<li> nobody looked at the app on Internet Explorer 6</li>
</ul>
<p>Just like in agile reflections, the changes made coming out of these meetings stick with the team. During one session, the developers decided that there were just too many mistakes that someone else would have easily caught&#8211; so they always needed two sets of eyes on every checkin. I&#8217;d advocated this before, but it was never applied consistently. To my surprise though, after the reflection, everyone was  disciplined about this policy&#8211; and our quality was much better.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/01/agile/recipe-for-5-whys-with-an-agile-software-team/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>assert_changes and assert_no_changes in Ruby</title>
		<link>http://blog.carbonfive.com/2009/04/testing/assert_changes-and-assert_no_changes-in-ruby</link>
		<comments>http://blog.carbonfive.com/2009/04/testing/assert_changes-and-assert_no_changes-in-ruby#comments</comments>
		<pubDate>Sat, 04 Apr 2009 00:26:51 +0000</pubDate>
		<dc:creator>andy</dc:creator>
				<category><![CDATA[Ruby (on Rails)]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[fixtures]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=567</guid>
		<description><![CDATA[Update: This code and documentation is now available on github: http://github.com/ndp/assert_changes/tree/master The Problem On our work on gobalto.com, we spend time to have good fixture data for our tests&#8211; data that can represent all the important application states that our tests require. As a result, our tests are very dependent on the data. It&#8217;s important [...]]]></description>
			<content:encoded><![CDATA[<h3><span style="color: #000080;">Update:</span><span style="color: #000080;"> This code and documentation is now available on github:<a href="http://github.com/ndp/assert_changes/tree/master" target="_blank"> http://github.com/ndp/assert_changes/tree/master</a></span></h3>
<h2>The Problem</h2>
<p>On our work on <a href="http://www.gobalto.com">gobalto.com</a>, we spend time to have good fixture data for our tests&#8211; data that can represent all the important application states that our tests require. As a result, our tests are very dependent on the data. It&#8217;s important that someone doesn&#8217;t inadvertantly change it in subtle ways. This has led us to write not only asserts at the end of tests, but pre-conditions as well. For example,</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    ...
    <span style="color:#9900CC;">inotech</span> = companies<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:inotech</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    assert inotech.<span style="color:#9900CC;">services</span>.<span style="color:#9900CC;">public</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>categories<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:a</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    assert inotech.<span style="color:#9900CC;">services</span>.<span style="color:#9900CC;">public</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>categories<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:b</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    assert inotech.<span style="color:#9900CC;">services</span>.<span style="color:#9900CC;">public</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>categories<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:c</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    post <span style="color:#ff3333; font-weight:bold;">:edit_services_dialog</span>, <span style="color:#ff3333; font-weight:bold;">:id</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;inotech.<span style="color:#9900CC;">id</span>,
                                          <span style="color:#ff3333; font-weight:bold;">:service_category_id</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;categories<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:a</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">id</span>
    inotech.<span style="color:#9900CC;">reload</span>
&nbsp;
    assert inotech.<span style="color:#9900CC;">services</span>.<span style="color:#9900CC;">public</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>categories<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:a</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    assert !inotech.<span style="color:#9900CC;">services</span>.<span style="color:#9900CC;">public</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>categories<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:b</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    assert !inotech.<span style="color:#9900CC;">services</span>.<span style="color:#9900CC;">public</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>categories<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:c</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Although the pre-conditions were introduced to guard against accidentally changing fixture data (or just to figure out what&#8217;s going on), we don&#8217;t necessarily delete them. They provide stronger tests. And in some ways, leaving in pre-conditions make the code more readable by providing documentation of your assumptions to the readers. The code above would be hard to follow without the clarifying pre-conditions. What do we expect to change and what stays the same?</p>
<p>Unfortunately all these asserts make the tests twice as long. And there&#8217;s a subtle readability problem: there&#8217;s no relationship between the corresponding pre- and post-conditions. In the example above, you have to scan carefully to see that the three assertions are repeated, but negated (b and c only). The reader must mentally put pieces together. And it&#8217;s not DRY. Using local variables doesn&#8217;t help much.</p>
<h2>The Solution</h2>
<p>I was inspired by a nice little test helper called assert_difference. It takes a string to evaluate and a block to execute. It&#8217;s useful for checking on state changes&#8211; especially database changes&#8211; during a test:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">assert_difference<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;color: blue;">'Company.count'</span>, <span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    Company.<span style="color:#9900CC;">delete_one</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>(Without this method, we rely on a count of all database records, or merely look for specific ones. The former approach leads to brittle tests, and the latter to incomplete assertions.)</p>
<p>A limitation of assert_difference is that it only deals with integers. What if it were generalized? Here goes:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    i = <span style="color:#0000FF; font-weight:bold;">true</span>
    assert_changes <span style="color:#996600;color: blue;">'i'</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#0000FF; font-weight:bold;">false</span> <span style="color:#9966CC; font-weight:bold;">do</span>   <span style="color:#008000; font-style:italic;"># read as: i changes to false</span>
      i = <span style="color:#0000FF; font-weight:bold;">false</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p><span id="more-567"></span>The string passed to assert changes is evaluated in the block context, both before and after the block is run. So this block asserts that i becomes false (and by deduction, starts out as true). It executes asserts on both ends, just like we want.</p>
<p>Of course sometimes you want to be explicit about a state change, so you can specify both the starting and ending values using an array:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    o.<span style="color:#9900CC;">answer</span> = <span style="color:#996600;color: blue;">'yes'</span>
    assert_changes <span style="color:#996600;color: blue;">'o.answer'</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;color: blue;">'yes'</span>,<span style="color:#996600;color: blue;">'no'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      o.<span style="color:#9900CC;">answer</span> = <span style="color:#996600;color: blue;">'no'</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>To handle the original example, you can pass multiple pre/post conditions of arbitrary complexity and they are all evaluated before and after the block is executed:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">      assert_changes <span style="color:#996600;color: blue;">'post(:a).status'</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:preview</span>, <span style="color:#ff3333; font-weight:bold;">:published</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
                            <span style="color:#996600;color: blue;">'comment(:c).status'</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:preview</span>, <span style="color:#ff3333; font-weight:bold;">:deleted</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        ...
      <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Finally, I added support for a :no_change symbol. Now I can re-write my original problem in a clearer form:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    assert_changes
        <span style="color:#996600;color: blue;">'inotech.services.public.include?(categories(:a))'</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:no_change</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
            <span style="color:#996600;color: blue;">'inotech.services.public.include?(categories(:b))'</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;false,
            <span style="color:#996600;color: blue;">'inotech.services.public.include?(categories(:c))'</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;false <span style="color:#9966CC; font-weight:bold;">do</span>
      post <span style="color:#ff3333; font-weight:bold;">:edit_services_dialog</span>, <span style="color:#ff3333; font-weight:bold;">:id</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;inotech.<span style="color:#9900CC;">id</span>, <span style="color:#ff3333; font-weight:bold;">:service_category_id</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;categories<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:a</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">id</span>
      inotech.<span style="color:#9900CC;">reload</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>For completeness, I added assert_no_changes, with slightly extended parameter possibilities:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    i,j = <span style="color:#996600;color: blue;">'hello'</span>,<span style="color:#996600;color: blue;">'hi'</span>
    assert_no_changes <span style="color:#996600;color: blue;">'i'</span> <span style="color:#9966CC; font-weight:bold;">do</span> ...  <span style="color:#008000; font-style:italic;"># i (before) == i (after)</span>
    assert_no_changes <span style="color:#996600;color: blue;">'i'</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;<span style="color:#996600;color: blue;">'hello'</span> <span style="color:#9966CC; font-weight:bold;">do</span> ... <span style="color:#008000; font-style:italic;"># i == 'hello' before and after</span>
    assert_no_changes <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;color: blue;">'i'</span>,<span style="color:#996600;color: blue;">'j'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">do</span> ... <span style="color:#008000; font-style:italic;"># neither i or j change</span>
    assert_no_changes <span style="color:#996600;color: blue;">'i'</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;<span style="color:#996600;color: blue;">'hello'</span>,<span style="color:#996600;color: blue;">'j'</span>=<span style="color:#006600; font-weight:bold;">&amp;</span>gt;<span style="color:#996600;color: blue;">'hi'</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#008000; font-style:italic;"># or be explicit</span></pre></div></div>

<h3><span style="color: #000080;">Update:</span><span style="color: #000080;"> This code and documentation is now available on github:<a href="http://github.com/ndp/assert_changes/tree/master" target="_blank"> http://github.com/ndp/assert_changes/tree/master</a></span></h3>
<p>Thoughts? Comments?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2009/04/testing/assert_changes-and-assert_no_changes-in-ruby/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Agile Modeling Techniques for Story Writing</title>
		<link>http://blog.carbonfive.com/2009/03/software-design/agile-modeling-techniques-for-story-writing</link>
		<comments>http://blog.carbonfive.com/2009/03/software-design/agile-modeling-techniques-for-story-writing#comments</comments>
		<pubDate>Thu, 12 Mar 2009 23:48:45 +0000</pubDate>
		<dc:creator>rob</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Software Design]]></category>
		<category><![CDATA[modeling]]></category>
		<category><![CDATA[uml]]></category>
		<category><![CDATA[xp]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=431</guid>
		<description><![CDATA[At Carbon Five, all our projects begin with &#8216;customer facing&#8217; meetings focused around determining scope and expectations. A core component of these early meetings involves one or more story writing sessions. The end goal of story writing sessions is to have most user stories in a project documented (i.e. in Pivotal Tracker) regardless of whether [...]]]></description>
			<content:encoded><![CDATA[<div class="mceTemp">At Carbon Five, all our projects begin with &#8216;customer facing&#8217; meetings focused around determining scope and expectations. A core component of these early meetings involves one or more story writing sessions. The end goal of story writing sessions is to have most <a href="http://en.wikipedia.org/wiki/User_story">user stories</a> in a project documented (i.e. in <a href="http://www.pivotaltracker.com">Pivotal Tracker</a>) regardless of whether you have a requirements document or not. Story writing sessions are informal and conversational in nature, where information from customers are digested by a Team Lead and converted into stories. Most of the time, I compile user stories as a linear list in Tracker (displayed on the wall using a projector) while discussing functionality with a customer. However, sometimes customers have a difficult time ‘connecting the dots’ because of the linear nature of a list.       </p>
<p class="MsoNormal">On those occasions, I supplement my list in Tracker with another technique for capturing user stories. It involves modeling using a <a href="http://en.wikipedia.org/wiki/List_of_UML_tools">UML IDE</a>. Primarily, I use <a href="http://en.wikipedia.org/wiki/Activity_diagram">Activity Diagrams</a> because they capture behavior using ‘actions&#8217; and allow for flow. Because activity diagrams are essentially flow charts, they provide a simple comprehension mechanism for all customers regardless of their technical background. I usually display my desktop in the conference room using a projector and interactively add elements to the diagram as I receive customer input. For demonstrating modeling techniques, I will use a &#8216;Music Store&#8217; web application as an example.</p>
<p class="MsoNormal"><strong>Summary of Steps:</strong></p>
<ol style="margin-top: 0in;" type="1">
<li class="MsoNormal">Create an Activity      Diagram from a High-Level Functional Requirement.</li>
<li class="MsoNormal">Capture Customer Input for Identified Functional Requirement.</li>
<li class="MsoNormal">Model Flow for Activity, Link Actions with Diagram Elements.</li>
<li class="MsoNormal">Aggregate Similar Actions to Separate Activity.</li>
<li class="MsoNormal">Convert Activity Diagram into <a href="http://en.wikipedia.org/wiki/User_story">User Stories</a>.</li>
<li class="MsoNormal">Repeat Steps until all Functional Requirements are Exhausted.</li>
</ol>
<h3 class="MsoNormal">Step 1: Create an Activity Diagram from a High-Level Functional Requirement</h3>
<p>Start      with a known high-level functional requirement and create an Activity diagram. When starting, I will identify a large chunk of functionality that I know to be required for the project and use that as a discussion point with the audience. For my sample Music Store project, I would choose &#8216;Browsing the Inventory&#8217; as a large piece of functionality. At this point, the audience might begin to shout out other large pieces of functionality (i.e. &#8216;Customers can create accounts&#8217;, &#8216;Employees can add to inventory&#8217;). If this occurs, I like to create empty Activity diagrams named appropriately. These large pieces of functionality will eventually be decomposed into smaller, more manageable, Activities and Actions.</p>
<p> </p>
<div id="attachment_508" class="wp-caption aligncenter" style="width: 395px"><a href="http://blog.carbonfive.com/wp-content/uploads/2009/03/browsing-the-inventory-1.gif"><img class="size-medium wp-image-508" title="High-Level Functional Requirement as an Activity" src="http://blog.carbonfive.com/wp-content/uploads/2009/03/browsing-the-inventory-1.gif" alt="" width="385" height="252" /></a><p class="wp-caption-text">High-Level Functional Requirement as an Activity</p></div>
<h3>Step 2: Capture Customer Input for Identified Functional Requirement</h3>
<p>Gather input from the audience regarding this Activity / functional requirement and capture pertinent information as Actions. Essentially, what you are trying to do here is decompose the larger &#8216;Browsing the Inventory&#8217; functional requirement into smaller ones. Make an attempt to name each of the Actions with story-like syntax (i.e. ‘As a &lt;role&gt; I can &lt;result&gt; so that &lt;benefit&gt;’). The goal of this step is to create a catalog of smaller functional requirements so that you can start modeling flow.</p>
<div id="attachment_509" class="wp-caption aligncenter" style="width: 571px"><a href="http://blog.carbonfive.com/wp-content/uploads/2009/03/browsing-the-inventory-2.gif"><img class="size-medium wp-image-509 " title="Capturing Smaller Functional Requirements as Actions" src="http://blog.carbonfive.com/wp-content/uploads/2009/03/browsing-the-inventory-2.gif" alt="" width="561" height="324" /></a><p class="wp-caption-text">Capturing Smaller Functional Requirements as Actions</p></div>
<h3>Step 3: Model Flow for Activity, Link Actions with Diagram Elements</h3>
<p>Start      modeling flow for this Activity, linking Actions with other diagram      elements. All Activities must have a start as well as an end point. I model my Activities so that my flow is complete. This ensures that all known paths have been captured. This step is crucial in capturing all known functionality for the high-level requirement.</p>
<p>Remember that this is an interactive step with the audience. The audience / customer will provide input as to the flow of the Activity from Action to Action.</p>
<div id="attachment_510" class="wp-caption alignnone" style="width: 741px"><a href="http://blog.carbonfive.com/wp-content/uploads/2009/03/browsing-the-inventory-final.gif"><img class="size-medium wp-image-510" title="Adding Flow to Activity" src="http://blog.carbonfive.com/wp-content/uploads/2009/03/browsing-the-inventory-final.gif" alt="Adding Flow to Activity" width="731" height="439" /></a><p class="wp-caption-text">Adding Flow to Activity</p></div>
<h3>Step 4: Aggregate Similar Actions to Separate Activity</h3>
<p>If the diagram begins to flow outside of your viewable area, this is an indicator for breaking out one or more actions into a separate Activity. Several actions can be converted into one abstract action that encompasses all the functionality provided by all those actions. In the figure in step 3, the Action &#8216;Purchase an Item&#8217;, was created to represent another Activity diagram. The separate Activity diagram that I created was named &#8216;Purchasing an Item&#8217; and contains the detailed flow for that functionality.</p>
<p>This step is reliant on the Tech Lead&#8217;s skill to identify similar areas of responsibility within the activity. </p>
<h3>Step 5: Convert Activity Diagram into User Stories</h3>
<p>After one Activity diagram is fairly complete, begin entering them into Tracker as <a href="http://en.wikipedia.org/wiki/User_story">Stories</a>. Each Action should be converted into a user story using a consistent syntax (i.e. ‘As a &lt;role&gt; I can &lt;result&gt; so that &lt;benefit&gt;’).</p>
<p> </p>
<div id="attachment_515" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2009/03/convert2stories.png"><img class="size-medium wp-image-515 " title="convert2stories" src="http://blog.carbonfive.com/wp-content/uploads/2009/03/convert2stories.png" alt="Convert Action elements into User Stories" width="300" height="180" /></a><p class="wp-caption-text">Convert Action elements into User Stories</p></div>
</div>
<div class="mceTemp">
<div id="attachment_516" class="wp-caption aligncenter" style="width: 514px"><a href="http://blog.carbonfive.com/wp-content/uploads/2009/03/icebox.png"><img class="size-medium wp-image-516 " title="icebox" src="http://blog.carbonfive.com/wp-content/uploads/2009/03/icebox.png" alt="User Story list with Activities as Milestones" width="504" height="370" /></a><p class="wp-caption-text">User Story list with Activities as Milestones</p></div>
<p> </p>
<h3>Step 6: Repeat Steps until all Functional Requirements are Exhausted</h3>
<p>Steps 1-5 must be repeated until all high-level functional requirements have been modeled as Activities during discussion. In the end, I will have a catalog of Activity diagrams. In the figure below, a Package Diagram displays all the Activity Diagrams that I have modeled. I like to use each of the Activities as a milestone during planning. This may or may not be ideal depending on how granular your functional requirements are.</p>
<div id="attachment_513" class="wp-caption aligncenter" style="width: 221px"><a href="http://blog.carbonfive.com/wp-content/uploads/2009/03/milestones.gif"><img class="size-full wp-image-513 " title="milestones" src="http://blog.carbonfive.com/wp-content/uploads/2009/03/milestones.gif" alt="Inventory of Activities as Milestones" width="211" height="298" /></a><p class="wp-caption-text">Package Diagram: Inventory of Activities as Milestones</p></div>
<p class="MsoNormal"> </p>
<h3 class="MsoNormal">Conclusion</h3>
<p class="MsoNormal">There are many arguments against modeling in the agile communities, so it is important to view modeling as being supplemental to the process. In the end, our models are used to aid in the process of conveying and gathering information with the customer. Some other benefits include:</p>
<ul>
<li>The diagrams can serve as a documentation deliverable</li>
<li>Interactive modeling along with the diagrams, which serve as a visual aid, improves customer comprehension of our software development process</li>
<li>This is a great way to capture requirements when none exist</li>
<li>The Activity diagram allows us to write stories in a format that follows an accompanied wireframe (if available)</li>
<li>User roles can be added to Activity diagrams as swimlanes (partitions). This aids in separating functionality by use case</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2009/03/software-design/agile-modeling-techniques-for-story-writing/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Continuous Integration and Build Promotion</title>
		<link>http://blog.carbonfive.com/2009/03/agile/continuous-integration-and-build-promotion</link>
		<comments>http://blog.carbonfive.com/2009/03/agile/continuous-integration-and-build-promotion#comments</comments>
		<pubDate>Wed, 04 Mar 2009 17:24:33 +0000</pubDate>
		<dc:creator>christian</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[continuous integration]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=340</guid>
		<description><![CDATA[We have a build server and we practice continuous integration on all of our projects. In fact, it&#8217;s pretty much the first thing we set up after version control. We&#8217;re feedback junkies. It became especially apparent while working on a client project last year where we used their development infrastructure. They had a build server [...]]]></description>
			<content:encoded><![CDATA[<p>We have a build server and we practice continuous integration on all of our projects.  In fact, it&#8217;s pretty much the first thing we set up after version control.  We&#8217;re feedback junkies.  It became especially apparent while working on a client project last year where we used their development infrastructure.  They had a build server running, but the problem was that it took too long to get feedback.  I was lost and jonesing.  They had a monolithic build that took about 45 minutes to run its course and give me the affirmation I was seeking.</p>
<p>While setting up my current project, I decided to take a different approach when configuring our build server and continuous integration.  I had a few goals in mind:</p>
<ul>
<li>Super fast feedback</li>
<li>&#8220;Promoted&#8221; builds get pushed to the acceptance server</li>
<li>Minimize issues with the build infrastructure</li>
</ul>
<p>I split our build into three plans:</p>
<p><a href="http://blog.carbonfive.com/wp-content/uploads/2009/03/build.png"><img src="http://blog.carbonfive.com/wp-content/uploads/2009/03/build.png" alt="" title="Build Progression" width="613" height="217" class="aligncenter size-medium wp-image-396" /></a></p>
<h3>Continuous Integration Build Plan</h3>
<p>This resets the unit test database (using <a href="http://code.google.com/p/c5-db-migration/">c5-db-migrations</a>), compiles the project, runs all of the unit tests, and if there are no errors or failures, produces a war.  The war is installed locally using Maven so that it&#8217;s accessible to other processes in a known location.  This build is very fast and is triggered on every subversion commit.  The command used for this build plan is:</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">mvn db-migration:reset clean install</pre></div></div>

<h3>Functional Tests Build Plan</h3>
<p>This resets the functional test database, deploys the war built during the continuous integration build to tomcat using <a href="http://cargo.codehaus.org/">Cargo</a>, runs all of the functional tests, and shuts down tomcat.  This build is triggered on every successful continuous integration build (i.e. as a dependent build).  A very short script performs the work of this build:</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">mvn -Pdev db-migration:reset
cd functional-tests; mvn -Pdev clean test-compile cargo:start surefire:test cargo:stop</pre></div></div>

<p>And here&#8217;s the cargo-maven-plugin configuration:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
...
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.cargo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>cargo-maven2-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0-beta-2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wait<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>false<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wait<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;deployables<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;deployable<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.acme<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>acme-web<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>war<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;context<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>acme-web<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/context<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/deployable<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/deployables<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;container<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;containerId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>tomcat6x<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/containerId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;zipUrlInstaller<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www.apache.org/dist/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.zip<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/zipUrlInstaller<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/container<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<h3>Deploy to Acceptance Build Plan</h3>
<p>This step doesn&#8217;t build anything or run any tests, but is a little more complicated than the others because it&#8217;s interacting with a another machine: our dedicated project acceptance server.  We scp the war (built during the continuous integration phase) to our acceptance server.  Next, we shutdown tomcat and clean a few things up (logs, old webapp, and work).  Then we migrate the database (no reset because we care about the data).  Last, we bring tomcat back up with the new war.  This build is triggered on every successful functional test build.  Here&#8217;s the script that&#8217;s run by the build server:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">ARTIFACT_NAME</span>=.<span style="color: #000000; font-weight: bold;">/</span>ROOT.war
&nbsp;
<span style="color: #666666; font-style: italic;"># SCP Application and Scripts</span>
<span style="color: #007800;">WAR</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">find</span> ~<span style="color: #000000; font-weight: bold;">/</span>.m2<span style="color: #000000; font-weight: bold;">/</span>repository<span style="color: #000000; font-weight: bold;">/</span>com<span style="color: #000000; font-weight: bold;">/</span>acme<span style="color: #000000; font-weight: bold;">/</span>acme-web <span style="color: #660033;">-name</span> <span style="color: #ff0000;color: blue;">&quot;*-*.war&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">tail</span> -<span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;color: blue;">&quot;Copying <span style="color: #007800;">$WAR</span> to acceptance server.&quot;</span>
<span style="color: #c20cb9; font-weight: bold;">scp</span> <span style="color: #007800;">$WAR</span> acme<span style="color: #000000; font-weight: bold;">@</span>acme-acceptance:<span style="color: #007800;">$ARTIFACT_NAME</span>
<span style="color: #c20cb9; font-weight: bold;">scp</span> .<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/*</span>_as.sh acme<span style="color: #000000; font-weight: bold;">@</span>acme-acceptance:.
&nbsp;
<span style="color: #666666; font-style: italic;"># Shutdown and Clean Tomcat</span>
<span style="color: #c20cb9; font-weight: bold;">ssh</span> acme<span style="color: #000000; font-weight: bold;">@</span>acme-acceptance <span style="color: #c20cb9; font-weight: bold;">sh</span> .<span style="color: #000000; font-weight: bold;">/</span>shutdown_as.sh
&nbsp;
<span style="color: #666666; font-style: italic;"># DB Migration</span>
mvn <span style="color: #660033;">-Pdev</span> db-migration:migrate -Djdbc.host=acme-acceptance
&nbsp;
<span style="color: #666666; font-style: italic;"># Install Application</span>
<span style="color: #c20cb9; font-weight: bold;">ssh</span> acme<span style="color: #000000; font-weight: bold;">@</span>acme-acceptance <span style="color: #c20cb9; font-weight: bold;">mv</span> <span style="color: #007800;">$ARTIFACT_NAME</span> .<span style="color: #000000; font-weight: bold;">/</span>apache-tomcat<span style="color: #000000; font-weight: bold;">/</span>webapps<span style="color: #000000; font-weight: bold;">/</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Startup</span>
<span style="color: #c20cb9; font-weight: bold;">ssh</span> acme<span style="color: #000000; font-weight: bold;">@</span>acme-acceptance <span style="color: #c20cb9; font-weight: bold;">sh</span> .<span style="color: #000000; font-weight: bold;">/</span>startup_as.sh</pre></div></div>

<h3>Conclusion</h3>
<p>This has worked out really well for the project and we get feedback very quickly.</p>
<p>You may wonder why we broke functional tests into their own plan.  I find that functional tests can be a little less stable than unit tests (especially if selenium is involved), and they run much more slowly.  I&#8217;ve seen cases where flaky functional tests caused a team to start ignoring build results because it was usually a problem with the infrastructure, not with the code.  So, the decision was somewhat defensive and in retrospect, probably unnecessary.</p>
<p>We&#8217;ve spent less time maintaining our build plans than in the past as well.  At some point, our build server MySQL instance crapped out and even though all of the databases were deleted, our builds all ran successfully when the build server came back up because they start with a database reset, which creates the target database and migrates it to the latest schema.</p>
<p>A single war is promoted as it passes a greater level of testing, and is eventually deployed to the acceptance server if all of the tests pass.  While we&#8217;re saving a little time by not rebuilding the archive for each plan, that&#8217;s not the only thing I like about it.  It just feels a little more right and it completely eliminates the chance that something about the artifact changes as it makes its way through the pipelines.  The same war can make its way from the first CI build all the way to production.  This is possible because we include default configuration for the application which matches our development environments, and then provide <a href="http://blog.carbonfive.com/2008/04/java/configuring-applications-with-spring">a mechanism for externalizing application configuration</a> for the one-off environments.</p>
<p>I think most modern build server software provides everything you need to do something like this as it&#8217;s rather straight forward.  However, for those who are curious, we have been using <a href="http://www.atlassian.com/software/bamboo/">Bamboo</a> for the last year or two and recently installed <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> so that we can give it a proper try.  Both are great products, and if you&#8217;re on a smallish team, TeamCity is completely free (and is superior to the open source alternatives, IMHO).</p>
<p>How are you using your build server?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2009/03/agile/continuous-integration-and-build-promotion/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Agile User Experience (UX) Resources</title>
		<link>http://blog.carbonfive.com/2007/09/flexflash/agile-user-experience-ux-resources</link>
		<comments>http://blog.carbonfive.com/2007/09/flexflash/agile-user-experience-ux-resources#comments</comments>
		<pubDate>Thu, 06 Sep 2007 23:12:19 +0000</pubDate>
		<dc:creator>alon</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Flex/Flash]]></category>
		<category><![CDATA[Rescue Mission]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[sxsw]]></category>

		<guid isPermaLink="false">http://blog/?p=17</guid>
		<description><![CDATA[For the seven years that we have been evolving our Extreme Programming practice, we have repeatedly readdressed the question of how to best integrate user experience design (visual design, information architecture,&#8230;) with an agile process. As a consulting company, it has always been a requirement that we flex our process to accommodate our clients and [...]]]></description>
			<content:encoded><![CDATA[<p>For the seven years that we have been evolving our Extreme Programming practice, we have repeatedly readdressed the question of how to best integrate user experience design (visual design, information architecture,&#8230;) with an agile process. As a consulting company, it has always been a requirement that we flex our process to accommodate our clients and partners. Over the last year or two we have found our clients and partners increasingly interested in flexing their processes to work more agile and collaboratively with us.</p>
<p>The post is the first of a series on user experience (UX) design practices for agile software development teams. In an upcoming project with our partner Hot Studios we will be exploring new ways to integrate their user experience design process with our software development process. We&#8217;ll share some learnings from that, experiences from the past and new ideas for the future.</p>
<p>First we have a growing reading list of existing resources on the topic that I am posting here for you. If you have other resources for us, please share.</p>
<p><a href="http://timiti.blogspot.com/2008/02/user-research-as-commodity.html">User Research as a Commodity</a><br />
<i>Added 2008-02-14</i><br />
Alex at Pivotal Labs <a href="http://pivots.pivotallabs.com/users/alex/blog/articles/400-user-research-as-a-commodity">noted this post</a> from a user experience manager at Kaiser Permanente who describes a strategy for including regular user testing in an agile development process. The strategy is attractive because it fits with a key characteristic of agile where simple practices performed regularly produce high level complex results.</p>
<p><a href="http://web.archive.org/web/20070313205440/http://www.fawcette.com/interviews/beck_cooper/">Kent Beck v. Alan Cooper</a><br />
This is a 2002 article with the following abstract &#8220;Kent Beck is known as the father of &#8216;extreme programming,&#8217; a process created to help developers design and build software that effectively meets user expectations. Alan Cooper is the prime proponent of interaction design, a process with similar goals but different methodology. We brought these two visionaries together to compare philosophies, looking for points of consensus—and points of irreconcilable difference.&#8221; The difference in perspective between the two is very expressive of the conflicts we have seen between design and agile development processes. Many of the following resources reference this discussion.</p>
<p><i>Note: the original source for this great interview appears to have been taken over by another entity that is no longer making the article available. I am linking to it in the <a href="http://www.archive.org">Internet Archive</a>.</i></p>
<p><a href="http://www.disambiguity.com/waterfall-bad-washing-machine-good-ia-summit-07-slides/">Waterfall Bad, Washing Machine Good</a><br />
Leisa Reichelt&#8217;s IA Summit 07 presentation on the role of IA in the design process identifies the failures of a waterfall design process and argues that an agile, iterative design process is superior. Slide 14 is right on.</p>
<p><a href="http://www.agilemodeling.com/essays/agileUsability.htm">User Experience Activities on Agile Development Projects</a><br />
Recent article by Scott Ambler addresses the gap between Beck and Cooper by identifying a middle ground that requires UX and agile practitioners to learn a bit more about each others&#8217; practices and to adopt some of each.</p>
<p><a href="http://agileproductdesign.com/blog/index.html">Holistic Product Design &amp; Development</a><br />
A series of blog posts by Jeff Patton on agile software development and user centered design. Jeff moderates the <span class="nobr"><a href="http://tech.groups.yahoo.com/group/agile-usability/">agile-usability Yahoo group</a></span>.</p>
<p><a href="http://tech.groups.yahoo.com/group/agile-usability/">Agile Usability Yahoo! Group</a><br />
The description for this group provides a good summary of the issues we are tackling here. You are invited to jump into the fray.</p>
<p><a href="http://www.agilelogic.com/files/ExperiencesIntegratingUEDPractices.pdf">Experiences Integrating UED Practices</a><br />
In this experience report Paul Hodgetts presents his &#8220;teams&#8217; struggles to come to grips with the often programming-centric orientation of agile processes, and their ongoing efforts to integrate their UED (user experience design) best practices into the incremental, collaborative world of agile processes.&#8221; He provides an overview to the range of UX practices, identifies challenges and discusses practices that he found were particularly useful in integrating UX and and agile development.</p>
<p><a href="http://lists.interactiondesigners.com/htdig.cgi/discuss-interactiondesigners.com/2004-March/001083.html">Agile User-Centered Design</a><br />
A post to ID-discuss that presents one designer&#8217;s struggle to reconcile agile and user-centered design.</p>
<p><a href="http://www.foruse.com/articles/agiledesign.pdf">Process Agility and Software Usability: Toward Lightweight Usage-Centered Design</a><br />
2001 paper by Larry Constantine presents concrete practices for UX that map to agile practices. His approach is simple and pragmatic.</p>
<p><a href="http://www.slideshare.net/theinfonaut/are-agile-projects-doomed-to-halfbaked-design/">The Challenge of Agile Design</a><br />
These are slides from a talk given by our friends at Pivotal Labs and Satisfaction.</p>
<p><a href="http://agiletoolkit.libsyn.com/index.php?post_id=15584">User Centered Design Round Table</a><br />
Podcast of a discussion on user-centered design and agile development with Lynn Miller, Jeff Patton and Rebecca Wirfs-Brock.</p>
<p><i>Originally posted 2007-09-06</i><br />
<i>Last updated 2008-02-14</i></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2007/09/flexflash/agile-user-experience-ux-resources/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
