<?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/" version="2.0">

<channel>
	<title>Richard Lawrence</title>
	
	<link>http://www.richardlawrence.info</link>
	<description>On making software teams happier and more productive</description>
	<lastBuildDate>Fri, 07 Jun 2013 13:38:03 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/RichardLawrence" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="richardlawrence" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">RichardLawrence</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Splitting Stories in Spanish (or, Como Dividir una Historia de Usuario)</title>
		<link>http://www.richardlawrence.info/2013/06/03/splitting-stories-in-spanish-or-como-dividir-una-historia-de-usuario/</link>
		<comments>http://www.richardlawrence.info/2013/06/03/splitting-stories-in-spanish-or-como-dividir-una-historia-de-usuario/#comments</comments>
		<pubDate>Tue, 04 Jun 2013 00:00:00 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=461</guid>
		<description><![CDATA[Thanks to Joserra Díaz for the translation (with feedback from Matin Alaimo and Alan Cyment). This poster is also available in English, French, German, and Russian. You&#8217;re welcome to print copies for personal use. For more information, see the original story splitting patterns post.]]></description>
				<content:encoded><![CDATA[<p></p><p>Thanks to <a href="https://twitter.com/joserra_diaz">Joserra Díaz</a> for the translation (with feedback from <a href="https://twitter.com/martinalaimo">Matin Alaimo</a> and <a href="https://twitter.com/acyment">Alan Cyment</a>). <span id="more-461"></span></p>
<p><a href="http://www.richardlawrence.info/wp-content/uploads/2013/06/Story-Splitting-Flowchart-ES.pdf"><img src="http://www.richardlawrence.info/wp-content/uploads/2013/06/Story-Splitting-Flowchart-ES-Thumbnail.png" alt="Story Splitting Flowchart ES" width="669" height="433" class="alignnone size-full wp-image-463" /></a></p>
<p>This poster is also available in <a href="http://www.richardlawrence.info/2012/01/27/new-story-splitting-resource/" title="Story Splitting Flowchart">English</a>, <a href="http://www.richardlawrence.info/2013/02/26/splitting-stories-in-french/" title="Splitting Stories in French (or, Comment découper un récit utilisateur)">French</a>, <a href="http://www.richardlawrence.info/2012/08/24/splitting-stories-in-german-or-user-stories-aufteilen/" title="Splitting Stories in German (or, User Stories Aufteilen)">German</a>, and <a href="http://www.richardlawrence.info/2013/05/21/story-splitting-in-russian/" title="Story Splitting in Russian (or, Как Разделять Истории Пользователей)">Russian</a>. You&#8217;re welcome to print copies for personal use. </p>
<p>For more information, see <a href="http://www.richardlawrence.info/2009/10/28/patterns-for-splitting-user-stories/" title="Patterns for Splitting User Stories">the original story splitting patterns post</a>.</p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/5GNlgxPIlJE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2013/06/03/splitting-stories-in-spanish-or-como-dividir-una-historia-de-usuario/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Story Splitting in Russian (or, Как Разделять Истории Пользователей)</title>
		<link>http://www.richardlawrence.info/2013/05/21/story-splitting-in-russian/</link>
		<comments>http://www.richardlawrence.info/2013/05/21/story-splitting-in-russian/#comments</comments>
		<pubDate>Wed, 22 May 2013 01:41:16 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=457</guid>
		<description><![CDATA[Thanks to Alexander Lutsaevsky for the translation. This poster is also available in English, French, German, and Spanish. You&#8217;re welcome to print copies for personal use. For more information, see the original story splitting patterns post.]]></description>
				<content:encoded><![CDATA[<p></p><p>Thanks to <a href="http://www.linkedin.com/in/aluts">Alexander Lutsaevsky</a> for the translation.<span id="more-457"></span></p>
<p><a href="http://www.richardlawrence.info/wp-content/uploads/2013/05/Story-Splitting-Flowchart-RUS.pdf"><img src="http://www.richardlawrence.info/wp-content/uploads/2013/05/Story-Splitting-Flowchart-RUS-Thumbnail.png" alt="Как Разделять Истории Пользователей" width="669" height="433" class="alignnone size-full wp-image-459" /></a></p>
<p>This poster is also available in <a href="http://www.richardlawrence.info/2012/01/27/new-story-splitting-resource/" title="Story Splitting Flowchart">English</a>, <a href="http://www.richardlawrence.info/2013/02/26/splitting-stories-in-french/" title="Splitting Stories in French (or, Comment découper un récit utilisateur)">French</a>,  <a href="http://www.richardlawrence.info/2012/08/24/splitting-stories-in-german-or-user-stories-aufteilen/" title="Splitting Stories in German (or, User Stories Aufteilen)">German</a>, and <a href="http://www.richardlawrence.info/2013/06/03/splitting-stories-in-spanish-or-como-dividir-una-historia-de-usuario/" title="Splitting Stories in Spanish (or, Como Dividir una Historia de Usuario)">Spanish</a>. You&#8217;re welcome to print copies for personal use. </p>
<p>For more information, see <a href="http://www.richardlawrence.info/2009/10/28/patterns-for-splitting-user-stories/" title="Patterns for Splitting User Stories">the original story splitting patterns post</a>.</p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/k8BsvobmUzw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2013/05/21/story-splitting-in-russian/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Splitting Stories in French (or, Comment découper un récit utilisateur)</title>
		<link>http://www.richardlawrence.info/2013/02/26/splitting-stories-in-french/</link>
		<comments>http://www.richardlawrence.info/2013/02/26/splitting-stories-in-french/#comments</comments>
		<pubDate>Tue, 26 Feb 2013 13:32:05 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[product management]]></category>
		<category><![CDATA[Product Owner]]></category>
		<category><![CDATA[user stories]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=450</guid>
		<description><![CDATA[Thanks to Jean-Jacques Lévesque, my &#8220;How to Split a User Story&#8221; poster is now available in French. Click the thumbnail below to get the PDF. This poster is also available in English, German,Russian, and Spanish. You&#8217;re welcome to print copies for personal use. For more information, see the original story splitting patterns post.]]></description>
				<content:encoded><![CDATA[<p></p><p>Thanks to <a href="http://InCycleSoftware.com">Jean-Jacques Lévesque</a>, my <a href="/2012/01/27/new-story-splitting-resource/" title="New Story Splitting Resource">&#8220;How to Split a User Story&#8221; poster</a> is now available in French. <span id="more-450"></span></p>
<p>Click the thumbnail below to get the PDF.</p>
<p><a href="/wp-content/uploads/2013/02/Story-Splitting-Flowchart-FR.pdf"><img src="/wp-content/uploads/2013/02/Story-Splitting-Flowchart-FR.png" alt="Comment découper un récit utilisateur" width="669" height="433" class="alignnone size-full wp-image-451" /></a></p>
<p>This poster is also available in <a href="http://www.richardlawrence.info/2012/01/27/new-story-splitting-resource/" title="Story Splitting Flowchart">English</a>, <a href="http://www.richardlawrence.info/2012/08/24/splitting-stories-in-german-or-user-stories-aufteilen/" title="Splitting Stories in German (or, User Stories Aufteilen)">German</a>,<a href="http://www.richardlawrence.info/2013/05/21/story-splitting-in-russian/" title="Story Splitting in Russian (or, Как Разделять Истории Пользователей)">Russian</a>, and <a href="http://www.richardlawrence.info/2013/06/03/splitting-stories-in-spanish-or-como-dividir-una-historia-de-usuario/" title="Splitting Stories in Spanish (or, Como Dividir una Historia de Usuario)">Spanish</a>. You&#8217;re welcome to print copies for personal use. </p>
<p>For more information, see <a href="http://www.richardlawrence.info/2009/10/28/patterns-for-splitting-user-stories/" title="Patterns for Splitting User Stories">the original story splitting patterns post</a>.</p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/oBqAa8n8Rm4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2013/02/26/splitting-stories-in-french/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Functional Managers in Agile</title>
		<link>http://www.richardlawrence.info/2012/11/19/functional-managers-in-agile/</link>
		<comments>http://www.richardlawrence.info/2012/11/19/functional-managers-in-agile/#comments</comments>
		<pubDate>Mon, 19 Nov 2012 21:29:32 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=446</guid>
		<description><![CDATA[As an organization transforms to an agile way of working, functional managers (e.g. a dev manager or a test manager) can feel lost. Many of their traditional responsibilities move to other roles or disappear altogether. How can functional managers continue to add value in an agile organization? Here are a few ideas&#8230; Build a community [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>As an organization transforms to an agile way of working, functional managers (e.g. a dev manager or a test manager) can feel lost. Many of their traditional responsibilities move to other roles or disappear altogether.</p>
<p>How can functional managers continue to add value in an agile organization? Here are a few ideas&#8230;<span id="more-446"></span></p>
<ol>
<li>Build a community of practice for the function across multiple agile teams. This allows lessons learned by the testers on one team to spread to testers on the others. It makes it more natural for developers on one team to seek help from developers on another.</li>
<li>Provide training and other skill development opportunities and resources across teams.</li>
<li>Take a strategic view on the function. Look across multiple teams&#8217; product road maps and evaluate how well the current skills and knowledge match future needs. Take steps to fix any gaps (i.e. through training, hiring, etc.).</li>
<li>Help team members, HR, etc. align functional, team, and organizational measurements, goals, etc. For example, agile teams often see the best results when team members are willing to work across specialties as needed. But traditional metrics and goals might penalize a developer for helping with testing. Functional managers can help break down these disincentives to collaboration.</li>
<li>Continue to take care of personnel responsibilities such as performance reviews, hiring, and firing. However, because functional managers are likely to have less direct, day-to-day interaction with employees, they need more input from Scrum team members to do these than they might have in the past.</li>
</ol>
<p>Are you a functional manager in an agile organization? How has your role changed? How do you add value now? Share in the comments.</p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/pFEY3Hb9GS8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2012/11/19/functional-managers-in-agile/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Splitting Stories in German (or, User Stories Aufteilen)</title>
		<link>http://www.richardlawrence.info/2012/08/24/splitting-stories-in-german-or-user-stories-aufteilen/</link>
		<comments>http://www.richardlawrence.info/2012/08/24/splitting-stories-in-german-or-user-stories-aufteilen/#comments</comments>
		<pubDate>Fri, 24 Aug 2012 16:29:37 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=440</guid>
		<description><![CDATA[Thanks to translation from Kai Simons, my &#8220;How to Split a User Story&#8221; flowchart is now available in German. Click the thumbnail below to download the full-size PDF version. This poster is also available in English, French, Russian, and Spanish. You&#8217;re welcome to print copies for personal use. For more information, see the original story [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>Thanks to translation from <a href="http://agilist.de/">Kai Simons</a>, my <a href="http://www.richardlawrence.info/2012/01/27/new-story-splitting-resource/" title="New Story Splitting Resource">&#8220;How to Split a User Story&#8221; flowchart</a> is now available in German. <span id="more-440"></span></p>
<p>Click the thumbnail below to download the full-size PDF version.</p>
<p><a href='http://www.richardlawrence.info/wp-content/uploads/2012/08/Story-Splitting-Flowchart-DE.pdf'><img src="http://www.richardlawrence.info/wp-content/uploads/2012/08/Story-Splitting-Flowchart-DE-Thumbnail.png" alt="" title="User Stories Aufteilen" width="669" height="433" class="alignnone size-full wp-image-441" /></a></p>
<p>This poster is also available in <a href="http://www.richardlawrence.info/2012/01/27/new-story-splitting-resource/" title="Story Splitting Flowchart">English</a>, <a href="http://www.richardlawrence.info/2013/02/26/splitting-stories-in-french/" title="Splitting Stories in French (or, Comment découper un récit utilisateur)">French</a>,  <a href="http://www.richardlawrence.info/2013/05/21/story-splitting-in-russian/" title="Story Splitting in Russian (or, Как Разделять Истории Пользователей)">Russian</a>, and <a href="http://www.richardlawrence.info/2013/06/03/splitting-stories-in-spanish-or-como-dividir-una-historia-de-usuario/" title="Splitting Stories in Spanish (or, Como Dividir una Historia de Usuario)">Spanish</a>. You&#8217;re welcome to print copies for personal use. </p>
<p>For more information, see <a href="http://www.richardlawrence.info/2009/10/28/patterns-for-splitting-user-stories/" title="Patterns for Splitting User Stories">the original story splitting patterns post</a>.</p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/Frbd6F8TW3s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2012/08/24/splitting-stories-in-german-or-user-stories-aufteilen/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>New Story Splitting Resource</title>
		<link>http://www.richardlawrence.info/2012/01/27/new-story-splitting-resource/</link>
		<comments>http://www.richardlawrence.info/2012/01/27/new-story-splitting-resource/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 18:41:27 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[product management]]></category>
		<category><![CDATA[Product Owner]]></category>
		<category><![CDATA[user stories]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=421</guid>
		<description><![CDATA[More than two years after I originally published it, &#8220;Patterns for Splitting User Stories&#8221; remains one of the most visited posts on my blog. Splitting user stories continues to be one of the areas where the teams I work with most often need coaching. To support the teams I coach, I&#8217;ve created a flow chart [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>More than two years after I originally published it, <a href="/2009/10/28/patterns-for-splitting-user-stories/">&#8220;Patterns for Splitting User Stories&#8221;</a> remains one of the most visited posts on my blog. Splitting user stories continues to be one of the areas where the teams I work with most often need coaching. </p>
<p>To support the teams I coach, I&#8217;ve created a flow chart that goes through the questions I&#8217;ll ask when I&#8217;m helping a team split their stories.<span id="more-421"></span> I was going to keep this resource for my coaching clients, but I&#8217;ve decided to share it here for free. Click the thumbnail below to download the full-size PDF version.</p>
<p><a href='/wp-content/uploads/2012/01/Story-Splitting-Flowchart.pdf'><img src="/wp-content/uploads/2012/01/Story-Splitting-Flowchart-Thumbnail.png" alt="" title="&quot;How to Split a User Story&quot; Flowchart" width="669" height="438" class="aligncenter size-full wp-image-422" /></a></p>
<p>Let me know in the comments if you find this useful. If you can share them, I&#8217;d love to see examples of how you&#8217;ve used it, what the stories looked like before and after splitting. You&#8217;re welcome to print copies for personal use.</p>
<p>Update: This poster is now also available in <a href="http://www.richardlawrence.info/2012/08/24/splitting-stories-in-german-or-user-stories-aufteilen/" title="Splitting Stories in German (or, User Stories Aufteilen)">German</a>, <a href="http://www.richardlawrence.info/2013/02/26/splitting-stories-in-french/" title="Splitting Stories in French (or, Comment découper un récit utilisateur)">French</a>, <a href="http://www.richardlawrence.info/2013/05/21/story-splitting-in-russian/" title="Story Splitting in Russian (or, Как Разделять Истории Пользователей)">Russian</a>, and <a href="http://www.richardlawrence.info/2013/06/03/splitting-stories-in-spanish-or-como-dividir-una-historia-de-usuario/" title="Splitting Stories in Spanish (or, Como Dividir una Historia de Usuario)">Spanish</a>.</p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/VTitbk7ZXJk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2012/01/27/new-story-splitting-resource/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Coaching Surgeons, Cyclists, and Software Teams</title>
		<link>http://www.richardlawrence.info/2012/01/11/coaching-surgeons-cyclists-and-software-teams/</link>
		<comments>http://www.richardlawrence.info/2012/01/11/coaching-surgeons-cyclists-and-software-teams/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 17:26:56 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[coaching]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=411</guid>
		<description><![CDATA[Atul Gawande is a surgeon and author who has written some excellent books and New Yorker articles reflecting on the state of modern medicine. Recently, his writing has gone beyond medicine in interesting ways. As he looks for lessons for medicine from other disciplines, he ends up with things to teach both medical professionals and [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>Atul Gawande is a surgeon and author who has written some excellent books and New Yorker articles reflecting on the state of modern medicine. Recently, his writing has gone beyond medicine in interesting ways. As he looks for lessons for medicine from other disciplines, he ends up with things to teach both medical professionals and skilled knowledge workers more generally. His book <a href="http://amzn.com/0805091742"><em>The Checklist Manifesto</em></a> manages to be a riveting 224 pages on what ought to be one of the least interesting topics possible: the checklist.</p>
<p>So I was intrigued to see a link to <a href="http://www.newyorker.com/reporting/2011/10/03/111003fa_fact_gawande?mbid=social_retweet&#038;currentPage=all">a New Yorker article from Dr. Gawande on my own specialty, coaching</a>. It&#8217;s as good as I might have hoped.<span id="more-411"></span> Noticing that his own performance as a surgeon seems to have plateaued, he wonders whether a brief experience with a tennis coach might apply to surgery:</p>
<blockquote><p>
One July day a couple of years ago, when I was at a medical meeting in Nantucket, I had an afternoon free and went looking for someone to hit with. I found a local tennis club and asked if there was anyone who wanted to play. There wasn’t. I saw that there was a ball machine, and I asked the club pro if I could use it to practice ground strokes. He told me that it was for members only. But I could pay for a lesson and hit with him.</p>
<p>He was in his early twenties, a recent graduate who’d played on his college team. We hit back and forth for a while. He went easy on me at first, and then started running me around. I served a few points, and the tennis coach in him came out. You know, he said, you could get more power from your serve.</p>
<p>I was dubious. My serve had always been the best part of my game. But I listened. He had me pay attention to my feet as I served, and I gradually recognized that my legs weren’t really underneath me when I swung my racquet up into the air. My right leg dragged a few inches behind my body, reducing my power. With a few minutes of tinkering, he’d added at least ten miles an hour to my serve. I was serving harder than I ever had in my life.</p>
<p>Not long afterward, I watched Rafael Nadal play a tournament match on the Tennis Channel. The camera flashed to his coach, and the obvious struck me as interesting: even Rafael Nadal has a coach. Nearly every élite tennis player in the world does. Professional athletes use coaches to make sure they are as good as they can be.</p>
<p>But doctors don’t. I’d paid to have a kid just out of college look at my serve. So why did I find it inconceivable to pay someone to come into my operating room and coach me on my surgical technique?
</p></blockquote>
<p>The rest of the article wanders through a history of coaching; interesting examples from sports, music, and education; and describes his own experience engaging a coach. He concludes,</p>
<blockquote><p>
There was a moment in sports when employing a coach was unimaginable—and then came a time when not doing so was unimaginable. We care about results in sports, and if we care half as much about results in schools and in hospitals we may reach the same conclusion.
</p></blockquote>
<p>I value coaching enough to spend my own money on it. I&#8217;ve hired a mountain bike coach, <a href="http://www.leelikesbikes.com/">Lee McCormack</a>, to help me prepare for this summer&#8217;s <a href="http://trestlebikepark.com/enduro.html">Trestle All Mountain Enduro race</a>. It&#8217;ll be my first downhill race. I don&#8217;t expect to win, but I want to get a result I can be happy about and enjoy the experience.</p>
<p>I used to do cross-country mountain bike races, and I have a pretty good idea how to train for an event. I have Lee&#8217;s books. I could probably do this on my own. But I know from my own experience as a software development coach how much faster a good coach can help you improve.</p>
<p><div class="wp-caption alignright" style="width: 320px">
	<a href="http://www.leelikesbikes.com/testing-my-pump-track.html"><img alt="Lee McCormack on his backyard pump track" src="http://www.leelikesbikes.com/wp-content/pump13.jpg" title="Lee McCormack on his backyard pump track" width="320" /></a>
	<p class="wp-caption-text">Lee McCormack on his backyard pump track</p>
</div>I started working with Lee yesterday morning. We spent a couple hours working on basic pumping and cornering skills on his pump track and practicing seated and standing pedaling on the roads around his house in the Boulder foothills. Lee would demonstrate a technique. I&#8217;d try it. He&#8217;d give me feedback. I&#8217;d try it again. He&#8217;d modify the exercise to focus on whatever I was struggling with, and I&#8217;d ride a bit more. </p>
<p>After just two hours of coaching—working on things I would have said I already knew how to do—I could see a marked improvement in my skills. And I had a nice list of things to practice on my own.</p>
<p>This brings me back around to software development. Our world today runs on software. But most software teams struggle to deliver anywhere near as quickly and reliably as they could. A software profession living up to its potential would transform the world. <strong>So, to paraphrase Gawande: If we care half as much about results in software development as we do in sports, how is it imaginable that so few teams engage a coach? How is it imaginable that so many teams with access to coaching fail to make the most of it?</strong></p>
<p>What about your team? Do you have a coach? If so, do you make the most of the coaching you have available to you? </p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/cynih-Z9wIo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2012/01/11/coaching-surgeons-cyclists-and-software-teams/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cucumber Tip: IRB From Inside a Step Definition</title>
		<link>http://www.richardlawrence.info/2011/12/07/cucumber-tip-irb-from-inside-a-step-definition/</link>
		<comments>http://www.richardlawrence.info/2011/12/07/cucumber-tip-irb-from-inside-a-step-definition/#comments</comments>
		<pubDate>Wed, 07 Dec 2011 20:05:35 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Cucumber]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=401</guid>
		<description><![CDATA[Most Ruby programmers know about Ruby&#8217;s interactive console, IRB. (If you don&#8217;t, stop right here, open up a command window and run irb. Type some Ruby code. See how it returns the result of each line right away.) IRB is great for poking around with unfamiliar libraries. Suppose you&#8217;re using Capybara with Cucumber for the [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>Most Ruby programmers know about Ruby&#8217;s interactive console, IRB. (If you don&#8217;t, stop right here, open up a command window and run <code class="codecolorer text default"><span class="text">irb</span></code>. Type some Ruby code. See how it returns the result of each line right away.) IRB is great for poking around with unfamiliar libraries.</p>
<p>Suppose you&#8217;re using Capybara with Cucumber for the first time. It would be nice to use IRB to experiment with what Capybara can do on a particular page. You could launch an IRB session and duplicate all the Capybara setup from your Cucumber <code class="codecolorer text default"><span class="text">support/env.rb</span></code> file. But wouldn&#8217;t it be nice if you could just fire up IRB in the context of a step definition so you know everything in your IRB session matches what you&#8217;d get in the step def? Turns out you can. Here&#8217;s how&#8230;<span id="more-401"></span></p>
<p>Install the ruby-debug gem. If you&#8217;re using Ruby 1.9 like me, you need the ruby-debug19 gem. In Rails 3, just add <code class="codecolorer text default"><span class="text">gem ruby-debug19</span></code> to your Gemfile, probably in the test group, and run <code class="codecolorer text default"><span class="text">bundle install</span></code>.</p>
<p>Require ruby-debug in <code class="codecolorer text default"><span class="text">support/env.rb</span></code>.</p>
<p>Add <code class="codecolorer text default"><span class="text">breakpoint</span></code> where you want to jump into IRB. For example:</p>
<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Given <span style="color:#006600; font-weight:bold;">/</span>^I am on the advanced search page$<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; visit <span style="color:#996600;">'http://http://www.google.com/advanced_search'</span><br />
&nbsp; breakpoint<br />
&nbsp; <span style="color:#006666;">0</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>(Note the extra line after <code class="codecolorer text default"><span class="text">breakpoint</span></code> with <code class="codecolorer text default"><span class="text">0</span></code> on it. <code class="codecolorer text default"><span class="text">breakpoint</span></code> breaks before executing the next line, so if it&#8217;s the last thing in a block, you won&#8217;t jump into the debugger in the context you expect; <code class="codecolorer text default"><span class="text">0</span></code> is a dummy line to keep us in the right context.)</p>
<p>Run Cucumber like normal. When it reaches <code class="codecolorer text default"><span class="text">breakpoint</span></code>, ruby-debug will take over, and you&#8217;ll see a prompt like this: <code class="codecolorer text default"><span class="text">(rdb:1)</span></code>.</p>
<p>You can do a lot of different things at this prompt, but we only care about one right now: type <code class="codecolorer text default"><span class="text">irb</span></code> and hit Enter. Now you should see a an IRB prompt. You&#8217;re in the context of a Cucumber step definition. Type <code class="codecolorer text default"><span class="text">self</span></code> and hit Enter. You&#8217;ll see that <code class="codecolorer text default"><span class="text">self</span></code> is an instance of Cucumber&#8217;s World with various things mixed in. From here, you can do anything you would do inside that step definition.</p>
<p>When you&#8217;re done, run <code class="codecolorer text default"><span class="text">quit</span></code> to get out of IRB and <code class="codecolorer text default"><span class="text">continue</span></code> to get out of the debugger. Cucumber execution will continue like normal. Keep in mind, though, that if you change the state of your system from IRB, you might not get the test results you expect.</p>
<p>Enhancements and variations for you to explore:</p>
<ul>
<li>Make IRB nicer to use with gems such as irbtools</li>
<li>Create a step definition just for launching the debugger</li>
<li>Create a tagged scenario just for launching the debugger</li>
</ul>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/ze2ENODZ5BE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2011/12/07/cucumber-tip-irb-from-inside-a-step-definition/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Building a Useful Task Board</title>
		<link>http://www.richardlawrence.info/2011/11/21/building-a-useful-task-board/</link>
		<comments>http://www.richardlawrence.info/2011/11/21/building-a-useful-task-board/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 16:42:55 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=388</guid>
		<description><![CDATA[The task board is a simple, yet powerful, tool for Scrum teams. As a coach, I can tell a lot about a team just by looking at their task board in the middle of a sprint. If your Scrum team is in the same location, I can&#8217;t think of a good reason why you wouldn&#8217;t [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>The task board is a simple, yet powerful, tool for Scrum teams. As a coach, I can tell a lot about a team just by looking at their task board in the middle of a sprint. If your Scrum team is in the same location, I can&#8217;t think of a good reason why you wouldn&#8217;t want to build and use a task board.</p>
<p>Here&#8217;s how to build a basic task board, various ways to enhance it to convey more information, and some analysis of the many things you can learn from this simple tool.<span id="more-388"></span></p>
<h2>Supplies Required</h2>
<ul>
<li>A black or blue poster marker</li>
<li>A black fine tip marker</li>
<li><a href="http://amzn.com/B0002DOF7E">3 inch square Super Sticky Post-It notes in yellow</a> (generic sticky notes tend not to stick for a whole sprint)</li>
<li>A large surface (e.g. whiteboard, foam core, smooth wall, etc.)</li>
</ul>
<h2>Optional Supplies</h2>
<ul>
<li>Blue and red fine tip markers</li>
<li>Two 1&#8243; photos of each team member</li>
<li><a href="http://amzn.com/B000YD1XNG">Larger sticky notes in another color</a> such as blue or green</li>
<li>Square or small sticky notes in orange or red</li>
<li>Removable, semi-transparent color dot stickers</li>
<li>Narrow electrical tape</li>
<li><a href="/2009/12/21/growing-done-how-to-make-the-definition-of-done-work-for-your-team/">Story Definition of Done</a> printed as checklists</li>
<li><a href="http://amzn.com/B00006IFBO">Post-It glue stick</a></li>
<li>Blue masking tape</li>
</ul>
<h2>Basic setup and use</h2>
<p>Make sure you place your task board where the team will use it. Ideally, the team is in a team room together and the board is in the same room. At the very least, it should be in a place where the team will see it several times a day. It&#8217;s very valuable to use the board to focus the Daily Scrum, so there should be enough space for the whole team to stand around it.</p>
<p>On your task board surface, mark out the following columns with marker or tape: Story, Not Started, In Progress, Done.</p>
<p>Create a card (on a sticky note) for each story you committed to in the current sprint. If you have two colors of stickies or a larger sticky available, use that for the stories. Use the black fine marker to write a title for the story in large, clear print. If the story is in the typical &#8220;As a <user>, I want <feature> so that <value>&#8221; format, you&#8217;ll want to shorten it to a 3-6 word title. You can write the full story on the card with a pen if you want. Write the story point estimate on the card, in a different color marker if you have one. The story titles on the cards should be readable from about 6 feet away. Arrange the story cards in priority order in the first column, leaving space between them. Each story thus defines a horizontal lane across the board. (I don&#8217;t recommend drawing or taping horizontal lines, though; different stories need different amounts of space at different times.)</p>
<p>Create a card for each task you&#8217;ve defined. Again, use the black fine marker and a short title to make them readable from 3-6 feet away. Arrange the tasks in the Not Started column with their corresponding story.</p>
<p>Some teams generate all or most of their tasks at sprint planning. Some generate tasks as they start a story or just-in-time. Still others don&#8217;t use tasks at all. If you generate tasks throughout the sprint, you can expand and contract the story lanes to make room for tasks as needed. If you don&#8217;t use tasks, you&#8217;ll want to eliminate the Story column and move the story cards through the other three columns.</p>
<p>Tasks will almost always be placed on the board in the Not Started column. As a team member assigns a task to himself, he&#8217;ll write his name or initials on the card and move the card into the In Progress column. When the task is done, he&#8217;ll move it into the Done column and likely choose another task to start.</p>
<p>The basic board should look something like this:</p>
<p><img src="/wp-content/uploads/2011/11/basic-task-board.png" alt="" title="Basic Scrum Task Board" width="660" height="400" class="alignnone size-full wp-image-394" /></p>
<h2>Enhancements and variations</h2>
<p>If you have photos for each team member, attach them to small sticky notes or put Post-It glue on the back. Place the photo stickies on the edge of the board to indicate team members available for tasks. I suggest only making one sticky per person readily available. You can have a second sticky available for the rare times a task is blocked and they need to work on a second task. Instead of writing their names on tasks, team members will use their photo to indicate task assignments.</p>
<p>Make a half- or quarter-page checklist for your story definition of done. Print a stack of them. Place one on the board for each story and use it to make sure you generate the right tasks and actually reach done for the story.</p>
<p>If you regularly get work outside your sprint commitment that has to be addressed right away, such as production support, consider adding an &#8220;Expedite&#8221; lane above the first story. When something new appears in the Not Started column on the Expedite lane, the team focuses on that item rather than stories in order to get it done as soon as possible. (If the &#8220;urgent&#8221; item doesn&#8217;t trump the other stories, it probably should be added to the product backlog and wait until a future sprint, so this rule is a good way to distinguish between truly urgent work and someone just trying to change the team&#8217;s priorities mid-sprint.)</p>
<p>Use the red or orange stickies to represent impediments. Place them directly on the items they&#8217;re blocking. This avoids the disconnect between an impediment list and the task board and may explain otherwise strange indications on the board (e.g. a high-priority story in progress while low-priority stories get done).</p>
<p>Use different color cards or dots on cards to indicate themes, larger features, dependencies on other teams, etc. </p>
<p>Consider setting a WIP limit, a restriction on the number of stories you can have in progress at once. Post this number in the header of the In Progress column. Note: It&#8217;s helpful to write &#8220;limit 3 stories&#8221; rather than just &#8220;3&#8243; because you&#8217;re limiting the number of stories in progress even though the column actually contains tasks.</p>
<h2>What the task board can tell you</h2>
<p><strong>What have we committed to?</strong> The stories on the left of the board reflect the team&#8217;s commitment for the sprint. Because they&#8217;re readable at the 6&#8242; distance, someone can see the overall commitment at a glance.</p>
<p><strong>What&#8217;s done?</strong> Assuming you&#8217;ve created all the tasks for a story to get done, the presence of all a story&#8217;s task cards in the Done column indicates that the story is done.</p>
<p><strong>What are we currently working on?</strong> The presence of task cards in In Progress indicates that the team is currently working on the corresponding story.</p>
<p><strong>Are we working on the right things?</strong> Since stories on the task board are ordered according to their priority in the product backlog, the top stories should be getting to done first. If stories in the middle or at the bottom of the board are done while stories at the top are not started or in-progress, this can indicate a problem. For example, maybe there&#8217;s an impediment blocking a high-priority story but no one is talking about it.</p>
<p><strong>Are we working together?</strong> The number of stories in progress and the distribution of names reveals whether the team is collaborating or whether each team member is working on her own story.</p>
<p><strong>What&#8217;s blocked?</strong> If you use impediment stickies, you can see at a glance what&#8217;s blocked and make sure something is being done about the impediment.</p>
<p><strong>How much urgent/unplanned work is being added?</strong> If you use the Expedite lane, you can see by the accumulation of cards how much work has been added after the start of the sprint. This may lead the team to discuss with the Product Owner dropping one or more stories from the bottom of the board.</p>
<p><strong>What work should I do next?</strong> When you&#8217;re ready for a new task, the task board can tell you which stories are open so you can find a way to contribute to the highest priority open stories rather than opening a new story.</p>
<h2>Next steps</h2>
<p>Check out fellow CSC Xavier Quesada Allue&#8217;s <a href="http://www.xqa.com.ar/visualmanagement/">excellent blog on visual management</a>, which covers this topic in much more detail.</p>
<p>Share in the comments: How have you made the task board work better for your team? Which suggestions from above are you going to try? </p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/Sl5Ms0jgyYc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2011/11/21/building-a-useful-task-board/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cucumber Tip: Key-Value Tables</title>
		<link>http://www.richardlawrence.info/2011/10/27/cucumber-tip-key-value-tables/</link>
		<comments>http://www.richardlawrence.info/2011/10/27/cucumber-tip-key-value-tables/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 21:38:28 +0000</pubDate>
		<dc:creator>Richard Lawrence</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ATDD]]></category>
		<category><![CDATA[BDD]]></category>
		<category><![CDATA[Cucumber]]></category>

		<guid isPermaLink="false">http://www.richardlawrence.info/?p=375</guid>
		<description><![CDATA[You may not realize this: Tables in Cucumber steps don&#8217;t have to have a header row. Sometimes it can work really well to use a headerless table of key-value pairs. Let&#8217;s look at an example. Suppose we have a scenario that fills out an advanced search form to search for medical providers matching certain criteria. [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>You may not realize this: Tables in Cucumber steps don&#8217;t have to have a header row. Sometimes it can work really well to use a headerless table of key-value pairs. </p>
<p>Let&#8217;s look at an example. Suppose we have a scenario that fills out an advanced search form to search for medical providers matching certain criteria. A mockup of the form looks something like this:</p>
<p><img src="/wp-content/uploads/2011/10/medical-provider-advanced-search-form.png" alt="" title="Advanced Provider Search Mock-up" width="358" height="544" class="aligncenter size-full wp-image-378" /></p>
<p>If we were using the <a href="http://aslakhellesoy.com/post/11055981222/the-training-wheels-came-off">recently deprecated web steps</a> generated by cucumber-rails, we might write steps to perform a search like these:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Given I'm on the advanced search page<br />
And I select &quot;Endocrinology&quot; from &quot;Specialty&quot;<br />
And I choose &quot;Yes&quot; within &quot;Accepts Insurance&quot;<br />
And I fill in &quot;ZIP Code&quot; with &quot;90010&quot;<br />
And I select &quot;5 miles&quot; from &quot;Search Radius&quot;<br />
When I press &quot;Search&quot;</div></td></tr></tbody></table></div>
<p>But we know better than to do that, right? After all, we&#8217;re trying to describe how the search logic should work, not how the form should look. <span id="more-375"></span>So we try to write our own steps to do these same thing without talking about the implementation so much, but it&#8217;s really hard to get away from the implementation. Even if we drive out words like select, fill in, and click, we still have a step per form element. </p>
<p>Suppose we try to combine them into a single step for the domain concept of performing a search. We might get something like:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">When I search for an endocrinologist within 5 miles of 90010 who accepts insurance</div></td></tr></tbody></table></div>
<p>The implementation details are gone, but it&#8217;s long and hard to read. Enter the key-value table:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">When I search for a provider with the criteria:<br />
&nbsp;| Provider Type &nbsp; &nbsp; | Doctor &nbsp; &nbsp; &nbsp; &nbsp;|<br />
&nbsp;| Specialty &nbsp; &nbsp; &nbsp; &nbsp; | Endocrinology |<br />
&nbsp;| Accepts Insurance | Yes &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
&nbsp;| ZIP &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | 90010 &nbsp; &nbsp; &nbsp; &nbsp; |<br />
&nbsp;| Search Radius &nbsp; &nbsp; | 5 miles &nbsp; &nbsp; &nbsp; |</div></td></tr></tbody></table></div>
<p>In the step definition, we can use the <code class="codecolorer ruby default"><span class="ruby">rows_hash</span></code> method on the table object to convert that key-value table to a single hash. There&#8217;s no need to iterate through the rows ourselves. For example, assuming a helper method called <code class="codecolorer ruby default"><span class="ruby">provider_search</span></code> that actually performs the search,</p>
<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">When</span> <span style="color:#006600; font-weight:bold;">/</span>^I search <span style="color:#9966CC; font-weight:bold;">for</span> a provider with the criteria:$<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>table<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; criteria = table.<span style="color:#9900CC;">rows_hash</span><br />
&nbsp; provider_search <span style="color:#ff3333; font-weight:bold;">:provider_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Provider Type'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:specialty</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Specialty'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:accepts_insurance</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Accepts Insurance'</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_bool</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:zip_code</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'ZIP'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:radius</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Search Radius'</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_i</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>You may have noticed the call to <code class="codecolorer ruby default"><span class="ruby">to_bool</span></code>. This uses a helper method like the following to allow us to use <em>yes</em> and <em>no</em> instead of <em>true</em> and <em>false</em> to make more readable scenarios. Put this somewhere in the support directory.</p>
<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> to_bool<br />
&nbsp; &nbsp; !!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span> =~ <span style="color:#006600; font-weight:bold;">/</span>^yes<span style="color:#006600; font-weight:bold;">|</span>y<span style="color:#006600; font-weight:bold;">|</span><span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span><span style="color:#006666;">1</span>$<span style="color:#006600; font-weight:bold;">/</span>i<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>The call to <code class="codecolorer ruby default"><span class="ruby">to_i</span></code> on the search radius takes advantage of Ruby&#8217;s string to integer conversion behavior—if a string starts with an integer but has other text after the integer, the other text is stripped off during the conversion. Try it: Fire up <code class="codecolorer text default"><span class="text">irb</span></code> (the interactive Ruby console) in a command window and run <code class="codecolorer ruby default"><span class="ruby"><span style="color:#996600;">&quot;5 miles&quot;</span>.<span style="color:#9900CC;">to_i</span></span></code>.</p>
<p>These key-value tables can get long for a complex entity. Not all the details will matter each time. We can make the step read better by introducing a concept of a default provider search. Maybe we have to supply a ZIP code and search radius, but the scenario we&#8217;re working on is really about specialties and insurance. We could say,</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">When I search for a provider with the default criteria and:<br />
&nbsp;| Provider Type &nbsp; &nbsp; | Doctor &nbsp; &nbsp; &nbsp; &nbsp;|<br />
&nbsp;| Specialty &nbsp; &nbsp; &nbsp; &nbsp; | Endocrinology |<br />
&nbsp;| Accepts Insurance | Yes &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div></td></tr></tbody></table></div>
<p>In the step definition, we&#8217;ll declare the default values in a hash and merge it with the supplied values.</p>
<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">When</span> <span style="color:#006600; font-weight:bold;">/</span>^I search <span style="color:#9966CC; font-weight:bold;">for</span> a provider with the default criteria <span style="color:#9966CC; font-weight:bold;">and</span>:$<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>table<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; default_criteria = <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color:#996600;">'Provider Type'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Doctor'</span>,<br />
&nbsp; &nbsp; <span style="color:#996600;">'Specialty'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'General'</span>,<br />
&nbsp; &nbsp; <span style="color:#996600;">'Accepts Insurance'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Yes'</span>,<br />
&nbsp; &nbsp; <span style="color:#996600;">'ZIP'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">90010</span>,<br />
&nbsp; &nbsp; <span style="color:#996600;">'Search Radius'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'5 miles'</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
&nbsp; criteria = default_criteria.<span style="color:#9900CC;">merge</span><span style="color:#006600; font-weight:bold;">&#40;</span>table.<span style="color:#9900CC;">rows_hash</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; provider_search <span style="color:#ff3333; font-weight:bold;">:provider_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Provider Type'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:specialty</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Specialty'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:accepts_insurance</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Accepts Insurance'</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_bool</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:zip_code</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'ZIP'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:radius</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> criteria<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Search Radius'</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_i</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>If the defaults are well known, this is enough. If they need to be documented, one way I like to do it is as executable documentation with a scenario like this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Scenario: Default Search Criteria<br />
&nbsp; When I search for a provider with the default criteria<br />
&nbsp; Then the search criteria should include:<br />
&nbsp; &nbsp;| Provider Type &nbsp; &nbsp; | Doctor &nbsp; &nbsp; &nbsp; &nbsp;|<br />
&nbsp; &nbsp;| Specialty &nbsp; &nbsp; &nbsp; &nbsp; | General &nbsp; &nbsp; &nbsp; |<br />
&nbsp; &nbsp;| Accepts Insurance | Yes &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
&nbsp; &nbsp;| ZIP &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | 90010 &nbsp; &nbsp; &nbsp; &nbsp; |<br />
&nbsp; &nbsp;| Search Radius &nbsp; &nbsp; | 5 miles &nbsp; &nbsp; &nbsp; |</div></td></tr></tbody></table></div>
<p>If you do this, you&#8217;ll want to move the default criteria hash into a helper method or constant to make sure it&#8217;s the same hash used in the real scenario and the documentation scenario.</p>
<p>We could make the step definition read better by separating the key and value conversions from the use of the data. Cucumber&#8217;s table object has <code class="codecolorer ruby default"><span class="ruby">map_headers!</span></code> and <code class="codecolorer ruby default"><span class="ruby">map_column!</span></code>. Unfortunately, those don&#8217;t work for <code class="codecolorer ruby default"><span class="ruby">rows_hash</span></code> at this time. I recently submitted a pull request to make it work. Hopefully, we&#8217;ll see that in a Cucumber release soon.</p>
<img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/6MnXZEkS9wU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.richardlawrence.info/2011/10/27/cucumber-tip-key-value-tables/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	<item><title>Links for 2011-09-16 [del.icio.us]</title><link>http://del.icio.us/rslawrence/blog-this#2011-09-16</link><pubDate>Sat, 17 Sep 2011 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/rslawrence/blog-this#2011-09-16</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="None"&gt;None&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/AYB2_j7SPn8" height="1" width="1"/&gt;</description></item><item><title>Links for 2010-08-18 [del.icio.us]</title><link>http://del.icio.us/rslawrence/blog-this#2010-08-18</link><pubDate>Thu, 19 Aug 2010 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/rslawrence/blog-this#2010-08-18</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://findarticles.com/p/articles/mi_m1154/is_n10_v79/ai_11319024/pg_3/"&gt;Moving fast by standing still - Herbert D. Kelleher, Southwest Airlines - page 3 | Nation's Business&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/0zBqg4Y87gA" height="1" width="1"/&gt;</description></item><item><title>Links for 2007-08-03 [del.icio.us]</title><link>http://del.icio.us/rslawrence/blog-this#2007-08-03</link><pubDate>Sat, 04 Aug 2007 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/rslawrence/blog-this#2007-08-03</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.adaptivepath.com/blog/wp-content/uploads/2007/07/ambidextrous_article.pdf"&gt;Design lessons from the kitchen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://paulstovell.net/blog/index.php/we-are-what-we-repeatedly-code/"&gt;Great coders can&amp;rsquo;t write anything else&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/pBjRzCPO2EI" height="1" width="1"/&gt;</description></item><item><title>Links for 2007-07-24 [del.icio.us]</title><link>http://del.icio.us/rslawrence/blog-this#2007-07-24</link><pubDate>Wed, 25 Jul 2007 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/rslawrence/blog-this#2007-07-24</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://ridiculous.rubyforge.org/"&gt;Ridiculous&lt;/a&gt;&lt;br/&gt;
Ridiculous is a simple wrapper for del.icio.us API writing in Ruby.&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/RichardLawrence/~4/MtAKGwOXmbM" height="1" width="1"/&gt;</description></item></channel>
</rss>
