<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Software Greenhouses</title>
	<atom:link href="http://softwaregreenhouses.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://softwaregreenhouses.com</link>
	<description>Nurturing living abstractions...</description>
	<lastBuildDate>Fri, 27 Jan 2012 00:46:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='softwaregreenhouses.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://1.gravatar.com/blavatar/5c017217ffced956979f16f819f6d35b?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Software Greenhouses</title>
		<link>http://softwaregreenhouses.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://softwaregreenhouses.com/osd.xml" title="Software Greenhouses" />
	<atom:link rel='hub' href='http://softwaregreenhouses.com/?pushpress=hub'/>
		<item>
		<title>An Introduction to Outcome Driven Software (ODS)</title>
		<link>http://softwaregreenhouses.com/2012/01/26/an-introduction-to-outcome-driven-software-ods/</link>
		<comments>http://softwaregreenhouses.com/2012/01/26/an-introduction-to-outcome-driven-software-ods/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 21:07:46 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[ODS]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.com/?p=297</guid>
		<description><![CDATA[For the past year or so, I have been working on a new technique for creating software. I was frustrated with the disconnect between the efforts of development teams (both those I have been on and those I have helped manage) and the outcomes the software was providing when it was actually used. TDD and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=297&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>For the past year or so, I have been working on a new technique for creating software. I was frustrated with the disconnect between the efforts of development teams (both those I have been on and those I have helped manage) and the outcomes the software was providing when it was actually used.</p>
<p>TDD and other technical practices (exemplified by the Software Craftsmanship movement) are great for validating the correctness and quality of the code, but how do we establish the validity and quality of running software for its intended use? (No, I don&#8217;t believe ATDD solves that problem. I&#8217;ll dive into the differences in a bit).</p>
<p>Outcome Driven Software (ODS) represents a new way to create software. In short, it is a way to make software by first creating the demonstrative outcomes that will prove validity, then using those outcomes to drive the creation of the functional systems to support them.</p>
<p><span id="more-297"></span></p>
<p>Part process, part technique &#8211; ODS is still a journey, not a destination. My hope is that others can contribute to its refinement and evolution, as well as the production of tooling (similar to xUnit frameworks) that aid in the process.</p>
<h3>Change Your Perspective: Software Is Massless</h3>
<p>Before diving into the practical application, there are a few key concepts and insights I want to run by you. Much of this I have not seen mentioned elsewhere, if you know of other sources or pioneers of the past who have been here before, please let me know.</p>
<p>The first thing may seems obvious, but is not at all reflected in the habits of modern software development: software is what runs on hardware when it is used by its users. Please read that one more time.</p>
<p>It&#8217;s not about your code, your development process, your tests, your continuous integration or deployment, your build process, your stories, your fixtures, your methodology, your tools, your IDE or any of that stuff far removed from what it actually is and what&#8217;s really important and that&#8217;s those human beings sitting at the other end who use and live through what is actually your software.</p>
<p>I use the mantra &#8220;Software Is Massless&#8221; as a reminder that it&#8217;s electrons running through the CPU and I/O activity and impulses from input devices and to display devices &#8211; all being exercised by, or at the bequest of, users aka human beings. And what those humans want more than anything else from your software is positive emotional outcomes. They want to feel good about your software and they want to feel good knowing they got what they wanted out of your software.</p>
<p>Beyond validity, ODS is also designed to improve the <em>quality</em> of outcomes – moving beyond acceptable or satisfactory and instead delighting and exceeding expectations. Ultimately, the quality of software depends on the creativity and empathy of those involved in creating it. However, ODS structures the process to allow this to happen more freely and as an upfront requisite before system design.</p>
<p>ODS is complimentary to core XP technical practices, though it fundamentally changes the act of coding and largely reduces the amount of TDD required.</p>
<p>ODS <em>is</em> a replacement for Acceptance Test Driven Development (and other derivatives such as BDD and Specification by Example). The intense focus on stakeholder conversations and collaboration from these techniques is directly applicable. However, the practices are different in two regards:</p>
<ol>
<li>ODS creates running software instead of separate fixtures or artifacts that only run in the development shop and are not part of the software <strong><em>as it is used</em></strong>.</li>
<li>At the start, ODS explicitly avoids system design and focuses only on outcomes. In the “Given, When, Then” parlance of BDD, ODS starts by creating “Then” to the exclusion of “Given” and “When” which are created <em>from</em> &#8220;Then&#8221;.</li>
</ol>
<h3>Understanding the Difference between Functional and Demonstrative Parts of Technology</h3>
<p>One way to think about any technology is as a progression from inputs to outputs and then from outputs to outcomes.</p>
<p style="text-align:center;"><a href="http://softwaregreenhouses.files.wordpress.com/2012/01/input-output-outcome-simple.png"><img class="aligncenter size-medium wp-image-365" style="border-color:initial;border-style:initial;border-width:0;" title="input-output-outcome-simple" src="http://softwaregreenhouses.files.wordpress.com/2012/01/input-output-outcome-simple.png?w=136&#038;h=300" alt="" width="136" height="300" /></a></p>
<p>Realize though that the boxes and arrows are somewhat misleading because what we actually create are the arrows not the boxes:</p>
<p style="text-align:center;"><a href="http://softwaregreenhouses.files.wordpress.com/2012/01/input-output-outcome.png"><img class="size-medium wp-image-364 aligncenter" style="border-color:initial;border-style:initial;border-width:0;" title="Input-Output-Outcome" src="http://softwaregreenhouses.files.wordpress.com/2012/01/input-output-outcome.png?w=139&#038;h=300" alt="" width="139" height="300" /></a></p>
<p>The progression from input to output occurs through a functional mechanism (or functional system if you like). This translates quite easily into code, for example consider the following:</p>
<pre style="background:#FDF6E3;border:1px solid burlywood;padding:5px;">function add(a, b) { return a + b }</pre>
<p>Given an input of 1 and 2, the output will be 3. The “rightness” of input/output relationships is usually expressed via “test”:</p>
<pre>assert.equal(3, add(1,2))</pre>
<p>Understanding the progression from output to outcome can be more difficult. This is because the outcome exists at the intersection between the running software and its user(s). Meaning outcome can only be understood as running software, not as code. Expanding the add example:</p>
<pre class="code">function add(a, b) { return a+b }
var prompt = require('./console-prompt')
prompt(['First number:', 'Second number:'], function(addends){
   var a = addends[0], b = addends[1]
   console.log(a + ' + ' + b + ' = ' + add(a,b))
})</pre>
<p>it will yield the following when run:</p>
<pre class="console">C:\node\ods&gt;node add.js
First number: 1
Second number: 2
1 + 2 = 3</pre>
<p>Given the simplicity of this example, we can consider the entirity of the three lines:</p>
<pre class="code">First number: 1
Second number: 2
1 + 2 = 3</pre>
<p>to be the demonstrated outcome. But to simplify for a momment, let&#8217;s just look at the last line presented to the user:</p>
<pre class="code">1 + 2 = 3</pre>
<p>as the outcome. The demonstrative system (meaning the part of the software that produces this output to the console)  produces this &#8216;artifact&#8217; to provide validation of the outcome. This artifact of outcome can be judged qualitatively. It could have been:</p>
<pre style="background:#FDF6E3;border:1px solid burlywood;padding:5px;">Your answer is 3</pre>
<p>Or as is too often the case today, the output could also have been provided directly (technically the REPL facilities are being leveraged to deliver the outcome via an on-screen presentation of the number) with no attempt to consider outcome:</p>
<pre style="background:#FDF6E3;border:1px solid burlywood;padding:5px;">3</pre>
<p>In this very simple example as presented, this may be fine. But imagine the potential frustration if the originally provided addends were not visible and the user had to re-run the software. The important thing is the conversation and collaboration to discover the best demonstration the outcome. The ‘right’ thing to do is bound to context and focused conversation with users and stakeholders on the outcome reveals all the subtle nuances and details.</p>
<p>It is also very critical to realize that the discussion about outcome can occur <em>without the functional system</em>. This fact is exploited by ODS: outcomes are discussed and determined early on and the functional system is only built after the purpose of the software is understood.</p>
<p>[If you’re wondering about more complex software, ODS can be applied at multiple levels. Software systems, and system here includes input all the way through outcome, can have nested sub-systems.  For example, the prompt for addend can be thought of as a sub-system. This example is so simple there is hardly any difference between the output and outcome other than display of the number as it is produced.]</p>
<h3>The Outcome-First Process</h3>
<p>In the add example, as I mentioned, because it so simple we can consider the outcome as the total record of supplying and adding the numbers. So let’s assume that for the process of adding the number 1 and 2, we work with the user to come up with the following:</p>
<pre class="console">C:\node\ods-add&gt;node addition.js
First number:  1
Second number: 2
<span style="color:green;">1 + 2 = 3</span></pre>
<p>This is implemented very simply as:</p>
<pre class="code">var colors = require('colors')
console.log('First number:  1')
console.log('Second number: 2')
console.log('1 + 2 = 3'.green)</pre>
<p>Notice that this is a fully runnable, complete software. The user is not being asked in the abstract or conceptual about what they want. No tables or fixtures are being created. They are evaluating real software in its real target environment. The delivery and deployment can also be exercised.</p>
<p>It just only covers the specified example (adding the numbers 1 and 2). Only the outcome needs to be produced, allowing rapid iteration and interaction with the user to find the best possible outcome.</p>
<p>Once there is agreement on the outcome, the next step is to pin this outcome and set up a test that will check that the same outcome is being produced. This will allow making changes that allow us to safely move backwards in creating the rest of the software.</p>
<p>Just like with xUnit for TDD, some basic tooling can help with this process. ODS utilizes tooling that can do <em>photocopy testing</em>. Photocopy testing is the process of capturing the representation of the outcome as an agreed upon ‘standard’ and then being able to compare subsequent outcome production against the captured ‘standard’.</p>
<p>For this CLI example, I’ve created a simple utility that can both pin the outcome and test subsequent executions against that tooling. My main focus is on web development and I have <em>blueprint</em>, a web-based ODS tool for web application development. The process works fine for command line apps as well. It just goes to show how much detail is exposed by focusing on <em>running software </em>versus <em>developing code</em>.</p>
<pre class="console">C:\node\ods-add&gt;node test.js addition.js -p
<span style="color:yellow;">pinned</span> addition.js <span style="color:yellow;">outcome to</span> addition.outcome.txt
<span style="color:yellow;">saved outcome:</span>
First number:  1
Second number: 2
<span style="color:green;">1 + 2 = 3</span></pre>
<p>With the –p pin option, it saves the stdout output to a text file. Without the pin option, the program tests the outcome against the expected result:</p>
<pre class="console">C:\node\ods-add&gt;node test.js addition.js
First number:  1
Second number: 2
<span style="color:green;">1 + 2 = 3</span>
----------
<span style="color:green;">passed</span>
----------</pre>
<p>Combining this with watch enables a continuous real-time feedback mechanism. When the program is modified (and the file saved) we will know immediately if we are no longer producing the agreed upon outcome, for example if we change the last line to:</p>
<pre class="code">console.log('1 + 2 = 4'.green)</pre>
<p>we see:</p>
<pre class="console">C:\node\ods-add&gt;..\watch\watch node test.js addition.js
First number:  1
Second number: 2
<span style="color:green;">1 + 2 = 3</span>
----------
<span style="color:green;">passed</span>
----------

First number:  1
Second number: 2
<span style="color:green;">1 + 2 = 3</span>
----------
<span style="color:green;">passed</span>
----------

<span style="color:red;">failed!</span>

<span style="color:red;">Expected&gt;&gt;</span>First number:  1
Second number: 2
<span style="color:green;">1 + 2 = 3</span>
<span style="color:red;">&lt;&lt;</span>
<span style="color:red;">Actual  &gt;&gt;</span>First number:  1
Second number: 2
<span style="color:green;">1 + 2 = 4</span>
<span style="color:red;">&lt;&lt;</span>
----------</pre>
<p>Working backwards is essentially a refactoring effort from static to dynamic input. In ODS, the first step is to extract the output from the outcome. In practical terms, that means creating a view and a model (not showing the first three lines):</p>
<pre class="code">console.log('%s = %s'.green, '1 + 2', '3')</pre>
<p>One difference for me in working backwards from a fully functional outcome, versus building up an output, is that I see the totality of what is being described. So I’ve decided to isolate the addends as a unit, rather than discrete numbers.</p>
<pre class="code">var addends = [1, 2]
,  sum = 3
console.log('%s = %s'.green, addends.join(' + '), sum)</pre>
<p>With the simplicity of this example, we’ve not only isolated the output (<code>sum</code>), but the input as well (<code>addends</code>).  Now the functional mechanism can be added:</p>
<pre class="code">var addends = [1, 2]
,  sum = addends[0] + addends[1]
console.log('%s = %s'.green, addends.join(' + '), sum)</pre>
<p>You can take this in many directions. You could create an add method:</p>
<pre class="code">function add(a,b) { return a+b }
var addends = [1, 2]
,  sum = add(addends[0], addends[1])
console.log('%s = %s'.green, addends.join(' + '), sum)</pre>
<p>Or maybe a class:</p>
<pre class="code">var addition = {
 ,  addends: [1,2]
 ,  sum: 3
 ,  toString: function() {
       return util.format('%s = %s'.green,
       this.addends.join(' + '), this.sum)}</pre>
<pre class="code">}

console.log('%s'.green, addition)</pre>
<p>Or an event emitter/service approach:</p>
<pre class="code">calculator.on('sum', function(addition) {
  console.log(formatter.render(addition))
})</pre>
<p>ODS provides focus on and awareness of code design. Various designs can be tried and discarded at low cost.</p>
<p>Keeping this example simple, the last step is to implement the input mechanism:</p>
<pre class="code">var colors = require('colors')

var prompt = function(prompts, cb) {
  console.log(prompts[0] + '1')
  console.log(prompts[1] + '2')
  cb([1, 2])
}

prompt(['First number:  ', 'Second number: '], function(addends) {
  var sum = addends[0] + addends[1]
  console.log('%s = %s'.green, addends.join(' + '), sum)
})</pre>
<p>Now the ‘real’ library can be swapped in (but…):</p>
<pre class="code">var colors = require('colors')
,  prompt = require('./console-prompt')

prompt(['First number:  ', 'Second number: '], function(addends) {
  var sum = addends[0] + addends[1]
  console.log('%s = %s'.green, addends.join(' + '), sum)
})</pre>
<p>But, the test now needs to be modify to provide the inputs (full code on gitub):</p>
<pre class="code">var answers = ['1','2']
child.stdout.on('data', function(data){
  buf.push(data)
  process.stdout.write(data)
  var answer = answers.shift()
  if(answer) { writeLine(answer) }
})</pre>
<p>And the test passes:</p>
<pre class="console">C:\node\ods-add&gt;node test.js addition.js
First number:  1
Second number: 2
<span style="color:green;">1 + 2 = 3</span>
----------
<span style="color:green;">passed</span>
----------</pre>
<p>Of course, there is the working software:</p>
<pre style="background:black;color:#ffffff;">C:\node\ods-add&gt;node addition.js
First number:  34
Second number: 15
<span style="color:green;">34 + 15 = 49</span></pre>
<h3>Reviewing the Steps of the ODS Outcome-First Process</h3>
<p>Reviewing, here are the foundational steps:</p>
<ol>
<li>Establish an agreed upon outcome (go big and create delight!)</li>
<li>Pin the outcome via test</li>
<li>Extract the inputs into the outcome</li>
<li>Outcome inputs are also the (functional) system outputs</li>
<li>Work backwards through the functional system to the inputs</li>
</ol>
<p>Project is available on github <a href="https://github.com/martypdx/ods-add" target="_blank">here</a>.</p>
<p>You can also check out an Event Registration example I did about a year ago <a title="Feature TDD Example with node.js (1 of 2)" href="http://softwaregreenhouses.com/2011/02/26/neoagile-part-ii-example-1-of-2/">here</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/297/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/297/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/297/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/297/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/297/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/297/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/297/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/297/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/297/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/297/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/297/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/297/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/297/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/297/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=297&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2012/01/26/an-introduction-to-outcome-driven-software-ods/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2012/01/input-output-outcome-simple.png?w=136" medium="image">
			<media:title type="html">input-output-outcome-simple</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2012/01/input-output-outcome.png?w=139" medium="image">
			<media:title type="html">Input-Output-Outcome</media:title>
		</media:content>
	</item>
		<item>
		<title>Support the Irish Language Kickstarter Project</title>
		<link>http://softwaregreenhouses.com/2011/12/27/lh-irish-language-kickstarter-project/</link>
		<comments>http://softwaregreenhouses.com/2011/12/27/lh-irish-language-kickstarter-project/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 22:35:12 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Language Hunting]]></category>
		<category><![CDATA[audacious goal]]></category>
		<category><![CDATA[heritage languages]]></category>
		<category><![CDATA[irish language]]></category>
		<category><![CDATA[multilingual world]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.com/?p=319</guid>
		<description><![CDATA[UPDATE! Thanks to your support, the project has succesfully funded: http://www.kickstarter.com/projects/242604490/irish-language-hunt Thanks again to everyone who helped out! I need your help. This last summer a new non-profit, Language Hunters (LH), was formed by my friend Willem Larsen who asked me to sit on the board. LH is one of those big, hairy, audacious goal [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=319&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>UPDATE! Thanks to your support, the project has succesfully funded:</p>
<p><a href="http://www.kickstarter.com/projects/242604490/irish-language-hunt">http://www.kickstarter.com/projects/242604490/irish-language-hunt</a></p>
<p>Thanks again to everyone who helped out!</p>
<p><span id="more-319"></span></p>
<p>I need your help.</p>
<p>This last summer a new non-profit, Language Hunters (LH), was formed by my friend Willem Larsen who asked me to sit on the board. LH is one of those big, hairy, audacious goal kind of non-profits that not only wants to change the world, but I believe <em>can</em> change the world.</p>
<div style="background:#FDF6E3;border:1px solid burlywood;margin-bottom:10px;padding:10px 10px 5px;">
<p><strong>Hey Marty, just get to it and give me the short version!</strong></p>
<p>Language Hunters is expanding its amazing rapid language learning game to include a video version of the endangered Irish language (Gaeilge). I need you to:</p>
<ul>
<li style="margin-bottom:5px;"><a title="Language Hunters' Irish Language Project on Kickstarter" href="http://www.kickstarter.com/projects/242604490/irish-language-hunt">Go to Kickstarter and make a pledge</a>. Even if it’s only $1 it helps increase the project’s popularity and draws more attention and pledges. Kickstarter is integrated with Facebook and Amazon, it’s super easy! <a title="LH Irish Language Kickstarter Project" href="http://www.kickstarter.com/projects/242604490/irish-language-hunt">Really, just go do it</a>.</li>
<li>Tell everyone you know about it.  Just a few clicks will spread the word. You can use one of the Share links below to link to this page, or Share from <a title="LH Irish Language Project" href="http://www.kickstarter.com/projects/242604490/irish-language-hunt">the project page on Kickstarter</a>.  Seriously, how easy is that?</li>
</ul>
</div>
<p><!--more-->See, LH uses a game play technique to teach language that’s nothing like those dull, boring language courses most of us sat through in high school. A year (or more) of focus on vocabulary and grammar, yet how many of us would now feel comfortable having a conversation with a native speaker or even taking care of basic needs when travelling abroad?</p>
<p>What Willem and his colleagues figured out is that mimicry and copying is how people learn languages. Think about it, did any of us take English lessons as babies and toddlers? Now imagine that same natural learning occurring at much faster rate because, well, we’re not babies anymore.  The best part is that we don’t have to work at it, or memorize anything, we just play along.</p>
<p>LH’s goal is to create a multilingual world where kids (and adults!) can routinely speak 20 or more languages. And not just French, Spanish and German – but indigenous and heritage languages which are currently in a state of crisis and are at risk of being lost forever!</p>
<p>To accomplish this, LH has to both develop language specific programs and services as well as create opportunities to deliver those programs and services. LH has done that in past through workshops, often with specific indigenous communities. LH is also looking to expand programming in schools in 2012.</p>
<p>What I need from you today is to help fund a project to expand the reach of LH through the use of game videos that can be used by anyone around the world who has access to the internet. There is now a project on Kickstarter to create a video game to learn the endangered Irish language (Gaeilge).</p>
<p>LH has already spent over 400 person-hours to create a sample of the first “set” (over 20 sample videos!) and this project would allow them to revamp those videos, create the next 3 sets along with transcripts and supporting materials. <a title="LH Irish Language Project on Kickstarter" href="http://www.kickstarter.com/projects/242604490/irish-language-hunt">Head on over</a>, check those out and learn some Irish.</p>
<p>Then, I need you to do two things:</p>
<ul>
<li><a title="LH Irish Language Project on Kickstarter" href="http://www.kickstarter.com/projects/242604490/irish-language-hunt">Make a pledge</a>. Even if it’s only $1 it helps by elevating the project’s popularity and draws more attention and pledges! Of course, I’d love for you to pledge more to help us reach our goal of $3,500 (already over $1,000 has been pledged after only six days!). Kickerstarter even has easy integration with Amazon, so if you’ve already got an account you don’t even need to both with typing all that credit card info!</li>
<li>Tell everyone you know about it.  Just a few clicks will spread the word. You can use one of the Share links below to link to this page, or Share from <a title="LH Irish Language Project" href="http://www.kickstarter.com/projects/242604490/irish-language-hunt">the project page on Kickstarter</a>.  Seriously, how easy is that?</li>
</ul>
<p>I appreciate your support and thank you in advance,</p>
<p>- Marty</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/319/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/319/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/319/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/319/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/319/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/319/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/319/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/319/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/319/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/319/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/319/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/319/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/319/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/319/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=319&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/12/27/lh-irish-language-kickstarter-project/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>
	</item>
		<item>
		<title>&#8216;Software Is Massless&#8217; &#8211; My SAO TechIgnite Talk</title>
		<link>http://softwaregreenhouses.com/2011/10/25/software-is-massless-my-sao-techignite-talk/</link>
		<comments>http://softwaregreenhouses.com/2011/10/25/software-is-massless-my-sao-techignite-talk/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 18:44:30 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Empathy & Compassion]]></category>
		<category><![CDATA[Feature TDD]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.com/?p=286</guid>
		<description><![CDATA[Last month I had the opportunity to experience the thrill-ride of a five minute Ignite talk at SAO&#8217;s first ever TechIgnite event.  Here&#8217;s the intro description and video: Software Is Massless Our approach to software creation is largely based on our experience of constructing and interacting with physical objects. Software is massless and moves at [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=286&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Last month I had the opportunity to experience the thrill-ride of a five minute Ignite talk at SAO&#8217;s first ever TechIgnite event.  Here&#8217;s the intro description and video:</p>
<p><span class="Apple-style-span" style="font-weight:bold;">Software Is Massless</span></p>
<p>Our approach to software creation is largely based on our experience of constructing and interacting with physical objects. Software is massless and moves at the speed of light, so why do we delay our high aspirations for ecstatic outcomes and allow them to fade as we labor on structure, mechanisms and infrastructure? The time has come to break these self-inflicted chains that hold us back from our true potential as wizards of creation.</p>
<p>Lifting the veil, I’ll show you how to reconnect with the power to empathize and collaborate directly with customers and users to create the most important, meaningful parts of your software right from start instead of falling down the rat hole of system design. Then see how this inversion of fulfillment simplifies and minimizes the creation of the system necessary to support the outcomes that have already been created.</p>
<p></p>
<span style="text-align:center; display: block;"><a href="http://softwaregreenhouses.com/2011/10/25/software-is-massless-my-sao-techignite-talk/"><img src="http://img.youtube.com/vi/XuMD1oDOKr8/2.jpg" alt="" /></a></span>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/286/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/286/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/286/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/286/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/286/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/286/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/286/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/286/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/286/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/286/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/286/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/286/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/286/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/286/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=286&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/10/25/software-is-massless-my-sao-techignite-talk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>
	</item>
		<item>
		<title>The &#8216;Systems Thinking&#8217; Trap and How to Use &#8216;Empathetic Visioning&#8217; to Avoid It</title>
		<link>http://softwaregreenhouses.com/2011/04/17/the-systems-thinking-trap-and-how-to-use-empathetic-visioning-to-avoid-it/</link>
		<comments>http://softwaregreenhouses.com/2011/04/17/the-systems-thinking-trap-and-how-to-use-empathetic-visioning-to-avoid-it/#comments</comments>
		<pubDate>Sun, 17 Apr 2011 15:32:40 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Empathy & Compassion]]></category>
		<category><![CDATA[Feature TDD]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.com/?p=276</guid>
		<description><![CDATA[The problem with &#8216;systems thinking&#8217; is, well, thinking about the system. It is a trap to envision creation as a set of processes, steps, or mechanisms that need to be &#8216;figured out&#8217;. It typically results in either building predictable, yet uninspiring, solutions for known problems (clocks[1]), or ineffectively searching by trial and error for solutions [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=276&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The problem with &#8216;systems thinking&#8217; is, well, thinking about the system. It is a trap to envision creation as a set of processes, steps, or mechanisms that need to be &#8216;figured out&#8217;. It typically results in either building predictable, yet uninspiring, solutions for known problems (clocks<sup>[1]</sup>), or ineffectively searching by trial and error for solutions to unknown problems (clouds<sup>[1]</sup>).</p>
<p>We should set aside &#8220;the system&#8221; and &#8220;thinking&#8221; entirely. Instead, focus on a moment in time after the system has already been used and ask what is required to bring about positive emotional outcomes for the participants. This is a different type of labor, one Seth Godin in his book Linchpin describes as &#8220;emotional labor&#8221; (<a title="Seth Godin 'Emotional Labor'" href="http://www.squidoo.com/linchpin-by-seth-godin-review-ebizboosterblog" target="_blank">read about</a> or <a title="Seth's Blog" href="http://sethgodin.typepad.com/freeprize/2010/04/index.html" target="_blank">read on Seth&#8217;s blog</a> or <a title="Seth Godin 'Emotional Labor'" href="http://www.slideshare.net/lucgaloppin/one-minute-interview-seth-godin-on-emotional-labor" target="_blank">one-minute video</a>). I refer to it more generally as just empathy.</p>
<p>It is effective because it allows us to directly envision what will delight and fulfill the emotional needs and wants that truly drive human behavior and satisfaction. It also liberates us creatively because we temporarily remove any focus on the constraints of what the mind believes is possible in the construction of any system.</p>
<p>If we start by this process of &#8220;empathetic visioning&#8221;, then the subsequent use of systems thinking is done with a clear knowledge of the set of outcomes that must be produced to support the vision. In my experience thus far (it forms the basis of <a title="Feature TDD Example with node.js (1 of 2)" href="http://softwaregreenhouses.com/2011/02/26/neoagile-part-ii-example-1-of-2/" target="_blank">Feature TDD</a>), this reduces system problems to either trivial concerns or makes them well suited to solving by traditional analytical creativity.</p>
<p><em><sup>[1]</sup> From Karl Popper, I was recently introduced to the concept by my father who sent me a link to Gaurav Mishra&#8217;s <a title="Gaurav Mishra's post on applying clocks or cloud to social media" href="http://www.gauravonomics.com/blog/revisiting-karl-popper-is-social-media-a-clock-system-or-a-cloud-system/" target="_blank">interesting post on applying clocks or cloud to social media</a>.</em></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/276/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=276&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/04/17/the-systems-thinking-trap-and-how-to-use-empathetic-visioning-to-avoid-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>
	</item>
		<item>
		<title>Is Empathy the Practice of &#8216;Customer Pulls Value&#8217;?</title>
		<link>http://softwaregreenhouses.com/2011/04/07/is-empathy-the-practice-of-customer-pulls-value/</link>
		<comments>http://softwaregreenhouses.com/2011/04/07/is-empathy-the-practice-of-customer-pulls-value/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 12:51:37 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Empathy & Compassion]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.com/?p=267</guid>
		<description><![CDATA[I&#8217;ve been having a hard time seeing what the practice of the lean principal &#8216;customer pulls value&#8217; means in the context of creating software. The only true pull I could think of is a crowd sourced backlog. That&#8217;s useful some of the time, but not in all cases. Otherwise, it seems that some type of stimulation needs to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=267&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been having a hard time seeing what the <em><strong>practice</strong> </em>of the lean principal &#8216;customer pulls value&#8217; means in the context of creating software. The only true pull I could think of is a crowd sourced backlog. That&#8217;s useful some of the time, but not in all cases. Otherwise, it seems that some type of stimulation needs to occur (&#8216;pull on behalf of&#8217;).</p>
<p>This leads me to two possible (and not mutually exclusive) conclusions:</p>
<ol>
<li>&#8216;Customer pulls value&#8217; is not a principal, but rather is itself a practice (a technique to be used in certain contexts) used in support of a principal such as &#8220;customer co-creation and collaboration&#8221; (in which both push and pull occur).</li>
<li>We recognize empathy as the practice that supports the &#8216;customer pulls value&#8217; principal, as it can be proactively initiated while fully maintaining receptivity to pulling.</li>
</ol>
<p>From wikipedia:</p>
<blockquote><p><span style="color:#000080;"><strong>Empathy</strong> is the capacity to recognize and, to some extent, share feelings (such as sadness or happiness) that are being experienced by another semi-sentient being. Someone may need to have a certain amount of empathy before they are able to feel compassion.</span></p></blockquote>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/267/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=267&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/04/07/is-empathy-the-practice-of-customer-pulls-value/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>
	</item>
		<item>
		<title>Early Jumping Mouse Photo</title>
		<link>http://softwaregreenhouses.com/2011/03/18/early-jumping-mouse-photo/</link>
		<comments>http://softwaregreenhouses.com/2011/03/18/early-jumping-mouse-photo/#comments</comments>
		<pubDate>Sat, 19 Mar 2011 01:02:25 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Jumping Mouse]]></category>

		<guid isPermaLink="false">https://softwaregreenhouses.wordpress.com/?p=254</guid>
		<description><![CDATA[Right-side: in jade designer Left-side: duostack hosted (in chrome) Bottom: iPad &#160;<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=254&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<ol>
<li>Right-side: in jade designer</li>
<li>Left-side: duostack hosted (in chrome)</li>
<li>Bottom: iPad</li>
</ol>
<p><img class="alignleft" style="display:block;margin-right:auto;margin-left:auto;" src="http://softwaregreenhouses.files.wordpress.com/2011/03/wpid-img_20110318_164626.jpg?w=490" alt="image" /></p>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/254/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=254&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/03/18/early-jumping-mouse-photo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/03/wpid-img_20110318_164626.jpg" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Feature TDD Example with node.js (2 of 2)</title>
		<link>http://softwaregreenhouses.com/2011/02/28/neoagile-part-ii-example-2-of-2/</link>
		<comments>http://softwaregreenhouses.com/2011/02/28/neoagile-part-ii-example-2-of-2/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 02:55:46 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.wordpress.com/?p=233</guid>
		<description><![CDATA[In the first post, I created the confirmational aspects of a simple event registration web site.  Now I am well set up to use that to drive the functional aspects. Implement the Functional Behavior The Existing Event Spec Let&#8217;s look again at the main part of event-spec.js: vows.describe('Event').addBatch({ 'An Event': { 'when asked for guests': [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=233&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In the <a title="Neoagile Part II: Feature TDD Example with node.js (1 of 2)" href="http://softwaregreenhouses.wordpress.com/2011/02/26/neoagile-part-ii-example-1-of-2/">first post</a>, I created the confirmational aspects of a simple event registration web site.  Now I am well set up to use that to drive the functional aspects.</p>
<h2><em>Implement the Functional Behavior</em></h2>
<p><strong> </strong><br />
<em>The Existing Event Spec</em></p>
<p>Let&#8217;s look again at the main part of <strong><code>event-spec.js</code></strong>:</p>
<pre><strong><code>vows.describe('Event').addBatch({
  'An Event': {
    'when asked for guests': {
      topic: function () {
        Event.getGuests(this.callback);
      },
      'should return the standard guests':
        function (err, guests) {
          assert.deepEqual (guests,
            ['Bob', 'Sally', 'Tim', 'Joe']);
        }
    },
  'when registering Bob': {
      topic: function() {
        Event.register('Bob', this.callback);
      },
      'should return Bob':
        function (err, guest){
          assert.equal(guest, 'Bob');
        }
     }
  }
}</code></strong></pre>
<p><em>Adding Event Registration<span id="more-233"></span></em></p>
<p><em> </em>What I want to do is register the four standard guests, then execute the guest list test to see that those four guests are returned. Vows executes sibling contexts in parallel, so I need to either use separate batches or use a sub-context. I messed around with both, and for now I decided to go with two batches. The basic structure will be:</p>
<pre><strong><code>vows.describe('An Event')
.addBatch({
  'when guests register' : //register each guests
})
.addBatch({
  'when asked for guest list': //get confirmation list
}).export(module);</code></strong></pre>
<p>For the first <strong><code>addBatch</code></strong> (register), I&#8217;ll take the current test and move it into that block:</p>
<pre><strong><code>.addBatch({
  'when guests register' : {
    'like Bob': {
      topic: function() {
        Event.register('Bob', this.callback);
      },
      'should return Bob': function (err, guest) {
        assert.equal(guest, 'Bob');
      }
    }
  }
}</code></strong></pre>
<p>This would get repetitive for multiple register calls, so I&#8217;ll refactor out the context into a method:</p>
<pre><strong><code>.addBatch({
  'when guests register' : {
    'like Bob': registerGuest()
  }
}
...
function registerGuest() {
  return {
    topic: function() {
      Event.register('Bob', this.callback);
    },
    'should confirm Bob': function (err, guest) {
      assert.equal(guest, 'Bob');
    }
  };
}</code></strong></pre>
<p>Which can be parameterized to:</p>
<pre><strong><code>'like Bob': registerGuest('Bob')
...
function registerGuest(guest) {
  var context = {};
  context.topic = function() {
      Event.register(guest, this.callback);
  };
  context['should confirm ' + guest] = function (err,
    response) {
        assert.equal(response, guest);
    }
  return context;
}
</code></strong></pre>
<p>Adding in each of the four expected guests makes the <strong><code>'when guests register'</code></strong> context:</p>
<pre><strong><code>'when guests register' : {
  'like Bob': registerGuest('Bob'),
  'like Sally': registerGuest('Sally'),
  'like Tim': registerGuest('Tim'),
  'like Joe': registerGuest('Joe')
}</code></strong></pre>
<p>I don&#8217;t like the duplication on each line, nor the overall duplication for each guest. I can clean this up by introducing this method:</p>
<pre><strong><code>function registerGuests(){
  var context = {};
  for(arg in arguments){
    var guest = arguments[arg];
    context['like ' + guest] = registerGuest(guest);
  }
  return context;
}</code></strong></pre>
<p>Here is the entire event test suite file at this point:</p>
<pre><strong><code>var vows = require('vows'),
assert = require('assert')

var Event = require('../lib/event').getEvent();

vows.describe('An Event')
.addBatch({
  'when guests register' :
    registerGuests('Bob', 'Sally', 'Tim', 'Joe')
}).addBatch({
  'when asked for guests': {
    topic: function () {
      Event.getGuests(this.callback);
    },
    'should return the standard guests':
      function (err, guests) {
        assert.deepEqual (guests,
          ['Bob', 'Sally', 'Tim', 'Joe']);
    }
  },
}).export(module);

function registerGuests() {
  var context = {};
  for(arg in arguments) {
    var guest = arguments[arg];
    context['like ' + guest] = registerGuest(guest);
  }
  return context;
}

function registerGuest(guest) {
  var context = {};
  context.topic = function() {
    Event.register(guest, this.callback);
  };
  context['should confirm ' + guest] = function (err,
    response) {
      assert.equal(response, guest);
  }
  return context;
}</code></strong></pre>
<p>The corresponding code in <strong><code>event.js</code></strong> is:</p>
<pre><strong><code>exports.getEvent = function () {

  return new Event();

  function Event() {
    var guests = [];
    this.getGuests = function(callback) {
      callback(null, guests);
    };
    this.register = function(guest, callback) {
      guests.push(guest)
      callback(null, guests[guests.indexOf(guest)]);
    };
  }
}</code></strong></pre>
<p><em>The Data Store Functionality</em></p>
<p>Yes, this is just a simple in-memory array based solution. I&#8217;ve done the simplest possible thing for my purposes right now. It is appealing to be able to validate the system with an in-memory data storage structure, then implement a more appropriate data store. Either way, what I want you to notice is that the technique puts an emphasis on minimizing the functional aspect while providing a design that has cleanly decoupled the actual data store implementation.</p>
<p>For those looking for more on data with node, there are (multiple) open-source modules for <a title="cradle on github" href="https://github.com/cloudhead/cradle" target="_blank">CouchDb </a>(<a title="More on couchone and node" href="http://blog.couchone.com/post/2314470878/nodejitsu-couchone-couchdb" target="_blank">see here for more</a>), <a title="node-mongodb-native" href="https://github.com/christkv/node-mongodb-native" target="_blank">Mongo</a>, <a title="node-sqlite3 on github" href="https://github.com/developmentseed/node-sqlite3" target="_blank">SqlLite </a>and others; plus some light-weight keyed value stores like <a title="node-dirty on github" href="https://github.com/felixge/node-dirty" target="_blank">node-dirty</a> and <a title="nStore blog post and link to github" href="http://thechangelog.com/post/807837625/nstore-easy-database-written-for-node-js-in-node-js" target="_blank">nStore</a> (also, check <a title="Chris Strom on CouchDB and node-dirty" href="http://japhr.blogspot.com/2010/09/down-and-node-dirty.html" target="_blank">this post by Chris Strom where he does both a CouchDB and node-dirty implementation</a>).</p>
<p><em>Some Loose Ends</em></p>
<p><em> </em>I still need that test for registering with a missing name:</p>
<pre><strong><code>'with missing name' : {
  topic: function() {
    theEvent.register('', this.callback);
  },
  'should return an error': function (err, ignore) {
    assert.isNotNull(err);
  }
},</code></strong></pre>
<p>Which I can extract and follow a similar pattern as the register tests in order to expand to multiple &#8216;bad&#8217; inputs:</p>
<pre><strong><code>'with missing name' : noMissingNames({
  'empty string': '',
  'null': null,
  'white space': '    ',
  'undefined': undefined}),
...
function noMissingNames(missingNames) {
  var context = {};
  for(label in missingNames) {
    context[label] = noMissingName(missingNames[label]);
  }
  return context;
}

function noMissingName(missingName) {
  return {
    topic: function() {
      Event.register(missingName, this.callback);
    },
    'should return an error': function (err, ignore) {
      assert.isNotNull(err);
    }
  };
}</code></strong></pre>
<p>And now that I&#8217;m actually using the <strong><code>err</code></strong> parameter for register, I&#8217;ll add a check in my <strong><code>registerGuest</code></strong> method to make sure no error is returned on a good confirmation:</p>
<pre><code>function registerGuest(guest) {
  var context = {};
  context.topic = function() {
    Event.register(guest, this.callback);
  };
  <strong>context['should not return any errors'] =
    function (err, ignore) {
      assert.isNull(err);
  };</strong>
  context['should confirm ' + guest] = function (err,
    response) {
      assert.equal(response, guest);
  }
  return context;
}
</code></pre>
<p>The guard clause in event for missing names is:</p>
<pre><strong><code>this.register = function(guest, callback) {
  if(!(guest) || (/^\s*$/).test(guest)) {
    callback ('Name must be provided');
    return;
  }
...</code></strong></pre>
<p>I also added tests and code to make supplying no <strong><code>callback</code></strong> parameter safe (check those out on github if you&#8217;re interested).</p>
<p><em>The Whole Test Suite</em></p>
<p>Running the <strong><code>event-spec.js</code></strong> test suite now yields:</p>
<pre><strong><code>$ vows --spec event-spec.js

♢ An Event

  when guests register like Bob
    ✓ should not return any errors
    ✓ should confirm Bob
  when guests register like Sally
    ✓ should not return any errors
    ✓ should confirm Sally
  when guests register like Tim
    ✓ should not return any errors
    ✓ should confirm Tim
  when guests register like Joe
    ✓ should not return any errors
    ✓ should confirm Joe
  with missing name empty string
    ✓ should return an error
  with missing name null
    ✓ should return an error
  with missing name white space
    ✓ should return an error
  with missing name undefined
    ✓ should return an error
  when asked for guests
    ✓ should return the standard guests
  No callback provided on getGuests
    ✓ is safe
  No callback provided on register
    ✓ is safe

✓ OK » 15 honored (0.023s)
</code></strong></pre>
<h2><em>Create the Functional User Interface</em></h2>
<p><strong> </strong><br />
<em>The Registration Templates</em></p>
<p>I&#8217;ll use the same initial technique to create the jade template for registering as I did for the initial registration confirmations:</p>
<pre><strong><code>h1 Register for Larry's Event
form(action: '/guests', method: 'post')
  fieldset
    p
      label(for="name") Name:
      input(name: 'name')
    p
      input(type: 'submit', value="register")</code></strong></pre>
<p>Which renders as:</p>
<p><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/signupform.png"><img title="SignupForm" src="http://softwaregreenhouses.files.wordpress.com/2011/02/signupform.png?w=300&#038;h=229" alt="" width="300" height="229" /></a></p>
<p>I create the static, literal output and can again pin it with a test:</p>
<pre><strong><code>'Registration form': getContext('registration',
  function () {
    client.get('/registration', this.callback);
  })</code></strong></pre>
<p>And add the get method to the server code:</p>
<pre><strong><code>app.get('/registration', function (request, response) {
  Render(response, 'signupform');
});</code></strong></pre>
<p>I also need to create a template for the error condition, which is just a variation in the signup form (versus a separate response page):</p>
<pre><strong><code>h1 Register for Larry's Event
form(action: '/guests', method: 'post')
  fieldset
    p#error(style="color: red")
      | Name must be provided
    p
      label(for="name") Name:
      input(name: 'name')
    p
    input(type: 'submit', value="register")</code></strong></pre>
<p>I&#8217;ll create another literal template spec:</p>
<pre><strong><code>'Registration form with error': getContext(
  'registration-error', function () {
    client.get('/registration-error', this.callback);
  })</code></strong></pre>
<p>And until these two templates get united via refactor, I&#8217;ll create a separate get in the server code:</p>
<pre><strong><code>app.get('/registration-error', function (request,
  response) {
    Render(response, 'registration-error');
});</code></strong></pre>
<p>Now I&#8217;ll modify the <strong><code>registration.jade</code></strong> template:</p>
<pre><strong><code>h1 Register for Larry's Event
form(action: '/guests', method: 'post')
  fieldset
    - if (locals.error)
      p#error(style="color: red")= error
    p
      label(for="name") Name:
      input(name: 'name')
    p
      input(type: 'submit', value="register")</code></strong></pre>
<p>The registration-error get can now use the same template and pass in the error:</p>
<pre><strong><code>app.get('/registration-error', function (request,
  response) {
    Render(response, 'registration',
      {error: 'Name must be provided'});
});</code></strong></pre>
<p>The spec tests pass. Now I&#8217;ll refactor out a <strong><code>renderRegistration</code></strong> method for both gets:</p>
<pre><strong><code>app.get('/registration', function (request, response) {
  renderRegistration(response, 'registration');
});

app.get('/registration-error', function (request,
  response) {
    renderRegistration(response, 'registration',
      'Name must be provided');
});

function renderRegistration(error) {
  var locals = (error) ? {error: error} : null;
  render(response, 'registration', locals);
}</code></strong></pre>
<p><em>Thoughts on Application Context</em></p>
<p>The registration-error &#8216;get&#8217; can technically be deleted once we get the registration functionality in place. However, I&#8217;d like to find a way to preserve the standard tests as a different application context, but that will need to be a problem for another day.</p>
<h2><em>Test-Drive the Integration to the Finish Line</em></h2>
<p><strong> </strong><br />
<em>Automated Browser Tests</em><br />
I&#8217;ll bring in one more testing tool to drive our final integration steps.  Meet <a title="Zombie - Insanely fast, headless full-stack testing using Node.js" href="http://zombie.labnotes.org/" target="_blank">zombie</a>, the &#8216;Insanely fast, headless full-stack testing using Node.js&#8217;. I&#8217;ll use zombie in the vows tests to simulate the user browser activity.</p>
<p>There are two tests I&#8217;ll write, one for a successful registration, and the other for a missing name registeration:</p>
<pre><strong><code>var vows = require('vows'),
    assert = require('assert'),
    zombie = require('Zombie');

vows.describe('Event Registration').addBatch({
  'Register Guest' : {
    topic: function () {
      var callback = this.callback;
      zombie.visit('http://127.0.0.1:3003/registration',
        function (err, browser, status) {
          browser.fill('name', 'Pablo');
          browser.pressButton('register', callback);
      });
    },
    'browser should respond without error': function (err,
      browser, status) {
        assert.isNull(err);
    },
    'and with http status 200': function (err, browser,
      status) {
        assert.equal(status, 200);
    },
    'and contain the confirmation': function (err, browser,
      status) {
        assert.notEqual(browser.html().indexOf(
          'Thanks for registering Pablo!'), -1);
    }
  },
  'Register with No Name' : {
    topic: function () {
      var callback = this.callback;
      zombie.visit('http://127.0.0.1:3003/registration',
        function (err, browser, status) {
          browser.fill('name', '');
          browser.pressButton('register', callback);
      });
    },
    'browser should respond without error': function (err,
        browser, status) {
          assert.isNull(err);
    },
    'and with http status 200': function (err,
      browser, status) {
        assert.equal(status, 200);
    },
    'and contain the confirmation': function (err,
    browser, status) {
        var error = browser.querySelector("#error");
        assert.ok(error);
        assert.equal(error.textContent,
          'Name must be provided')
    }
  }
}).export(module);</code></strong></pre>
<p>Now we can wire up the registration, here is the server code in its entirety:</p>
<pre><strong><code>express = require('express'),
connect = require('connect'),
app = express.createServer(
  express.bodyDecoder());
app.set('views', __dirname + '/views/');

var Event = require('./lib/event').getEvent();

app.get('/guests', function (request, response) {
  Event.getGuests(function(err, guests) {
    render(response, 'guests', {guests: guests});
  });
});

app.post('/guests', function (request, response) {
  console.log('name', request.param('name'));
  Event.register(request.param('name'),
    function(err, data) {
      if(err) {
        renderRegistration(response, err);
      } else {
        render(response, 'confirmation', {guest: data});
      }
    });
});

app.get('/registration', function (request, response) {
  renderRegistration(response);
});

function renderRegistration(response, error) {
  var locals = (error) ? {error: error} : null;
  render(response, 'registration', locals);
}

function render(response, template, locals) {
	var options = { layout: false };
	if(locals) { options.locals = locals; }
	response.render(template + '.jade', options);
}

app.listen(3003);
console.log("Listening on port 3003");</code></strong></pre>
<h2><em>Final Thoughts</em></h2>
<p><strong> </strong><br />
Again, the code is available in <a title="This example on github" href="https://github.com/martypdx/Larry-s-Event" target="_blank">github</a>.</p>
<p>The basic difference from traditional software development was to start with a literal projection of the confirmations that would show the customer and user they got what they wanted. From that I was able drive the functional part of the application by pulling the data and functionality out of the literal templates and into the application.</p>
<p>There are still some rough spots, and I am also relatively new to javascript, node.js and modern web design.  My next goal, besides continuing to use the new technique, is to develop some tooling to help with some of the boiler-plate activities.</p>
<p>In the third post in my Neoagility series, I&#8217;ll take a step back up a level and look at some of the ramifications of doing software development in this manner.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/233/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/233/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/233/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/233/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/233/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/233/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/233/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/233/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/233/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/233/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/233/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/233/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/233/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/233/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=233&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/02/28/neoagile-part-ii-example-2-of-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/signupform.png?w=300" medium="image">
			<media:title type="html">SignupForm</media:title>
		</media:content>
	</item>
		<item>
		<title>Feature TDD Example with node.js (1 of 2)</title>
		<link>http://softwaregreenhouses.com/2011/02/26/neoagile-part-ii-example-1-of-2/</link>
		<comments>http://softwaregreenhouses.com/2011/02/26/neoagile-part-ii-example-1-of-2/#comments</comments>
		<pubDate>Sun, 27 Feb 2011 00:01:42 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.wordpress.com/?p=134</guid>
		<description><![CDATA[I&#8217;d like to introduce a new software development technique that is reminiscent of TDD, but at a higher, feature-oriented level. It&#8217;s based on the observation that features have both a confirmational and functional aspect. In brief summary: The functional aspect is the mechanism used to bring about a result The confirmational aspect is what lets the user know that their desires and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=134&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;d like to introduce a new software development technique that is reminiscent of TDD, but at a higher, feature-oriented level. It&#8217;s based on the observation that features have both a <a title="Confirmational versus Functional feature aspects in GMail" href="http://softwaregreenhouses.wordpress.com/2011/02/24/a-few-confirmation-versus-functional-features-in-gmail/">confirmational and functional aspect</a>. In brief summary:</p>
<ul>
<li>The <em>functional</em> aspect is the mechanism used to bring about a result</li>
<li>The <em>confirmational </em>aspect is what lets the user know that their desires and goals for using the software have been met.</li>
</ul>
<p>The key to Feature TDD is to build the confirmational aspect first, which then serves as the &#8216;test&#8217; for the subsequently developed functional aspect. Here are the steps I&#8217;ll be using:</p>
<ol>
<li>Capture vision and intent through literal confirmational representation</li>
<li>Pin output of #1 via test</li>
<li>Make vision templates data-driven</li>
<li>Extract data model and create functional stubs</li>
<li>Implement functional behavior</li>
<li>Use techniques #1 and #2 to create functional user interfaces</li>
<li>Link #6 to functional behavior created in #5</li>
</ol>
<p>In the post, I&#8217;ll cover steps #1-#4.<span id="more-134"></span></p>
<p>This simple example is going to be focused on a very simple event registration web site for our hypothetical customer Larry. I&#8217;m going to be using <a title="node.js" href="http://nodejs.org/" target="_blank">node.js</a> for this exercise. I have playing around with it for the past few months, and it has been a very compelling technology thus far.</p>
<h2><em>Capture Vision and Intent</em></h2>
<p><strong> </strong><br />
<em>Conversation</em></p>
<p>The goal for this step is to work with the customers and users to agree upon a set of interfaces and indications that will demonstrate that their vision or intent has been satisfied by the system (you can also think about it as answering &#8220;what will will make them happy?&#8221;). This is very similar to Specification by Example or BDD, except that the focus is solely on the confirmational aspects of the features.</p>
<p>For more detailed specific techniques for engaging the customer, check out <a title="An Example of Asking “Show Value” Questions" href="http://softwaregreenhouses.wordpress.com/2011/02/11/asking-show-value-questions/" target="_blank">my post here</a>, and also <a title="Effect Mapping by Gojko Adzic" href="http://gojko.net/effect-map/" target="_blank">Gojko Adzic&#8217;s interesting new technique of effect-maps</a>. A real conversation with Larry would expose a lot of in-depth contextual answers.</p>
<p>Right now, I want to show the end-to-end technique so I&#8217;m going to keep this extremely simple and say that Larry really just wants to see a list of names of those who have registered for his event.</p>
<p><em>Literal Templates</em></p>
<p>I&#8217;ll be using the <a title="jade template engine for nodejs" href="https://github.com/visionmedia/jade/" target="_blank">templating engine jade</a> to quickly work up the presentation. It&#8217;s format is fairly simple, and I like it because it can yield a visualization very simply and quickly. Here is the literal template for the guest list:</p>
<pre><strong><code>h1 Guest List for Larry's Event
ul#guests
  li Bob
  li Sally
  li Tim
  li Joe
</code></strong></pre>
<p>And here is the node.js server-side code for rendering this (I&#8217;m also using <a href="http://expressjs.com/" target="_blank">express </a>and connect, a web framework for even simpler application routing and server) :</p>
<pre><strong><code>express = require('express'),
connect = require('connect'),
app = express.createServer();
app.set('views', __dirname + '/views/');

app.get('/guests', function (request, response) {
  response.render('guests.jade',
          { layout: false, });
});

app.listen(3003);
console.log("Listening on port 3003");
</code></strong></pre>
<p>This renders as:<br />
<a href="http://softwaregreenhouses.files.wordpress.com/2011/02/guests.png"><img class="alignnone size-medium wp-image-147" title="Guests_Browser" src="http://softwaregreenhouses.files.wordpress.com/2011/02/guests.png?w=300&#038;h=227" alt="" width="300" height="227" /></a></p>
<p>I won&#8217;t be going any further than running on my local dev machine at this point, but with this simple, small fragment, there is enough to begin learning (by doing) about (continuous) deployment.</p>
<p>Also, with my tester hat on I notice that Larry probably wants to prevent empty names from showing on his list. For now, I&#8217;ll just record this observation.</p>
<p>Moving on to the next step I&#8217;ll focus on the guest who registers. Again, after deferring to Larry, I&#8217;ll assume we can  keep this very simple:</p>
<pre><strong><code>h1 You Are Registered for Larry's Event
p Thanks for registering Bob! We look forward to seeing you.</code></strong></pre>
<p>Another get method is added to the code and a Render method can be refactored out:</p>
<pre><strong><code>app.get('/guests', function (request, response) {
  Render(response, 'guests');
});

app.get('/guests/confirmation', function (request, response) {
  Render(response, 'confirmation');
});

function Render(response, template) {
	var options = { layout: false };
	response.render(template + '.jade', options);
}</code></strong></pre>
<p>The new method will soon be changed to <strong><code>app.post('/guests'</code></strong>, but initially we want the resource to be directly accessible so the outcome is demonstrable (some of the tooling I’ll show later makes this step unnecessary). This renders:</p>
<p><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/confirmation.png"><img class="alignnone size-medium wp-image-151" title="Confirmation" src="http://softwaregreenhouses.files.wordpress.com/2011/02/confirmation.png?w=300&#038;h=227" alt="" width="300" height="227" /></a></p>
<p>At this point, these confirmation &#8216;tests&#8217; have been validated by Larry, and we can consider that the output is now the &#8216;gold standard&#8217; of captured intent and vision.</p>
<h2><em>Pin the Standards with Tests</em></h2>
<p><strong> </strong><br />
The output is pinned so that the next step of making the templates data-driven can be made with the confidence that the standard has not changed. Fixing the html output from jade is trivial from the command line:</p>
<pre><strong><code>$ jade guests.jade confirmation.jade
  create : guests.html
  create : confirmation.html</code></strong></pre>
<p>There are a number of node.js testing frameworks, I&#8217;m going to use <a title="Vows BDD for nodejs" href="http://vowsjs.org" target="_blank">Vows</a> to write the tests. I rolled my own quick http-client module which is picked up at <strong><code>var client = require('./http-client'). </code></strong>There&#8217;s probably a good node module for this that I just haven&#8217;t found yet.</p>
<p>Here is the basic structure of the test, the client http response is compared against the spec standard:</p>
<pre><strong><code>topic: function () {
  client.get('/guests', this.callback);
},
'should return the standard':
  function (err, httpResponse) {
    fs.readFile('./html standards/guests.html', 'utf-8',
      function(err, standard) {
        assert.isNull(err);
        assert.equal(httpResponse.data, standard);
    });
  }</code></strong></pre>
<p>Adding both tests and refactoring out the common aspects leaves the initial test file as:</p>
<pre><strong><code>var vows = require('vows'),
assert = require('assert'),
fs = require('fs');

var client = require('./http-client');

vows.describe('Event Registration Confirmation')
  .addBatch({
    'Guest List Confirmation': getContext('guests',
      function () {
        client.get('/guests', this.callback);
      }),
    'Registration Confirmation': getContext('confirmation',
      function () {
        client.getPost('/guests', this.callback);
      })
  }).export(module);

function getContext(standard, httpGet) {
  return {
    topic: httpGet,
    'should return the standard': function (err,
      httpResponse) {
        fs.readFile('./html standards/' + standard + '.html',
          function(err, response) {
            assert.isNull(err);
            assert.equal(httpResponse.data, response);
      });
    }
  }
}</code></strong></pre>
<p>The signature of the registration confirmation is changed to be a post operation, and running the tests (the server app also needs to be running too) yields the following:</p>
<pre><strong><code>Marty.Nelson@Laptop-Mnelson7 ~/Larry's Event/tests
$ vows --spec confirmation_specs.js

♢ Event Registration Confirmation

  Registration Confirmation
    ✓ should return the standard
  Guest List Confirmation
    ✓ should return the standard

✓ OK » 2 honored (0.119s)</code></strong></pre>
<h2><em>Data-Drive the Templates</em></h2>
<p><strong> </strong><br />
With tests in place, the templates can be safely changed to be data driven. There are two parts to the change, the first is to pull the literal data values out of the templates and into the server code (passing them into the template):</p>
<pre><strong><code>app.get('/guests', function (request, response) {
  Render(response, 'guests',
    {guests: ['Bob', 'Sally', 'Tim', 'Joe']});
});

app.post('/guests', function (request, response) {
  Render(response, 'confirmation', {guest: 'Bob'});
});

function Render(response, template, locals) {
	var options = { layout: false };
	if(locals) { options.locals = locals; }
	response.render(template + '.jade', options);
}</code></strong></pre>
<p>And the second is to parameterize the jade templates:</p>
<pre><strong><code>h1 Guest List for Larry's Event
ul#guests
  - each guest in guests
    li= guest</code></strong></pre>
<p>and</p>
<pre><strong><code>h1 You Are Registered for Larry's Event
p
  | Thanks for registering #{guest}!
  | We look forward to seeing you.</code></strong></pre>
<p>The tests still pass (I&#8217;ve removed the more verbose &#8211;spec option):<br />
<strong> </strong></p>
<pre><strong><code>$ vows specs.js
··

? OK » 2 honored (0.051s)</code></strong></pre>
<p><strong> </strong></p>
<p><strong> </strong></p>
<h2><em>Functional Stub</em></h2>
<p><strong> </strong><br />
Next, I&#8217;ll push the literal code into an Event stub. Because node.js code should be non-blocking, the calls into the Event follow the pattern of supplying a callback, and that callback (by convention) has the signature <code><strong>(err, data)</strong></code>:</p>
<pre><strong><code>Event.getGuests(function(err, data) {
    if(err) { console.log('we got an error', err'); }
    console.log('return data:', data);</code></strong></pre>
<p>I&#8217;ll start by extracting it from the server get methods:</p>
<pre><strong><code>var Event = {};
Event.getGuests = function(callback) {
  callback(null, ['Bob', 'Sally', 'Tim', 'Joe']);
};
Event.register = function(name, callback) {
  callback(null, 'Bob');
};

app.get('/guests', function (request, response) {
  Event.getGuests(function(err, data) {
    Render(response, 'guests', {guests: data});
  });
});

app.post('/guests', function (request, response) {
  Event.register(request.param('name'), function(err, data) {
    Render(response, 'confirmation', {guest: data});
  });
});</code></strong></pre>
<p>Then I&#8217;ll move the Event code into another file (under the <strong><code>lib</code></strong> folder):</p>
<pre><strong><code>exports.getEvent = function () {

  return new Event();

  function Event() {
    this.getGuests = function(callback) {
      callback(null, ['Bob', 'Sally', 'Tim', 'Joe']);
    };
    this.register = function(name, callback) {
      callback(null, 'Bob');
    };
  }
}</code></strong></pre>
<p>And require it as a node module in the server code:</p>
<pre><strong><code>var Event  = require('./lib/event').getEvent();</code></strong></pre>
<p>Now I want to use traditional TDD to flush it out. Oddly, I need to backfill tests at the Event module level that are coming after the stub.  Another approach would have been to build up the identical interface to what was extracted in the server code. After the first few cycles, the tests looks like:</p>
<pre><strong><code>var vows = require('vows'),
    assert = require('assert')

var Event = require('../lib/event').getEvent();
vows.describe('Event').addBatch({
  'An Event': {
    'when asked for guests': {
      topic: function () {
        Event.getGuests(this.callback);
      },
      'should return the standard guests':
        function (err, guests) {
          assert.deepEqual (guests,
            ['Bob', 'Sally', 'Tim', 'Joe']);
        }
    },
  'when registering Bob': {
      topic: function() {
        Event.register('Bob', this.callback);
      },
      'should return Bob':
        function (err, guest){
          assert.equal(guest, 'Bob');
        }
     }
  }
}).export(module);</code></strong></pre>
<p>Running these tests yields:</p>
<pre><strong><code>$ vows --spec event_specs.js

♢ Event

  An Event when asked for guests
    ✓ should return the standard guests
  An Event when registering Bob
    ✓ should return Bob

✓ OK » 2 honored (0.013s)</code></strong></pre>
<h2><em>Next Steps</em></h2>
<p><strong> </strong><br />
I&#8217;m well setup to  flush out the functional aspects of the Event class. In the <a title="Neoagile Part II: Feature TDD Example with node.js (2 of 2)" href="http://softwaregreenhouses.wordpress.com/2011/02/28/neoagile-part-ii-example-2-of-2/">next post</a>, I&#8217;ll do this and then work my way back to the Registration interface to complete the applicaton.</p>
<p>You can view the code at <a title="This example on github" href="https://github.com/martypdx/Larry-s-Event" target="_blank">github</a>. If you know how to view history, the commit for the first part is labelled.</p>
<p><em>P.S. Thoughts on Tooling&#8230;</em></p>
<p><em> </em>In doing a few of these templates, I created a web tool intended to be a rapid collaborative environment for this technique:</p>
<p><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/jadetooling.png"><img class="alignnone size-full wp-image-224" title="JadeTooling" src="http://softwaregreenhouses.files.wordpress.com/2011/02/jadetooling.png?w=490&#038;h=368" alt="" width="490" height="368" /></a></p>
<p>The output in the upper-right updates in real-time as the template is modified. The &#8220;save template&#8221; button saves the template to the project and also creates the static html &#8216;standard&#8217; representation. The CSS area is not currently functional, but you can see how this be used to provide design aspects.</p>
<p>I have also been working on making these editors collaborative so that you could have multiple team members working up the confirmation feature (ideally with the customer or product owner) at the same time.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/134/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=134&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/02/26/neoagile-part-ii-example-1-of-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/guests.png?w=300" medium="image">
			<media:title type="html">Guests_Browser</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/confirmation.png?w=300" medium="image">
			<media:title type="html">Confirmation</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/jadetooling.png" medium="image">
			<media:title type="html">JadeTooling</media:title>
		</media:content>
	</item>
		<item>
		<title>Confirmational versus Functional feature aspects in GMail</title>
		<link>http://softwaregreenhouses.com/2011/02/24/a-few-confirmation-versus-functional-features-in-gmail/</link>
		<comments>http://softwaregreenhouses.com/2011/02/24/a-few-confirmation-versus-functional-features-in-gmail/#comments</comments>
		<pubDate>Fri, 25 Feb 2011 02:07:25 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.wordpress.com/?p=181</guid>
		<description><![CDATA[Once I realized that software features had a duel confirmational and functional aspect, I began to see that pattern at all levels. While it is much more apparent in transactional or workflow application, it can be found anywhere in software. Keep in mind that currently, because it is traditional written after the functional part of the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=181&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Once I realized that software <a title="Neoagile Part I: Why we need to evolve the agile methodology" href="http://softwaregreenhouses.wordpress.com/2011/02/17/neoagile-part-i-why/" target="_blank">features had a duel confirmational and functional aspect</a>, I began to see that pattern at all levels. While it is much more apparent in transactional or workflow application, it can be found anywhere in software.</p>
<p>Keep in mind that currently, because it is traditional written after the functional part of the feature, the confirmational aspects may be missing or poorly implemented. <span style="font-size:small;">Google does a pretty decent job on simple usability, so let&#8217;s look at Gmail for a visible example of the conformational versus functional aspect of features.</span></p>
<h2><em>Sending an Email</em></h2>
<p>When I send an email from GMail by clicking the send email button, I am exercising the functional aspect of sending an email. My button click causes browser code to execute and a call gets made to the server which uses SMTP to send that message to the recipient(s):</p>
<p style="padding-left:30px;"><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_functional.png"><img class="alignnone size-full wp-image-185" title="GMail_SendEmail_Functional" src="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_functional.png?w=490&#038;h=295" alt="" width="490" height="295" /><span id="more-181"></span></a></p>
<h2><em>But how do I know it worked?</em></h2>
<p>It can be helpful to think of confirmation as a contract for the software that answers this question. Actually reading the contents of the recipients inbox to validate the email was sent poses security and privacy issues. &#8216;Read Receipt&#8217; type approaches also are not generally excepted social practices outside of some segments of the business world. So, the &#8216;contract&#8217; is fulfilled by Google by putting a banner at the top of the browser (something added during the time when sending an email became an AJAX call, instead of a page submit):</p>
<p style="padding-left:30px;"><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_confirmation1.png"><img class="alignnone size-full wp-image-183" title="GMail_SendEmail_confirmation1" src="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_confirmation1.png?w=490&#038;h=167" alt="" width="490" height="167" /></a></p>
<p>And by maintaining a &#8216;Sent Mail&#8217; folder which offers of view of all email that have been sent:</p>
<p style="padding-left:30px;"><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_confirmation2.png"><img class="alignnone size-full wp-image-184" title="GMail_SendEmail_confirmation2" src="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_confirmation2.png?w=490&#038;h=185" alt="" width="490" height="185" /></a></p>
<h2><em>Features Within Features</em></h2>
<p><em>Font Editing</em></p>
<p>Even the small operations in the email text editor itself are split into functional and confirmation aspects:</p>
<p><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat1.png"><img class="alignnone size-full wp-image-186" title="GMail_TextFormat1" src="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat1.png?w=490&#038;h=97" alt="" width="490" height="97" /></a></p>
<p>The functional aspect is invoked when the buttons are clicked and the functional operation that is performed is to modify the underlying text representation (I believe Html).  What is the confirmational aspect? Why the WYSIWYG visualization!</p>
<p><em>Spell-Checking</em></p>
<p>The spell-checker confirms by high lighting the misspelled words. The functional aspect is the looking up of each word in a dictionary:</p>
<p><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat2.png"><img class="alignnone size-full wp-image-187" title="Gmail_TextFormat2" src="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat2.png?w=490&#038;h=112" alt="" width="490" height="112" /></a></p>
<p>In the Chrome browser, misspelled words are just high lighted without invocation (no button pressing required). This minimizing of the functional aspect is something that is encouraged in confirmation-first development. Good design means minimizing steps as user&#8217;s first click is on how to correct the mistake, not click to see if there are any mistakes, then having to click on the mistake.</p>
<p><a href="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat3.png"><img class="alignnone size-full wp-image-188" title="Gmail_TextFormat3" src="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat3.png?w=490&#038;h=103" alt="" width="490" height="103" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/181/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/181/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/181/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/181/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/181/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/181/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/181/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/181/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/181/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/181/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/181/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/181/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/181/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/181/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=181&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/02/24/a-few-confirmation-versus-functional-features-in-gmail/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_functional.png" medium="image">
			<media:title type="html">GMail_SendEmail_Functional</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_confirmation1.png" medium="image">
			<media:title type="html">GMail_SendEmail_confirmation1</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_sendemail_confirmation2.png" medium="image">
			<media:title type="html">GMail_SendEmail_confirmation2</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat1.png" medium="image">
			<media:title type="html">GMail_TextFormat1</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat2.png" medium="image">
			<media:title type="html">Gmail_TextFormat2</media:title>
		</media:content>

		<media:content url="http://softwaregreenhouses.files.wordpress.com/2011/02/gmail_textformat3.png" medium="image">
			<media:title type="html">Gmail_TextFormat3</media:title>
		</media:content>
	</item>
		<item>
		<title>Why we need to evolve the agile methodology</title>
		<link>http://softwaregreenhouses.com/2011/02/17/neoagile-part-i-why/</link>
		<comments>http://softwaregreenhouses.com/2011/02/17/neoagile-part-i-why/#comments</comments>
		<pubDate>Fri, 18 Feb 2011 01:29:13 +0000</pubDate>
		<dc:creator>Marty</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://softwaregreenhouses.wordpress.com/?p=118</guid>
		<description><![CDATA[It has been said that to be successful in software we need to do &#8216;The Right Thing Right&#8217;. The second &#8216;Right&#8217; is about Technical Excellence, to which there is already much attention. The first &#8216;Right&#8217; is more problematic. Iterations introduced a way to tame chaos by successively asking &#8216;is this right?&#8217;. User Stories and XP&#8217;s [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=118&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>It has been said that to be successful in software we need to do &#8216;The Right Thing Right&#8217;. The second &#8216;Right&#8217; is about Technical Excellence, to <a title="Software Craftsmanship" href="http://softwarecraftsmanship.org/" target="_blank">which there is already much attention</a>. The first &#8216;Right&#8217; is more problematic.</p>
<p>Iterations introduced a way to tame chaos by successively asking &#8216;is this right?&#8217;. User Stories and XP&#8217;s on-site customer foster collaboration, but that conversation is typically about &#8216;what the system should do&#8217; with the Product Owner left, in scrum terms, responsible for ROI.</p>
<p>ATDD formalized this concept into a set of system inputs and outputs that are meant to represent that &#8216;if the system can do this&#8217; then it is assumed that we (the development team) have &#8216;delivered the right thing&#8217;.</p>
<p>There are major weaknesses to this model:<span id="more-118"></span></p>
<h4>1. The inability of customers and users to design software.</h4>
<p><a title="Jenea Hayes &quot;Users are not designers&quot;" href="http://www.cooper.com/journal/2011/02/understand_the_players.html" target="_blank">Jenea Hayes at cooper design said this very well when she wrote</a>:</p>
<blockquote><p>Many of our clients come to us with a history of producing bad user interfaces, and they can’t understand why when they have included every popular feature request from their users.</p>
<p>The reason for this is very simple: users are not designers or visionaries. We should no sooner ask them to design a product than we would ask them to write the code.</p></blockquote>
<h4>2. It puts the primary focus on the technology</h4>
<p>The conversation is about what the system should do, not on the customer and the &#8216;why?&#8217; driving the need for software in the first place.</p>
<h4>3. It introduces a two-tiered goal system</h4>
<p>Development teams can end up in the vulnerable and awkward position of succeeding at what they do, but still having the software fail overall.  One has to wonder what the effect on moral is in such an environment, whether through lack of belief in a real, meaningful goal or through an antagonistic relationship with product management.</p>
<h4>4. It encourages mediocrity</h4>
<p>Both parties (customer and business) usually have already invested heavily in the process and &#8216;good enough&#8217; salvages existing effort. It lowers the bar to what is functional, not what is good.</p>
<p>These observations are not entirely new. Techniques like <a title="BDD" href="http://behaviour-driven.org/" target="_blank">BDD</a>, <a title="Specification by Example" href="http://specificationbyexample.com/" target="_blank">Specification by Example</a>, and more recently <a title="Lean Startup" href="http://www.startuplessonslearned.com/2008/09/lean-startup.html" target="_blank">Lean Startup</a> have emerged that are all addressing this same fundamental problem that understanding the customer goals and outcomes is essential in designing the right system. These are good techniques, more people should use them.</p>
<p>Yet they are all techniques for deriving a set of requirements. Desires and outcomes are still *translated* into a feature that is believed to satisfy those goals, largely for the benefit of fitting into a development machinery tuned for delivering features in a pipeline manner. The focus is on defining an input to some function then testing an output.</p>
<p>Why is it that we feel compelled to translate customer desires? Is it perhaps because we believe we must homogenize the development process into one single fundamental unit of &#8216;feature&#8217; driven by functional requirement?</p>
<p><em><strong>What if we instead addressed the satisfaction of customer desires head-on and as our top priority?</strong></em></p>
<p>What does this mean exactly? I propose that we ask the customer this question directly by asking a question framed as an inquiry to what they want to be shown that proves they got the value at a moment in time <em>after</em> the system has been used in the traditional sense of a piece of functionality.</p>
<p>In fact, isn&#8217;t this exactly what we do one level down in TDD? We start by asking &#8216;how can I show that the code worked&#8217; and that test becomes the thing that proves that it does work.</p>
<p>This suggests a natural dichotomy of features into 1) those that confirm that the value was realized (confirmation, or test features), and 2) features that are used as mechanisms to fulfill the requirements of creating the value (functional features). Indeed when we look at software through this lens we can begin to see both types of features. One of the most common examples is presenting a confirmation feature after a data entry feature.</p>
<p>And just like doing test-after instead of TDD, we may, more often than not, find the confirmation to be missing and wish there was better insight into the use of the system. And how often is that confirmation feature dropped or never executed because it is viewed as a &#8216;nice-to-have&#8217;?</p>
<p>Focusing customer conversations in this manner is very revealing. I posted an example from the <a title="An Example of Asking “Show Value” Questions" href="http://softwaregreenhouses.wordpress.com/2011/02/11/asking-show-value-questions/" target="_blank">first time I used this technique</a>. It appears to be the most direct route to talking about what is important to customers and is incredibly sensitive to context. It also lends itself to revealing complexities of stakeholders, dovetailing nicely into the <a title="Effect Mapping by Gojko Adzic" href="http://gojko.net/effect-map/" target="_blank">&#8216;Effect Mapping&#8217; technique recently introduced by Gojko Adzic</a>.</p>
<p>All of this leads us to one more fundamental question: if we have not been doing our &#8216;test&#8217; confirmation features upfront, what does that say about the amount of churn and the quality of the features we normally do first: those mechanistic, complicated, expensive functional features?</p>
<p>Think about it, the sum total of confirmation features across all stakeholders represents the required output of the functional feature. If we define this upfront we avoid adding unnecessary things to our functional features. In fact we now have the outcome side of a traditional acceptance test.</p>
<p>One has to wonder if the introduction of iterations (not increments) was something of unnecessary thing. I like iterations as a safety net or as a method of successive approxiamation when dealing with an unknown problem or qualitative issue. But it really should be a technique of last resort for validation.</p>
<p>That&#8217;s the theory. In the next post, <a title="Neoagile Part II: Feature TDD Example with node.js (1 of 2)" href="http://softwaregreenhouses.wordpress.com/2011/02/26/neoagile-part-ii-example-1-of-2/">I&#8217;ll show an example of how this works in practice</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/softwaregreenhouses.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/softwaregreenhouses.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/softwaregreenhouses.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/softwaregreenhouses.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/softwaregreenhouses.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/softwaregreenhouses.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/softwaregreenhouses.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/softwaregreenhouses.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/softwaregreenhouses.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/softwaregreenhouses.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/softwaregreenhouses.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/softwaregreenhouses.wordpress.com/118/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/softwaregreenhouses.wordpress.com/118/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/softwaregreenhouses.wordpress.com/118/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=softwaregreenhouses.com&amp;blog=14144732&amp;post=118&amp;subd=softwaregreenhouses&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://softwaregreenhouses.com/2011/02/17/neoagile-part-i-why/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/37d657337d068659bf0bcf1bf2c02cfb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">martypdx</media:title>
		</media:content>
	</item>
	</channel>
</rss>
