<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-381129527146258002</id><updated>2012-01-28T10:32:30.052-08:00</updated><category term='teamwork'/><category term='ottinger'/><category term='attentive work'/><category term='continuous integration'/><category term='tools'/><category term='refactoring poop method comment cleanup'/><category term='multitasking'/><category term='Motivation'/><category term='cooperation.'/><category term='accus'/><category term='informative workspace'/><category term='development'/><category term='free'/><category term='eLearning'/><category term='ambient annunciator'/><category term='pork barrel'/><category term='strategy'/><category term='cheap'/><category term='customer'/><category term='getting things done'/><category term='scheduled'/><category term='interruptions'/><category term='scrum master'/><category term='unequal'/><category term='short reach'/><category term='tim ottinger'/><category term='rockstars'/><category term='daunted'/><category term='Esther Derby'/><category term='priority'/><category term='extreme feedback'/><category term='perturbation'/><category term='procrastination'/><category term='rewrites'/><category term='xp'/><category term='duplication'/><category term='rant'/><category term='scrum masters'/><category term='techniques'/><category term='agile coach'/><category term='oversight'/><category term='retrospective'/><category term='refactoring'/><category term='transition'/><category term='schedule'/><category term='dinwiddie'/><category term='evaluations'/><category term='Demotivators'/><category term='bash'/><category term='teams'/><category term='shell programming'/><category term='raspberry jam'/><category term='pair programming'/><category term='clever code'/><category term='respect'/><category term='tutorials'/><category term='build'/><category term='software'/><category term='clean code'/><category term='meddling'/><category term='practices'/><category term='Coaching Camp'/><category term='intimidated'/><category term='elegance'/><category term='summary'/><category term='version control'/><category term='meetings'/><category term='overdesign'/><category term='stories'/><category term='testing'/><category term='iterations'/><category term='fizzbuzz'/><category term='error'/><category term='concise'/><category term='value'/><category term='columbus'/><category term='jenkins'/><category term='objections'/><category term='change'/><category term='guided experience'/><category term='jim hood'/><category term='skill development'/><category term='crispin'/><category term='agile coach camp'/><category term='information radiators'/><category term='textura agile practices'/><category term='tasks'/><category term='diffs'/><category term='feedback'/><category term='agile'/><category term='python'/><category term='start'/><category term='microtests'/><category term='chicago'/><category term='object mentor'/><category term='tdd'/><category term='variable replacement'/><category term='code'/><category term='business value'/><category term='learning'/><category term='naming'/><category term='learning organization'/><category term='linux'/><category term='user groups'/><category term='agile in a flash'/><category term='branching'/><category term='programming'/><category term='remote'/><category term='dysfunction'/><category term='levinson'/><category term='fears'/><category term='ugly code'/><category term='time'/><category term='pylons'/><category term='technical debt'/><category term='expansion'/><category term='fluid development'/><category term='gold-plating'/><category term='cool'/><category term='agile manager'/><category term='pimpl'/><category term='scrum'/><category term='yesterdays weather'/><category term='features'/><category term='failure'/><category term='fear'/><category term='self improvement'/><category term='management'/><category term='clean'/><title type='text'>Agile Otter Blog</title><subtitle type='html'>Tim Ottinger as an agile consultant, practitioner, manager, remote agile team member... and whatever happens next.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default?start-index=101&amp;max-results=100'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>236</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1016110713084542287</id><published>2012-01-19T09:24:00.000-08:00</published><updated>2012-01-19T11:35:55.888-08:00</updated><title type='text'>Why not C++ all the time?</title><content type='html'>&lt;div class="p1"&gt;In the why-we-don't-prefer-programming-in-c++ exhibit of evidence:&lt;/div&gt;&lt;div class="p1"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;python:&amp;nbsp;&lt;/div&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;result = line.split(',')&lt;/pre&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;C#:&lt;/div&gt;&lt;pre&gt;&amp;nbsp; var result = line.Split(',');&lt;/pre&gt;&lt;br /&gt;&lt;div class="p1"&gt;C++:&lt;/div&gt;&lt;pre&gt;&lt;div class="p3"&gt;&lt;span class="s1"&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp; vector&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;string&lt;span class="s1"&gt;&amp;gt; result;&lt;/span&gt;&lt;/div&gt;&lt;div class="p4"&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&lt;span class="s2"&gt;&amp;nbsp; ostringstream&lt;/span&gt; sourcestream(sourceString);&lt;/div&gt;&lt;div class="p4"&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&amp;nbsp; copy(&lt;/div&gt;&lt;div class="p4"&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;istream_iterator&amp;lt;&lt;span class="s2"&gt;string&lt;/span&gt;&amp;gt;(sourcestream),&amp;nbsp;&lt;/div&gt;&lt;div class="p4"&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;istream_itearator&amp;lt;&lt;span class="s2"&gt;string&lt;/span&gt;&amp;gt;(),&amp;nbsp;&lt;/div&gt;&lt;div class="p4"&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;back_inserter&amp;lt;&lt;span class="s2"&gt;vector&lt;/span&gt;&amp;lt;&lt;span class="s2"&gt;string&lt;/span&gt;&amp;gt; &amp;gt;(result)&amp;nbsp;&lt;/div&gt;&lt;div class="p4"&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&amp;nbsp; );&lt;/div&gt;&lt;div class="p4"&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div class="p4"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p4"&gt;Special thanks to StackOverflow &lt;a href="http://stackoverflow.com/users/30767/zunino"&gt;&amp;nbsp;Zunino&lt;/a&gt; at &lt;a href="http://stackoverflow.com/"&gt;Stack Overflow&lt;/a&gt; for this &lt;a href="http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c"&gt;answer&lt;/a&gt;, one of the most concise and standards-respecting.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1016110713084542287?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1016110713084542287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2012/01/why-not-c-all-time.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1016110713084542287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1016110713084542287'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2012/01/why-not-c-all-time.html' title='Why not C++ all the time?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5286750389378235399</id><published>2011-12-05T18:31:00.000-08:00</published><updated>2011-12-05T18:31:38.071-08:00</updated><title type='text'>Join Fresh Start Week 2012</title><content type='html'>Soon we'll be on the other side of Christmas and starting a new year.&lt;br /&gt;&lt;br /&gt;How about for the first week of January we try doing without copy-and-edit programming. What would happen if we were to write code off the top of our heads?&lt;br /&gt;&lt;br /&gt;Don't just hand-type the example code you would have copied anyway, but try writing it as&lt;i&gt; if the code you really wanted already existed&lt;/i&gt;. &amp;nbsp;How would you have liked to initialize that class? When you are writing a test, do the order of the parameters of that method make sense? Are you doing three- or four- or five-step operations that ought to be their own function? Is the method you need a member of the object where you would expect to find it? You can't find out by doing copy-and-edit programming.&lt;br /&gt;&lt;br /&gt;Let's all try the grand experiment of not copying ANYTHING for the first work week of January. What could it teach us? What could it hurt?&lt;br /&gt;&lt;br /&gt;The hashtag will be #freshstartweek.&lt;br /&gt;&lt;br /&gt;See you there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5286750389378235399?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5286750389378235399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/12/join-fresh-start-week-2012.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5286750389378235399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5286750389378235399'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/12/join-fresh-start-week-2012.html' title='Join Fresh Start Week 2012'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7245526228788295225</id><published>2011-12-02T12:09:00.000-08:00</published><updated>2011-12-02T15:25:27.568-08:00</updated><title type='text'>Single-Return, AKA: Elephant-proofing your bathtub</title><content type='html'>&lt;div class="p1"&gt;Single-entry, single-exit programming was a great breakthrough that led to a serious improvement in the lives of many programmers. In the jurassic period of software development, anyway. In the modern era, among good programmers, I think that single-exit is an example of the many &lt;i&gt;once-best practices&lt;/i&gt; that outlive their usefulness.&lt;/div&gt;&lt;div class="p1"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;Method length and nesting are our primary enemies. Multiple returns in nested, long methods turn trouble into disaster for the poor developer who has to understand and debug a routine, not to mention the guy who lost the coin toss and has to actually modify it. &amp;nbsp;Once code is bad, multiple returns makes it far worse.&lt;/div&gt;&lt;div class="p1"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p2"&gt;Start with pure function length:&lt;/div&gt;&lt;div class="p1"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;In a 500-line function two returns is dangerous, and five would be maddening.&lt;/li&gt;&lt;li&gt;Drop to 50 lines, and it's still pretty daunting.&lt;/li&gt;&lt;li&gt;Drop to 10 lines, and the risk of missing a return or misunderstanding the method is slight.&lt;/li&gt;&lt;li&gt;At 5 lines, there's no hint of the problem that single-exit solves.&lt;/li&gt;&lt;/ul&gt;&lt;div class="p2"&gt;Switch to nesting depth:&lt;/div&gt;&lt;div class="p1"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&amp;nbsp;If you are nested 15 conditionals and loops deep, that extra return is obscure with a capital O.&amp;nbsp;&lt;/li&gt;&lt;li&gt;At 5 conditionals deep it's frightful. It's hard to tell at a glance which lines are being executed and when.&lt;/li&gt;&lt;li&gt;But what if you're never more than two levels deep in a function? Returns are crazy obvious.&lt;/li&gt;&lt;/ul&gt;&lt;div class="p2"&gt;See how this one rule serves you supremely well when your code stinks, but does you no favors when your code is short and clear?&amp;nbsp;&lt;/div&gt;&lt;div class="p1"&gt;&lt;/div&gt;&lt;blockquote class="tr_bq"&gt;Q: "Doctor, I broke my arm in two places! What should I do?"&lt;br /&gt;A: "Stay out of those places!"&lt;/blockquote&gt;&lt;div class="p2"&gt;Single-entry/single-exit can even be harmful to the readability of an otherwise short function if it forces variables to be created up front instead of at first use, or if it causes code to be more deeply nested.&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int doSomething(int parameter) {&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span"&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; int result = 0;&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ( 0 != parameter ) {&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;result = x/parameter;&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return result&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="p2"&gt;Here the real feature of the function (the division) is hidden inside an if clause. It makes the code seem as if its goal is to return zero, and that the division is a side effect that occurs when a condition is just right. It'a s funny de-emphasis of the essential goal of the function.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;Let's invert the condition to create a guard clause instead:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;int doSomething(int parameter) {&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if ( 0 == parameter ) {&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return 0;&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return x/parameter;&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;The actual functionality is exalted, and the early return is more clearly an effect of having a parameter that you must protect against. The readability here is not degraded, but instead enhanced. &amp;nbsp;This is a good time to remind the reader that the shortness of the function makes it so.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;It is no worse even if I squish an if onto one line (another no-no in many shops).&amp;nbsp;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int doSomething(parameter) {&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if ( 0 == parameter ) {return 0;}&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return x/parameter;&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="p1"&gt;The same rule seems to apply when there are more parameters to check and when the work to be done is more than a single line:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;int doSomething(int parameter1, double parameter2) {&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if ( 0 == parameter1 ) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return 0;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if ( (parameter2 &amp;lt; 0) || (parameter2 &amp;gt; 1)) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return 0;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;double part1 = parameter2 * x;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;int result = int(part1/parameter);&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return result;&lt;/span&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;We have the advantage that the function is divided into checking parameters and returning results, so it is still pretty readable and clean. There is little nesting, and few lines. On the other hand, the astute reader will notice that we're up to 11 lines now, and with a little more expansion we could have a Long Method on our hands, at which time the single-exit rule will apply again (welcome back to the Jurassic period).&lt;br /&gt;&lt;br /&gt;We will outgrow an awful lot of our hard-n-fast rules by writing small, clear functions. A lot of "best practices" are really just "ways to tolerate poor practices." &amp;nbsp;&lt;/div&gt;&lt;div class="p1"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;Some of our old 1970s C programming rules were very valid in their time, but following them when they don't apply is as silly as a Chicagoan elephant-proofing his bathtub. &amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7245526228788295225?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7245526228788295225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/12/single-return-aka-elephant-proofing.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7245526228788295225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7245526228788295225'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/12/single-return-aka-elephant-proofing.html' title='Single-Return, AKA: Elephant-proofing your bathtub'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1513108879159798131</id><published>2011-12-01T07:29:00.000-08:00</published><updated>2011-12-01T07:29:38.160-08:00</updated><title type='text'>Performance Appraisal Time?</title><content type='html'>&lt;div id="yui_3_2_0_15_132275063509648" style="background-color: white; font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;"&gt;As you head into year-end appraisals, here are a few resources for you.&lt;/div&gt;&lt;div id="yui_3_2_0_15_132275063509648" style="background-color: white; font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;"&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.estherderby.com/tag/performance-appraisals"&gt;Time for the Annual Performance Review&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.estherderby.com/2011/11/supporting-team-based-work.html"&gt;Supporting Team-Based Work&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.estherderby.com/2010/07/performance-without-appraisal-addressing-the-most-common-concerns.html" style="font-size: medium;"&gt;Addressing The Most Common Concerns&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.estherderby.com/weblog/2009/09/performance-without-appraisal-build.html"&gt;Building Feedback Into The System&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://pscholtes.com/performance/"&gt;Notes From Peter Scholtes&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.systemsthinking.co.uk/6-14.asp"&gt;A Perspective from Vanguard&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div id="yui_3_2_0_15_132275063509648" style="background-color: white; font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;"&gt;&lt;span id="yui_3_2_0_15_1322750635096118"&gt;Note: most of you employees do want time with their bosses, they just don't want a once-a-year backward-looking judgement. They'd rather the boss was a part of their team and gave forward-looking direction all of the time. More feedback is better than less, and more engagement too.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div id="yui_3_2_0_15_132275063509648" style="background-color: white; font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;"&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div id="yui_3_2_0_15_132275063509648" style="background-color: white; font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;"&gt;&lt;span&gt;For some other pointers, see:&lt;/span&gt;&lt;/div&gt;&lt;div id="yui_3_2_0_15_132275063509648" style="background-color: white;"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'times new roman', 'new york', times, serif;"&gt;&lt;a href="http://agileinaflash.blogspot.com/2011/10/management-theater.html"&gt;Management Theater&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'times new roman', 'new york', times, serif;"&gt;&lt;a href="http://agileinaflash.blogspot.com/2011/11/4-ts-of-engaging-management.html"&gt;The Four Ts.&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div id="yui_3_2_0_15_132275063509648" style="background-color: white; font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1513108879159798131?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1513108879159798131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/12/performance-appraisal-time.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1513108879159798131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1513108879159798131'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/12/performance-appraisal-time.html' title='Performance Appraisal Time?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2912418722518317165</id><published>2011-11-18T10:00:00.000-08:00</published><updated>2011-11-18T10:00:38.281-08:00</updated><title type='text'>Preserving Wasteful Practices</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-uQ8jqJFr-i8/TsadDEpPzeI/AAAAAAAABQA/u3DUCYmvS5k/s1600/PracticePreservationVenn.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="414" src="http://3.bp.blogspot.com/-uQ8jqJFr-i8/TsadDEpPzeI/AAAAAAAABQA/u3DUCYmvS5k/s640/PracticePreservationVenn.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2912418722518317165?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2912418722518317165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/11/blog-post.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2912418722518317165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2912418722518317165'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/11/blog-post.html' title='Preserving Wasteful Practices'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-uQ8jqJFr-i8/TsadDEpPzeI/AAAAAAAABQA/u3DUCYmvS5k/s72-c/PracticePreservationVenn.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8078817953790964796</id><published>2011-10-28T05:38:00.000-07:00</published><updated>2011-11-01T22:00:28.432-07:00</updated><title type='text'>If We Had Done The Right Thing To Begin With</title><content type='html'>Error-avoiding is overrated. Too often people want to wait surprisingly long periods of time before making a move, in fear that their move might be the wrong thing to do. The amount of fear and pre-thought we put into projects can be staggering.&lt;br /&gt;&lt;br /&gt;I'm not here to say that design and architecture and platform design aren't important. Clearly there is value to having a workable plan and a goal in sight. &amp;nbsp;However, the idea that you must be right on the first day of development flies in the face of all our experience with application development. You only need to be "right enough" at first, and able to correct as time goes on.&lt;br /&gt;&lt;br /&gt;We can become invested in concepts, ideas, development stacks, and architectures to the point that we forget that all up-front design decisions are just guesses. It's akin to a man walking up to the blackjack table with the intention to draw twice on the first hand and once on the second, even though those hands have not been dealt. The problem is that many smart developers will stick to the plan even if it fails to make development fluid and predictable, but if the gambler draws an 18 he wil decide not to draw twice after all. Do we realize that design is a bet? Do we continue to evaluate it, or do we take it as law on the day it is handed down from The Architect?&lt;br /&gt;&lt;br /&gt;There are a small number of problems with being "right to begin with":&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;You'd have to know what "the right thing" is.&lt;/b&gt; A lot of systems have emergent designs that surprise their developers. Larry Wall is famous for saying that he had no idea Perl would look like it does today. An application may be written well in many ways, how can you know the One Right way in advance of actually building it?&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;b&gt;You'd have to know that "the right thing" is right.&lt;/b&gt; In a system with many choices, any number of right-seeming ideas may be wrong. The iPhone showed us that a radical design may be more right and more influential than many conventional ideas of what is right. Countless other unnamed products have shown us the reverse. Being convinced of the rightness of their conventional design, one large mobile phone company ended up missing out on the most lucrative phone design of our lifetimes.&lt;/li&gt;&lt;li&gt;&lt;b&gt;"The right thing" would have to already exist&lt;/b&gt;. It might be that the innovation your product needs will be invented/released/discovered six months into your product development effort. A Lean Startup approach involves constant "persevere or pivot" decisions, which can be applied to architecture as well as feature set.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The cost of discovering "the right thing" up-front needs to be less than the cost of discovering it through experimentation and development&lt;/b&gt;. If you took three months to design a system, and you could have discovered the same solution by building three three-weeks prototypes, you were not being responsible but wasteful. Always remember that design is a gamble.&amp;nbsp;&lt;/li&gt;&lt;/ol&gt;The alternative is to learn and adjust as you go. It's no surprise that this is how software projects have succeeded (when they've succeeded) over the years.&lt;br /&gt;&lt;br /&gt;&lt;table style="width: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="https://picasaweb.google.com/lh/photo/i4hCl6_EZ5dy29WYe6lgCi3OtjxAD-jJkFL1-F6N0xY?feat=embedwebsite"&gt;&lt;img height="480" src="https://lh4.googleusercontent.com/-WyvzspT5GnE/TqqhVMs5wFI/AAAAAAAABOs/kIvGtMa0d2E/s640/IMG_20110909_110510.jpg" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family: arial,sans-serif; font-size: 11px; text-align: right;"&gt;From &lt;a href="https://picasaweb.google.com/tottinge/AgileOtterBlog?authuser=0&amp;amp;authkey=Gv1sRgCJPZ-_SLqNLTYw&amp;amp;feat=embedwebsite"&gt;Agile Otter Blog&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Architectural decisions are hard to make once-for-all in a system where functionality and platform and development practices change fluidly. A good choice of language, platform, and early features will give us a good early start, but these decisions need to change (with requisite changes in code) if they no longer serve the needs of the business, which includes the need for fluid delivery of functionality to customers.&lt;br /&gt;&lt;br /&gt;Maybe finding the right thing is a combination of up-front thinking and ongoing discovery; maybe it always has been.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8078817953790964796?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8078817953790964796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/10/if-we-had-done-right-thing-to-begin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8078817953790964796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8078817953790964796'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/10/if-we-had-done-right-thing-to-begin.html' title='If We Had Done The Right Thing To Begin With'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh4.googleusercontent.com/-WyvzspT5GnE/TqqhVMs5wFI/AAAAAAAABOs/kIvGtMa0d2E/s72-c/IMG_20110909_110510.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6703638389229000141</id><published>2011-10-26T07:51:00.000-07:00</published><updated>2011-10-26T07:51:20.301-07:00</updated><title type='text'>What should the well-dressed virtualenv wear?</title><content type='html'>I'm back to hacking some python (fun stuff!) and have been noting some packages that every well-dressed virtualenv should have. I'm interested in knowing what you use, and for what.&lt;br /&gt;&lt;br /&gt;Essential packages I can hardly live without:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;bpython - because it's my favorite shell&lt;/li&gt;&lt;li&gt;sniffer - because CT is the bomb, and sniffer works on mac (autonose not so much)&lt;/li&gt;&lt;li&gt;mox - though I don't totally love it, I'm somewhat used to it now. May switch to something more context-manager-like.&lt;/li&gt;&lt;/ul&gt;Task-specific stuff:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;BeautifulSoup - if I'm parsing stuff. I really like this library&lt;/li&gt;&lt;li&gt;mechanize - if I'm writing tests on a web framework. Other than js weakness, it's quite nice&lt;/li&gt;&lt;li&gt;feedparser - for rss stuff&lt;/li&gt;&lt;li&gt;PIL - because image manipulation is no fun without it&lt;/li&gt;&lt;/ul&gt;What do you feel a well-dressed virtualenv should wear this season?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6703638389229000141?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6703638389229000141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/10/what-should-well-dressed-virtualenv.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6703638389229000141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6703638389229000141'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/10/what-should-well-dressed-virtualenv.html' title='What should the well-dressed virtualenv wear?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8939567276227803758</id><published>2011-10-05T09:56:00.000-07:00</published><updated>2011-10-05T09:56:57.554-07:00</updated><title type='text'>Mercurial team workflow</title><content type='html'>Dear Mercurial, I don't love you (yet).&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://secretgeek.net/image/mercurial_workflow_image.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="261" src="http://secretgeek.net/image/mercurial_workflow_image.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This looks fine if you only spend a few minutes in the 2-3-2-3 loop. On the other hand, if you're in a very busy team and there are refactorings going on (and when shouldn't there be?) then you will want to have a loop from 3 to 1 pretty darned often (at LEAST a handful of times a day).&lt;br /&gt;&lt;br /&gt;At step 1, "For a while" should mean "if a couple of commits have been made by coworkers."&lt;br /&gt;&lt;br /&gt;The problem I have with mercurial is that the process of pull, merge, commit is too cumbersome. I have coworkers who swear by rebase, and others who have been bitten enough that they're scared to death to use rebase, and instead pile up the "merge" commits.&lt;br /&gt;There needs to be some kind of change made, if only to fix rebase, because this work flow is broken for active, productive, agile teams.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8939567276227803758?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8939567276227803758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/10/mercurial-team-workflow.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8939567276227803758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8939567276227803758'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/10/mercurial-team-workflow.html' title='Mercurial team workflow'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1227919614018240800</id><published>2011-10-03T17:00:00.000-07:00</published><updated>2011-10-03T17:50:13.509-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='teams'/><category scheme='http://www.blogger.com/atom/ns#' term='multitasking'/><category scheme='http://www.blogger.com/atom/ns#' term='teamwork'/><category scheme='http://www.blogger.com/atom/ns#' term='retrospective'/><category scheme='http://www.blogger.com/atom/ns#' term='guided experience'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='feedback'/><category scheme='http://www.blogger.com/atom/ns#' term='attentive work'/><category scheme='http://www.blogger.com/atom/ns#' term='learning organization'/><category scheme='http://www.blogger.com/atom/ns#' term='tasks'/><category scheme='http://www.blogger.com/atom/ns#' term='agile coach'/><title type='text'>The First Puzzle Challenge</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;Today we held the first ever Puzzle Challenge at my client's site.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-3d6quiAgC9M/TopXTUFuUiI/AAAAAAAABNA/CYeXt8s5jYI/s1600/IMG_20111003_141933.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="239" src="http://3.bp.blogspot.com/-3d6quiAgC9M/TopXTUFuUiI/AAAAAAAABNA/CYeXt8s5jYI/s320/IMG_20111003_141933.jpg" width="320" /&gt;&lt;/a&gt;The goal of the challenge was for each team to pick a work style that aided them in getting the greatest number of puzzles completed in a very short time (10 minutes per sprint).  The set of puzzles to solved was a mix of crosswords, mazes, word-search, sudoku, word jumbles, and number blocks. The teams were told that there was no partial credit at the end of the ten minute sprint. The teams were given a menu of practices to choose from:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://4.bp.blogspot.com/-kCbiNtqwqhE/Too-D61YLwI/AAAAAAAABM4/LeA33ZkxGSI/s1600/PuzzleWorkstyleKey.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" float="left" height="400" src="http://4.bp.blogspot.com/-kCbiNtqwqhE/Too-D61YLwI/AAAAAAAABM4/LeA33ZkxGSI/s400/PuzzleWorkstyleKey.jpg" width="316" /&gt;&lt;/a&gt; &lt;/div&gt;Team members could one mode of adaptation, leadership, teamwork, noise level, and task switching. A style of 11111 would mean a 1 in each of these categories, a style strongly resembling an "ideal" organization in the buttoned-down 80s. A style of 33333 is basically a productive chaos, which might have been more widely recommended in the free-spirited 60s.&lt;br /&gt;&lt;br /&gt;Teams made an initial selection, then were allowed some adaptation. &lt;br /&gt;&lt;br /&gt;In initial selection of work style, teams tended toward twos or threes. As the challenge progressed and they realized how hard the "work" was and how short the time was, they tended to migrate toward 33333 in their style.&lt;br /&gt;&lt;br /&gt;Is it surprising that when the chips are down, they opted for &lt;i&gt;less&lt;/i&gt; command-and-control to help them increase speed?&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;.&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/-IAA3YKdZJE4/Too8EgqZ8sI/AAAAAAAABMo/9Ac5qG4_kvs/s1600/scorecard.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="149" src="http://3.bp.blogspot.com/-IAA3YKdZJE4/Too8EgqZ8sI/AAAAAAAABMo/9Ac5qG4_kvs/s200/scorecard.jpg" width="200" /&gt;&lt;/a&gt;Teams with the highest scores did a few surprising things. One is that they "cheated" by rejecting all work they could not accomplish easily within the 10-minute span. Although they were initially told that they should do the work in the priority order (as it was given to them), they quickly realized that the system was flawed and that taking on tasks larger than 10-minutes was a waste of their time and talent. Rejecting over-sized work gave them a distinctive edge. This is a lesson most agile teams should learn.&lt;br /&gt;&lt;br /&gt;Another advantage went to teams where people chose the work based on their skills and interests instead of having work handed to them by a strong leader or by following strict priority. Doing work that interested them, in areas where they had already developed skills, moved them forward. Even so, they found a huge disadvantage in working alone. Most puzzles had at least two people working on them by the end of the second sprint, and this trend continued through the end of the challenge. Even when skills differed, there was no other advantage as great as having a partner.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-4Jqo1JvPCnc/TopXmjyZviI/AAAAAAAABNI/ZXIVdMyjh_8/s1600/IMG_20111003_141920.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="239" src="http://1.bp.blogspot.com/-4Jqo1JvPCnc/TopXmjyZviI/AAAAAAAABNI/ZXIVdMyjh_8/s320/IMG_20111003_141920.jpg" width="320" /&gt;&lt;/a&gt;&lt;br /&gt;Teams were further accelerated if they found the "Work-In-Progress sweet spot."&amp;nbsp; If they had too much in progress, very little got finished. If they had too little in progress, stuff got done but scores were lower.&lt;br /&gt;&lt;br /&gt;Some teams stopped taking on new work at the 2 minute (remaining) mark. There was little chance in starting jobs that could not be finished by the end of the sprint. Instead they spent the time talking about how they could perform better on the next sprint. Again, a lesson worth learning.&lt;br /&gt;&lt;br /&gt;One challenge attendee said that he learned that chaos is hard to manage or predict, but it really helped get things done. I applaud his insight.&lt;br /&gt;&lt;br /&gt;I was a little disappointed that some rebel didn't totally crush it by using a style I would never have chosen. That would have been cool, if puzzling. I suppose I'll have to settle for having my agile mindset validated once again. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1227919614018240800?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1227919614018240800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/10/first-puzzle-challenge.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1227919614018240800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1227919614018240800'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/10/first-puzzle-challenge.html' title='The First Puzzle Challenge'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-3d6quiAgC9M/TopXTUFuUiI/AAAAAAAABNA/CYeXt8s5jYI/s72-c/IMG_20111003_141933.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-603070868970168482</id><published>2011-09-30T11:11:00.001-07:00</published><updated>2011-09-30T11:11:05.470-07:00</updated><title type='text'>Python History Visualized</title><content type='html'>&lt;iframe allowfullscreen="" frameborder="0" height="302" src="http://player.vimeo.com/video/1093745?title=0&amp;amp;byline=0&amp;amp;portrait=0" webkitallowfullscreen="" width="400"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/1093745"&gt;code_swarm - Python&lt;/a&gt; from &lt;a href="http://vimeo.com/michaelogawa"&gt;Michael Ogawa&lt;/a&gt; on &lt;a href="http://vimeo.com/"&gt;Vimeo&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-603070868970168482?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/603070868970168482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/python-history-visualized.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/603070868970168482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/603070868970168482'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/python-history-visualized.html' title='Python History Visualized'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5960302854057803220</id><published>2011-09-27T10:25:00.000-07:00</published><updated>2011-09-27T12:41:12.336-07:00</updated><title type='text'>Lean Startup and Efficiency</title><content type='html'>Poignant quote on working in cross-functional teams with learning milestones:&lt;br /&gt;&lt;blockquote&gt;"I predict that you pretty quickly will get feedback from your teams that the new process is reducing their productivity. They will ask to go back to the old way of working, in which they had the opportunity to “stay efficient” by working in larger batches and passing work between departments."&lt;/blockquote&gt;&lt;span class="Apple-style-span" style="font-size: xx-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: xx-small;"&gt;Ries, Eric (2011-09-13). The Lean Startup: How Today's Entrepreneurs Use Continuous Innovation to Create Radically Successful Businesses (p. 19). Crown Business. Kindle Edition.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5960302854057803220?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5960302854057803220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/lean-startup-and-efficiency.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5960302854057803220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5960302854057803220'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/lean-startup-and-efficiency.html' title='Lean Startup and Efficiency'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4409245893164694997</id><published>2011-09-27T08:32:00.000-07:00</published><updated>2011-09-27T10:28:43.418-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='management'/><title type='text'>Linus Torvalds Management Lessons</title><content type='html'>See the recent &lt;a href="http://h30565.www3.hp.com/t5/Feature-Articles/Linus-Torvalds-s-Lessons-on-Software-Development-Management/ba-p/440"&gt;article&lt;/a&gt; on management lessons from Linus Torvalds. &amp;nbsp;Some important call-outs:&lt;br /&gt;&lt;br /&gt;On external quality:&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="background-color: whitesmoke; color: #333333; font-family: Arial; font-size: 14px; line-height: 21px;"&gt;Torvalds concludes, “Way too many projects seem to think that the code is more important than the user, and they break things left and right, and they don't apologize for it, because they feel that they are ‘fixing’ the code and doing the right thing.”&lt;/span&gt;&lt;/blockquote&gt;On tooling:&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: whitesmoke; color: #333333; font-family: Arial; font-size: 14px; line-height: 21px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="background-color: whitesmoke; color: #333333; font-family: Arial; font-size: 14px; line-height: 21px;"&gt;“I don't think tools are all that fundamentally&amp;nbsp; important.”&lt;br /&gt;“Now, what is important is that there's&amp;nbsp;&lt;a href="http://h30565.www3.hp.com/t5/Feature-Articles/Designing-Workflows-as-if-People-Mattered/ba-p/47" style="color: #3399cc; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: none; outline-width: initial; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;" target="_blank"&gt;a good workflow for the project&lt;/a&gt;, and tools can certainly help with that,” said Torvalds. “But most projects don't necessarily really need tools. There's a lot of projects that simply don't have enough changes to really require any tools at all for their work flow;&amp;nbsp;[...]"&lt;/span&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4409245893164694997?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4409245893164694997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/see-recent-article-on-management.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4409245893164694997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4409245893164694997'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/see-recent-article-on-management.html' title='Linus Torvalds Management Lessons'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7469878848132505750</id><published>2011-09-26T14:19:00.000-07:00</published><updated>2011-09-26T20:41:43.839-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='accus'/><category scheme='http://www.blogger.com/atom/ns#' term='Coaching Camp'/><category scheme='http://www.blogger.com/atom/ns#' term='agile in a flash'/><category scheme='http://www.blogger.com/atom/ns#' term='agile coach'/><title type='text'>Agile Coaching Camp wrapup</title><content type='html'>I approached my second (their third) day of #ACCUS after a full night's sleep. The evening social time was great, because it involved some fine people. &lt;br /&gt;&lt;div&gt;I had two sessions, one each in the first and last timeslots of the day.&lt;/div&gt;&lt;div&gt;&lt;b&gt;Pairing Styles&lt;/b&gt;&lt;/div&gt;&lt;div&gt;The first was a little workshop to identify and evaluate pairing styles. I was there to collect data primarily, and I did. We mapped the styles I had identified and added to them. The best part was the conversation among the attendees as we tried to evaluate them. The emergent thesis is that styles are not inherently good or bad, but that they reveal the relationship of the partners. All styles could be energizing, or could be draining, depending primarily on:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The involvement they bring to the session&lt;/li&gt;&lt;li&gt;The degree to which they both focus on the code instead of each other&lt;/li&gt;&lt;li&gt;The degree to which each recognizes the contribution of the other&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;The Coaching Oracle Deck&lt;/b&gt;&lt;/div&gt;&lt;div&gt;This idea was based on Brian Eno's famous &lt;a href="http://imgs.xkcd.com/comics/sharing.png"&gt;Oblique Strategies&lt;/a&gt;&amp;nbsp;concept, and the fun of fortune cookies. Glen Smith and I played with the idea years ago (he introduced me to the idea), and even had a little program to pop up the strategies. Sadly, that code and the original list of ideas were lost. It came back up at Agile And Beyond in Ann Arbor this year, and I happened upon those cards while sorting through my stuff at ACCUS.&lt;/div&gt;&lt;div&gt;We play-tested it informally in the common area while sessions went on elsewhere. I figured it was worth a more formal play-test.&amp;nbsp;&lt;/div&gt;&lt;div&gt;I think that the session hit two snags. The first was that people were feeling much more emotionally involved as a result of other sessions going on that day, and the other was that I wasn't managing the pacing very well. Rather than play-testing a fun technique by stating a question and rating whether a randomly-drawn card just happened to be good advice in the scenario, we entered into a deeper talk about problems and possible directions. I really hadn't intended this to be a problem-solving session with deep emotional impact, but at an open space whatever happens is the only thing that could have.&amp;nbsp;&lt;/div&gt;&lt;div&gt;I suspect that the primary value of the cards is that they are generally good things to think about, the randomness of the draw means that they'll come out of left field, and considering them will help take us out of ourselves. This thesis was not supported by our session. &amp;nbsp;Instead, they were deeply considered, contextualized to the person drawing the card, and considered for their ability to point out a solution.&lt;/div&gt;&lt;div&gt;More on this as it happens.&lt;/div&gt;&lt;div&gt;&lt;b&gt;Other Thoughts of the Day&lt;/b&gt;&lt;/div&gt;&lt;div&gt;I hear that a couple of the sessions had people in tears, and approximated a self-help session far more than a professional conference. Certainly I felt that way with the "checking in" part of the session at the end, and the direction many of the "appreciations" took. I'm okay with that, and don't deny other people's need for it, but I'm either a little cold or a little emotionally squeamish, or perhaps just too focused on enjoying the work we do together to really participate. My primary feeling when I hear that a session had people in tears was, "glad I missed that." Maybe those people got more out of the conference than I did, I can't really say.&amp;nbsp;&lt;/div&gt;&lt;div&gt;On the other hand, I have a stack of new ideas and had some of my intentions and interests vetted and validated. I'm going to dig into more topics that will help me learn, analyze, and adapt my work. That's one of the reasons I've attended.&lt;/div&gt;&lt;div&gt;I also have new friends and contacts, and have connected with friends and colleagues. &amp;nbsp;This is the other reason I drove across the midwest in the middle of the night rather than going directly home to my family. &amp;nbsp;&lt;/div&gt;&lt;div&gt;It was &amp;nbsp;a very net-positive weekend, and I recommend Agile Coaching Camp to all my readers. &amp;nbsp;&lt;/div&gt;&lt;div&gt;Next year, in Minneapolis!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7469878848132505750?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7469878848132505750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/agile-coaching-camp-wrapup.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7469878848132505750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7469878848132505750'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/agile-coaching-camp-wrapup.html' title='Agile Coaching Camp wrapup'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5980491116711220685</id><published>2011-09-24T15:14:00.000-07:00</published><updated>2011-09-24T15:21:47.164-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dinwiddie'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='columbus'/><category scheme='http://www.blogger.com/atom/ns#' term='agile coach camp'/><category scheme='http://www.blogger.com/atom/ns#' term='crispin'/><category scheme='http://www.blogger.com/atom/ns#' term='agile coach'/><title type='text'>Agile Coach Camp U.S. - Saturday (#accus)</title><content type='html'>I missed the Friday session. I worked a full day in Des Moines and then drove 11 hours (and into an earlier time zone) overnight.&amp;nbsp;I only arrived this morning at about 4:30 or so and got parked and checked in. I slept from a little after 5 until 7, and then got up and headed to the conference after falling down some stairs and finally finding the conference site.&lt;br /&gt;&lt;br /&gt;Even tired, slightly battered, and a little frustrated, I had a wonderful day.&lt;br /&gt;&lt;br /&gt;I was pleased to meet up with many great coaches, devs, managers, and non-IT people here. I even have some new "new best friends."&lt;br /&gt;&lt;br /&gt;The morning sessions involved growing learning cultures, integrating project teams, and systems thinking. They were had great questions, wonderful discussions, and prankish humor. It was a great morning.&lt;br /&gt;&lt;br /&gt;I had intended to participate in the afternoon sessions, but the first one (on complacence, coincidentally) I missed to talk about other passions of mine with some of my coaching friends of old, and some brand new ones. We talked about coaching psychology, whether our coaching was necessarily agile, and how to avoid "going native."&lt;br /&gt;&lt;br /&gt;Entirely without any intention to do so, I missed all of the afternoon sessions. It was a really great time, though, and the contacts are very important to me.&lt;br /&gt;&lt;br /&gt;Tomorrow I'm running two sessions of the three time slots available, so I guess I can't miss much.&lt;br /&gt;&lt;br /&gt;In the morning we're cataloging pair programming patterns, and in the last session of the day we're playtesting an agile version of Eno's &lt;a href="http://www.rtqe.net/ObliqueStrategies/"&gt;"Oblique Strategies."&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There is a lot of interest in a new site/blog for posting and analyzing code, in the strategies deck, in Agile In A Flash, and in the new pair programming work that Jim Hood and I are starting to work on. I have great stuff to do and need to get cracking.&lt;br /&gt;&lt;br /&gt;I'm hoping to move one of my sessions so I can join George Dinwiddie and friends in a talk about metrics, but we'll see in the morning. I even had a minute or two with Lisa Crispin.&lt;br /&gt;&lt;br /&gt;I can recommend ACCUS for everyone in the business or in its periphery as a great meeting of minds. I'm tired, and yet it has kept me energized all day. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5980491116711220685?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5980491116711220685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/agile-coach-camp-us-saturday-accus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5980491116711220685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5980491116711220685'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/agile-coach-camp-us-saturday-accus.html' title='Agile Coach Camp U.S. - Saturday (#accus)'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5529337184544431846</id><published>2011-09-20T19:48:00.001-07:00</published><updated>2011-09-20T19:48:55.797-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='teamwork'/><category scheme='http://www.blogger.com/atom/ns#' term='build'/><category scheme='http://www.blogger.com/atom/ns#' term='version control'/><category scheme='http://www.blogger.com/atom/ns#' term='cooperation.'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>The Build is Broken, Now What?</title><content type='html'>Your team is hard at work, testing and coding and planning, and suddenly the build breaks.&amp;nbsp;Now what can you do? The broken build might not be your fault at all, and besides you have work of your own to do. You could go ahead and practice business-as-usual, but this is probably a bad idea.&lt;br /&gt;&lt;br /&gt;Here's what I say:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Never pull from a broken build. Assume that version control is poison. If you are not the one fixing the build (and shouldn't you be?) then you should leave it be. The last thing you want to do is import brokenness into your local build environment. Import from a "green" build, and you will know that any brokenness is your problem.&lt;/li&gt;&lt;li&gt;Test locally before considering pushing code to the CI build, even though it takes a bit more time. There is really no good time to NOT know that you've broken something. A little "due diligence" goes a long way.&lt;/li&gt;&lt;li&gt;Never push to the CI server if your local build is broken. If your build is broken, it inconveniences only you. If someone is working on the build and you push a second mistake, they won't know if they fixed it or broke it worse. If the build is not broken, why bother pushing errors to it?&amp;nbsp;&lt;/li&gt;&lt;li&gt;If you're not fixing the build, never push a working local change to a broken build. This is a kindness akin to not walking in the dirt your mother is sweeping up. If you push a change while the build is broken, the person fixing the build will have yet another update/build/test cycle on his hands before he can push his fix to the server. Don't punish the volunteer by pushing your changes. Wait, pull, merge, retest.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;We have installed annunciators for teams. Sometimes they are flashing lights, sometimes a glowing orb, sometimes speakers playing a particular noise, sometimes it's just a person standing up and yelling that the build is down. Usually there is some electronic communication (jabber message or email) as well.&lt;br /&gt;&lt;br /&gt;Why do we all need to know that the build is broken, and how long it is broken? So that we can alter our behavior. Someone needs to jump in and fix the build quickly, and everyone else needs to let them or help them. By leaving the build broken, continuing to build and push code as always, or pushing additional errors into the build, we are just getting in the way of the team.&lt;br /&gt;&lt;br /&gt;Build annunciators should let you know when you need to get out of the way. &amp;nbsp;They don't have to be piercing and shrill or overly bright, but they need to keep the team aware that the build is not "green."&lt;br /&gt;&lt;br /&gt;It's not just a good idea... well, actually it is.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5529337184544431846?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5529337184544431846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/build-is-broken-now-what.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5529337184544431846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5529337184544431846'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/build-is-broken-now-what.html' title='The Build is Broken, Now What?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7845316241052445956</id><published>2011-09-16T10:37:00.000-07:00</published><updated>2011-09-16T10:38:31.865-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clean code'/><category scheme='http://www.blogger.com/atom/ns#' term='naming'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='failure'/><title type='text'>Pycon: Examples of Atrocity in Python Programming</title><content type='html'>A nice discussion about things that should not be done in Python code, but frequently are.&lt;iframe src="http://blip.tv/play/g4VigquDJwI.html" width="550" height="442" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;embed type="application/x-shockwave-flash" src="http://a.blip.tv/api.swf#g4VigquDJwI" style="display:none"&gt;&lt;/embed&gt;Nice mention of Clean Code's naming rules (I'm a proud daddy).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7845316241052445956?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7845316241052445956/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/pycon-examples-of-atrocity-in-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7845316241052445956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7845316241052445956'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/pycon-examples-of-atrocity-in-python.html' title='Pycon: Examples of Atrocity in Python Programming'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1696537635325002296</id><published>2011-09-14T17:40:00.000-07:00</published><updated>2011-09-14T17:42:56.060-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='informative workspace'/><category scheme='http://www.blogger.com/atom/ns#' term='tim ottinger'/><category scheme='http://www.blogger.com/atom/ns#' term='information radiators'/><category scheme='http://www.blogger.com/atom/ns#' term='build'/><category scheme='http://www.blogger.com/atom/ns#' term='jenkins'/><category scheme='http://www.blogger.com/atom/ns#' term='feedback'/><category scheme='http://www.blogger.com/atom/ns#' term='attentive work'/><category scheme='http://www.blogger.com/atom/ns#' term='jim hood'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='extreme feedback'/><category scheme='http://www.blogger.com/atom/ns#' term='ambient annunciator'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>Ambient Annunciators</title><content type='html'>Jim Hood (of Pillar Technology) and I just installed our first ever "ambient annunciator" to announce our build's breakage. Well, technically our first two. What it does is watch for a build to fail in Jenkins, then start playing a series of randomly-selected choices from our assortment of spooky public domain sound files. Some are musical interludes, some are animal sounds, some are just weird.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-z5KoNBj-FjQ/TnFJU2lJNFI/AAAAAAAABH4/t6bGSkKu8Sc/s1600/Annunciator.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="238" src="http://4.bp.blogspot.com/-z5KoNBj-FjQ/TnFJU2lJNFI/AAAAAAAABH4/t6bGSkKu8Sc/s400/Annunciator.jpg" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Annunciator #2 video, woofer, and R/L speakers.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Our intention is that these sounds, playing through a decent set of speakers, will create an atmosphere of something being "not quite right." With both systems playing test noises, it was a tad eerie. You really felt that there was something different about the space. &lt;br /&gt;&lt;br /&gt;It is a bit more subtle than flashing lights, and we're hoping this will be an advantage. Developers will know the build is broken, and will have incentive to get the space back to normal (it is a little annoying) but will still be able to have conversations and won't get headaches associated with flashing lights.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1696537635325002296?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1696537635325002296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/ambient-annunciators.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1696537635325002296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1696537635325002296'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/ambient-annunciators.html' title='Ambient Annunciators'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-z5KoNBj-FjQ/TnFJU2lJNFI/AAAAAAAABH4/t6bGSkKu8Sc/s72-c/Annunciator.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-32141419474464753</id><published>2011-09-13T19:29:00.000-07:00</published><updated>2011-09-13T19:29:19.841-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='feedback'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum masters'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>How Do Scrum Masters Know?</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-1DwXObMhpmY/TnAP9dbBHXI/AAAAAAAABHs/m75K-_igxus/s1600/Screen+shot+2011-09-13+at+9.20.23+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="245" src="http://3.bp.blogspot.com/-1DwXObMhpmY/TnAP9dbBHXI/AAAAAAAABHs/m75K-_igxus/s400/Screen+shot+2011-09-13+at+9.20.23+PM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;How do Scrum Masters Know?&lt;/div&gt;This time the question is how the scrum masters know if they're doing a good job. They answered with this short list of feedback mechanisms.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Scrum of Scrums&lt;/li&gt;&lt;li&gt;Changes embodied in team behavior.&lt;/li&gt;&lt;li&gt;Retrospectives&lt;/li&gt;&lt;li&gt;Status of Kanban boards&lt;/li&gt;&lt;li&gt;Things missed&lt;/li&gt;&lt;/ul&gt;Overall, not a bad list. Your thoughts? &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-32141419474464753?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/32141419474464753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/how-do-scrum-masters-know.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/32141419474464753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/32141419474464753'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/how-do-scrum-masters-know.html' title='How Do Scrum Masters Know?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-1DwXObMhpmY/TnAP9dbBHXI/AAAAAAAABHs/m75K-_igxus/s72-c/Screen+shot+2011-09-13+at+9.20.23+PM.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4388105555542922938</id><published>2011-09-13T05:53:00.000-07:00</published><updated>2011-09-13T05:54:05.820-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clean code'/><category scheme='http://www.blogger.com/atom/ns#' term='duplication'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='error'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='failure'/><title type='text'>Learning from bad examples</title><content type='html'>I saw this in a python tutorial today:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if os.path.exists("/tmp/uPlayer"):&lt;br /&gt;   f = open("/tmp/uPlayer/STATUS", "w")&lt;br /&gt;   f.write("IDLE")&lt;br /&gt;   f.close&lt;br /&gt;else:&lt;br /&gt;   os.mkdir("/tmp/uPlayer")&lt;br /&gt;   f = open("/tmp/uPlayer/STATUS", "w")&lt;br /&gt;   f.write("IDLE")&lt;br /&gt;   f.close&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Really, now? We start by duplicating the whole open/write thing in order to create a directory? Maybe one of the problems people have with clean coding is that their examples are poor. If you write, it behooves you to write &lt;a href="http://butunclebob.com/ArticleS.BobKoss.RefrigeratorCode"&gt;refrigerator code.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Not to mention that close is a function, so it needs parentheses. This code doesn't even do what it thinks it is doing. It's closing the file when f goes out of scope, not when we reference the f.close bound method. &lt;/p&gt;&lt;p&gt;It makes me sad for the children.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4388105555542922938?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4388105555542922938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/learning-from-bad-examples.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4388105555542922938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4388105555542922938'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/learning-from-bad-examples.html' title='Learning from bad examples'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8965410103862649835</id><published>2011-09-12T11:51:00.000-07:00</published><updated>2011-09-12T11:52:23.098-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum master'/><category scheme='http://www.blogger.com/atom/ns#' term='tasks'/><title type='text'>Scrum Master Duties</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-rc-s9Ibf7pY/Tm5UdY_0NwI/AAAAAAAABHg/OxWHvxHn9VM/s1600/Snap3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="393" src="http://2.bp.blogspot.com/-rc-s9Ibf7pY/Tm5UdY_0NwI/AAAAAAAABHg/OxWHvxHn9VM/s640/Snap3.jpg" width="640" /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;This is the result from asking a team of scrum masters what their duties entail.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;What do you think? &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8965410103862649835?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8965410103862649835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/scrum-master-duties.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8965410103862649835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8965410103862649835'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/scrum-master-duties.html' title='Scrum Master Duties'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-rc-s9Ibf7pY/Tm5UdY_0NwI/AAAAAAAABHg/OxWHvxHn9VM/s72-c/Snap3.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8912451375178556388</id><published>2011-09-06T07:29:00.000-07:00</published><updated>2011-09-07T06:21:57.485-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='teamwork'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>You Cannot Possibly Do TDD after Coding</title><content type='html'>Just for the record: it is flat out impossible to "do the tdd" after the code is finished. This is just a matter of definition.&lt;br /&gt;&lt;br /&gt;You can write tests after the code is finished, but that has no relationship to TDD whatsoever. None. Nada. Zip.&lt;br /&gt;&lt;br /&gt;In TDD you write a new, failing test. Next you write enough code to pass the test. Then you refactor. This repeats until the code is done, writing and running tests continually. It shapes the way the code is written. It is a technique for making sure you write the right code, and that you do so in an incremental and iterative way.&lt;br /&gt;&lt;br /&gt;In ATDD, you have a failing acceptance tests. You take the first failing tests (or the easiest) and use TDD to build the code so that that part of the AT passes. You run the AT after each major step that you've built using TDD. When the AT is all green, you have completed the feature. This helps avoid early stop and also helps avoid gold-plating.&lt;br /&gt;&lt;br /&gt;If tests were product, then it would make no difference whether you do them first or last, and redundancy would be silly and worth avoiding.&lt;br /&gt;&lt;br /&gt;If tests are rightfully seen as process, then redundancy is "coherence" and not worth avoiding.  It helps us move forward.&lt;br /&gt;&lt;br /&gt;The biggest problem with TDD is that if you're not doing the process, then the product (tests) don't make sense.&lt;br /&gt;&lt;br /&gt;Hate TDD? Then there's a good chance you're not actually doing it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8912451375178556388?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8912451375178556388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/09/you-cannot-possibly-do-tdd-after-coding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8912451375178556388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8912451375178556388'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/09/you-cannot-possibly-do-tdd-after-coding.html' title='You Cannot Possibly Do TDD after Coding'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2326778889251581798</id><published>2011-08-29T18:14:00.000-07:00</published><updated>2011-08-31T06:46:40.114-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clean code'/><category scheme='http://www.blogger.com/atom/ns#' term='getting things done'/><category scheme='http://www.blogger.com/atom/ns#' term='refactoring poop method comment cleanup'/><category scheme='http://www.blogger.com/atom/ns#' term='fear'/><title type='text'>Poop: The Refactoring Method</title><content type='html'>I developed an quirky technique for dealing with the intermediate states of a refactoring. I call it the "poop" method (no biological metaphor implied). This method is far less controversial than one might suspect, but it is mildly unsettling.&lt;br /&gt;&lt;br /&gt;I find myself working in a legacy code base. Refactoring requires me to take several small steps, each of which leaves a sub-optimal intermediate state. I decide to mark the code with some kind of comment that will indicate that the work there is incomplete. &lt;br /&gt;&lt;br /&gt;It needs to be a word that doesn't normally appear in code, and which is clearly and obviously undesirable. If I put TODO, it will either get lost in the other TODOs left by well-intentioned people, or else will be stopped by a lint tool that takes such things seriously. Most obscenities would also be a little too likely to be duplicated by someone having a bad day.&lt;br /&gt;&lt;br /&gt;My marker comment should not be something so obscene that it will offend or embarrass myself or my reviewers.  Something common in baby-talk and yet biologically insensitive will work. I add a comment that says merely "poop." The fact of the comment being in my code creates a mild sense of uneasiness. After all, I don't want my colleagues finding it in production code.&lt;br /&gt;&lt;br /&gt;As I finish my refactoring, I do a global search. Sure enough, the word only appears where I've written it in as a marker. As long as I clean up the code and remove the markers, nobody will find a "poop" in my code. &lt;br /&gt;&lt;br /&gt;Actually, once my friend George and I left a "poop" in our code. Our coworkers found it. It was easy to tell we'd been caught because the pair looking at the code were laughing and asking why it would say that. It was a little reminder that all was not complete and tidy in our little world. We immediately fixed the code and removed the comment.  &lt;br /&gt;&lt;br /&gt;I have also used this as an indicator that I need to rename a method. If I don't know what to call a method or test initially, the word 'poop' reminds me that I need to revisit that code and determine why it is hard to name. Usually poor naming is a sign of poor design; well-designed components seem to practically name themselves. &lt;br /&gt;&lt;br /&gt;Maybe you object to the word, but that's okay. The value of the poop method is ensuring you will be uneasy in the presence of unfinished work. Come up with your own variation (be nice) and see how it changes your work habits. &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2326778889251581798?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2326778889251581798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/08/poop-refactoring-method.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2326778889251581798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2326778889251581798'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/08/poop-refactoring-method.html' title='Poop: The Refactoring Method'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4434000209083667952</id><published>2011-08-12T11:11:00.000-07:00</published><updated>2011-08-12T11:14:47.019-07:00</updated><title type='text'>Agile2011 Day 4</title><content type='html'>This was a wonderful, long, crazy day.&lt;br /&gt;&lt;br /&gt;I woke up with a &lt;a href="http://tottinge.blogsome.com/2011/08/11/connectedness/"&gt;meditation&lt;/a&gt; on my mind. I was feeling calm, happy, centered. Morning routine was a breeze, and the walking route to the conference hotel is much more comfortable than the old one.&lt;br /&gt;&lt;br /&gt;I spent a lot of time in coaches' corner again. I met some really nice people and had some great talks. I learned the "S.C.A.R.F." acronym and how to use it. I saw old friends. I met new friends. &lt;br /&gt;&lt;br /&gt;The Grand American hotel is a wonderful conference hotel. It is comfortable, attractive, and divides into smaller areas nicely. The staff are ninjas, keeping the place clean and preparing for all the events and reconfigurations quickly and quietly. In fact, if you turn your back on your soda, it may totally disappear. James Grenning gave me a glass emblazoned with his book cover, and I had to guard it carefully lest it be swept away by cleaning ninjas. They are so quiet, polite, and efficient that one can never be annoyed with them. They are all superheroes.&lt;br /&gt;&lt;br /&gt;I saw the few remaining Agile In A Flash cards (all sold out by end of day) and the three signed copies in the auction (also gone now). This has been a good week for us as authors, and there are new connections and new initiatives that have opened up to us because of Agile In A flash. It is all the more satisfying because the idea was so unusual and only Pragmatic Programmers understood what we were up to. I had a good time talking with other authors, coaches, consultants. I fear to list them all, because I will not remember all of them, but will mention that I really enjoyed chatting with Diana Larsen who I just met. She's invited me to a greater participation in some work at the Agile Alliance fringe and with other professional coaches like myself (perhaps better).&lt;br /&gt;&lt;br /&gt;I was sad to see that my &lt;a href="http://industriallogic.com/"&gt;Industrial Logic&lt;/a&gt; colleague, Bill Wake, was scheduled give a talk on breaking down stories at 3:30, the same time as my Agile Apologetic talk. Then I found that my coauthor, Jeff Langr was scheduled to give his talk about whether to buy agile tools at the same time. My talk was small but we were engaged and attendees seemed to have a good time. Jeff's and Bill's were better attended, and I hear they were quite good. I suspect my lightning talk on Tuesday will the be one most likely remembered. &lt;br /&gt;&lt;br /&gt;When I was done in Coaches' Corner I made it outside to see the freerunners, and was in a cloud of people (new friends and old) which was swept into the grand ballroom. Matt Barcomb and I appropriated an empty table, which soon became the "cool table" as we crunched together to allow more people to join. Lean Dog brethren joined us and entertained us. We watched a trampoline team do arial skiing and arial gymnastics and arial snowboarding. They were amazing olympic athletes, and one was even a contestant in American Ninja Warrior (obstacle course game show).  The final scheduled entertainment was a band playing classics old and new, but they were sadly plagued with sound problems. &lt;br /&gt;&lt;br /&gt;Following the scheduled entertainment I was invited to a room party which included many recognized great people of the Agile community and many sharp newcomers. Bonnie introduced us to fire spinning via two led-light green balls on chains, which stood in the place of actual fire. We took turns being schooled in elementary moves and it was a good time. I also had time to argue with Bryan Beachum. I talked with Diana and George and Jeff about the possibilities of helping to create cirriculum, and talked over general coaching stuff with James Shore. It was a really great time, but lasted longer into the evening/morning than I'm accustomed.&lt;br /&gt;&lt;br /&gt;I've new friends and new ideas, and so ended day 4.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4434000209083667952?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4434000209083667952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/08/agile2011-day-4.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4434000209083667952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4434000209083667952'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/08/agile2011-day-4.html' title='Agile2011 Day 4'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7704109792569719394</id><published>2011-08-11T09:01:00.000-07:00</published><updated>2011-09-08T06:08:04.752-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cheap'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='scheduled'/><category scheme='http://www.blogger.com/atom/ns#' term='retrospective'/><category scheme='http://www.blogger.com/atom/ns#' term='free'/><category scheme='http://www.blogger.com/atom/ns#' term='learning organization'/><category scheme='http://www.blogger.com/atom/ns#' term='change'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><category scheme='http://www.blogger.com/atom/ns#' term='schedule'/><title type='text'>Free, Cheap, Scheduled: retrospective technique</title><content type='html'>I was telling Esther Derby about a little trick I worked out some time ago at one of my clients. The retrospectives had gone stale, with team members offering the same "we should..." list iteration after iteration. &amp;nbsp;I suspected that they didn't feel that they really had the authority or permission to change their process for the better.&lt;br /&gt;&lt;br /&gt;I had a good relationship with the CIO and wandered into his office.&lt;br /&gt;&lt;br /&gt;I said, "we have some changes we want to make, and they won't really cost any money or affect other departments, and I just wondered if you think it would be okay to do them." &amp;nbsp;The CIO looked at me incredulously, "Of course. That's a silly question to ask."&lt;br /&gt;&lt;br /&gt;"Alright, then there is this other change. &amp;nbsp;It might take a few man days out of each iteration, but it will be helpful for the team. &amp;nbsp;Would that be okay?" &amp;nbsp;He sighed, "If it's a few man days per iteration, we can afford that. Go ahead and take that time. You don't need my permission for that."&lt;br /&gt;&lt;br /&gt;I paused a few seconds for effect. "We also have recognized some tough changes we need to make. &amp;nbsp;They might take a few man weeks out of an iteration. &amp;nbsp;Would those be okay?"&lt;br /&gt;&lt;br /&gt;This time I got a few seconds of silence in return. "Tim, we can do that kind of change, but we have to schedule it. We can't put releases at risk, and we have promises to fulfill, so we just need to make sure we do them at the right time. &amp;nbsp;They need to be worth it, but we can do that."&lt;br /&gt;&lt;br /&gt;I thanked the CIO and wandered back to my team in time for the retrospective. &amp;nbsp;The team identified many of the same problems, and proposed the same solutions they hadn't worked on the last few times. I went up to the flip chart and divided it into three sections called "Free", "Cheap", and "Scheduled." I explained that these categories had been approved by the CIO and we should begin making changes immediately after the retro.  I asked them to pick things they really wanted to do.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-k98XaaBWr6w/TkP7yxkLhTI/AAAAAAAABBA/wuAIzRVxiA4/h301/11+-+1" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-k98XaaBWr6w/TkP7yxkLhTI/AAAAAAAABBA/wuAIzRVxiA4/h301/11+-+1" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The team put changes into the correct buckets, and we picked the ones they felt that they had the energy to work on. The scrum master took the task of moving the "scheduled" items into the schedule, the rest we started on immediately.&lt;br /&gt;&lt;br /&gt;If your team is having trouble believing that they really have permission to "spend money" making changes to they way they work, maybe you will find this technique useful. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7704109792569719394?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7704109792569719394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/08/free-cheap-scheduled-retrospective.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7704109792569719394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7704109792569719394'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/08/free-cheap-scheduled-retrospective.html' title='Free, Cheap, Scheduled: retrospective technique'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6521666179315585754</id><published>2011-08-10T22:50:00.000-07:00</published><updated>2011-08-10T22:50:26.228-07:00</updated><title type='text'>Agile2011 Day 3</title><content type='html'>I just can't get it in my head this was Wednesday. &amp;nbsp;I'm very tired. &amp;nbsp;I'm an introvert, you know, and we draw energy from alone time or time with a small number of close friends. &amp;nbsp;Being in rooms with hundreds of people most of the time is really work. &amp;nbsp;On the other hand, I get energy from my work, and spent a lot of time talking about work.&lt;br /&gt;&lt;br /&gt;I spent the morning with Michelle from NavTeq, talking about people, processes, transitions, and strategies for making other people more successful. I'd re-met a fellow from NavTeq after my talk on pairing yesterday, so it's cool that I'm seeing so many of my Chicago cousins. I'm hoping to see more of them in the future.&lt;br /&gt;&lt;br /&gt;I attended a tool demo later, but I didn't realize it was a testing tool for C#. I thought it was going to be a talk on how to bring testers and coders closer together and blur the lines between them. I left disappointed, but on the way out met a nice fellow who is a new scrum master. We chatted until time for lunch.&lt;br /&gt;&lt;br /&gt;Lunch I had with a number of my Deere friends (heh). Deere sent a lot of delegates to this conference, which really speaks to their level of management support. Thanks to the John Deere executives who made it possible for all these good people to come, absorb, learn, and converse with the constellation of Agile dignitaries here. May they pay you back tenfold in fresh learning and new techniques.&lt;br /&gt;&lt;br /&gt;After lunch I went to GeePaw Hill's talk on geek leadership. I learned some useful techniques that I will put into practice in the near future. It's good to have smart friends.&lt;br /&gt;&lt;br /&gt;Later I ended up mostly hanging out, populating coaches' corner, and eating food. I saw a lot of good people. I met people who have been following my blogs (always a kick for a blogger) and showed off the card deck. I also had some good responses to my talk yesterday "will pair programming ruin my company."&lt;br /&gt;&lt;br /&gt;Today there was an announcement that Industrial Logic and Version One have a strategic agreement. Announcements focus on V1 market our eLearning as part of their offerings. I have new brothers.&lt;br /&gt;&lt;br /&gt;Tomorrow Jeff Langr and I will be pushing the limits of acceptable behavior in our individual talks. He has a talk on "the only agile tools you really need" (a must-see, controversy-stirring feast of common sense) and I will present "the fundamental agile apologetic." &amp;nbsp;Actually, &amp;nbsp;I only hope it will be a fundamental apologetic, but I have decided to allow the talk to go in new directions if need be. &amp;nbsp;Teaching, learning -- I'll be doing at least one of the two.&lt;br /&gt;&lt;br /&gt;It's hard to say what tomorrow will bring, but it should be interesting at least.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6521666179315585754?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6521666179315585754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/08/agile2011-day-3.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6521666179315585754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6521666179315585754'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/08/agile2011-day-3.html' title='Agile2011 Day 3'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-502744663715962634</id><published>2011-08-10T13:06:00.000-07:00</published><updated>2011-09-08T06:12:47.351-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='teamwork'/><category scheme='http://www.blogger.com/atom/ns#' term='pair programming'/><category scheme='http://www.blogger.com/atom/ns#' term='objections'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Pairing Styles</title><content type='html'>Overall, pair programming isn't as controversial as you've heard. It depends on your styles of pairing. Some styles of pairing are very common, even among non-agile teams. They tend to be episodic, and last just long enough to get or give some aid. The good news is that they work. If a team views pairing with trepidation, these are common, non-threatening forms to start with:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Rescue Pairing&lt;/li&gt;&lt;li&gt;Training Pairing&lt;/li&gt;&lt;li&gt;Brainstorming&lt;/li&gt;&lt;li&gt;Experimenter/Researcher&lt;/li&gt;&lt;/ul&gt;Others are such bad ideas that they are rightfully avoided by all sane teams I've seen so far. &amp;nbsp;If you are considering pairing, and a team member balks, you should see if their mental model of pairing matches one of these styles. I suspect a team should decide that these styles will never be practiced personally, or tolerated within the team's pod. &amp;nbsp;You have my blessings to object to pairing if "pairing" means:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Worker/Rester&lt;/li&gt;&lt;li&gt;Worker/Watcher&lt;/li&gt;&lt;li&gt;Master/Slave&lt;/li&gt;&lt;li&gt;Bully/Victim&lt;/li&gt;&lt;li&gt;Writer/Critic&lt;/li&gt;&lt;li&gt;Ball-and-chain pair marriage&lt;/li&gt;&lt;/ul&gt;And then there is the form of pairing that matters most.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Peer pairing&lt;/li&gt;&lt;/ul&gt;Peer pairing is about two people who know what they are doing, who have skills, who are not stuck or lost or confused, designing and implementing ideas as fast as they can. A peer pair constantly vets ideas, tries alternatives, detects surprising failure modes, revises plans, teaches, learns, experiments, laughs, tests, commiserates, and grows together. &amp;nbsp;At least for a few great, exciting, exhausting hours.&lt;br /&gt;&lt;br /&gt;The problem with peer pairing is that to the observer it might seem like rescue pairing or training. If you are always being trained or always being rescued, then you might seem like you're not much of a programmer. &amp;nbsp;In this case, seeming is the enemy of being. A team may be so concerned about seeming competent by not pairing that they don't increase their competence by peer pairing. &amp;nbsp;I suggest that this is a human foible, and we have to recognize.&lt;br /&gt;&lt;br /&gt;When we talk about pair programming, we usually intend peer pairing (and the other good types at the top of the list), but people often hear us as meaning one or more of the bad types in the middle. &lt;br /&gt;&lt;br /&gt;I hope to rephrase the question. &amp;nbsp;When you tell me you "don't believe in pair programming" then I hope to ask you about the pair programming you object to. &amp;nbsp;Chances are I will feel the same way, and with that out of the way we can talk about the kinds of pairings we might actually try.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-502744663715962634?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/502744663715962634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/08/pairing-styles.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/502744663715962634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/502744663715962634'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/08/pairing-styles.html' title='Pairing Styles'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8942134017165380905</id><published>2011-08-10T12:30:00.000-07:00</published><updated>2011-08-10T12:30:19.222-07:00</updated><title type='text'>Agile2011 Day 2</title><content type='html'>A lot of today was spent in the Coaches' Corner, where several more convention-goers were served with expert advice.&lt;br /&gt;&lt;br /&gt;I spent a chunk of my "alone time" today working on my "Agile Fundamental Apologetic" talk for Thursday (Fringe stage). &amp;nbsp;I hope to establish that if we weren't doing agile, we would have to do something very like it. I even got to pair on some of the slides, which was a great time.&lt;br /&gt;&lt;br /&gt;Jeff was finalizing his Test Abstraction talk (based on our Agile In A Flash card), in which he showed some poorly-composed Fitnesse tests, and some much more well-composed, abstract versions of the same test. It was practical and useful. I think he opened testers' eyes to new possibilities, and that 7 minutes talk will have reverberations in many places. &lt;br /&gt;&lt;br /&gt;After Jeff's talk was my own. Mine was titled "Will Pair Programming Ruin My Company?" in which I answered a few questions I've heard from managers over the years. Given how much controversy and resistance arise over this crucial practice, I think the talk was well-timed. It was also well-received. I had a great room, appreciative and inquisitive and thoughtful.&lt;br /&gt;&lt;br /&gt;I also did a very small, personal session on my Agile Coaching Metaprocess. &amp;nbsp;Actually, it was a conversation with two people, one of which has heard it a million times already. &amp;nbsp;It wasn't a box office smash, but I've given the same talk with others through the week.&lt;br /&gt;&lt;br /&gt;Quite a bit of time was spend in talks about consortiums, guilds, and interest groups. There are many great ideas bubbling under the surface of the Agile Alliance umbrella. &amp;nbsp;I spent the evening (late into the evening) having supper with an impressive group of agile luminaries. I know I was impressed. &amp;nbsp;We talked about providing programmers with an agile education. &amp;nbsp;Of course, as an Industrial Logic member this was of interest, but it has also been a long-term interest of mine as an agile coach. Thanks to Matt Barcomb for putting the evening together.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8942134017165380905?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8942134017165380905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/08/agile2011-day-2.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8942134017165380905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8942134017165380905'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/08/agile2011-day-2.html' title='Agile2011 Day 2'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2330666302509902962</id><published>2011-08-08T20:35:00.000-07:00</published><updated>2011-08-08T20:35:44.314-07:00</updated><title type='text'>Agile2011 Day 1</title><content type='html'>This has been a very good day. &amp;nbsp;I was able to staff the Coaches' Corner and visit with other coaches when we weren't engaged with convention-goers. &amp;nbsp;I enjoy the interaction, though I'm admittedly an introvert.&lt;br /&gt;&lt;br /&gt;Jeff Langr is here, and we were able to talk about many things and even promote the Agile In A Flash deck. &amp;nbsp;Three copies went to the live aid silent auction.&lt;br /&gt;&lt;br /&gt;I was looking dapper in my blue Industrial Logic shirt and sharing the Agile love and coaching philosophy with people who were interested. We talked about measurement, e-learning, and raising self-coaching teams. We talked about business and busyness and listened to many stories. &amp;nbsp;I was also given a Lean Dog fuzzy hat, which I sometimes wore when I wasn't feeling to warm or was unconcerned about creating mental ambiguity about my situation.&lt;br /&gt;&lt;br /&gt;This place is a who's who of object mentor alumni. All my old friends have new gigs and new ideas and it's wonderful to see them all.&lt;br /&gt;&lt;br /&gt;The ice breaker is over, and I'm about to wander off to join some friends, but I wanted to mention to any attendees that I'm speaking tomorrow, a lightning talk on "will pair programming ruin my company." Teaser: it just might.&lt;br /&gt;&lt;br /&gt;Good night to all.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2330666302509902962?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2330666302509902962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/08/agile2011-day-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2330666302509902962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2330666302509902962'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/08/agile2011-day-1.html' title='Agile2011 Day 1'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6344814543063449882</id><published>2011-08-01T05:22:00.000-07:00</published><updated>2011-08-01T05:22:28.506-07:00</updated><title type='text'>Leadership</title><content type='html'>I'm doing some reading and some experiencing, keeping my eyes open for the concept of leadership. &lt;br /&gt;&lt;br /&gt;One can see leadership as a combination of visibility and confidence. This seems to work out pretty well, as an observation in arrears. Leaders who are successful often have high visibility and make decisions with a high confidence that things will work out well.&lt;br /&gt;&lt;br /&gt;When leadership works, I see it as the leader understanding the team and promoting the team by &amp;nbsp;improving the teams alignment with the hierarchy of the company and its customers, making use of the team's strengths, and helping . Such a path seems to grow confidence, and the success gives visibility to the team and its leaders. This is the slow, steady path.&lt;br /&gt;&lt;br /&gt;I see some leaders succeed by other means, some seeming rather virtuous and others less so. I'm particularly critical of those who see leadership as wresting authority from others though political games and social manipulation. Such leaders may actually inspire confidence, since the leader is seen as growing in influence and respect. It may bring such a leader up the hierarchy quickly, but will also tend to give the leader a shaky support base. For such a person, support is something comes from the hierarchy and the role of follower must be inflicted on competitors. It is a quick path, but the innate self-centeredness competitiveness may result in a very unpopular position and many enemies.&lt;br /&gt;&lt;br /&gt;A juvenile view of leadership is that it is about being seen and telling others what to do; a starring role with the hierarchy and team as&amp;nbsp;supporting cast. This seldom translates into the kind of leadership any organization really needs, but is quite reasonable. After all, a leader is visible and has authority.&lt;br /&gt;&lt;br /&gt;I'm leaning toward the idea that he leader I want to be is the guy who prepares the way for the team, aligns them with the hierarchy and customers, and looks for ways to help them achieve their goals more fluently.&lt;br /&gt;&lt;br /&gt;I'm still most motivated by our &lt;a href="http://agileinaflash.blogspot.com/2010/01/best-leadership.html"&gt;B.E.S.T.&lt;/a&gt; leadership card. I find it sums up all the best leaders I've known.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6344814543063449882?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6344814543063449882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/08/leadership.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6344814543063449882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6344814543063449882'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/08/leadership.html' title='Leadership'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2711507785682980551</id><published>2011-07-18T19:25:00.000-07:00</published><updated>2011-07-18T19:25:09.873-07:00</updated><title type='text'>Fun with Squish and Python</title><content type='html'>At my current gig, we are using Squish to test a new QT-based GUI app. It's been a hoot. Squish is frameworks, eclipse, and python. Oh, yes, squishy yummy python.&lt;br /&gt;&lt;br /&gt;To start with, we used the QT interface to start measuring and checking UI widgets. There are some very exacting standards on color, placement, and size of visual elements and squish is helping get the specs converted to a runnable form.  This was my original goal for the tool. &lt;br /&gt;&lt;br /&gt;The team was recording tests post-facto, so I jumped in and we build up some libraries and syntax sugar so that it's easy to build the tests before the code. Hopefully we'll see a lot less code being returned over minutae now that programmers can run the specifications while they're building the code.&lt;br /&gt;&lt;br /&gt;The next step was to automate to the simulators that sit under the app. This was delivered last week, and we added some more sweet syntactic sugar to make it easy to script simulators in the gui tests. It's still not lightning-fast, but it does the job. There was quite the buzz about it, as it enables the company to do a lot of end-to-end testing and demonstration.&lt;br /&gt;&lt;br /&gt;Squish is an interesting environment, and they did a few things I didn't care for like adding an 'object' module which hides the built-in type. I've learned to work around some of the &lt;i&gt;gotcha&lt;/i&gt;s so those don't bother me too much. It was just an interesting learning experience.&lt;br /&gt;&lt;br /&gt;What I love is that the environment allows me (a developer) to provide rather powerful support to the testers on the team, and allows them to do quite a bit of programming in a way that it resembles simple data tables and English. Those who've stopped by for the demos have remarked that the tests read clearly enough that they can understand and critique them.  &lt;br /&gt;&lt;br /&gt;Our next trick will be using Squish and PIL to test some aspects of UI rendering that are not really feasible in native Squish and QT. This has been a fun trip so far, and we'll see where it takes us next.&lt;br /&gt;&lt;br /&gt;I have mixed thoughts about gui testing. It is slow and requires you to stand up a complete image (with all that mean in setup and teardown). It scales better than manual testing, but can have a certain brittleness that manual testing to textual scripts does not. Even so, Squish does a good job and covers our platforms, so I think I'll stay with it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2711507785682980551?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2711507785682980551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/07/fun-with-squish-and-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2711507785682980551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2711507785682980551'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/07/fun-with-squish-and-python.html' title='Fun with Squish and Python'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4690441704370040227</id><published>2011-06-28T08:20:00.000-07:00</published><updated>2011-09-08T06:13:32.356-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='guided experience'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='microtests'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='eLearning'/><title type='text'>Microtesting Python Album</title><content type='html'>I'm working with Industrial Logic's newest Python album on &lt;a href="http://bit.ly/glEjP7"&gt;microtesting&lt;/a&gt; (not yet released) and was lucky enough to get to test out the automated critique. &lt;br /&gt;&lt;br /&gt;So the way this eLearning works is that you download a problem to work on, and you're given tasks to perform. In this case, it's all about writing microtests for some simple python code. When you finish, you upload your results and an automated critique system digs through the code and gives you ratings and pointers. This is rather like having a mentor sitting with you, reviewing the code.&lt;br /&gt;&lt;br /&gt;I tell people that the eLearning here is something like they've never seen, but people think I'm marketing or something.  Today I have a story for you:&lt;br /&gt;&lt;br /&gt;Yesterday I made a mistake and the automated critique busted me. The mistake was one where I constructed an object incorrectly and invalidated the premise of the test, yet I did this in such a way that the test passed for the wrong reason. I was feeling so sure I'd done it correctly that I thought the  critique was wrong.  I pasted a copy of the test into my error report before I realized I was in the wrong.&lt;br /&gt;&lt;br /&gt;The coolness didn't stop there, though. Through all of this, my tests looked nothing like the tests that were presented in the course material. The eLearning system allowed for my stylistic differences only flagged the actual error in my code.&lt;br /&gt;&lt;br /&gt;Slightly humbled, I corrected my test and uploaded it again for analysis. This time I was 100%. The online course gave me advice and allowed me to try again. &lt;br /&gt;&lt;br /&gt;When it comes to developing skills, anyone in the business will tell you that guided experience is the best teacher, but I've never seen a system guide my skill development like this one does.  Today I found out there's even more guiding intelligence on the way. Watch this space for details.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4690441704370040227?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://bit.ly/glEjP7' title='Microtesting Python Album'/><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4690441704370040227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/06/microtesting-python-album.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4690441704370040227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4690441704370040227'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/06/microtesting-python-album.html' title='Microtesting Python Album'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5377782663089857374</id><published>2011-06-21T16:38:00.000-07:00</published><updated>2011-09-08T09:17:50.797-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='short reach'/><category scheme='http://www.blogger.com/atom/ns#' term='iterations'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='practices'/><category scheme='http://www.blogger.com/atom/ns#' term='techniques'/><category scheme='http://www.blogger.com/atom/ns#' term='yesterdays weather'/><title type='text'>Short Reach Revived</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Verdana,Helvetica,sans-serif; font-size: 12px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;h2 class="title" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;This first appeared on the &lt;a href="http://www.objectmentor.com/"&gt;Object Mentor&lt;/a&gt; blog in 2007, but I had to get a cached copy from google to reread it. I'm reviving it here so we don't lose it forever. I think it is still carries a valid point, and I would like to revisit it in the near future.&lt;/span&gt;&lt;/h2&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif; font-size: x-large;"&gt;Short Reach&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Posted by tottinger on Monday, April 23, 2007&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I’m always trying to find newer, better, shorter, more powerful ways to explain what Agile is about. I suppose I’m some kind of obsessive about expressive power and economy.&lt;br /&gt;&lt;br /&gt;Finally I decided that Agile, as I understand it today, is about the short reach.&lt;br /&gt;&lt;br /&gt;It seems to me that all of the agile practices are about shortening our reach, the distance in time-and-space that one leaves an assumption, decision, or line of code untested and unconfirmed. All the practices seem to follow this one rule.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The customer/analyst is keep in the same room, in the same short reach.&amp;nbsp;&lt;/li&gt;&lt;li&gt;We feed back the iterations to the customer/analyst so that his every decision has a shorter reach.&amp;nbsp;&lt;/li&gt;&lt;li&gt;We do iterations to ensure our planning has short reach.&amp;nbsp;&lt;/li&gt;&lt;li&gt;We keep our teammates very close, in the same room, so that it’s a shorter reach to them.&amp;nbsp;&lt;/li&gt;&lt;li&gt;The test is written first, so that implementation has shorter feedback on correctness.&amp;nbsp;&lt;/li&gt;&lt;li&gt;We compile/test frequently because our code time should have a short reach.&amp;nbsp;&lt;/li&gt;&lt;li&gt;We pair so that our code is instantly vetted through a peer. We don’t pile it up and review it after the tests pass.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Our planning is based on “yesterday’s weather”, data collected a very short time ago.&amp;nbsp;&lt;/li&gt;&lt;li&gt;We don’t plan the team structure and the assignments, we self-organize so that tasks are waiting for the shortest time possible.&amp;nbsp;&lt;/li&gt;&lt;li&gt;We talk face-to-face, not across chat and email and official company documents.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Tell-dont-ask and the Law of Demeter guide us in keeping the reach of our objects very short.&amp;nbsp;&lt;/li&gt;&lt;li&gt;We use unit tests to exercise a class directly, and we isolate with mocks to reduce the reach of our tests through the system.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Shared code ownership means that the guy sitting behind your keyboard has all the permission he needs to do excellent work, even if it impacts existing design.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Test-first development means that the guy who makes a change knows very quickly whether his change is safe or not. He doesn’t have to wait until the week before integration when the “real” tests are run.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Where does Agile run into logistical or operational difficulties? Wherever a long reach is required or imposed. Where an organization chooses to continue in waterfall-style management, where the team is distributed among managers with appointed “point of contact” and “official channels”, and where the developers are not placed in a common work area agility is very difficult.&lt;br /&gt;&lt;br /&gt;I’m not saying that agile techniques can’t work for large companies, but that is an area where a lot of experts are trying (maybe succeeding) to extend the agile techniques and where the average “agilist” finds challenges. When it works, it is almost certain it will be because someone has found a way to shorten the reach of the teams so that all they need to know is never more than a few seconds or minutes away.&lt;br /&gt;&lt;br /&gt;At least that’s my half-baked observation of the day. Let me know if I’m wrong here. Or if I’m more right than I think I am.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5377782663089857374?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5377782663089857374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/06/short-reach-revived.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5377782663089857374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5377782663089857374'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/06/short-reach-revived.html' title='Short Reach Revived'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-650829338893718443</id><published>2011-05-19T08:30:00.000-07:00</published><updated>2011-05-19T08:31:19.755-07:00</updated><title type='text'>Get Back On Track</title><content type='html'>There are hard times, and things can pile up. Don't wallow. Don't spend time trying to feel better. &amp;nbsp;Try to get back on track.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Things can get you down, so you need to borrow energy from others. &amp;nbsp;Try user groups, pairing, friends, fun programming exercises.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Quit thinking you should be able to do new things all alone. &amp;nbsp;Getting up to speed is always dicey, and best done with someone who is already up to speed.&amp;nbsp;&lt;/li&gt;&lt;li&gt;If problems are short-term, like a flooded basement, broken lawnmower, minor health troubles, a child's academic crisis, &amp;nbsp;take time for them so you can get back on track sooner. Get it over with.&lt;/li&gt;&lt;li&gt;If the problem is long-term, start building up the emotional muscle to deal with it, which means getting on with life despite the long-term trouble and trying to cope with whatever "long-term trouble" is going to mean.&lt;/li&gt;&lt;li&gt;When you're not feeling particularly confident (ie depressed) don't get caught up in large meta-issues. Keep your focus on smaller things you can achieve. Build a quick triage rule to help determine what you can deal with right now. &amp;nbsp;Big issues will stop you dead in your tracks.&lt;/li&gt;&lt;li&gt;Get UNSTUCK.&lt;/li&gt;&lt;li&gt;Don't waste time, find new uses for it.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-650829338893718443?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/650829338893718443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/05/get-back-on-track.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/650829338893718443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/650829338893718443'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/05/get-back-on-track.html' title='Get Back On Track'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6143879156313962947</id><published>2011-05-17T19:41:00.000-07:00</published><updated>2011-05-17T19:41:59.082-07:00</updated><title type='text'>GOing to Software Craftsmanship McHenry County</title><content type='html'>I was a little overwhelmed with how slowly I'm absorbing information, especially while dealing with household issues (like gas fumes from garage and flooding in basement) on top of trying to do something worthwhile (ANYthing) at work. It's just the way life comes at you sometimes.&lt;br /&gt;&lt;br /&gt;My escape for the night was running out to a meeting of &lt;a href="http://mchenry.softwarecraftsmanship.org/"&gt;Software Craftsmenship McHenry County&lt;/a&gt; (SCMC). This was my second meeting ever. &amp;nbsp;I mis-timed the trip and ended up a few minutes behind the start of&amp;nbsp;Steven Degutis' slide show. Pizza and pop were in good supply though, so I settled in and enjoyed a presentation on the language Go.&lt;br /&gt;&lt;br /&gt;Go is a strange little language, but a lot of fun. We had a quick presentation, thankfully mostly consisting of code examples, and then were given time to dive in. &amp;nbsp;Even though I'd been kind of blue and a little angry all day, I was soon laughing and having a great time while we tried to find ways to clutter a perfectly simple little problem's solution with threads and channels and anonymous functions. It was almost a reverse kata, where the goal was to be as overly sophisticated and absurd as possible.&lt;br /&gt;&lt;br /&gt;In the course of making and fixing mistakes, we learned a little, shared a little, and bonded over the absurd joy of it. &amp;nbsp;I left in a much better mood than I came, and in that joyful mood I'm writing this blog entry.&lt;br /&gt;&lt;br /&gt;I'm reminded again that when I stagnate, it's because I allow myself to feel the enormity of the world of things I don't know and to feel alone in the face of it. &amp;nbsp;I find again that the answer is to join into a little community; pairing or comparing, learning or teaching, playing or working. Sometimes there is a lot of release in having a silly little problem and some crazy peers to share it with.&lt;br /&gt;&lt;br /&gt;If you are in the far NW burbs and like to program or like to learn about programming, give SCMC a chance. It's a group of people of varying ages and experiences where you can feel unashamed and enjoy programming education as a harmless&amp;nbsp;pastime. Heck, you might even learn something useful.&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6143879156313962947?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6143879156313962947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/05/going-to-software-craftsmanship-mchenry.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6143879156313962947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6143879156313962947'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/05/going-to-software-craftsmanship-mchenry.html' title='GOing to Software Craftsmanship McHenry County'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4483812945470035759</id><published>2011-05-16T06:50:00.000-07:00</published><updated>2011-05-16T09:01:34.149-07:00</updated><title type='text'>Chicago Code Camp 2011</title><content type='html'>I spent the day at &lt;a href="http://chicagocodecamp.com/"&gt;Chicago Code Camp&lt;/a&gt;. &amp;nbsp;It's a good thing because it's a pretty pure conference for programmers. It's all run by volunteers, all free, all in one day, all short talks (1 hour).&lt;br /&gt;&lt;br /&gt;CLC had good wifi, plenty of space. Actually, one of the problems we had was finding out where the registration desk and refreshments were "hidden" in the huge Technology Building. &amp;nbsp;I came in a different door than organizers expected, as did dozens of us who were found wandering the halls. &amp;nbsp;We like calling that the "mandatory fitness segment."&lt;br /&gt;&lt;br /&gt;One of the things that is particularly good is that you can quickly guage where you stand with the community, what people want to hear about, and what people want to talk about. &lt;br /&gt;&lt;br /&gt;The first presentation I attended was on refactoring javascript, and programmers were rapt. They wanted to know about testing and test frameworks, how to do the refactoring steps, and how to incorporate the tests in in CI. The introductory topics included refactoring, unit testing, and dealing emotionally with 'tangled code'. &amp;nbsp;I sometimes felt that the presenter was quoting from things I have written about naming and the like, but I think that mostly he was pulling from the same sources as Jeff and I did with &lt;a href="http://agileinaflash.com/"&gt;agile in a flash&lt;/a&gt;. I picked on the presenter a little, and gave him a deck of Agile In A Flash cards as a kind of apology. &amp;nbsp;I hope he likes them.&lt;br /&gt;&lt;br /&gt;The second talk was on git. I was surprised how few people knew about git and how to use it. There were more microsofters there than I expected, and they were using VSS and the m$ team server stuff, subversion, and cvs. &amp;nbsp;There were few of us who used git, bzr, hg. &amp;nbsp;I suppose that means we need to talk and write and present more on agile version control, or it means we're far enough ahead of the parade taht nobody is really interested. &amp;nbsp;Folks in the group would get confused and walk out.&lt;br /&gt;&lt;br /&gt;The third session I had planned to listen to either Michael Norton (&lt;a href="http://twitter.com/#!/docondev"&gt;@docondev&lt;/a&gt;), but against my earlier plans I ended up checking out the talk on &lt;a href="http://bit.ly/ikaevs"&gt;WebSockets and Pusher &lt;/a&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: Arial, 'Helvetica Neue', sans-serif; font-size: 15px; line-height: 19px;"&gt;&amp;nbsp; with Damien Tanner (&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: Arial, 'Helvetica Neue', sans-serif; font-size: 15px; line-height: 19px;"&gt;&lt;a class="  twitter-atreply" data-screen-name="dctanner" href="http://twitter.com/dctanner" rel="nofollow" style="color: #0084b4; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; white-space: nowrap;"&gt;&lt;span class="at" style="color: #0084b4; display: inline-block; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; opacity: 0.5; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; white-space: nowrap;"&gt;@&lt;/span&gt;&lt;span class="at-text" style="color: #0084b4; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; white-space: nowrap;"&gt;dctanner&lt;/span&gt;&lt;/a&gt;)&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: Arial, 'Helvetica Neue', sans-serif; font-size: 15px; line-height: 19px;"&gt;&amp;nbsp;and&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: Arial, 'Helvetica Neue', sans-serif; font-size: 15px; line-height: 19px;"&gt;&lt;strong style="font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Dave&lt;/strong&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: Arial, 'Helvetica Neue', sans-serif; font-size: 15px; line-height: 19px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: Arial, 'Helvetica Neue', sans-serif; font-size: 15px; line-height: 19px;"&gt;&lt;strong style="font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Hoover&lt;/strong&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: Arial, 'Helvetica Neue', sans-serif; font-size: 15px; line-height: 19px;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: Arial, 'Helvetica Neue', sans-serif; font-size: 15px; line-height: 19px;"&gt;&lt;a class="  twitter-atreply" data-screen-name="redsquirrel" href="http://twitter.com/redsquirrel" rel="nofollow" style="color: #0084b4; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; white-space: nowrap;"&gt;&lt;span class="at" style="color: #0084b4; display: inline-block; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; opacity: 0.5; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; white-space: nowrap;"&gt;@&lt;/span&gt;&lt;span class="at-text" style="color: #0084b4; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; white-space: nowrap;"&gt;redsquirrel&lt;/span&gt;&lt;/a&gt;). &amp;nbsp;Damien was a surprise guest. &amp;nbsp;It was handy that the author of the pusher shows up to join Dave's talk. One feature of the talk was the audience's impatience to see code. God bless the Code Camp audience. Questions about performance were not long in coming.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The latter part of the day was spent in Clojure with Micah Martin (a face from my old Object Mentor days) and Gnu Smalltalk with Steve Kim. Both were enjoyable. I am not a Clojure nor a Smalltalk guy, but I was able to keep up and enjoy both the presentation and the conversation.&lt;br /&gt;&lt;br /&gt;A few quick observations:&lt;br /&gt;* People were using vim, textmate, and emacs; they were not using IDEs much&lt;br /&gt;* Macs are platform of choice even though this conference series is known for windows devs.&lt;br /&gt;* The ratio of sexes was far skewed to the male side.&lt;br /&gt;* The age mix was much more even. There were probably as many 50+ as teens, and 40s as 20s.&lt;br /&gt;* Even with a rep for having microsoft developers, there were many platform-agnostic language talks.&lt;br /&gt;* Organizers did a very good job for a free (sponsor-supported) conference.&lt;br /&gt;* CLC in Greyslake, IL has a great facility.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4483812945470035759?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4483812945470035759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/05/chicago-code-camp-2011.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4483812945470035759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4483812945470035759'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/05/chicago-code-camp-2011.html' title='Chicago Code Camp 2011'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6933759876928220080</id><published>2011-05-10T13:18:00.000-07:00</published><updated>2011-05-10T13:18:45.905-07:00</updated><title type='text'>Agile Coaching Stories</title><content type='html'>This is your turn to brag, complain, and post observations.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;If you were on an agile transition, it is likely that your company hired a coach. &amp;nbsp;The coach may have been awesome, may have been horrible, and may even have been me. &amp;nbsp;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;I'm interested in your stories. Were you pleased? Disappointed? Did you learn things you didn't even know you needed to learn? What was the long-term impact on the coach your team, your skillset, or your company?&amp;nbsp;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6933759876928220080?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6933759876928220080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/05/agile-coaching-stories.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6933759876928220080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6933759876928220080'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/05/agile-coaching-stories.html' title='Agile Coaching Stories'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1824082855868472887</id><published>2011-05-07T17:12:00.000-07:00</published><updated>2011-05-07T21:32:33.582-07:00</updated><title type='text'>Adhesion Example</title><content type='html'>A while back, Glenn Vanderburg wrote an &lt;a href="http://www.vanderburg.org/blog/Software/Development/cohesion.rdoc"&gt;article about software cohesion v. software adhesion&lt;/a&gt;. Today I got a great example of adhesion.&lt;br /&gt;&lt;br /&gt;We are starting our second year in the house. It is a quirky house and I know it was managed by people who were self-reliant, so there are always some odd surprises here and there. It kind of reminds me of a legacy code base, because the product (house) is pretty good, and mostly meets our needs and many of our desires. &amp;nbsp;We got it because we liked it and because it fit our price range, and it helps us with other goals (close to train station, 15 minutes from church, nearer friends, nearer my son's school, etc).&lt;br /&gt;&lt;br /&gt;Today I needed to change a bulb in the upstairs shower for the first time. &amp;nbsp;I was stymied at first, because the cover didn't have any visible way to remove it. &amp;nbsp;The glass cover didn't have a catch, didn't screw off, didn't have a release detent that I could twist to release, nothing. &amp;nbsp;I finally decided that the outer plastic ring must drop down, but it didn't want to. &lt;br /&gt;&lt;br /&gt;The cover had been caulked and painted to the ceiling, rendering the incandescent 70-watt bulb a permanent fixture of the house. &amp;nbsp;Think about that for a minute. In order to change a lightbulb, I have to tear into the ceiling of the shower. When I pulled down the outer ring, I found it was indeed made to pull down and release in order to change light bulbs, but I suppose the former owners were in a hurry when they put it in. &lt;br /&gt;&lt;br /&gt;The ceiling was cut a little larger than it needed to be for the fixture. With the ring up, it leaves a little opening here and there. &amp;nbsp;To fix that, it looks like they just glued the hole with caulk and then painted it over so it didn't look so bad. &amp;nbsp;It seemed fine when I bought the place.&lt;br /&gt;&lt;br /&gt;It sounds like a particularly bad design to me, because in order to solve one problem (not enough light in the shower) I have cause and then fix another one (holes in the ceiling). It is more disturbing to me because I'm not skilled in drywall repair or showers. &amp;nbsp;I'm going to have to ask for help now (another problem for me) to make sure I fix this in a way that doesn't cause more trouble in the future.&lt;br /&gt;&lt;br /&gt;It didn't have to be that way.&lt;br /&gt;&lt;br /&gt;This house really is organic in the way that legacy code is organic: things just sort of become the way they are through minimal effort and short-term problem-solving. &amp;nbsp;Nobody designed the house to have a hole in the ceiling or a permanent lightbulb, but that's how it is. &amp;nbsp;It's is as if "crappy" was a feature, and it probably sounded like a good cost/benefit tradeoff at the time. After all, a lightbulb over the shower should last for years, and caulking and painting are not hard to do.&lt;br /&gt;&lt;br /&gt;I am not going to obsess over the issue, and I've got the bulb changed, but I am going to put in a fix that makes the lightbulb a supply instead of a permanent fixture. I'm putting in a florescent bulb this time, and it may last a long time, but the next time we need to make a change it won't be a big hassle. It will be easy. &amp;nbsp;I don't want to become accustomed to doing unsatisfying hacks in my house.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1824082855868472887?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1824082855868472887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/05/adhesion-example.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1824082855868472887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1824082855868472887'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/05/adhesion-example.html' title='Adhesion Example'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8560888255192838238</id><published>2011-05-06T15:07:00.000-07:00</published><updated>2011-05-06T15:07:13.659-07:00</updated><title type='text'>Organizing Stepwise Considered Harmful</title><content type='html'>There are different ways to organize repeating code. &lt;br /&gt;&lt;br /&gt;One is step-wise, in which near-identical steps are stacked together:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;button1 &lt;span style="color: #990000;"&gt;=&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;QPushButton&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'Button 1'&lt;/span&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;br /&gt;button2 &lt;span style="color: #990000;"&gt;=&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;QPushButton&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'Button 2'&lt;/span&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;button1&lt;span style="color: #990000;"&gt;.&lt;/span&gt;clicked&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;connect&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;lambda&lt;span style="color: #990000;"&gt;:&lt;/span&gt; self&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;on_button&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: #993399;"&gt;1&lt;/span&gt;&lt;span style="color: #990000;"&gt;))&lt;/span&gt;&lt;br /&gt;button2&lt;span style="color: #990000;"&gt;.&lt;/span&gt;clicked&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;connect&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;lambda&lt;span style="color: #990000;"&gt;:&lt;/span&gt; self&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;on_button&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: #993399;"&gt;2&lt;/span&gt;&lt;span style="color: #990000;"&gt;))&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;layout&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;addWidget&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;button1&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;br /&gt;layout&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;addWidget&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;button2&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The other is subject-wise where the code for button1 is separated from the code for button2:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="Apple-style-span" style="font-family: Times; white-space: normal;"&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="font-size: inherit;"&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;button1 &lt;/span&gt;&lt;span style="color: #990000;"&gt;=&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt; &lt;/span&gt;&lt;span style="color: navy; font-weight: bold;"&gt;&lt;span style="color: black;"&gt;QPushButton&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'Button 1'&lt;/span&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;&lt;br /&gt;button1&lt;/span&gt;&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;clicked&lt;/span&gt;&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="color: navy; font-weight: bold;"&gt;&lt;span style="color: black;"&gt;connect&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;lambda&lt;/span&gt;&lt;span style="color: #990000;"&gt;:&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt; self&lt;/span&gt;&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="color: navy; font-weight: bold;"&gt;&lt;span style="color: black;"&gt;on_button&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: #993399;"&gt;1&lt;/span&gt;&lt;span style="color: #990000;"&gt;))&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;layout&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;addWidget&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;button1&lt;/span&gt;&lt;/tt&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;&lt;span style="color: #990000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;&lt;span style="color: #990000;"&gt;&lt;/span&gt;button2 &lt;/span&gt;&lt;span style="color: #990000;"&gt;=&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt; &lt;/span&gt;&lt;span style="color: navy; font-weight: bold;"&gt;&lt;span style="color: black;"&gt;QPushButton&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'Button 2'&lt;/span&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="font-size: inherit;"&gt;button2&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;clicked&lt;/span&gt;&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="color: navy; font-weight: bold;"&gt;&lt;span style="color: black;"&gt;connect&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;lambda&lt;/span&gt;&lt;span style="color: #990000;"&gt;:&lt;/span&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt; self&lt;/span&gt;&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="color: navy; font-weight: bold;"&gt;&lt;span style="color: black;"&gt;on_button&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: #993399;"&gt;2&lt;/span&gt;&lt;span style="color: #990000;"&gt;))&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;&lt;span style="color: #990000;"&gt;&lt;span class="Apple-style-span" style="color: black; font-family: Times; white-space: normal;"&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;layout&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;addWidget&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;button2&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;div&gt;The step-wise version makes the code repetition more obvious, but the novice code-cleaner is likely to extract constants to variables and leave it alone. &amp;nbsp;In the second case (subject-wise) the code-cleaner is more likely to realize that there is a multiple-step process that can be extracted to a function, leaving something more like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;CreateButtonWithAction&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;span class="Apple-style-span" style="color: navy;"&gt;layout&lt;/span&gt;&lt;/span&gt;&lt;/tt&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;&lt;span style="color: #990000;"&gt;, &lt;/span&gt;&lt;span style="color: red;"&gt;'Button 1',&amp;nbsp;&lt;/span&gt;&lt;/tt&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;lambda&lt;span style="color: #990000;"&gt;:&lt;/span&gt; self&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;on_button&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: #993399;"&gt;1&lt;/span&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;&lt;span class="Apple-style-span" style="color: black; font-family: Times; white-space: normal;"&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;CreateButtonWithAction&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;span class="Apple-style-span" style="color: navy;"&gt;layout&lt;/span&gt;&lt;/span&gt;&lt;/tt&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;&lt;span style="color: #990000;"&gt;, &lt;/span&gt;&lt;span style="color: red;"&gt;'Button 2',&amp;nbsp;&lt;/span&gt;&lt;/tt&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;lambda&lt;span style="color: #990000;"&gt;:&lt;/span&gt; self&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;on_button&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: #993399;"&gt;2&lt;/span&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;At this point it becomes obvious that the only difference in the two lines is two constant values, which might suggest more ways to simplify the code. &amp;nbsp;The astute observer will also recognize that the first parameter in the call is always the layout class, which suggests a wrapper class or "move method" which will in turn result in a more well-developed abstraction. Well-developed abstractions make writing client code easier and quicker.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="font-size: inherit;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;tt style="font-size: inherit;"&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;layout&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;.&lt;/span&gt;&lt;/tt&gt;&lt;/span&gt;CreateButtonWithAction&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;/tt&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;&lt;span style="color: red;"&gt;'Button 1',&amp;nbsp;&lt;/span&gt;&lt;/tt&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;lambda&lt;span style="color: #990000;"&gt;:&lt;/span&gt; self&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;on_button&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: #993399;"&gt;1&lt;/span&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: Times; white-space: normal;"&gt;&lt;pre style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tt style="font-size: inherit;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;tt style="font-size: inherit;"&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;layout&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;.&lt;/span&gt;&lt;/tt&gt;&lt;/span&gt;CreateButtonWithAction&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;/tt&gt;&lt;tt style="color: navy; font-size: inherit;"&gt;&lt;span style="color: red;"&gt;'Button 2',&amp;nbsp;&lt;/span&gt;&lt;/tt&gt;&lt;span class="Apple-style-span" style="color: navy;"&gt;lambda&lt;span style="color: #990000;"&gt;:&lt;/span&gt; self&lt;span style="color: #990000;"&gt;.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: black;"&gt;on_button&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #990000;"&gt;(&lt;/span&gt;&lt;span style="color: #993399;"&gt;2&lt;/span&gt;&lt;span style="color: #990000;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;I'm not saying that this is the ultimate, optimal form for the code to take. &amp;nbsp;I'm only saying that once it is organized subject-wise, the refactoring starts to flow very naturally.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8560888255192838238?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8560888255192838238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/05/organizing-stepwise-considered-harmful.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8560888255192838238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8560888255192838238'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/05/organizing-stepwise-considered-harmful.html' title='Organizing Stepwise Considered Harmful'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5637787179908269966</id><published>2011-05-03T07:43:00.000-07:00</published><updated>2011-05-03T07:43:59.114-07:00</updated><title type='text'>Why Not?</title><content type='html'>I have officially declared 2011 the year of "Why not?"&lt;br /&gt;&lt;br /&gt;I don't mean "why not" in the sense of doing anything possible without thinking about it. I'm actually thinking it is a good year to ask why we can't do things, or why we won't do things, because it is interesting to understand the forces behind it.&lt;br /&gt;&lt;br /&gt;Take personal development. Who among us has done all they planned to do regarding new tech, new languages, projects to start, products to build in the past year? Who would not have benefitted from reading a book, doing some kata, learning a new language, or writing something new? And yet we do not.&lt;br /&gt;&lt;br /&gt;Let's refuse to commit the Fundamental Attribution Error here, and not say "because they don't care" or "because they're lazy." &amp;nbsp;A ton of information is available about improving a person's ability to program, or the number of platforms and tools they can program with, and yet most people don't reach beyond the level that is absolutely necessary for them to muddle through at work.&lt;br /&gt;&lt;br /&gt;Why not?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5637787179908269966?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5637787179908269966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/05/why-not.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5637787179908269966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5637787179908269966'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/05/why-not.html' title='Why Not?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7757057199440644469</id><published>2011-04-21T08:53:00.000-07:00</published><updated>2011-04-21T08:53:17.420-07:00</updated><title type='text'>Java's Greatest Hits And Misses</title><content type='html'>If you were mentoring someone who is pretty new in java, you would surely tell them about JUnit and your favorite mocking framework and the language grammar. However, you know that Java is a culture and a history and a spoken language as much as a written language. You would start talking about jakarta, or tomcat, or a DI, or a bean, or a war file, or eclipse workspaces and your apprentice would scratch his head and stammer. &amp;nbsp;The truth of the matter is that the grammar isn't but 10% of what java programmers know.&lt;br /&gt;&lt;br /&gt;Which projects would you have your student study in order to soak up the rich history, culture, and language of the java programmer? What are Java's greatest hits and misses?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7757057199440644469?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7757057199440644469/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/04/javas-greatest-hits.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7757057199440644469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7757057199440644469'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/04/javas-greatest-hits.html' title='Java&apos;s Greatest Hits And Misses'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7804141343805435229</id><published>2011-04-08T20:04:00.000-07:00</published><updated>2011-04-11T08:18:44.968-07:00</updated><title type='text'>"Managing" Velocity</title><content type='html'>The term &lt;i&gt;velocity&lt;/i&gt; is very well-chosen. It means speed in a certain direction, with the intention that it refers to the teams rate of travel toward a product release.&amp;nbsp; I have suggested that&lt;a href="http://blog.objectmentor.com/articles/2008/04/02/velocity-is-just-capacity"&gt; velocity is just capacity&lt;/a&gt; and my intention was good and maybe even right in many ways. Velocity is the practical measure of our capacity being applied toward the completion of a release. The term still stands superior to my older suggestion.&lt;br /&gt;Lets start with the definition that velocity is the speed of progress in a given direction. &lt;br /&gt;&lt;br /&gt;The direction part gets missed. People (including my slightly younger self) want to do things like track bugs ("&lt;a href="http://en.wikipedia.org/wiki/Lean_services#Value_Demand_and_Failure_Demand"&gt;failure demand&lt;/a&gt;") as velocity. It might be good to see how much capacity is being lost to failure demand, but it is not velocity toward the same goal, not really.&amp;nbsp; We don't want to know that the team is busy, we want to see when the project will be done. &lt;i&gt;So we do not count bugs toward velocity.&lt;/i&gt; We want to see quality problems drive velocity down; that's what velocity measurement is for. If bugs are driving velocity down, wrap a bunch of tests around your &lt;a href="http://pragprog.com/magazines/2011-03/software-volatility"&gt;most volatile&lt;/a&gt; or &lt;a href="http://agileotter.blogspot.com/2010/10/heatmap-new-hotness.html"&gt;hottest code&lt;/a&gt; and clean it up. Watch what happens to velocity after an iteration or two.&lt;br /&gt;&lt;br /&gt;Some think that when I don't offer partial credit or bug points or  meeting points it is because I don't care about velocity, but it is  actually because I care too much about it to pollute it. Done well, velocity is the speed toward a goal. &lt;br /&gt;&lt;br /&gt;The fact that we use words like "velocity" and "sprint" makes it  sound like we are in a race. Indeed, one can see the goal as one of  releasing as quickly as possible, and we can all applaud that goal. What, then, is the  ideal velocity of a team? Infinity? Isn't faster always better? It feels wrong to have a velocity "dip" and teams will go to great lengths (often the wrong ones) to shore up their numbers.&lt;br /&gt;&lt;br /&gt;Too often a team will turn to &lt;a href="http://www.softwarequalityconnection.com/2011/04/an-agile-pace/"&gt;chronic overtime&lt;/a&gt; to &lt;a href="http://agile.dzone.com/news/stabilizing-velocity"&gt;fix the velocity problem&lt;/a&gt;.  This is a huge mistake. Velocity is the amount of capacity spent in the  direction of completing a release, and attempting to inflate capacity  does not solve the problem.&amp;nbsp; In fact, &lt;a href="http://www.planningforfailure.com/post/1461931855/the-problem-with-working-overtime"&gt;overtime just leads to bigger, more unpredictable problems.&lt;/a&gt;  Agile method are supposed to uncover problems, so just be &lt;a href="http://agileinaflash.blogspot.com/2009/02/courage.html"&gt;transparent&lt;/a&gt; and let velocity become useful. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Instead, we should actually increase the amount of capacity toward a goal by eliminating wasteful practices, wait states, wasted efforts. We should increase our capacity by making the code more workable and the team more skillful. We might improve our velocity quite a bit if we do it in ways that make our future easier than our past has been. The work might get easier and more pleasant over time instead of being a never-ending "trudge in the sludge."&lt;br /&gt;&lt;br /&gt;This leaves us with velocity as the rate progress at constant, sustainable pace toward a goal.&lt;br /&gt;&lt;br /&gt;Even so, velocity will fluctuate. You don't have the same capacity to expend every week. Maybe you're tired from overtime, or life at home is requiring more attention. Maybe it is because estimates are imprecise or because each iteration has  troubles of its own. Maybe exciting new features need to be vetted by the team. Maybe a member gets pulled out for sales support. There could be an illness or a birth. Don't bother trying to force  velocity. It will stabilize well enough if you don't mistreat it. Then you can separate normal variation from special variation and can monitor the trends over time&lt;br /&gt;&lt;br /&gt;If velocity is going to have some normal variation, then wise managers know to plan with a little slack. If you run your team at 100% capacity, there is no reserve to help with technical or requirement issues, no way to allow a programmer to participate in the proposal process or vet sales' ideas for new features. One dental appointment or sudden bout of the stomach flu would ruin your plans of success. Too much &lt;a href="http://www.amazon.com/Slack-Getting-Burnout-Busywork-Efficiency/dp/0767907698"&gt;good content&lt;/a&gt; is written for me to try to do this topic justice, so I'll spare you.&lt;br /&gt;&lt;br /&gt;Velocity should be a measure of actual, non-waste progress toward a goal at a sustainable pace. For planning, velocity is the same but with a prudent amount of slack figured in based on the team's history of normal variation. &lt;br /&gt;&lt;br /&gt;This is a lot of opinion and some link-mongering, but I only promised to write up a quick summary of my thoughts. I've done my part. According to the deal on Twitter, it's your turn to start beating on it so we both may learn something from the exchange.&lt;br /&gt;&lt;br /&gt;Cheers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7804141343805435229?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7804141343805435229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/04/managing-velocity.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7804141343805435229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7804141343805435229'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/04/managing-velocity.html' title='&quot;Managing&quot; Velocity'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1243350326374300171</id><published>2011-04-04T15:23:00.000-07:00</published><updated>2011-04-04T15:23:00.187-07:00</updated><title type='text'>Overtime on Agile Teams?</title><content type='html'>My recent article on &lt;a href="http://bit.ly/fpHWfB"&gt;Overtime and Agile Teams&lt;/a&gt; was accepted and published in &lt;a href="http://softwarequalityconnection.com/"&gt;Software Quality Connection&lt;/a&gt;.&amp;nbsp; Here are a few statements extracted from the article to summarize its direction:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"Predicating project plans on constant overtime is a bad idea."&amp;nbsp;&lt;/li&gt;&lt;li&gt;"Agile requires whole people." &lt;/li&gt;&lt;li&gt;"Overtime is for bumps."&lt;/li&gt;&lt;li&gt;"You have to ask if your overtime is hiding problems instead of exposing them so that the team can solve them." &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1243350326374300171?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1243350326374300171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/04/overtime-on-agile-teams.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1243350326374300171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1243350326374300171'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/04/overtime-on-agile-teams.html' title='Overtime on Agile Teams?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4421237350578139289</id><published>2011-04-04T09:06:00.000-07:00</published><updated>2011-04-04T09:06:26.089-07:00</updated><title type='text'>My OSS Software (inventory)</title><content type='html'>What I need to replace when I get the new machine:&lt;br /&gt;&lt;br /&gt;Chrome, Firefox, Midori: Browsers - usually two or more open at one time.&lt;br /&gt;gvim, git, svn, poor ole' cvs: Essentials for software dev, b/c I often have three or four bash sessions open.&lt;br /&gt;Miro, Gpodder: audio and video subscribe/play - free video, audio, kept consistent.&lt;br /&gt;FBReader, Calibre: ebook &amp;amp; magazine readers -- I need to move my ebook collection, too.&lt;br /&gt;OpenShot, Arista transcoder, mencoder, Istanbul: video editing, transcoding, and screen capture&lt;br /&gt;Inkscape, Gimp,&amp;nbsp; F-Spot:&amp;nbsp; svg drawing, image editing, image manager&lt;br /&gt;OpenOffice: free office suite w/ word processor, drawing, spreadsheet, presentation&lt;br /&gt;FreeMind: mind mapping&lt;br /&gt;Skype, TeamViewer: remote pairing&lt;br /&gt;Rhythmbox: music player and access to UbuntuOne DRM-free music store. &lt;br /&gt;Eclipse: rare instances when I need to use an IDE (I don't do much Java).&lt;br /&gt;&lt;br /&gt;Most of the stuff I do is with these.&amp;nbsp; I am surprised that it's such a short list, but programming is mostly in gvim, using python (pip, etc) or a little ruby, and some fun stuff in bash. Not as many apps as I thought.&amp;nbsp; An awful lot of what I do is "in the cloud" rather than local these days, and hopefully more if it will move that way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4421237350578139289?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4421237350578139289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/04/my-oss-software-inventory.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4421237350578139289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4421237350578139289'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/04/my-oss-software-inventory.html' title='My OSS Software (inventory)'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1917624499993040148</id><published>2011-04-01T18:23:00.000-07:00</published><updated>2011-04-01T18:23:20.510-07:00</updated><title type='text'>Sell Me A Computer?</title><content type='html'>I do everything as a geek would do it, because I am a geek. This extends to buying a computer.  I'm picking out my next home-wherever-I-am now, and I'm wanting to ask questions that nobody answers.  Here's what I'm about:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Does it come with a non-shiny screen? I don't know how "glare" ever became a feature.&lt;/li&gt;&lt;li&gt;If I'm just reading and editing text files, will the battery last all through a 6-hour flight?&lt;/li&gt;&lt;li&gt;How much battery life can I get if I'm programming in python with autonose running?&amp;nbsp;&lt;/li&gt;&lt;li&gt;When I put Ubuntu on it, will it find drivers for everything? Video? Wifi? Camera?&amp;nbsp;&lt;/li&gt;&lt;li&gt;Which extended function keys won't work in Linux?&lt;/li&gt;&lt;li&gt;Will the oversensitive touchpad register a mouse activity when I come within 1/2 inch of it? Can I shut it off?&lt;/li&gt;&lt;li&gt;How badly will I get burned if I put the laptop on my knees while compiling a .NET project?&amp;nbsp;&lt;/li&gt;&lt;li&gt;Is there enough RAM for me to run my OS, a windows virtual box with VS.NET and resharper in it, a browser on the side? &lt;/li&gt;&lt;li&gt;Can I use it comfortably on a train or on an airplane, even if the inconsiderate jerk in front of me slams his seat back against my knees like usual?&lt;/li&gt;&lt;li&gt;How long is the fan going to last? Is it going to die after a measly 4 years like my previous two full-sized laptop computers?&amp;nbsp;&lt;/li&gt;&lt;li&gt;How much does it suck battery when suspended? How much does it eat on reboot if hibernated?&lt;/li&gt;&lt;li&gt;Can I hook it up to digital video? HDMI?&lt;/li&gt;&lt;li&gt;How water-resistant is it? If I spill one drop into the keyboard, is it gone forever, or is there some hope?&amp;nbsp;&lt;/li&gt;&lt;li&gt;How sturdy is the hinge? I've seen too many laptops gone forever when the hinge weakens.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;I know that's not the normal set of questions, but that's why I'm so much fun to shop with.&lt;br /&gt;&lt;br /&gt;I've had great luck with Thinkpads and my Asus EEE PC is just wonderful with Ubuntu. I don't have the battery life I want, but a guy makes compromises. We're pragmatists. &lt;br /&gt;&lt;br /&gt;My only problems with the Asus EEE PC have been the oversensitive touchpad, lower battery life than desired (2 hours + with Ubuntu), smallish hard drive (160G), small RAM (1G originally), and being vga-only (later models solve this). For the money, I can heartily endorse these little netbooks. Actually, despite these problems, I've come to love the little beast. It's just underpowered for my needs now.&lt;br /&gt;&lt;br /&gt;I'm thinking about a Thinkpad T410s, loaded with RAM, 500GB drive, and 9-cell battery.  I'm betting it will come as close as anything to what I want.  &lt;br /&gt;&lt;br /&gt;I'm still considering a Mac, though. I don't like OS X as much as Ubuntu, but if it is solid and my windows VM runs okay, I bet I can comfort myself with a real *nix file system and a good bash shell. Last time I was frustrated by not having a great APT/YUM repositories (ports was not as good) and the whole issue of native app updates. Either each app checks for itself, or you have to go check for them and download new versions. On OS X, I had to do a lot more manual system management, and Windows was worse than that in addition to being slower and buggier.&lt;br /&gt;&lt;br /&gt;On the other hand, OS/X had some great power management and ergonomics and the MBP had some really stellar hardware. It did work well, only crashing maybe twice in the year I had it (far better than windows, not as good as Ubuntu). The only thing I would consider superior about windows is its power management. My son's Asus EEE is identical to mine, but windows stretches the power use over a much greater period.&lt;br /&gt;&lt;br /&gt;Well, unless someone talks me out of it, it will either be a MBP or a Thinkpad when I place my order. It will be either Ubuntu or OS/X and windows in a VM.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1917624499993040148?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1917624499993040148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/04/sell-me-computer.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1917624499993040148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1917624499993040148'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/04/sell-me-computer.html' title='Sell Me A Computer?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-804311960368694517</id><published>2011-03-31T07:31:00.000-07:00</published><updated>2011-03-31T07:31:27.719-07:00</updated><title type='text'>Fun times in Honeymoon Mode</title><content type='html'>I started the new job at Industrial Logic. In addition to receiving online training from my peers here, I'm getting into the source code of our products (some cool stuff in there).  Yesterday I got to exercise my google and stackoverflow skills as we dug into a windows-based product. My .NET work until now has been web, not native, so this was new territory for me and I had a great time. &lt;br /&gt;&lt;br /&gt;In addition, I'm getting involved in contract work here and strategy.  It's only day 4, and I'm feeling like I'm really a part of the team.  You would not believe how much we are in contact even as remotes. I probably talk to my coworkers ("boss" included) much more often than you cubicle-dwellers do. I still get think-time alone, but I'm getting to know and enjoy people pretty well.&lt;br /&gt;&lt;br /&gt;Enough of this, there's code waiting...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-804311960368694517?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/804311960368694517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/fun-times-in-honeymoon-mode.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/804311960368694517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/804311960368694517'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/fun-times-in-honeymoon-mode.html' title='Fun times in Honeymoon Mode'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7485871727007584208</id><published>2011-03-24T17:45:00.000-07:00</published><updated>2011-03-24T17:45:35.907-07:00</updated><title type='text'>Industrial Logic</title><content type='html'>Your agile otter has joined Industrial Logic. We have so much in common that it didn't make sense not to join forces. I will be neck deep in products, courseware, metrics, and all of the other work that makes them so cool. This will be like chocolate and peanut butter, friends. I can't wait to join all my new best friends!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7485871727007584208?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7485871727007584208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/industrial-logic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7485871727007584208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7485871727007584208'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/industrial-logic.html' title='Industrial Logic'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4130981917492098444</id><published>2011-03-18T20:14:00.000-07:00</published><updated>2011-03-18T20:15:00.366-07:00</updated><title type='text'>Uncle Bob's Clean Code Video</title><content type='html'>The latest &lt;a href="http://www.cleancoders.com/codecast/clean-code-episode-2/show"&gt;Clean Coders&lt;/a&gt; video by Uncle Bob Martin covers Chapter 2 of the book &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code&lt;/a&gt;. This is a chapter that is near to my heart, since it bears my name and Uncle Bob even presents some flattering introductory material with a decidedly unflattering picture of me (all in good fun). The video is $12.00, but is quite well done and interesting. &lt;br /&gt;&lt;br /&gt;The &lt;a href="http://tottinge.blogsome.com/meaningfulnames/"&gt;less entertaining version&lt;/a&gt; which was the source for the well-edited version in Clean code is still available, and has examples in Python rather than Java. Bob's presentation has some thoughts not included in my paper (and which I endorse).  The paper is not a replacement for watching Bob's zany and entertaining video but it can give you some of the same material while you ponder spending your hard-earned ten-spot-and-change.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4130981917492098444?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4130981917492098444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/uncle-bobs-clean-code-video.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4130981917492098444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4130981917492098444'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/uncle-bobs-clean-code-video.html' title='Uncle Bob&apos;s Clean Code Video'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2466758064847028942</id><published>2011-03-16T06:25:00.000-07:00</published><updated>2011-03-16T06:25:22.650-07:00</updated><title type='text'>Make the Retrospective Effective</title><content type='html'>With my last employer, we had noticed that our retrospectives were starting to lag in effectiveness and attendance. People felt like they were too busy delivering stories and solving problems to do anything substantial toward meeting retrospective goals. I knew that it wasn't the kind of company that would accept stalled improvement, yet developers were instinctively afraid to invest time.&lt;br /&gt;&lt;br /&gt;To resolve the problem, I talked with the CIO. Our discussion ended up with this set of triage rules for retrospective follow-ups:&lt;br /&gt;&lt;dl&gt;&lt;dt&gt;If it is free, just do it.&lt;/dt&gt;&lt;dd&gt;There is no reason to delay implementing some changes, including (but not limited to): &lt;ul&gt;&lt;li&gt;posting a graph,&lt;/li&gt;&lt;li&gt;composing a "top-ten" list,&lt;/li&gt;&lt;li&gt;swapping pairs more often, &lt;/li&gt;&lt;li&gt;trying pomodoro technique,&lt;/li&gt;&lt;li&gt;changing how stand-up meetings are performed,&lt;/li&gt;&lt;li&gt;making better use of QA, tech writing, or Customer resources&lt;/li&gt;&lt;li&gt;instituting changes to coding standard&lt;/li&gt;&lt;/ul&gt;There is no reason to delay this kind of work. The CIO told us he considered it &lt;b&gt;our job&lt;/b&gt; to keep improving the team through reflection and experiment, or else he would have asked us to stop months earlier. Other behaviors developers were skittish about (refactoring, speeding the tests, getting legacy code under test) were considered part of the job but programmers were afraid of "losing" productivity to those tasks. Our enlightened management re-affirmed a commitment to quality work.&lt;/dd&gt;&lt;dt&gt;If it takes a couple of man days, just do it.&lt;/dt&gt;&lt;dd&gt;The team was surprised that they could peel off a member or a pair to do technical work that would improve the team. This allowed the team to take on tasks like improving the build system, metrics gathering, checking out new mocking libraries, solving version control process problems, performing global clean-ups like duplication removal, writing instructions on the team wiki. We were, in fact, not permitted to &lt;b&gt;not&lt;/b&gt; do these things. We happily devoted a few man days per iteration to accelerating the team.&lt;/dd&gt;&lt;dt&gt;If it will take longer, we should talk about it&lt;/dt&gt;&lt;dd&gt;There were architectural changes, large legacy code reworks, and grand experiments that came up in the retrospectives. Some people were afraid to even mention something that might take *weeks* of developer time to complete. People were surprised to hear that management was not against such things, but merely wanted to be measured and cautious with goals, measurement, and timing. We did some large things, and we failed some grand changes (as one might suspect) but we didn't fail for lack of permission.&lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;This triage system worked, and for the next several months we had items in all three categories. &lt;br /&gt;&lt;br /&gt;No retrospective technique I've found will be able to single-handedly keep retrospectives fresh and vibrant and productive in perpetuity, but this one was useful to shake off a fear of lost productivity long enough to get some good changes in place and to conduct some good experiments. We did a few large-scale changes, which really were also experiments. A lot of the work paid off. &lt;br /&gt;&lt;br /&gt;If your retrospectives are going stale, you might talk with your C-level supporters and bring the team a policy that clearly spells out their permission to try, change, and grow. Developers want to be productive (a fact worthy of a blog series if not a new book), and may need to be encouraged to look past the stories and tasks to work that might accelerate the whole team.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2466758064847028942?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2466758064847028942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/make-retrospective-effective.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2466758064847028942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2466758064847028942'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/make-retrospective-effective.html' title='Make the Retrospective Effective'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7940499280675150506</id><published>2011-03-15T20:55:00.000-07:00</published><updated>2011-03-15T20:55:22.526-07:00</updated><title type='text'>Agile And Beyond Party</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-5veSRCKqCpY/TYAyiJPcZLI/AAAAAAAAAd4/syaYLVIwQ9A/s1600/IMG_0025.JPG" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="240" width="320" src="http://3.bp.blogspot.com/-5veSRCKqCpY/TYAyiJPcZLI/AAAAAAAAAd4/syaYLVIwQ9A/s320/IMG_0025.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;Here is the table from&lt;a href="http://agileandbeyond.org/"&gt; Agile And Beyond&lt;/a&gt; last weekend. There are a few interesting features here. You can see the cool phones, the notebooks, the &lt;a href="http://agileinaflash.com/"&gt;Agile In A Flash&lt;/a&gt; cards being shared on the table, and to the left of the diet coke is an &lt;a href="http://timottingerconsulting.com/"&gt;Agile Otter&lt;/a&gt; business card.&lt;br /&gt;&lt;br /&gt;I attended only two talks, and spent the rest of the time hanging out with my peers and having fun. The two talks were Mary Poppendieck's talk about where she sees post-agile going (a nice talk, btw, well given) and Dr. Michael Norton (docondev's) talk about technical debt. &lt;br /&gt;&lt;br /&gt;I was ill-rested, over-caffeinated, and a little eager. I had motormouth, but it was still a great time )for me).  I hope that Mike Hill, Tracy and Angela Harms, Matthew Weitzel, Patrick Wilson-Welsh, Michael Norton, Zachary Spencer, Nayan Hajratwala, Matt Barcomb, Jon Stahl, Bill Tozier, and all the rest (drop me a note if I forgot to mention you) all had as much fun as I did.&lt;br /&gt;&lt;br /&gt;Best wishes to my colleagues on the other side of the lake!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7940499280675150506?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7940499280675150506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/agile-and-beyond-party.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7940499280675150506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7940499280675150506'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/agile-and-beyond-party.html' title='Agile And Beyond Party'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-5veSRCKqCpY/TYAyiJPcZLI/AAAAAAAAAd4/syaYLVIwQ9A/s72-c/IMG_0025.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1314911013396682312</id><published>2011-03-09T07:55:00.000-08:00</published><updated>2011-03-09T07:55:54.532-08:00</updated><title type='text'>Stop hating on the command line</title><content type='html'>Let's begin with this simple assertion: command.com sucks. It has always sucked, and always will. Powershell might be nicer, but most people haven't learned how to use it, and it's only available in one operating system anyway.&lt;br /&gt;&lt;br /&gt;If I say "command line" to a Windows-only person, they're thinking "command.com." Avoiding that command line is a huge part of making their lives pleasant. I am not slamming on hating the windows command line. All of us Unix/Linux geeks hate it too. I never feel much less productive than when I'm in command.com. I avoid it too.&lt;br /&gt;&lt;br /&gt;I started back when &lt;a href="http://en.wikipedia.org/wiki/CP/M"&gt;CP/M&lt;/a&gt; was the killer operating system. Its command line was not so great either, but it had a strong free software community who shipped programs to each other on floppy disks. As a result, we had this language called "submit" (and later "supersub") which you could actually do stuff in.  It was like a real language. The command line suddenly was pretty decent.&lt;br /&gt;&lt;br /&gt;When the PC came out, it pretty much got rid of the CP/M market, and with it the community. DOS had batch files and command.com, and those were okay. You really had to use those tools, because there was not much else. Eventually GEM and &lt;a href="http://en.wikipedia.org/wiki/DESQview"&gt;DESQview&lt;/a&gt; came along, and multitasked your DOS text apps nicely. They were taking hold when Windows first came out and destroyed the market and community for those programs. But that's neither here nor there. &lt;br /&gt;&lt;br /&gt;What happened in the 80s that turned me into a command-line fan was my defecting to Unix and learning to use a proper command line.  Bash and Zsh are the popular, ubiquitous shells these days but in the days when I jumped in the world was divided into csh and ksh users. All of these shells are command-line interfaces to the whole freaking operating system, and the Unix designers (then and now) worked to make everything available to the shell.  Instead of a crummy one-line window to slow-key commands into, these were full programming languages with proper variables, decent flow control, error reporting and handling, wildcarding, extensibility, event-handling, online help, and access to system innards. It went far beyond meager batch files. &lt;br /&gt;&lt;br /&gt;It just got better with each generation of shell. You an launch subshells, and stack shells so that you can "pop" back to an earlier context. Each subshell has its own current directory, and any one shell can have a stack of directories (pushd/popd/rotd), each shell has history and history search. There is process control and the ability to pull processes into background and foreground. There are rich stream-oriented languages and tools for processing data. There is more functionality in the command line than you can take in at a glance.&lt;br /&gt;&lt;br /&gt;The manual page for bash (arguably the most ubiquitous shell) is over 3000 lines long. I know because I did "man bash | wc -l" to find out. Considering that the documentation is terse, that represents a heck of a lot of functionality.  Zsh is so feature-rich its manual has been broken into 17 chapters.&lt;br /&gt;&lt;br /&gt;Of course, these are available via cygwin for you windows machines (if you really have to use windows) but will be slow because windows file systems are slow, and are a little crippled because windows has a different design philosophy than the Unixen do.&lt;br /&gt;&lt;br /&gt;But the point is that "avoid the command line," however reasonable when the command line is command.com, is hardly a universal goal. Instead, mac and linux and unix people almost universally embrace the command line, often preferring it to gui tools to do the same jobs.  It is explorable, scriptable, powerful, and useful.&lt;br /&gt;&lt;br /&gt;So stop hating on '&lt;b&gt;the&lt;/b&gt; command line.'  Next time, windows users, say "I hate &lt;b&gt;my&lt;/b&gt; command line."  Install cygwin (or better, Ubuntu) and give the manuals a little light read. You will be surprised what power lies just under the GUI.&lt;br /&gt;&lt;br /&gt;For the record, GUI is kinda cool, too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1314911013396682312?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1314911013396682312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/stop-hating-on-command-line.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1314911013396682312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1314911013396682312'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/stop-hating-on-command-line.html' title='Stop hating on the command line'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1093515194103509726</id><published>2011-03-07T22:40:00.000-08:00</published><updated>2011-03-07T22:40:38.440-08:00</updated><title type='text'>Python for Everyone At My House</title><content type='html'>I started teaching my youngest son python years ago. I started him with the turtle package and he drew circles, lines, and squares. He had a great time doing things like creating variables that carry his brother's name and setting them equal to "llama butt."  Now he's older, and wanting to do some more programming.&lt;br /&gt;&lt;br /&gt;We decided to start with a simple guessing game, and picked "battleship." I also decided that he's old enough to get a handle on tests and classes.  &lt;br /&gt;&lt;br /&gt;Tonight we decided what the rules were, and wrote some tests for creating ships and blowing them up. We'll be revisiting the stuff we've done, but by watching me and copying the text I typed he was able to run the tests a few dozen times, create a class, and start dealing with syntax and logic errors. &lt;br /&gt;&lt;br /&gt;It's just a start. We'll have to get into it more deeply before we'll know if he really likes it, but I'll keep you posted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1093515194103509726?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1093515194103509726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/python-for-everyone-at-my-house.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1093515194103509726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1093515194103509726'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/python-for-everyone-at-my-house.html' title='Python for Everyone At My House'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7245176824153221081</id><published>2011-03-04T19:58:00.000-08:00</published><updated>2011-03-04T19:58:13.678-08:00</updated><title type='text'>A Fun Teamwork Experiment</title><content type='html'>I want to take four teams of four people and arrange them in groups. Each group gets an identical book of crossword puzzles (or maybe a web printed book of a dozen puzzles of varying difficulty).  &lt;br /&gt;&lt;ul&gt;&lt;li&gt;The first group divides the book in four pieces and each member does 1/4 of the book. &lt;/li&gt;&lt;li&gt;The second group takes one page at a time. The first guy does as much as he can and passes it to the second, and so on.&lt;/li&gt;&lt;li&gt;The third group divides the book in half parts and solves puzzles as pairs.&lt;/li&gt;&lt;li&gt;The fourth group has no rules about how to divide and organize the work. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;We would count finished puzzles once per minute per team. We would let the experiment continue until one of the teams finishes its set of puzzles. &lt;br /&gt;&lt;br /&gt;Publish the findings, and publish notes on how each team *felt* about their work style, and what they think they would do differently.&lt;br /&gt;&lt;br /&gt;That's it. I would like to see how it comes out.  If you have the time and enough people to try this, please follow-up with a comment here to tell me how it went. Better yet, write it up on your blog and send me a link. This could be a load of fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7245176824153221081?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7245176824153221081/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/fun-teamwork-experiment.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7245176824153221081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7245176824153221081'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/fun-teamwork-experiment.html' title='A Fun Teamwork Experiment'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-3422842861472506180</id><published>2011-03-03T18:42:00.000-08:00</published><updated>2011-03-03T18:42:38.627-08:00</updated><title type='text'>Stepping up Django Efforts</title><content type='html'>Today we stepped it up a bit. Jeff Langr and I worked on our little project (shhh! it's a secret) and spent much of the day in django learning to test things. It cured a number of my developers' diseases and we got a bit done.&lt;br /&gt;&lt;br /&gt;We started out trying to use Lettuce, which is a good idea and worth improving. We got a couple of tests working, using the client to send get results from the server and BeautifulSoup to parse the returned html. It was mostly a good experience, but then we found out that our handlers weren't specific to the scenario or the feature or even the file or directory. If you register a 'before' it's 'before' everything (it seems).  Still we got some experience with it, and I think it'a great idea. With some scoping rules attached it would be totally awesome for ATDD, and I dig that it's pure python so you don't have to have a bunch of different languages &amp; tools to do the work. It's a good start.&lt;br /&gt;&lt;br /&gt;We picked up with more standard unit tests after lunch, calling the view function and letting it do the work. We figure that we don't really have to do a lot of through-the-browser testing, since django works pretty well and we're going to demo features before calling them 'done.' Heck, we'll probably try a few more ATDD tools before we're done. &lt;br /&gt;&lt;br /&gt;We made a little progress on another page, and started to refactor it into a decent shape. I'll probably go on with that on my own a while. I think I have a good handle on this now, but will still do a fair amount of experimenting before this is done.&lt;br /&gt;&lt;br /&gt;For django, my feelings are mostly positive. It's simple enough, works, and is fairly logical. I have not come to terms with which libraries I have to import everything from, but otherwise am gaining fluency. I have much to learn. I really wish that the objects were mapped to the ORM instead of being instances and attributes of ORM classes. They've gone to some lengths to make it easy to work with ORM classes instead of easy separation, but they've done a good job.&lt;br /&gt;&lt;br /&gt;More later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-3422842861472506180?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/3422842861472506180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/stepping-up-django-efforts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3422842861472506180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3422842861472506180'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/stepping-up-django-efforts.html' title='Stepping up Django Efforts'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4472822198502431392</id><published>2011-03-02T13:41:00.000-08:00</published><updated>2011-03-02T13:41:30.524-08:00</updated><title type='text'>Regaining Humility and Thereby Sanity</title><content type='html'>I got too big for my britches last week and was feeling kinda saucy. I figured that having read a tutorial some time ago should be enough for a smart guy like me, so I started up a web project and an app and slammed in some model work, splashed an url on, and was thinking I knew what i was doing. No tests, but heck it's only a few lines of code and some generated stuff.&lt;br /&gt;&lt;br /&gt;Then the test thing got to me. I started searching to see some testing tools, and ended up reading three paragraphs of every tool tutorial I could find. I pulled down a few testing tools. I started writing a test, and before I could really evaluate whether I liked how it was going started to mix different test libraries together. Pull the html parsing from here, the basic test setup from there, the helper routines from another place and pretty soon...&lt;br /&gt;&lt;br /&gt;Pretty soon I realized that I wasn't learning anymore. I was permuting and chasing error messages and flailing and feeling kind of frustrated and lost. &lt;br /&gt;&lt;br /&gt;Today I deleted everything I was working on, started a new virtualenv with just the stuff I really think I want to use, and I'm going to do things as the authors intended instead of the way that seems right to me.&lt;br /&gt;&lt;br /&gt;I learned a lot of little things while exploding in all directions, but I'd have learned more and probably been done if I had tried to maximize depth of learning and not surface-scraped too many things for my poor little brain. &lt;br /&gt;&lt;br /&gt;A little while ago someone put up a tweet suggesting that when you are trying to learn a lot of stuff, you should remember to chew and swallow the information.  I realized I'd stuffed my face. This time, I will respect that there is a rate of absorption, and see how much better I can get.&lt;br /&gt;&lt;br /&gt;I had exceeded the WIP limits of my own brain. I can never pick on managers for that again, because we all sometimes are tempted to use the blender-funnel-and-plunger method of taking in too much too fast, whether information, work, or whatever.&lt;br /&gt;&lt;br /&gt;Wish me and my newly regained humility some luck.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4472822198502431392?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4472822198502431392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/regaining-humility-and-thereby-sanity.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4472822198502431392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4472822198502431392'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/regaining-humility-and-thereby-sanity.html' title='Regaining Humility and Thereby Sanity'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7243715562541387411</id><published>2011-03-01T07:40:00.000-08:00</published><updated>2011-03-01T07:40:30.644-08:00</updated><title type='text'>COTW: Build Superior Systems With Simple Design</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh6.googleusercontent.com/-yE0crLl1-ow/TW0P8JI08ZI/AAAAAAAAAbo/0U7ceXm-p6Q/s1600/2011-03-01-092354.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="https://lh6.googleusercontent.com/-yE0crLl1-ow/TW0P8JI08ZI/AAAAAAAAAbo/0U7ceXm-p6Q/s320/2011-03-01-092354.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Our Card Of The Week from AgileInAFlash is #41&lt;br /&gt;&lt;br /&gt;The original article is at the &lt;a href="http://agileinaflash.blogspot.com/2009/02/simple-design.html"&gt;Agile In A Flash blog&lt;/a&gt;, and has slightly different wording. We adopted the phrasing from &lt;a href="http://c2.com/cgi/wiki?XpSimplicityRules"&gt;c2.com's page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I was pretty jazzed about having this card in our project, because it really does capture almost all of the code values and most design principles all in four little rules. It has always been profound in its simplicity.  I wish we were able to make all of our cards and articles as concise and deeply applicable. &lt;br /&gt;&lt;br /&gt;My idea of a great teaching program would be to start with this card, a testing library, and a programming language. We would do some exercises following these rules.  After doing some projects to get our testing and refactoring skills up to par, I would bring in the &lt;a href="http://agileinaflash.blogspot.com/2011/02/big-four.html"&gt;four big ideas&lt;/a&gt; one at a time, so we could see how to better focus our work. Then probably I would bring in the &lt;a href="http://agileinaflash.blogspot.com/2010/02/seven-code-virtues.html"&gt;seven code virtues&lt;/a&gt; and &lt;a href="http://agileinaflash.blogspot.com/2009/03/solid.html"&gt;SOLID&lt;/a&gt;. Then we would call it "a good start" and I would go home. The class could pick up books on continuous integration and refactoring, and probably be able to run on their own indefinitely.&lt;br /&gt;&lt;br /&gt;Learning the language, frameworks, and operating system quirks would be the other side of the coin. Ideas and ideals sound simple until you get to some ugliness in the OS or the web server or browser oddities.  That's when you go back to this card. With simple design, you can weather some pretty amazing technical crapstorms.&lt;br /&gt;&lt;br /&gt;This card is one part checklist, one part process. The rules are in priority order (just like "make it run, make it right, make it fast, make it small"), and also in process order. Cool stuff, huh?&lt;br /&gt;&lt;br /&gt;So, run all your tests. Write a new test. Make it pass. Look for duplication, and kill it. Do you and your current pair programming partner agree that it makes good sense as-written? If not, fix it.  Now, do you have any leftover bits that you don't need, any architectural artifacts you can live without? Unnecessary round-trips? Extra "cool" technology you can do without? Run all your tests. Start over.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7243715562541387411?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7243715562541387411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/03/cotw-build-superior-systems-with-simple.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7243715562541387411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7243715562541387411'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/03/cotw-build-superior-systems-with-simple.html' title='COTW: Build Superior Systems With Simple Design'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh6.googleusercontent.com/-yE0crLl1-ow/TW0P8JI08ZI/AAAAAAAAAbo/0U7ceXm-p6Q/s72-c/2011-03-01-092354.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-512340015131040891</id><published>2011-02-23T07:12:00.000-08:00</published><updated>2011-02-23T07:12:28.500-08:00</updated><title type='text'>Easy flowchart for communicators</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-4i-7VPLr6Ow/TWUh6qWgh4I/AAAAAAAAAbY/QfGOTEAtugM/s1600/THINK.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-4i-7VPLr6Ow/TWUh6qWgh4I/AAAAAAAAAbY/QfGOTEAtugM/s320/THINK.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I know it's simple, but why should it not be? Even simple things are hard.&lt;br /&gt;&lt;br /&gt;Reminder to self: don't skip three out of four boxes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-512340015131040891?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/512340015131040891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/02/easy-flowchart-for-communicators.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/512340015131040891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/512340015131040891'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/02/easy-flowchart-for-communicators.html' title='Easy flowchart for communicators'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-4i-7VPLr6Ow/TWUh6qWgh4I/AAAAAAAAAbY/QfGOTEAtugM/s72-c/THINK.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-916310956647727322</id><published>2011-02-21T10:13:00.000-08:00</published><updated>2011-02-21T10:13:43.505-08:00</updated><title type='text'>Grandpa Tim Tells A Scary Story</title><content type='html'>"Grandpa Tim, tell us about the old days."&lt;br /&gt;&lt;br /&gt;Grandpa Tim set aside his reading glasses and programming text. "Are you sure, children? It's nearly bed time. Maybe a story about ponies and puppies?"&lt;br /&gt;&lt;br /&gt;"No, Grandpa, we want to hear a scary story!"&lt;br /&gt;&lt;br /&gt;Tim looked around to be sure the lady of the house would not overhear and scold him for giving the little ones nightmares. "Very well," he sighed.&lt;br /&gt;&lt;br /&gt;"In the old, old, olden days programmers were isolated from each other by many barriers. Companies did not allow programmers in other companies to see their code, or to look at other companies' code. They built legal barriers and contracts that programmers had to sign if they wanted to make a living. This way, ideas could not be shared across company barriers. In many companies, they did not allow access to the internet for fear that ideas could escape from one company into another, or that people would spend time learning instead of typing."&lt;br /&gt;&lt;br /&gt;"But if you don't learn, how do you know what to type?"&lt;br /&gt;&lt;br /&gt;"This wasn't the way people thought in the old days. They thought that programmers should learn before working, not while working. They didn't send them to conventions, and they seldom offered training. It was before people understood 'maximize learning', so they marginalized it.&lt;br /&gt;&lt;br /&gt;"This was not the full extent of isolation. Within the company, they further separated teams by splitting them across time zones so communication was more difficult.&amp;nbsp; Then within any one location, they would separate small teams from each other with different management structures, and put them in separate rooms."&lt;br /&gt;&lt;br /&gt;Big-eyed, Leah asked: "At least the people within teams got to work together, right?"&lt;br /&gt;&lt;br /&gt;"Well, no. Within a team, the programmers were even more divided than among locations or companies. They were separated from each other by cubicle walls, and discouraged from talking to each other."&lt;br /&gt;&lt;br /&gt;"Even by text messaging?"&lt;br /&gt;&lt;br /&gt;"Especially by text messaging. In addition, each developer was given an individual task, so that the teams were not teams at all. They were all working on different things. One more division existed and it was more powerful than all of the others: they pitted the developers against each other and rewarded individuals instead of teams."&lt;br /&gt;&lt;br /&gt;Ian reflected thoughtfully, "So the best programmers got the most rewards? At least that part was fair." &lt;br /&gt;&lt;br /&gt;"Well, no. The rewards were based on everything but skill. They were given to the one who spent the most time in his isolated cubicle space, the ones who cranked out the most sloppy code to get features done, and the ones who could blame failures on other programmers credibly. Sometimes they were rewarded for conforming to the corporate structure better than their peers. Often the worst programmers would be rewarded, and promoted over their brethren. Most programmers realized that if they helped their colleagues, it would actually count against them. This was the most isolating practice of all.&lt;br /&gt;&lt;br /&gt;"Yet beyond isolation was a problem even more troubling. Programmers and their bosses were afraid to write code. They worked on systems they didn't understand, and were not free to explore the code. They were not allowed enough time and communication to understand the design of the system, so any change they made could break existing features."&lt;br /&gt;&lt;br /&gt;Ian interjected, "But Grandpa, the tests tell you if you've broken anything. It's not that hard!" &lt;br /&gt;&lt;br /&gt;"No, Ian, it was not so, because in those days the programmers did not write tests before writing code.  Managers thought programming was about typing the answers into the  computer, and didn't realize it was about understanding the code and inventing good answers. They tried to improve productivity by cutting down on programmer testing, and some convinced themselves it was right to do so after seeing how difficult, slow, and expensive after-the-fact testing was." &lt;br /&gt;&lt;br /&gt;"I don't understand, grandpa." said Ian. "If they don't have tests, how can they refactor?"&lt;br /&gt;&lt;br /&gt;"They avoided refactoring. The programmers did not want to create errors, and had no good way to catch them before release, so they tried not to touch any existing code.&amp;nbsp; They were afraid of undetected errors being released. Instead they would patch changes onto the software with the minimally-invasive techniques, like copying and pasting code or patching the code with flags instead of extending the design."&lt;br /&gt;&lt;br /&gt;"But if they couldn't refactor, how could they steer the design?"&lt;br /&gt;&lt;br /&gt;"They avoided changing. They hesitated to change direction even to please the customers who paid them. They were afraid that any change could wreck their existing plans and their existing code. In those dark days, programmers and their companies were very afraid indeed."&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"Didn't the partner help them be more brave?" asked Leah.&lt;br /&gt;&lt;br /&gt;"No,  darling. Managers assigned work to individuals. They reasoned that two  people using one keyboard would type only half as much code as two  people working alone. Again, they didn't understand that the bottleneck  was thinking. So without tests and without programming partners, the  isolated programmer often didn't really understand the system he was  working on and was rewarded on how fast he churned out features anyway."&lt;br /&gt;&lt;br /&gt;Leah frowned. "If it was like that, why did people code at all?"&lt;br /&gt;&lt;br /&gt;"They wrote code because they loved it and love covers many sins. They could overlook the poor workspace, the lack of community, the isolation, and the fear because ultimately they loved coding and testing and solving problems. You would be amazed what people will do out of love and the joy of creation. Even in the darkest times, programmers were people who loved their work. They would have programmed even with six-year old IDEs and outdated technologies and operating systems. They would program when the rewards systems turned against them.&lt;br /&gt;&lt;br /&gt;"Even then a programmer could make enough money to support his family, so there were people who didn't like programming but did it anyway so that they could pay their bills and have other things they liked. Because they didn't really love the work, it was hard for them to learn new ways and improve their world. Few of these programmers survived past the Big Change.&lt;br /&gt;&lt;br /&gt;"Around the turn of the century the world changed. During the 1990s and early 2000s the agilists started breaking down cubicle farms and replacing them with shared workspaces. They were successful in promoting pair programming and teamwork in many companies. They promoted communication within teams, among teams, and even got many businesses to allow access to the internet and the programming community outside the company. They had continuous testing, continuous integration, and continuous release. As we got into the 2000s, the craftsmen came and broke down barriers further, setting up programming studios where people could come and program with their developers on actual projects, for free. They promoted practicing programmer skills. They set up code camps and dojos and hackfests, and wore down the old ways with quality, teamwork, and community.&lt;br /&gt;&lt;br /&gt;The old way did not die out right away, but over time all software developers found that the world around them had changed substantially. Some of them left the isolated cube-world for the open, transparent studio. As the new ways showed success, more conservative businesses started to change. A few bastions of the old world, some small and some large, held out until the end when the more agile companies started to gain market share on the strength of their flexibility and shorter time-to-market. It was a sad time for those who didn't learn."&lt;br /&gt;&lt;br /&gt;"But it's good when the bad companies go away, right grandpa?" &lt;br /&gt;&lt;br /&gt;"Ian, it is always good when people get new opportunities and learn better ways of doing things.&amp;nbsp; It is always good when people start working out of joy and not fear. Yet it is always sad when companies close and when people lose jobs. Those who were content in isolation from new practices and the programming community struggled horribly when they lost their jobs. Some of them adjusted, some quit programming forever.&lt;br /&gt;&lt;br /&gt;Now it's getting late. Don't worry about old times, they're all gone now. The world changes, and brings new things every day. It's time to go to sleep. Who knows what we might learn tomorrow? It's best to be fresh and excited and ready to greet the day."&lt;br /&gt;&lt;br /&gt;Leah stopped by the staircase on the way up to bed. "Grandpa Tim," she said, "I'm never going to be afraid to write code."&amp;nbsp;&lt;br /&gt;&lt;br /&gt;"No," grandpa Tim said, "I think you never will."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-916310956647727322?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/916310956647727322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/02/grandpa-tim-tells-scary-story.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/916310956647727322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/916310956647727322'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/02/grandpa-tim-tells-scary-story.html' title='Grandpa Tim Tells A Scary Story'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7959549911372920439</id><published>2011-02-17T17:51:00.000-08:00</published><updated>2011-02-17T17:51:34.636-08:00</updated><title type='text'>Agile Otter Receives Love</title><content type='html'>Here are a few of the recommendations I've received: &lt;br /&gt;&lt;blockquote&gt;“Tim is the consummate software developer, with extensive knowledge and  capability. I had the opportunity to pair with Tim many times over the  course of year while at GeoLearning, and it was always the most  enjoyable pairing session to look forward to. Tim is sharp, patient,  knows how to explain things, and most importantly knows how to get  things done. I'd pick Tim in a heartbeat for my "dream team" of  developers.” J.L. &lt;span class="date"&gt;February 1, 2011&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;“Tim deeply understands the fundamentals of agile, lean, and test-driven  development and is able, like few others, to succinctly communicate  their essentials in a practical, "this is how we're gonna do it" kind of  way.  Moreover, when reality and theory collide, Tim has the depth of  understanding to help tweak and tailor practices and promote their  implementation in way that meshes with an organization's existing  culture/operations.  If you want your development team(s) to improve  what they do and how they do it then Tim's the guy for the job.” &lt;span class="date"&gt;D.T. February 11, 2009&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;“It was a real pleasure working with Tim.  His expertise in  organizational dynamics with respect to software development is such  that i would hesitate to put him in the same category as any other  normal manager of software teams.  This is to say that as a consultant  viewing organizations from the outside, he got a close-up view of the  ways that organizations can change, and the ways they can't, and it was  always interesting to hear his take on things when we asked him how we  could approach our process to improve it.    Tim was also a spot-on developer. He created a bunch of testing  frameworks that we used and built upon (and still use years after he  moved on).  There were some intricacies of these frameworks (especially  Fitnesse) and it was incredibly handy to have him around to debug and  decipher.    I would enjoy working with Tim again and would consider him an asset to  any organization that has him.” &lt;span class="date"&gt;K.R. April 22, 2010&lt;/span&gt; &lt;/blockquote&gt;&lt;blockquote&gt;“Tim was brought in to coach our team through our agile transition.  He  worked with us in the ways we needed, and he always focused on our  current state as much as where he wanted us to go.  Tim adapted his  approach daily based on our feedback, and when we ran out of questions,  he would push us to the next level with a new idea.” &lt;span class="date"&gt;K.S. October 1, 2007&lt;/span&gt;&lt;/blockquote&gt;&amp;nbsp;I thank you for the kind words. The Linked-in recommendations are always appreciated and always useful.&amp;nbsp; Hopefully we can add in a few recommendations for the books as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7959549911372920439?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7959549911372920439/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/02/agile-otter-receives-love.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7959549911372920439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7959549911372920439'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/02/agile-otter-receives-love.html' title='Agile Otter Receives Love'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7415189677046549245</id><published>2011-02-16T10:23:00.000-08:00</published><updated>2011-02-16T10:23:53.708-08:00</updated><title type='text'>Self-Promotion and Resume-writing</title><content type='html'>I've read some resume-writing tips and I've talked with good friends who have nailed a particular problem I'm having. I turn to my loving readership for general advice now. &lt;br /&gt;&lt;br /&gt;When reading a resume, I often see flashy hyperbole and unnecessary superlatives. I think "of course he's trying to make himself sound great, he wants something from me."&amp;nbsp; The more fantastically good the resume reads, the less I believe it.&amp;nbsp; I will be extra hard on people who sound like a combination of superman and Einstein, and might bypass them entirely and try to find someone more "honest."&lt;br /&gt;&lt;br /&gt;When writing a resume for myself, I strive to NOT trip that reflex. I write up my most satisfying successes as if they were workaday events, my biggest challenges as if they were normal problem-solving moments, and my best outcomes as if they were foregone conclusions.&amp;nbsp; I don't try to make it sound as if I did 8 impossible things before breakfast and had time for an extra scone, but rather tend to be dry in description.&lt;br /&gt;&lt;br /&gt;My friends and colleagues tell me that my resume, as a result, tends to not represent me well. It makes me sound boring, workaday, and unimpressive. They offer replacement paragraphs saying things like,&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Inspiring software architect who can take any team and lead them through excellent example and solid teachings to higher levels of productivity, quality and responsibility. Keen understanding of the processes involved in delivering quality software on time.&amp;nbsp; Accomplished author and educator.&amp;nbsp; Able to communicate clearly with business as well as and tech people. Extensive proven ability to take legacy code base and help bring down bug count, increase customer satisfaction and decreasing [sic] development time. Never-ending enthusiasm for anything software development including new languages, tools and ideas.&lt;/blockquote&gt;If my former CIO says this about me (as one indeed did, word-for-word), it sounds positively inspiring. But imagine I was sitting down with you, and said the same things about myself.&amp;nbsp; Would you flip the bozo bit, toss my resume to the circular file, and move on to someone with a less desperate grasp of self-inflating superlatives?&lt;br /&gt;&lt;br /&gt;The question, dear friends, is how one can incorporate the praise of others in their resume in a checkable, responsible, honest way? If others recommend me, how can I make those recommendations known? Is there a way I can do so without sounding like I made them up?&lt;br /&gt;&lt;br /&gt;I await your suggestions. Thanks for bearing with me in this rather personal interruption in the flow of Agile software topics.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7415189677046549245?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7415189677046549245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/02/self-promotion-and-resume-writing.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7415189677046549245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7415189677046549245'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/02/self-promotion-and-resume-writing.html' title='Self-Promotion and Resume-writing'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6862907317620781687</id><published>2011-02-14T09:24:00.000-08:00</published><updated>2011-02-14T09:24:22.989-08:00</updated><title type='text'>The Wicks</title><content type='html'>I had a good morning conversation with some good people in twitter (&lt;span class="tweet-user-name"&gt;&lt;span class="tweet-full-name"&gt;Jim Argeropoulos, &lt;/span&gt;&lt;/span&gt;&lt;span class="tweet-user-name"&gt;&lt;span class="tweet-full-name"&gt;Dean Goodmanson, others) about programmers and how many of them seem to have no real interest in the art/craft/vocation of programming. They tend to crank out the same code they did seven years ago, or longer, appending flags and if-then statements to masses of flags and conditionals, and never growing in their practice.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="tweet-user-name"&gt;&lt;span class="tweet-full-name"&gt;I offered a metaphor of candles:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="tweet-user-name"&gt;&lt;span class="tweet-full-name"&gt;A million candles, if not exposed to flame, will not light a room.&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;For the symbolism-challenged, candles are people in the programming vocation and flame is an active interest (if not outright love) of the work we do.&amp;nbsp; Here is my extended analogy for your consideration:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Burning Wicks&lt;/b&gt; are those who love programming and spend time learning, reading, studying, and improving their skills. They are contagious in their enthusiasm for better techniques and programming meta-considerations. They have done quite a bit of self-study, and have connected with kindred souls in the programming community.&amp;nbsp; They may have trouble fitting into some corporate cultures, unless the corporation values the kind of enthusiasm and learning-experiences these developers bring to them.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Dry Wicks&lt;/b&gt; are those who have entered the field of programming but never have been exposed to developers who have a burning love for the practice. They may have never heard about the issues of Coupling, Cohesion, Duplication, and Volatility. They may never have read Clean Code or Code Complete or the like. They have never heard a keynote speech or training session on better programming techniques.&lt;br /&gt;Dry wicks are ready to be lit. If a burning wick is introduced, a dry wick might catch flame. It may not take the introduction of two or three burning wicks before it picks up, but it will eventually light.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Burnt Wicks&lt;/b&gt; have been lit in the past, but circumstances (difficult work situations, bad corporate policies, poor coworker relations, etc) have caused the flame to go out.&amp;nbsp; Often a burnt wick can be re-lit, but it requires appropriate circumstances and a fresh application of flame. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Wet Wicks&lt;/b&gt; will not light. This is the true "just a paycheck" programmer, or the programmer who only programs so that he can do what he really wants to do (marketing, electronics design, management). It can be hard to tell a wet wick from a burnt or dry one at first. If a truly wet wick is found, the best thing to do is save your team from his influence by moving him to an area where he really has an interest. We can do better than "just a paycheck" programmers.&lt;/li&gt;&lt;/ul&gt;The question asked was what is the best we can do, then? I suggest that every programming team that isn't burning brightly needs a few burning wicks added. This infusion of fire can be in the form of contractors, consultants, or new team members. Some of us would be happy to come on as temporary full-time workers (say for a year or two). The first burning wick will catch some dry or burnt wicks, the next will pick up some more.&amp;nbsp; After a few attempts, you will find out which wicks will simply not light.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;It is not my practice to recommend any developer's termination, but if you have a few who act as a wet blanket on the others, or who refuse to develop any real interest in what they're doing for 8+ hours each day, you would be better to make a lateral move (do not promote a wet wick over a programing team!) or help them find a new place to work away from your burning-hot developers. &lt;br /&gt;&lt;br /&gt;Rather than a pronouncement from a greybeard developer, I would like this to be a conversation starter.&amp;nbsp; Tell me how you bring the fire to your team and what has not worked.&amp;nbsp; Help me know where the metaphor breaks down and what you would like to see done about it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="tweet-user-name"&gt; &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6862907317620781687?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6862907317620781687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/02/wicks.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6862907317620781687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6862907317620781687'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/02/wicks.html' title='The Wicks'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-9086164487487960674</id><published>2011-02-10T09:35:00.000-08:00</published><updated>2011-02-10T09:35:28.937-08:00</updated><title type='text'>4 Questions Film Project</title><content type='html'>&lt;span class="Apple-style-span" style="color: #444444; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px;"&gt;What would you say given only 60 seconds to answer:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px;"&gt;What do you do?&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px;"&gt;Why did you start?&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px;"&gt;Why do you love it?&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px;"&gt;Why does it matter?&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 14px; line-height: 18px;"&gt;You can make a 60-second (or less) film, answering these questions (or a subset thereof) for our collection. We hope to impact decision-making among young people, encouraging them to enter the software craft.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 14px; line-height: 18px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #444444; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 14px; line-height: 18px;"&gt;Can you help?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-9086164487487960674?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/9086164487487960674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/02/4-questions-film-project.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/9086164487487960674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/9086164487487960674'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/02/4-questions-film-project.html' title='4 Questions Film Project'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8319541329428193776</id><published>2011-02-03T08:08:00.000-08:00</published><updated>2011-02-04T05:48:42.673-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ottinger'/><category scheme='http://www.blogger.com/atom/ns#' term='dinwiddie'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='summary'/><category scheme='http://www.blogger.com/atom/ns#' term='levinson'/><category scheme='http://www.blogger.com/atom/ns#' term='concise'/><category scheme='http://www.blogger.com/atom/ns#' term='elegance'/><title type='text'>World's Shortest Agile Summary</title><content type='html'>Thanks to George Dinwiddie and Mark Levinson and that marvel we call Twitter, your agile otter presents the worlds briefest summation of Agile:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Do small things supremely well, and let them add up to large things.&lt;/li&gt;&lt;li&gt;Use feedback to steer to the results you want.&lt;/li&gt;&lt;li&gt;Defeat problems with teamwork. &lt;/li&gt;&lt;li&gt;Maintain an even strain. &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8319541329428193776?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8319541329428193776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/02/worlds-shortest-agile-summary.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8319541329428193776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8319541329428193776'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/02/worlds-shortest-agile-summary.html' title='World&apos;s Shortest Agile Summary'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5176956665871076193</id><published>2011-02-02T16:14:00.000-08:00</published><updated>2011-02-08T06:49:31.554-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='chicago'/><category scheme='http://www.blogger.com/atom/ns#' term='free'/><category scheme='http://www.blogger.com/atom/ns#' term='user groups'/><category scheme='http://www.blogger.com/atom/ns#' term='meetings'/><category scheme='http://www.blogger.com/atom/ns#' term='agile in a flash'/><title type='text'>The Great Giveaway Begins</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_WMyCPCNYrhk/TUnyAJbcMaI/AAAAAAAAAVI/d7kFmMNN9BQ/s1600/IMG_0006.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_WMyCPCNYrhk/TUnyAJbcMaI/AAAAAAAAAVI/d7kFmMNN9BQ/s320/IMG_0006.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;They're here!  &lt;br /&gt;&lt;br /&gt;Now that I have extra decks of &lt;a href="http://pragprog.com/titles/olag/agile-in-a-flash"&gt;Agile In A Flash&lt;/a&gt;,&amp;nbsp; I want to give them away in person as a door prize or in a contest of some sort.&amp;nbsp; The problem is that I'm located in the far NW 'burbs of Chicagoland.&amp;nbsp; I can get to Chicago or I can get to Milwaukee, maybe out to Rockland or some points in-between.&amp;nbsp; Invite me, and I'll see what I can do!&lt;br /&gt;&lt;br /&gt;I love hanging out with software developers of all types but prefer the meetings to be about agile, some programming language, or Linux.&amp;nbsp; I might even score some other goodies to hand out. Talk to me.&lt;br /&gt;&lt;br /&gt;If you want to talk to me about coaching your team, I might bring a copy to the interview, but I want the community to have dibs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5176956665871076193?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5176956665871076193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/02/theyre-here-now-i-have-extra-decks-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5176956665871076193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5176956665871076193'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/02/theyre-here-now-i-have-extra-decks-of.html' title='The Great Giveaway Begins'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_WMyCPCNYrhk/TUnyAJbcMaI/AAAAAAAAAVI/d7kFmMNN9BQ/s72-c/IMG_0006.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2828049971848448450</id><published>2011-01-28T07:00:00.000-08:00</published><updated>2011-02-04T05:52:09.362-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='skill development'/><category scheme='http://www.blogger.com/atom/ns#' term='objections'/><category scheme='http://www.blogger.com/atom/ns#' term='fears'/><category scheme='http://www.blogger.com/atom/ns#' term='rockstars'/><category scheme='http://www.blogger.com/atom/ns#' term='unequal'/><category scheme='http://www.blogger.com/atom/ns#' term='pair programming'/><category scheme='http://www.blogger.com/atom/ns#' term='teamwork'/><category scheme='http://www.blogger.com/atom/ns#' term='respect'/><category scheme='http://www.blogger.com/atom/ns#' term='feedback'/><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='evaluations'/><category scheme='http://www.blogger.com/atom/ns#' term='self improvement'/><title type='text'>Pairing, Competence, and Recognition</title><content type='html'>parIt's a common thread in agile transitions that people are not sure what pairing, teamwork, and self-organization will do to their status on the team.  Will the team be so leveled that nobody will stand out? Will the weak be exposed and humiliated? I am going to write this as if there were two states, strong and weak. Before reading anything that follows, remember that everyone is good in some areas and weaker in others. I have seen javascript gurus who weren't very database-smart, and people who were great with requirements and product knowledge but had no sense of scalability or performance. Any human characteristics are spectra, not point measurements.  With that in always in mind, read on:&lt;br /&gt;&lt;br /&gt;There is good news, more good news, and some hard and potentially sad news in all of this.  The first bit of good news is that nobody who works in an agile team ever asks these questions. In reality, it's not a problem. Let's get down to cases.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Rockstars&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you are the rock star of the team now, you will find that pairing will give you mentoring and teaching opportunities and respect that you've never had before. Invariably, a great programmer on any team (whether outgoing or quiet) becomes revered by the team. If you have the skills alone, you have the skills paired too. I've not seen any great programmers fall through the cracks. Sometimes a pair mismatch may be uncomfortable for a while, but you can elevate the skills of your teammate. Imagine what it is like when all the members of the team will listen and will up their game. You will find it is much cooler to be a revered member of a competent team than to be the high-and-mighty member of a mediocre team. You have nothing to lose and everything to win.&lt;br /&gt;&lt;br /&gt;Bob Anderson named a strategy "Attack The Weak" (tongue-in-cheek), in which the strong member of a team intentionally selects a less-established or less-experienced partner on purpose, as a teaching and sharing opportunity.  This is a good strategy, provided the strong member is nurturing and not dictating. The point is to raise the partner's skill level, not to expose them as weak. Not every pairing has to be of this form, but several a week is a good idea. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Growing Developers&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you are the weakest player on the team, you will find that pairing gives you an opportunity to learn from your teammates. In addition, as the partner shares the keyboard and ensures that you're doing test-first work, you will find that it's harder to make a mistake that gets through to integration (let alone release). You have a safer working/learning environment.&lt;br /&gt;&lt;br /&gt;In a strategy I call "eat the rich", you choose a partner who knows something you want to understand better. That partner may be a tester, a UI expert, a performance expert, the local ruby guru, or someone who really deeply groks the platform. By pairing with them a few times a week, you add their skills to your own.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Borg Collective&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;A common fear is that everyone will be assimilated, and the entire team becomes an amorphous mass of fungible "resources", that the strong and the weak will be indistinguishable, and that morale will collapse.  Some fear that incompetent developers will be able to hide in the team and drag down efforts, or that brilliant developers will be unrecognized.&lt;br /&gt;&lt;br /&gt;The fact is that people are different, and are drawn to different aspects of the work. We can all get better at everything, but some things will speak to us more deeply than others. As a result, we will have special strengths and weaknesses.&lt;br /&gt;&lt;br /&gt;When you work entirely in pairs, everyone who works with you will get to know you. While it makes no sense to recognize and reward individual efforts in a team (thereby creating competition and sabotaging the team effort), there is no question in anyone's mind who the strong and weak players are. This information is best kept within the team, but there is no question.  In a 360-degree review, the strong team players will be recognized. Think how great it would be if your coworkers were the ones who promoted you, because you have helped them improve and they respect the skills.  &lt;br /&gt;&lt;br /&gt;This is where the potentially sad part comes in. Some people cannot program well, but do it anyway. If an initially weak player shows potential and improvement, everybody is happy to see them grow and change. Sadly, some people don't get any better. If they don't take advantage of the team-learning and remain weak and unskilled, they will demoralize the team. Nobody wants to be hand-holding and nose-wiping and babysitting all the time. If someone is a continual drag on the team, and doesn't improve, and doesn't show any signs of potential, everybody on the team knows that too. In order to protect the team's morale and productivity, teammates may "vote him off the island" by asking their scrum master or project manager to consider counseling that person into a position more suited to their skills, even if that means another company. This is sad to the one who has to leave, but can actually improve the morale of the team.  It is doubly sad if the one asked to leave has an inflated self-image and thinks himself a rock star. On an agile team, though, it should never be a surprise to be asked to leave.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;School for Deserters&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The other concern is that people will improve their marketability as developers. After all, they've had months of self-improvement and now can put the big A word on their resume ("agile", not what you are thinking) so now they could command a higher salary if they leave.&lt;br /&gt;&lt;br /&gt;Okay, fair cop. You will suddenly have a team of developers that are the envy of the other companies in your area. Competitors and neighbors will start to take notice, and may extend some recruitment feelers into your team. &lt;br /&gt;&lt;br /&gt;Think about the mixed blessing here: You have the team that everyone wishes they had. If you want to look at this as a problem, go ahead. Might you have to hand out some bonuses or raises based on the performance of the team? You might, but don't you want to have a team that is deserving of recognition and reward? Isn't that better than the alternatives? &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Yes, when you become a true agile team, the teamwork does eliminate individual rankings in a traditional way. You can't say who completed a piece of work because the team did it (perhaps every single member had a hand in it), so old individual rewards are hard to give. Worse, individual rewards can break down a team if they create competition between the members, since competition can stymie free and open sharing of skills.  On the other hand, peer respect is more to be coveted and can be measured.  &lt;br /&gt;&lt;br /&gt;Even if there were no way to reward people for being great team members and mentors, imagine how much more pleasant it would be to work with a team of capable, motivated partners instead of a mixed bag of people who don't really have the on-the-job opportunity to up their game in a meaningful way. It's an exciting thought.&lt;br /&gt;&lt;br /&gt;All members of a team can grow and teach and develop in an agile pairing environment, and this makes the company stronger as well. It will fly in the face of some classic motivational schemes, but Agile is a little counter-intuitive that way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2828049971848448450?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2828049971848448450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/pairing-competence-and-recognition.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2828049971848448450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2828049971848448450'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/pairing-competence-and-recognition.html' title='Pairing, Competence, and Recognition'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7647842733232663750</id><published>2011-01-28T06:15:00.000-08:00</published><updated>2011-01-28T06:15:08.265-08:00</updated><title type='text'>Discoveries of the Week</title><content type='html'>This week I made some social networking advancements and started to build a few other new skills.&lt;br /&gt;&lt;br /&gt;The first is &lt;a href="http://tweetfeed.com/"&gt;Tweet Feed&lt;/a&gt; which is likely responsible for you seeing this short article. I am not going to have to hand-tweet the AgileInAFlash or AgileOtter articles because they're auto-tweeted for me.&lt;br /&gt;&lt;br /&gt;The second is that blogger's admin screens let me turn on the social button bar after each article, so readers may more easily promote anything they find interesting or outrageous. It's a small thing, but already I've seen a new tweet from the page. It's a very small thing, but sometimes small things matter.&lt;br /&gt;&lt;br /&gt;I'm on &lt;a href="http://www.ohloh.net/"&gt;ohloh&lt;/a&gt; now. My friend Sam Hart has prodded me a bit, and I finally realized he's right (it takes me a while sometimes) and I should take some credit for the work I've done in the public space, like the PDK. I never realized that I was the check-in leader there. Sam wants me to pick it up and make it a living project again, and I'm thinking he may be right. Mind you, I am a little more interested in the DITS concept, but I have opportunities.&lt;br /&gt;&lt;br /&gt;A big social breakthrough is that I realized that taking the train downtown isn't as bad as I made it out to be. Now that I'm moved a bit south and am near a station on a different line, it's just $12.00 for the round trip and it's a bit over an hour each way.  This is important because all my peers in the agile community are downtown and I could benefit much from being connected with the local community. It will help with the Talent Agency idea as well as Agile In A Flash, and we all know how iron sharpens iron.&lt;br /&gt;&lt;br /&gt;I have entered the world of video production.  I really am NOT great at it, but I made some progress in the video realm. I am now a fan of dead-simple transcoding front ends. &lt;a href="http://www.transcoder.org/"&gt;Arista&lt;/a&gt; has been handy for me. While &lt;a href="http://www.openshotvideo.com/"&gt;Open Shot&lt;/a&gt; is still my editor, I don't always get new content into the right format and size for media sites. I used Arista and encoded for iPod, and it turns out to be totally viewable by mac and windows users (the poor saps) in addition to more enlightened Ubuntu users (1/2 grin).&lt;br /&gt;&lt;br /&gt;I ended up putting opening and closing title images on the "Deal" video, and put a drum track at the beginning and end.  I still don't know anything about making interesting videos or screencasts, but I suppose that's the future.  It's a way to connect, and connecting is good.&lt;br /&gt;&lt;br /&gt;I also started with Django all over again. I've read a bit more of the book (on the train) and re-did the "Django for the impatient" and am getting to a point where I can more easily dig into the unit testing problems. I just needed some backgrounding. I've been invited to play in a nice open source project in Django, so I have a wealth of options.&lt;br /&gt;&lt;br /&gt;I also am looking at a few good opportunities for my next gig. There is so much to learn, and so many good people to work for, it is an embarrassing wealth of options.  Will I be Agile Otter or Django Otter next month?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7647842733232663750?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7647842733232663750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/discoveries-of-week.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7647842733232663750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7647842733232663750'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/discoveries-of-week.html' title='Discoveries of the Week'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7333216958330453762</id><published>2011-01-24T18:07:00.000-08:00</published><updated>2011-01-24T18:08:04.671-08:00</updated><title type='text'>One Video Wrapped Up</title><content type='html'>I have our first &lt;a href="http://agileinaflash.blogspot.com/2011/01/deal.html"&gt;video&lt;/a&gt; finished.&amp;nbsp; Notice how my face never appeared.&amp;nbsp; I'm going to have to get used to hearing my voice on these, maybe I'll do the full-frontal face thing in one of the future videos. Either way, we now have a commercial that explains what this whole &lt;a href="http://www.pragprog.com/titles/olag/agile-in-a-flash"&gt;Agile In A Flash&lt;/a&gt; thing is about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7333216958330453762?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7333216958330453762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/one-video-wrapped-up.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7333216958330453762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7333216958330453762'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/one-video-wrapped-up.html' title='One Video Wrapped Up'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5476534047820323651</id><published>2011-01-20T08:53:00.000-08:00</published><updated>2011-01-20T08:53:22.525-08:00</updated><title type='text'>Django Unit Test Hobby</title><content type='html'>I have played with Django, but never really did any work in it.  Even my toy app died before I got to a "good working model" state with it, because I did not maintain focus and wandered off too much. Since then I've developed a keen interest in learning more web technology, and so this time is Django Charge 2.0.&lt;br /&gt;&lt;br /&gt;I visited some very nice, very smart people this week to took me into their offices and showed me some of their Django code. We started to talk about testing, and I made a small abortive attempt to do some plain-old-unit-testing in their python code base.  It was not all that I hoped it would be (Dean, please revert that code if you haven't already).  I ran out of time to play, but hopefully will be back to enjoy some pair programming goodness in the near future.&lt;br /&gt;&lt;br /&gt;The cool and interesting bit about Django testing is that testing through manage.py will have you standing up an instance of the app complete with database.  The setup is fairly onerous, but the tests run quite quickly.  I think a lot of good &lt;i&gt;integration&lt;/i&gt; testing can be done this way, but I wanted to do proper unit testing, where "proper" means that I do not stand up an application instance, don't use the database, and all of my unit tests (even when there are 20K of them) will run in less than 45 seconds.  This becomes hard because Django's object mapper is in the DNA of django model objects.  I guess I'll end up designing around that limitation, hopefully without my &lt;a href="http://www.python.org/doc/essays/metaclasses/"&gt;head exploding&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The other complication is the virtualenv. We definitely want to run the tests in the virtual environment, but don't want to launch a shell instance to do it. I'd like to autonose this, or better yet hook it into pyCharm and/or eclipse pyDev. It shouldn't be much of a problem... worse case should be launching the tool inside the virtualenv. &lt;br /&gt;&lt;br /&gt;I'm not interested in doctest. I have a long-standing phobia against the use of magic comments. They offend my sense of how things should work. I'll be doing unittest (unless I succumb to pressure to write my own framework).&lt;br /&gt;&lt;br /&gt;Today I begin my new hobby.  I'll follow up here with links to interesting Django unit test links, and probably little discoveries. I'm not going to rush to solution, but try in code-camp style to work perfectly instead.  It will be fun.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5476534047820323651?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5476534047820323651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/django-unit-test-hobby.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5476534047820323651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5476534047820323651'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/django-unit-test-hobby.html' title='Django Unit Test Hobby'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7688645688681447083</id><published>2011-01-20T07:17:00.000-08:00</published><updated>2011-01-20T07:17:11.085-08:00</updated><title type='text'>Agile In A Flash</title><content type='html'>Today the deck is released for purchase. I'm getting tweets and messages from people who have either purchased  the eBook or placed an order for decks. Thanks to everyone for their support in our crazy little project. So far many retailers are selling.  &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://pragprog.com/titles/olag/agile-in-a-flash"&gt;Prag Prog&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Agile-Flash-Speed-Learning-Software-Development/dp/1934356719"&gt;Amazon&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oreilly.com/catalog/9781934356715"&gt;O'Reilly&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.borders.com/online/store/TitleDetail?sku=1934356719"&gt;Borders&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.buy.com/prod/agile-in-a-flash-speed-learning-agile-software-development/q/loc/106/217548621.html"&gt;Buy.Com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.deepdiscount.com/index.cfm/fuseaction/product.detail/categoryID/2FDFAA37-97B5-4BDB-A77F-7A8D55A0C8AB/productID/B6C027D0-6C61-4DDE-9FE6-4761A8150DC1/?utm_source=ChannelIntelligence&amp;utm_medium=referral&amp;utm_campaign=Google&amp;ci_src=14110944&amp;ci_sku=OREIL435671"&gt;Deep Discount&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ecampus.com/book/9781934356715"&gt;E Campus&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7688645688681447083?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7688645688681447083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/agile-in-flash.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7688645688681447083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7688645688681447083'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/agile-in-flash.html' title='Agile In A Flash'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-170106787699355523</id><published>2011-01-19T19:37:00.000-08:00</published><updated>2011-01-19T19:37:49.266-08:00</updated><title type='text'>Remote Pairing Matters</title><content type='html'>The one thing I haven't said about my time as a remote pair programmer is that remote pair programming is a brilliant idea and it matters.  The reason I didn't mention it there was because that was work. This is personal development.&lt;br /&gt;&lt;br /&gt;We improve our skills and our exposure in the world by pairing with more people. I've been a shy guy, not always jumping into the pairing sessions at conferences, and I'm the poorer for it. I could have been soaking up mojo from the greats instead of hiding out.&lt;br /&gt;&lt;br /&gt;But remote pairing? You are not in front of a whole bunch of strangers who are potentially judging you.  You're in a one-on-one situation with someone you couldn't have visited personally due to any number of travel constraints. It's just the two of you and your headphones. You can work on your code, or the other guy's code, and it doesn't matter. It can be 6am or 2am or noon on a saturday, any time your schedules just happen to coincide. &lt;br /&gt;&lt;br /&gt;This is something I think we need to foster. We need a good system for hooking up eager remote pair partners with their peers, betters, and rising stars all over the world. Imagine how much good we could do if it were possible to pop onto some web site (a software talent agency?) and hook up with Ward Cunningham or Andy Hunt or Corey Haines for a couple of hours after dinner.  It's not just name-brand acts either -- there are thousands of programmers who could teach me or learn from me in a session (maybe both).  We could form up community that spans the globs, one or two time zones at a time.&lt;br /&gt;&lt;br /&gt;The problem is that remote pairing tools all suck really bad or cost money.  &lt;br /&gt;&lt;br /&gt;Because remote pairing really matters, we need to all jump in the pool. We need to be filing reports for the likes of Yuuguu and WebEx and GoToMeeting or any other company with competence. We need a few open source projects to do screen-sharing or edit-session-sharing.  Eclipse needs better sharing, though they've got an interesting start.&lt;br /&gt;&lt;br /&gt;This is all solvable stuff. The technical side could be made to work. We just have to put ourselves into it.  If we can solve the pairing technical problems, the remote partner exchange idea is just a simple python or ruby script away.  &lt;br /&gt;&lt;br /&gt;Wouldn't you enjoy jumping into someone else's code on the weekend or in the evenings. Wouldn't it be fun to put the next patch into some great OS project if you had a guide and peer to join you? Wouldn't you love to have good working relationships with hundreds of people who could recommend you for interesting jobs and projects around the country (or the world)?&lt;br /&gt;&lt;br /&gt;Remote pairing matters, and it may be the way we all move the trade forward. It's a brilliant idea, and we need to support those who are out front, solving the big problems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-170106787699355523?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/170106787699355523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/remote-pairing-matters.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/170106787699355523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/170106787699355523'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/remote-pairing-matters.html' title='Remote Pairing Matters'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2999262018975775582</id><published>2011-01-15T07:52:00.000-08:00</published><updated>2011-01-15T07:52:45.343-08:00</updated><title type='text'>Reflecting on Being Employed as a Remote Pair Programmer</title><content type='html'>Being a telecommuter or remote team member is considered a pretty sweet deal and is recognized as a more "green" way of working.  Remotes don't share illnesses with their teammates, and yet work when ill. Remotes don't participate in office gossip or struggle with personalities the way locals can. The perceived problem with remotes is that they are unmanaged (in fact, they are impossible to micro-manage effectively). The actual problem with remotes is that they can be disconnected. &lt;br /&gt;&lt;br /&gt;The solution to the perceived and real problem seems to be in the sweet spot of remote pairing.  I was lucky enough to work for a few years as a remote pair-partner.  As a remote, I worked common hours just as my peers did.  I joined them in the morning, took lunch when they did, and worked until they went home in the evening. We spend most of the day on-camera together (or at least in voice via headsets), sharing the screen and development tools, writing tests and code, exploring technical problems, and building solutions.&lt;br /&gt;&lt;br /&gt;It is not the "remote developer concept" that many have in mind.  I worked from my home, but did not make my own hours.  I did not go to an office by day, but also did not work for myself. I could not take arbitrary days off as self-employed or many work-from-home people often do. It worked well for me and for my employer. &lt;br /&gt;&lt;br /&gt;We found a pretty sweet combination by using Skype for voice and video, git for version control, and Webex to do screen sharing. The latency for webex is surprisingly low, and suited our needs very nicely. I set up a netbook with a built-in camera for skype so the company laptop's CPUs could be fully devoted to programing and screen-sharing (so necessary when using cpu-hungry development tools). An Asus EEEPC netbook is under US$300 most places, and mine really does a great job. I have had a few headsets. They're inexpensive, but they also tend to get uncomfortable after a few hours, so I would definitely try several. I used a few logitech models and was more-or-less satisfied. &lt;br /&gt;&lt;br /&gt;The other useful tools for a remote pair partner? I second monitor (a large one) and synergy.  Synergy allows one keyboard and mouse to be used by multiple computers. It is easy to setup and use, and allowed me to switch between netbook and work notebook very easily.  I found myself mousing among three screens attached to two computers, and never thinking twice about it. It all just became transparent.&lt;br /&gt;&lt;br /&gt;If your organization is interested in using remote teammates, I cannot over-recommend the combination of WebEx, Skype, Netbook, Work Computer, Synergy. For very little cost, you have a powerful pairing system.  &lt;br /&gt;&lt;br /&gt;There are shortcomings to being a remote pair-programmer, though. You are not visible to your bosses, and can be forgotten sometimes. You do not participate in the conversations at the next cubicle, in the hallway, or at lunch.  You don't see the same visual cues as to the team's progress. You can't feel the emotional charge in the room to know when people are afraid, tired, angry, or excited.&lt;br /&gt;&lt;br /&gt;A remote does not have the physical presence necessary to be an agile coach or effective scrum master. Email and text will not truly fill the gap of rich, human communication.  Your view of the team is the webcam. That leaves you out of mentoring opportunities, so you learn and teach less than you could have on-site.&lt;br /&gt;&lt;br /&gt;Remote meeting participation is awful. The room is full of people, and there are one (or a few) mics. Inevitably the people doing the most speaking will be furthest from the microphones, and the most fidgety people will be close to them.  There will be long stretches when you can't make out what is being said behind the rustling papers, pen clicks, rhythmic tapping, layers of whispering, etc. The worst interruptions in sound are caused by the the other remote who is on speaker phone but didn't mute their mic. Every time a sound activates their mic, all other sound on the line is cut off. It is almost as if someone were toggling the mic in the meeting room. One can lose interest in trying to keep up and return to coding, missing the reason they were invited to the meeting in the first place.&lt;br /&gt;&lt;br /&gt;Finally, a remote is harder to promote and easier to release than a body you see every day in the office. That might be seen as an advantage to an employer, but will probably seem a little off-putting to the remote employee.  My intention was to try remote development for a quarter or two, yet we stuck it out together for over two years. That's a pretty nice experiment, and I thank GeoLearning for the great and mutually-beneficial opportunity.&lt;br /&gt;&lt;br /&gt;Would I be remote again? I think I would. I would remote with the same team in a heartbeat, because they're good people and we learned how to do this together.  I still learned, connected, and enjoyed software development with good people. But I think I would like to go onsite again for a while. However convenient it is to be distant, programming is still a social act and still best done shoulder-to-shoulder.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2999262018975775582?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2999262018975775582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/reflecting-on-being-employed-as-remote.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2999262018975775582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2999262018975775582'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/reflecting-on-being-employed-as-remote.html' title='Reflecting on Being Employed as a Remote Pair Programmer'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8272307356988121010</id><published>2011-01-15T06:50:00.000-08:00</published><updated>2011-01-15T06:50:32.669-08:00</updated><title type='text'>Observation on Growing Disconnected</title><content type='html'>People, software, and organizations often grow in this way: they accumulate without assimilating, and aggregate without integrating. As a result, they tend to be disconnected and fragmented and without a real focus or direction. In all three cases, it's amazing how functional they can be considering the shape they are in.&lt;br /&gt;&lt;br /&gt;Perhaps this is the different between innovative young companies and the well-worn thinking paths of large ones, between young turks and hold functionaries, between greenfield software and legacy.&lt;br /&gt;&lt;br /&gt;If so, then can we renew our creativity, youth, vigor, and clarity by ordering and integrating ourselves? &lt;br /&gt;&lt;br /&gt;I would like to believe it is so.  The idea, alas, is too grand for me. It's out here now, and maybe it will spark something more easily grasped and leveraged.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8272307356988121010?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8272307356988121010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/observation-on-growing-disconnected.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8272307356988121010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8272307356988121010'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/observation-on-growing-disconnected.html' title='Observation on Growing Disconnected'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-3019877771599170996</id><published>2011-01-13T09:05:00.000-08:00</published><updated>2011-01-13T09:05:30.921-08:00</updated><title type='text'>Software Talent Agency?</title><content type='html'>I had some thoughts cross my mind today, and wanted to write them down before they fade. &lt;br /&gt;&lt;br /&gt;I'm of some reputation in the agile community, a sometimes-recognized author, a consultant (ex-of Object Mentor, ex-of CSC Consulting) and an agile coach. I've taught thousands of developers to program in C or C++ or Python, how to do TDD in many more languages, and the intricacies of object-oriented design. I've refactored horrible code and tested and built tools and transformed teams. &lt;br /&gt;&lt;br /&gt;I am also a 48-year-old man who needs to establish his personal brand. Many of us are introverts by nature, and those of us with rural, midwestern upbringing tend to self-deprecation. I've always found self-promotion abhorrent. Writing a promotional bio actually makes me a little sick at my stomach. The shame of it is that I could have learned to be comfortable with it a long time ago.&lt;br /&gt;&lt;br /&gt;If I had begun the push earlier and had some coaching I would have made some different technology and career choices, but who knew? I jumped the track a few times, missed a few predictions, and didn't do some things that might have made me wealthier and more secure in my life and community.&lt;br /&gt;&lt;br /&gt;Now imagine that you are well-known in your community, and you heard of some upcoming new Corey Haines or Ben Rady or other talented kid.  You would have the contacts to introduce them around. You could help them to establish their web presence and write up promos. You could promote them among their peers. You could connect them with editors who could shepherd them into writing gigs with magazines. You could hook them up with local communities, find them speaking opportunities and help them polish their presentations. You could help them to write the kinds of things that get picked up on reddit, hackernews, and the like. You could find them side gigs, maybe help them negotiate rights to quote code and publish details on the work they do. You would have to learn about buzz and how it works, the way a publicist does.&lt;br /&gt;&lt;br /&gt;It would be a talent agency for programmers.&lt;br /&gt;&lt;br /&gt;With just one or two good success stories, you would raise the value of your organization and all of the people being coached there. Companies would be interested in using your people, and people would find value in joining.  &lt;br /&gt;&lt;br /&gt;It would be rough at first. You'd collect money much as a headhunter would. You would get a clip from placement, maybe a finders fee or the like. Maybe a clip from writing gigs you developed, deals you sign. There would be much to learn, but relationships would have a long tail. In time you could collect money on both sides.&lt;br /&gt;&lt;br /&gt;I know that people already get involved in the community and connect and conferences, but not all people know how to do that or how to build momentum that way. It's a knack that some charismatic people have and others do not. Not all talented people can keep a room spellbound like Bob Martin or connect with people so easily as Corey Haines.&lt;br /&gt;&lt;br /&gt;I wonder if the software world is big enough that we could have a talent development agency for software developers.  It's a really intriguing thought, since self-promotion is not always what good techies do best. &lt;br /&gt;&lt;br /&gt;I'm still the midwestern introvert, but I wonder if some of my extroverted peers see some value in the proposition.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-3019877771599170996?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/3019877771599170996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/i-had-some-thoughts-cross-my-mind-today.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3019877771599170996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3019877771599170996'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/i-had-some-thoughts-cross-my-mind-today.html' title='Software Talent Agency?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-5947842671024488857</id><published>2011-01-07T07:56:00.000-08:00</published><updated>2011-01-07T07:56:01.531-08:00</updated><title type='text'>About "Under Test"</title><content type='html'>I wrote earlier about code being &lt;a href="http://agileotter.blogspot.com/2010/11/under-test.html"&gt;under test&lt;/a&gt;, and how advantageous to have a test "under" several layers of testing.  As I was looking through my old google docs, I found this drawing I'd made to explain layers of testing in a web app. &lt;br /&gt;&lt;br /&gt;Terminology is catered to the audience of the time, and will probably confuse some.  For instance "controller" here is really more like the "model" layer with its duty of acting as facade and moderator for underlying objects.  Its purpose is primarily ensuring business rules and performing a single broad function that includes potentially many objects at the lower level.&lt;br /&gt;&lt;br /&gt;The "API" objects here are the business objects.  Again, tailored to the local terminology.  Apologies. Maybe the Agile Otter should redraw the whole thing sometime soon. Anyway...&lt;br /&gt;&lt;br /&gt;The idea is pretty simple, but sometimes people don't quite understand why the code-behind needs to be thin and why they shouldn't re-implement functionality in the fitnesse tests. If we use good &lt;a href="http://pragprog.com/magazines/2010-12/cohesive-software-design"&gt;cohesion&lt;/a&gt; and manage &lt;a href="http://pragprog.com/magazines/2011-01/code-coupling"&gt;coupling&lt;/a&gt; well, then the unit testing becomes fairly simple, as do the unit tests on the controller. &lt;br /&gt;&lt;br /&gt;We can test the code-behind through the web but even automated browser-tests are slow, often running for hours. It is handy to have browser tests, but nobody wants to sit and wait for them to finish. Most shops will push them off to the build farm so they don't suck up developer time.  If code it only tested by-hand through the user interface, testing is pushed off to a dedicated testing team who will script and re-run the sames tests month after month for hours. It quickly becomes too expensive to keep scaling that team, and they start selectively running ui tests, in which case errors will slip out to production and customer care will have extra work, and bug fix reports will pull programmers out of new feature engineering. Often a company will have to split off a separate full-time team to do production bug fixes and data repair. It gets expensive quickly.  Automating the tests means that we might be able to run all the tests every day, so that fewer defects can get out to the customers. It's cost-effective, but again very slow. The less the code-behind does, the better we can deal with it being potentially untested.&lt;br /&gt;&lt;br /&gt;Our integration and acceptance tests (shown here with FitNesse) are going to run many minutes, maybe an hour or more. If the tests take only a few minutes then programmers will run them several times a day, probably before committing or pushing code to the shared repository, almost certainly at the completion of a programming task. Ideally these tests will bypass the code-behind entirely, but not re-implement any of its functionality. In order to make these tests effective, we need to empty the code-behind so that it is little more than plumbing between the controller and the UI. The business function controller is pretty testable, but the tests are like integration tests with many objects involved and possibly significant effects. It can still be tricky to test at this level unless most of the interesting bigs are pushed down into the business objects. The less it does, the easier the testing is.&lt;br /&gt;&lt;br /&gt;Finally we're getting into the individual business objects. These tend to be pretty easy to test, as they mostly act only upon themselves. Good news for us.  We can write extensive tests to drive behaviors into the objects. They become robust and predictable and understandable to the degree we stick to what we know about coupling and cohesion. Because they are underneath layers of testing (UI, FitNesse, controller, and individual unit tests) we can have more confidence in the changes we make here.&lt;br /&gt;&lt;br /&gt;Maybe the picture isn't perfect, and the terminology is a little twisted, but the idea here is very simple. It works out that we can save ourselves time and money and even save face if we learn to keep the upper layers of the application thin, and save the meaty implementation for the areas where it is under layers of testing.&lt;br /&gt;&lt;br /&gt;Of course, all blessings are mixed and even dark clouds can have a silver lining, so simple ideas can have costs and side-effects all their own. But this simple idea seems to work and seems to reduce problems for development teams and companies which employ them.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_WMyCPCNYrhk/TScee7GYKYI/AAAAAAAAATg/NRVNfco_4n0/s1600/TheIdea.png" imageanchor="1" style=""&gt;&lt;img border="0" height="240" width="320" src="http://1.bp.blogspot.com/_WMyCPCNYrhk/TScee7GYKYI/AAAAAAAAATg/NRVNfco_4n0/s320/TheIdea.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-5947842671024488857?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/5947842671024488857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/about-under-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5947842671024488857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/5947842671024488857'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/about-under-test.html' title='About &quot;Under Test&quot;'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_WMyCPCNYrhk/TScee7GYKYI/AAAAAAAAATg/NRVNfco_4n0/s72-c/TheIdea.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4447606979335058857</id><published>2011-01-05T09:32:00.000-08:00</published><updated>2011-01-05T09:32:54.646-08:00</updated><title type='text'>Want Your Own Agile Otter?</title><content type='html'>This is a limited time offer.  If you would like to have The Agile Otter working for you, this might be your chance. &lt;br /&gt;&lt;br /&gt;If you are looking to expand your technical team or need an experienced Agile coach, feel free to drop me a line (tottinge@gmail.com) and we can talk through particulars. I can work as a remote pair-programming partner (tech team) or on-site in NW Chicago burbs (coaching).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4447606979335058857?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4447606979335058857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2011/01/want-your-own-agile-otter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4447606979335058857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4447606979335058857'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2011/01/want-your-own-agile-otter.html' title='Want Your Own Agile Otter?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6494162201864896705</id><published>2010-12-28T15:55:00.000-08:00</published><updated>2010-12-30T06:06:01.247-08:00</updated><title type='text'>Explaining What I Do For A Living</title><content type='html'>I had a friend once tell me that he didn't understand what it meant to program computers. He was not really a computer user, and was just getting ready to try email at the time. He wasn't a gamer, and frankly the whole computer thing seemed too weird to him. After all, it's a machine, right? How do you program a machine? Is it like choosing a darkness setting on the toaster? Typing data into quickbooks? What? That was many years ago, but it still sticks with me. Some people (most in fact) really don't know what I do.  If I tell them, they don't know any more than before.&lt;br /&gt;&lt;br /&gt;When most people hear "programmer" they think "IT", in which case I must be the guy who fixes network outages, distributes patches, and helps people when their machine crashes (admittedly, a weak view of what IT is about). But no, I'm not that guy. I love those guys, but I'm not one of them.&lt;br /&gt;&lt;br /&gt;A cousin of mine took an introductory course on programming, probably in Visual Basic, I don't recall.  He told me that what I do for a living is really easy, "just typing."  Of course I do some typing, but I'm not employed as a typist.  In fact, on my good days, the program I work on is net-negative in terms of lines of code. But then a one-semester course on music appreciation hardly makes one a symphony conductor, or even a musician.&lt;br /&gt;&lt;br /&gt;A &lt;a href="http://stackoverflow.com/questions/811246/how-to-hide-thinking-at-work-so-that-the-non-programmers-dont-suspect-slacking/"&gt;post on slashdot&lt;/a&gt; a while back asked how to disguise "think time" because people mistake it for slacking. Again, we forget that this is not obvious to non-programemrs. One follow-up from Ben Alabaster was useful&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;During their lunch break get them to do a simple task like as a crossword. Ask them to be conscious of the amount of time they spend reading/writing vs. the amount of time they spend thinking [or looking up the answer]. Tell them that this is exactly the same as the time you spend reading/typing vs. the amount of time you spend thinking and looking up answers.&lt;br /&gt;&lt;br /&gt;Better still Sudoku because it can involve hours of trying to figure out where you went wrong and why none of your numbers add up. So while the task itself seems relatively easy, after all, it's just numbers in boxes it can take time. Get them to predict how long it'll take them before they start and see if their prediction is right - guaranteed it won't be. You can hit them with a double whammy for why your time expectations never quite add up either.&lt;br /&gt;&lt;br /&gt;This is the only way I can really think of to get them to understand the way engineers work. I see lots of "those types just don't get us types" - people are adaptable, people can understand things if presented in a fashion they can understand, it's just that nobody's ever taken the time to present them with an argument they get.&lt;/blockquote&gt;&lt;br /&gt;I think it is a great answer.  We don't type for a living, we understand, reason, mentally try different solutions, hypothesize, disprove, reason, and invent.  If we already knew the solution, we would simply type it in and be done with it, just as someone who had already solved the sudoko puzzle could copy it onto paper in hardly a minute's effort.&lt;br /&gt;&lt;br /&gt;The majority of my work, though, is in diving into a system I don't understand (having read only a small percentage of its total verbiage), learning enough to understand why it is broken,  rearranging and rewriting things until they make sense, writing tests to prove that my understanding of the problem is right, making changes that should fix the problem, and testing that my changes don't introduce new problems, all within a system vast enough that no one person understands how it works. I guess that isn't so easy to understand.&lt;br /&gt;&lt;br /&gt;I spend more time learning than problem-solving, and more time problem-solving than typing. Basically, programmers learn and think for a living, and type their solutions into computers.&lt;br /&gt;&lt;br /&gt;I suppose the right analogy is that you are handed three pages in the middle of chapter 17 of a 40-chapter novel, and you're asked to make some plot changes in the next hour or so.  There is no chance you can read the whole book and make the changes in time.  You could ignore the book and make your little changes locally and hope it doesn't disrupt the overall plot line, or you can read the chapter you're in and wing it.  Eventually you'll have a solution you believe in, and you can type it in... but you shouldn't dive in with a typewriter until you've assessed what's going on, and the first thing you type probably won't be "good enough."&lt;br /&gt;&lt;br /&gt;But now imagine that the document isn't a novel, but a multi-million word legal contract. You have to be very, very precise. Any mistake might open the company up to lawsuits and issues and costly contract revisions. Now you have the idea.&lt;br /&gt;&lt;br /&gt;A really huge crossword puzzle is still a good approximation of a software system.  Any one letter of any word may be a part of several different words, and changing one word may force you to change several others, which might cascade out to several others as well. &lt;br /&gt;&lt;br /&gt;Do you understand why solving crossword puzzles isn't "just typing", and why it's faster if you have partners and reference materials? Do you understand why you might spend more time thinking than writing, and why sometimes you need to walk away from it for a few minutes if you're ever going to complete it? Then you probably understand programming well enough.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6494162201864896705?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6494162201864896705/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/12/explaining-what-i-do-for-living.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6494162201864896705'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6494162201864896705'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/12/explaining-what-i-do-for-living.html' title='Explaining What I Do For A Living'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4746663196963165925</id><published>2010-12-13T10:06:00.000-08:00</published><updated>2010-12-13T10:06:28.193-08:00</updated><title type='text'>Where's Tim</title><content type='html'>I've been quite busy of late, partly with holiday season, partly with medical matters (wife's ankle surgery), partly with church, partly with Agile In A Flash, and partly with the series of articles Jeff and I are writing for PragProg. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.pragprog.com/magazines"&gt;Last month's PragProg article&lt;/a&gt; brought some good feedback and kind words from some of you and we're thankful. We have two more "big topic" articles to go (abstraction and volatility) and then we're back to the stories behind the AgileInAFlash cards (on pre-order via online outlets and expected in January). Please keep up with us there as well as here and at &lt;a href="http://agileinaflash.com"&gt;Agile In A Flash&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'm looking at some new projects next year, hopefully some that pay and some that allow me to improve my chops on open source development. I don't foresee another book just yet, but some writing is definitely in the works. &lt;br /&gt;&lt;br /&gt;The only other news is that I dived into Ruby for a little while, and will be chasing that down via the three books I now own. I'll likely be playing with IronPython and other CLR languages this coming year, and I still have to get some Javascript skills together.&lt;br /&gt;&lt;br /&gt;It has been a great year, and I expect next year to be greater yet.  Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4746663196963165925?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4746663196963165925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/12/wheres-tim.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4746663196963165925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4746663196963165925'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/12/wheres-tim.html' title='Where&apos;s Tim'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1327813449219911845</id><published>2010-11-03T21:21:00.003-07:00</published><updated>2010-11-09T05:55:02.084-08:00</updated><title type='text'>Under Test</title><content type='html'>Today I was thinking about  the phrase "under test" as in "we've got to get this code under test so we can fix it."&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I started of thinking about the way the app we were discussing was laid out.  There was (at rock bottom) some persistence stuff. Above that was (on one side) reporting and query, and on the other was some business objects. Above the business objects are some model-like objects (sometimes) and above those are UI-related code.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Starting at the "top", with UI presentation, we can test through a browser. That makes it the territory of human by-hand testing and also of  browser emulators, browser drivers, and screen-scrapers.  Such tests are going to exercise a fully-integrated system, and can be slow due to many features such as database access, file system access, network access to services, etc. Human testing is particularly slow, as it involves reading time, typing time, and time to evaluate results. Human tests we can measure in minutes per test.  The automated tests are much faster, but we might be able to measure single-threaded testing in dozens per minute. There is a practical limit to how many of these slow tests we can tolerate. Human testing is most expensive and slow, so hundreds of thousands of tests per week is not reasonable, let alone per day. Human testing can be reserved for the areas requiring special, creative, intelligent effort.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Under the UI layer are code-behind classes, which are testable via normal unit testing techniques. The tests won't be very interesting, but mocking and dependency injection can make them crazy fast. We could have many thousands of these trivial tests, and they could run in tiny fractions of a second each. We could tolerate a lot of tests here without feeling like our development is dragged down. We can afford the tests to be plentiful and trivial.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Classes that show good cohesion will have some kind of Model class under them, allowing for an alternative UI like fitnesse or cucumber. The AT framework will take up some time in overhead, but hundreds of test steps per second are still possible, and tests can relatively straightforward to write. We can make many tests and tolerate hundreds of them before it becomes too expensive and they are pushed offline to the CI system.  Badly written tests can be hard to write and very slow to write, and are not uncommon. These hasten the day when running "all the tests" is too frustrating for developers.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Using mocking, we can do a lot of tests on the Model classes, crazy fast. Model layer tests might be some of the more important tests we run, as they ensure that the code behind the interfaces is sound. This is a great place for us to load up on fast unit tests. We should measure their execution in thousands per second.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Under Models are the business objects, which can be tested with normal unit testing techniques, and many thousands of tests can run in just a few seconds (if we can keep the database out of it). This is an area where we need a lot of tests, and can easily afford to run them all many times per day.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Queries and reports are a different story. We can write tests for them, but we can't tolerate the cost and expense of sitting around waiting for them. Reports are particularly rough, as there are going to be some onerous setup requirements for those. We're probably going to run them in CI and also maybe just once before pushing code to the CI system if we are diligent workers and think we might have affected them.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So what's the point? With this in mind, consider what "under test" means.  Testing is arranged in layers from the top of the system to the bottom. Code in the UI is up high, not "under" many tests.  It may not be tested very well at all, depending on how thorough the UI tests are and which ones the human testers choose to run. It's sketchy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So if a system has code making decisions in the HTML templating system, that code is barely under test at all and may never be safely under test. Changes there will always be dangerous.  Changes to the code-behind only slightly less so. If there is a model layer, though, it starts to look pretty healthy.  The business objects, are under their own unit tests, the model layer's tests, and the UI tests. They have a thick blanket of protection, and can be refactored with relative impunity.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Get it? "Under Test" is all about confidence to make changes. Code in higher layers is under fewer tests, so code needs to be extracted and moved downward, downward, downward until it is just high enough above the persistence layer to be tested quickly and well. Get it "under the tests."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1327813449219911845?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1327813449219911845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/11/under-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1327813449219911845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1327813449219911845'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/11/under-test.html' title='Under Test'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2143375890276646252</id><published>2010-10-12T06:08:00.000-07:00</published><updated>2010-10-12T06:08:56.363-07:00</updated><title type='text'>C# Curiously Nested Production Class</title><content type='html'>We tackled some code for refactoring, and I found an unusual construct. To wit:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public class Base: Many, Varied, Bases {&lt;br /&gt;    private int x;&lt;br /&gt;    &lt;br /&gt;    // ...&lt;br /&gt;&lt;br /&gt;    public class Derived: Base {&lt;br /&gt;        public setX(int value) { &lt;br /&gt;            x = value;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So here we have the derived class nested in its base class.  I am quite comfortable with nested anythings in python or a few other languages, so that's not a problem. I nest 'testable' classes in tests all the time so I can override or stub a few methods. In python it's a normal way of life to nest functions and classes. &lt;br /&gt;&lt;br /&gt;This one is odd because it is a production class, nested inside a production class, and deriving from its outer class.  It makes me think of a pregnant female, having a child inside it whose dna derives from the mother. &lt;br /&gt;&lt;br /&gt;So what powers does this odd nesting convey?   My first thought is that it is some kind of closure, but this turns out to be false. There is no real closure involved. The whole closure that derives from the parent made my head swim just a bit, but it is a wild goose chase. Nothing to it.&lt;br /&gt;&lt;br /&gt;What does happen is that the nesting bestows readability on the private variables inherited from the enclosing parent. The x in the setX is the Derived.x inherited from Base.  It is referencing its own variable, even though that variable is private instead of protected in the parent.  Indeed, resharper refused to move the class to an outer scope because its own variables would become unreachable to its own methods.  To do that extraction, we made the variables protected in the parent.&lt;br /&gt;&lt;br /&gt;The other thing that it did was hide the class from an automated test program. These classes are both code-behind for web pages.  We have an automated tool that searches the namespace for all classes derived from our base web component class and ensures that they all have page generation tests. This one did not. &lt;br /&gt;&lt;br /&gt;I am wondering if there is some interesting way to use this like a private interface class in C++ or Java.  It was curious, but I'm wondering if it can't also be useful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2143375890276646252?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2143375890276646252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/10/c-curiously-nested-production-class.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2143375890276646252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2143375890276646252'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/10/c-curiously-nested-production-class.html' title='C# Curiously Nested Production Class'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7293358745486356874</id><published>2010-10-08T21:05:00.000-07:00</published><updated>2010-10-08T21:07:33.947-07:00</updated><title type='text'>Explaining Refactoring</title><content type='html'>I &lt;a href="http://agileotter.blogspot.com/2010/10/heatmap-new-hotness.html"&gt;recently&lt;/a&gt; collected up some information from Jira and git about our software process.  &lt;br /&gt;&lt;br /&gt;I am mulling over an idea, and a little feedback is welcome. To help understand the context, among our products we have one codebase that was originally written pre-agile in a non-TDDed manner but greatly improved during and after the company's agile transition.  It is pretty good stuff, and constantly improving in quality and functionality, consistently delivering real value to customers. We're pretty of proud of it and its future.  There is a great team working on it. Sometimes, though, we find the need for a large-scale refactoring somewhere in the code base, and we have the &lt;a href="http://agileinaflash.blogspot.com/2009/02/courage.html"&gt;courage&lt;/a&gt; to tackle these.&lt;br /&gt;&lt;br /&gt;Basically the problem is that refactoring sounds bad to product managers. When it's done well, there is no visible difference in the code.  When it isn't done perfectly, it injects defects. The obvious knee-jerk reaction is to resist any large-scale refactoring efforts.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;As an aside: refactoring ought to be invisible.  It should be part of every task, and not a task on its own. If a system is built ground-up using TDD then no "refactoring tasks" should appear in release notes and no "refactoring tickets" need be filed.  Sometimes, however, there is legacy code with significant technical debt or significant code cruft in new code. That ugliness might be in key areas of the application.  Sometimes it is worthwhile to dedicate time to bringing a piece of code under control of tests.  Even so, if people outside of your development team are aware of refactoring it is because something is wrong somewhere. It is a process smell.&lt;/blockquote&gt;&lt;br /&gt;Of course the product manager is right about the risk of large-scale refactorings and also about the lack of end-user value from effective efforts. What is missing is an understanding of the value of improvements to code &lt;a href="http://agileinaflash.blogspot.com/2010/02/seven-code-virtues.html"&gt;virtues&lt;/a&gt;, maintainability, and leverage. &lt;i&gt;Product managers don't see code.&lt;/i&gt; &lt;br /&gt;&lt;br /&gt;Refactoring  done well speeds code changes. The reward is that we are able to sustainably produce more features faster, with better quality. The punishment for not refactoring is that the code becomes continually worse and changes become slower and more defective.  We need continual refactoring and testing, and sometimes we need some an initial "boost" to areas that are hard to test. This is only obvious to people who are elbows-deep in the code, and &lt;i&gt;product managers don't see code.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Since indeed cleaning up ugly code is somewhat risky, we technical people &lt;b&gt;should&lt;/b&gt; have a solid means to judge whether any large-scale effort is truly worth doing. Otherwise we may waste many weeks on a crazy "ugly code" witch hunt without significantly improving the fluidity of development. The product managers don't want that, and neither do we.&lt;br /&gt;&lt;br /&gt;Product managers see a bug here, a flaw there, a new bit of functionality, a slipped date, a funky side-effect here and there, all disconnected. They can't see the problems in the code because &lt;i&gt;they can't see code&lt;/i&gt;. Some of them don't even believe that the technical problems really exist because it sounds like programmers are just making excuses.&lt;br /&gt;&lt;br /&gt;I hacked together a simple similarity comparison of the text of our Jira tickets and compared them to code change records for those tickets. My efforts met with great disappointment.  Two similarly-described bugs may not involve the same code at all.  Conversely, if I show the tickets whose resolutions &lt;i&gt;do&lt;/i&gt; involve the same file, non-programmers strain to see any commonality between them.&lt;br /&gt;&lt;br /&gt;While product managers see only holes. programmers see only gophers. If product managers could see which set of bugs are connected to which source code files then they might demand remediation, but only for the code that really effects delivery and quality. At least in a rational world there would be such a level of data-based decision-making. &lt;br /&gt;&lt;br /&gt;One answer may be to have the product managers work in the code, but I doubt that coaches will often be successful with this strategy.   Instead, we may need a better way to illustrate the underlying connections.&lt;br /&gt;&lt;br /&gt;This is where the heat map comes in, but it was written from a programmer's point of view. As a step in a new direction, I coded up a report to list the tickets for any given file. Maybe in the coming weeks I can convert the data to a form that product managers can see and digest without becoming programmers first.  &lt;br /&gt;&lt;br /&gt;If you have any interesting ideas for further research or credible presentation of this data, drop me a comment below.  I'd love to walk in some day with a new way for my partners who are product managers to understand our work so that technical debt remediation can be properly assessed and prioritized. I'll settle for better criteria on which to base my choice of large-scale refactoring efforts.  &lt;br /&gt;&lt;br /&gt;It's a good dream. Waiting for your comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7293358745486356874?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7293358745486356874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/10/explaining-refactoring.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7293358745486356874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7293358745486356874'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/10/explaining-refactoring.html' title='Explaining Refactoring'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4410187870274539626</id><published>2010-10-08T20:08:00.000-07:00</published><updated>2010-10-13T10:17:07.099-07:00</updated><title type='text'>Heatmap: The new hotness</title><content type='html'>I had some fun recently after agonizing over the problem of bug prevention. &amp;nbsp;I put out the observation that bugs have a tendency to cluster, and that the more often code is edited the greater the need for the code to be frightfully &lt;a href="http://agileinaflash.blogspot.com/2010/02/seven-code-virtues.html"&gt;virtuous&lt;/a&gt;, &lt;a href="http://amzn.to/1G1pk"&gt;clean&lt;/a&gt;, and thoroughly &lt;a href="http://agileinaflash.blogspot.com/2009/07/essential-unit-test-cards.html"&gt;tested&lt;/a&gt;. The problem was with determining which code should be cleaned up in order to reduce the injection of bugs.&lt;br /&gt;&lt;br /&gt;I considered various metrics and measurements, including cyclomatic complexity, code duplication, and various design details, but ultimately dismissed them for fear that they would be unconvincing. I didn't want my audience to think the heat maps is just "coach Tim lecturing." &amp;nbsp;In keeping with our description of effective &lt;a href="http://agileinaflash.blogspot.com/2010/07/information-radiators.html"&gt; information radiators&lt;/a&gt; we needed the information to be simple and stark.&lt;br /&gt;&lt;br /&gt;Our SCM is based on git, and our tracking software is Jira. We have to include a recognizable, open, Jira ticket id in every code commit.  Many of the tickets are enhancements, improvements, or investigations. Some are problems with legacy data or data import, and some are defects. Tickets are associated with releases, and the release dates are in the database as custom fields. I decided to count tickets, and not commits. We commit frequently, and some more frequently than others. Counting commits would be mostly noise, but counting tickets seemed like a pretty good idea.&lt;br /&gt;&lt;br /&gt;I fired up python and grabbed a partner. By using the PyGit library, we were able to parse all the git commits, collect ticket numbers, and parse the diffs to find the names of all files touched in the commit.  I tossed together a shelf (bdb) of file names to ticket numbers. &lt;br /&gt;&lt;br /&gt;Next I pulled down SOAPpy and my Jira-smart partner helped me build a Jira query. We pulled down the tickets and created another handy shelf, including the ticket number as a key and key facts like the descriptions, summaries, a defect indicator for defect tickets, and release numbers with dates. &lt;br /&gt;&lt;br /&gt;Finally we walked through all of the tickets and ordered them by release date. I guess that's pretty coarse-grained, but it makes sense to keep it pegged to recognizable events.  Releases have more data available (BOMs, release notes, etc) in case we need to dive deeper. &lt;br /&gt;&lt;br /&gt;So then we get the fudgy part. A file that doesn't get any activity is not very interesting. It may be good or bad, tested or untested, clean or filthy, DRY or very non-dry, but nobody is messing with it so we can ignore it for a while.  On the other hand, the more a file is touched, the more important it is that the file is easy to work with. &lt;br /&gt;&lt;br /&gt;We don't have any information about which file(s) contained a defect, only the set of files that were touched while resolving the defect.  That rightfully includes any tests, flawed files, test utilities improved, and any other source files touched by renames or other refactorings. &amp;nbsp;The more often a file is updated in the resolution of a defects, the closer it probably is to the problem file.  I needed to weight activity related to defects much more highly than activity related to non-defect tickets.&lt;br /&gt;&lt;br /&gt;As a rough heat map metric, I took the total tickets for a period and added back the total defects * 2, counting each defect three times effectively. That just feels about right to me and my partners.  If I have two updates to one file with no defects, the code might not need much preventative maintenance. If I have two defects in one release then definitely needs some love. I came up with a ranking and graphed the top five files.&lt;br /&gt;&lt;br /&gt;That left me with a jittery graph, so I decided to use a longer period, which I settled on being 3 releases. The January release "heat index" (heh) is based on November through January, and the February heat index is December through February. It gives us a smoother graph, but may not be the smartest way to smooth it. &amp;nbsp;It is simple, though, and that counts for something.&lt;br /&gt;&lt;br /&gt;The top five files were pretty interesting.  When I looked over it with a production support (triage) person, the files were very familiar to them. A manager-type remembered the defects associated with them quite well. A features programmer told me that these files really were troublesome. Some files had been remedied by dedicated refactoring and testing time, and we could see how those files had lost 'heat' over the period of a year.  Other files were trending upward in heat, because of a combination of discovered defects and being in a functional area that is seeing a lot of expansion.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;We checked out the top two files which were trending hotter and found that they had low unit test coverage. We suspect a connection there.&lt;br /&gt;&lt;br /&gt;The interesting parts of this experiment (to me) were:&lt;br /&gt;1) We closed a feedback loop (request-&amp;gt;code-&amp;gt;release-&amp;gt;defect report-&amp;gt;code)&lt;br /&gt;2) The metric is not based on my ideas of quality, just historic fact. so the answers are credible&lt;br /&gt;3) There is so much more we can do with this data.&amp;nbsp;More on that later.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;This is the new hotness, and it is presented as an information radiator in the bullpen area. &amp;nbsp;We are all "hot" on the idea of testing and refactoring these files, so hopefully we'll see some marked improvement over the next few releases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4410187870274539626?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4410187870274539626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/10/heatmap-new-hotness.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4410187870274539626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4410187870274539626'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/10/heatmap-new-hotness.html' title='Heatmap: The new hotness'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6546941835635646314</id><published>2010-10-01T09:17:00.001-07:00</published><updated>2010-10-01T09:17:29.112-07:00</updated><title type='text'>Tests Are Code</title><content type='html'>I write an automated acceptance test (AT) and I find that I would  like to perform certain actions against the business objects.&amp;nbsp; I create a  method on the business objects and my test stays slim while my model  builds up more functions.&lt;br /&gt;&lt;br /&gt;So, there is potentially code  in the production system that is only used in the tests. The debate  today is whether that is "unnecessary bulk that solves no business need"  or is instead "first-class code."&lt;br /&gt;&lt;br /&gt;I am betting that  the code you need in the AT is code you probably also needed in the UI  and/or APIs to external clients. I am supposing that it is needed in the  test because it is likely written into the UIs instead of the model and  so the tests' logic is duplication. I also think that even a reasonably  poorly-written test is written to support business rules.&amp;nbsp; Therefore,  the tests express business logic so methods required by the tests are  methods required by business.&amp;nbsp; While some worry that a method on a  business object might be picked up and used by a programmer in the  production code, I hope that this is true.&lt;br /&gt;&lt;br /&gt;Your opinion  matters, so feel free to leave a comment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6546941835635646314?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6546941835635646314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/10/tests-are-code.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6546941835635646314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6546941835635646314'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/10/tests-are-code.html' title='Tests Are Code'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6289748036629379772</id><published>2010-09-10T12:09:00.000-07:00</published><updated>2010-09-10T12:32:46.171-07:00</updated><title type='text'>Pair Switching Degrades over Time</title><content type='html'>We had a nice talk today about the natural foot-dragging that is common among pair programmers when it comes time to switch partners. &lt;br /&gt;&lt;ol&gt;&lt;li&gt;It's not really social, as in partners gravitating to each other as buddies. Instead it tends to be more work-related.&amp;nbsp;&lt;/li&gt;&lt;li&gt;It does feel socially awkward to tell your partner you want to go work with someone else now. &lt;/li&gt;&lt;li&gt; It sometimes does happen that partners who are gung-ho agilists will prefer working together. They prefer partners who allow them to do their work well and will improve them over those who create drag by arguing against testing or refactoring.&lt;/li&gt;&lt;li&gt;People get comfortable in a particular task and want to see it through.&amp;nbsp; This is a good feature usually, and certainly is favorable for people who do individual, non-paired work. In an agile team, it's limiting. Someone needs to move on so that there are more eyes/hands/minds in the code.&lt;/li&gt;&lt;li&gt;If there is no standup there is no pair switching.&amp;nbsp; If the team relies on assignment from a manager (totally non-agile) then teams tend to complete tasks at different times. This means that no two pairs are finished at the same time, so any switching requires interrupting at least one pair.&lt;/li&gt;&lt;li&gt;Everyone wants to work in the "cool" stuff, but each person has their  own definition of "cool."&amp;nbsp; People will gravitate to tasks in the areas that excite them, and don't want to leave that work to do something else with a different partner.&lt;/li&gt;&lt;li&gt;People are nervous in work that they don't understand well. Rather than eagerly gaining experience in all areas of the app, they try to stay in an area where they have knowledge and leadership. Switching partners may take them into areas they don't understand.&lt;/li&gt;&lt;/ol&gt;I'd like to open this up to a larger conversation with agile and becoming-agile and surviving-as-non-agilist-on-agile-team people.&amp;nbsp; Why is it that you don't want to switch three or four times a day?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6289748036629379772?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6289748036629379772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/09/pair-switching-degrades-over-time.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6289748036629379772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6289748036629379772'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/09/pair-switching-degrades-over-time.html' title='Pair Switching Degrades over Time'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1785809743412997976</id><published>2010-09-01T10:16:00.001-07:00</published><updated>2010-09-01T10:16:19.922-07:00</updated><title type='text'>Where is the Agile Otter?</title><content type='html'>I've been developing new skills, and working with Jeff on the &lt;a href="http://agileinaflash.com"&gt;AgileInAFlash project&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;What's new? Our &lt;a href="http://www.pragprog.com/magazines/2010-09/agile-flash-cards"&gt;latest article&lt;/a&gt; for Pragmatic Programmers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1785809743412997976?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1785809743412997976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/09/where-is-agile-otter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1785809743412997976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1785809743412997976'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/09/where-is-agile-otter.html' title='Where is the Agile Otter?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2197572309253719340</id><published>2010-07-16T12:25:00.000-07:00</published><updated>2010-07-22T18:52:09.182-07:00</updated><title type='text'>Copy And Edit Revisited</title><content type='html'>Vadim reminds me that I need to address root causes of Copy-Paste-Edit programming, rather than merely &lt;a href="http://agileotter.blogspot.com/2010/02/problem-of-copying.html"&gt;ranting about how bad a practice it is and how it ruins good code&lt;/a&gt;. Of course, he is right. That is part of being Vadim.&lt;br /&gt;&lt;br /&gt;I've previously ranted about the ill-effects of copy-paste-edit  programming, but it would be unfair to say that there is never a need  for it, or that people who did it were simply stupid and lazy.&amp;nbsp; The  problem would not be so prevalent if it did not have some reasonable  basis for practice. However well-intentioned and useful it is, its net effect on a code base is overwhelming negative.&lt;br /&gt;&lt;br /&gt;Here are a few root causes I recognize, and I'm open to hear more.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Tedious construction semantics&lt;/b&gt; encourage copying. Many APIs are very thin access to bean-like objects, and yet using them correctly can be a trick. You have to know what to set, and in what order, and what to call next.&amp;nbsp; It is far easier to copy a correctly-set-up object use than to make one from scratch. &lt;/li&gt;&lt;li&gt;Copied code is a&lt;b&gt; working initial state&lt;/b&gt; from which to make progress. This is useful not only when dealing with complicated code in the current system, but is especially true and especially beneficial when copying code examples from docs, books, or online code repositories. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Complex multi-line operations&lt;/b&gt; have many ways to break. If the system shows poor cohesion or has multiple ways of doing the same job (and some ways work better than others) then copying a usage that works seems pretty safe.&amp;nbsp; It is worse when the API has a "seed and harvest" interface, where one  must set certain variables (seeding), then call a function, then collect  the results from various variables (sometimes the same ones, sometimes  not).&lt;/li&gt;&lt;li&gt;Copying &lt;b&gt;minimizes the chance of breaking existing code&lt;/b&gt;, which is the primary fear in legacy systems. If some (or most) code is ill-tested, then any editing of existing code can fail in unexpected ways. Copying an algorithm and changing the variable names to match the local context preserves the original code.&amp;nbsp; &lt;/li&gt;&lt;li&gt;&lt;b&gt;It is easier to copy than to study&lt;/b&gt;.&amp;nbsp; Copying code that pretty much works now, you can make minimal changes and hopefully it will work without you having to understand the underlying concerns. It allows you to get in and out quickly without doing research. Copy/paste creates a point in time at which it is basically sound, and can be refactored to purpose.&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Moving code into functions requires thinking about design&lt;/b&gt;.&amp;nbsp; Is it one method or several? To which class does it belong? The original owner of the code? The new code? A class currently used by both? A new class? An existing library?&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;Is copying always wrong? I think it is not.&amp;nbsp; The act of copying itself should kick in your "spider sense," but it is not necessarily harmful.&amp;nbsp; Copying examples from outside the system might be useful as a starting point.&amp;nbsp; Copying code from inside the system (including copying an existing test to help create a new test) can be helpful to the programmer.&amp;nbsp; However, having duplicated code in the system is always wrong, and having code that is placed badly is wrong as well.&lt;br /&gt;&lt;br /&gt;It could be useful to put some rules around your use of copying.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Don't leave duplicated code in the system. If you copy, consider your copy to be merely a starting point, and also point of technical debt. Pay it off quickly by refactoring the duplication out of existance as soon as possible. &lt;/li&gt;&lt;li&gt;Even when you write unique code, extract methods and move them to their most appropriate class, so methods can be called instead of copied next time. If you leave manipulations in the user of a class, you are encouraging the next user of that functionality to copy it as well.&amp;nbsp; &lt;/li&gt;&lt;li&gt;If the code is ugly enough (complex intialization, multi-step operations), extract the non-unique parts as new methods called from both copies. Interfaces do not have to be ugly and complex.&lt;/li&gt;&lt;li&gt;When you find duplication, or create duplication, finish your refactoring step by sweeping the code base for other copies, and correct them likewise.&amp;nbsp; It doesn't help if two versions out of a dozen are refactored. You want the whole system to improve as you work.&lt;/li&gt;&lt;li&gt;Copying might not be so bad if you refactor the area you're copying from and move the extracted methods to appropriate new homes.&amp;nbsp; Copying one or two function calls might not hurt you like copying blocks of code.&lt;/li&gt;&lt;/ul&gt;Everything I said about the evils of copying code still stand.&amp;nbsp; If you copy a block of code, you are probably going to screw over your whole development organization a little (especially when the system changes and your original is no longer correct).&amp;nbsp; Copy-Edit is still the way to make a bloated mess of your system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2197572309253719340?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2197572309253719340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/07/copy-and-edit-revisited.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2197572309253719340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2197572309253719340'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/07/copy-and-edit-revisited.html' title='Copy And Edit Revisited'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-6404271390039932024</id><published>2010-07-09T10:52:00.000-07:00</published><updated>2010-07-09T11:02:58.907-07:00</updated><title type='text'>Stop Playing Catch And Release In Quadrant 4.</title><content type='html'>Basically, a bug is a combination of a design flaw and a testing gap. &lt;br /&gt;&lt;br /&gt;When I say &lt;b&gt;design&lt;/b&gt;, I mean "design-as-written", not some keen plan that some keen mind build in some expensive drawing too. I mean the logic of the system. Built code can be said to have a design, in that it is intended to work in a particular way and has been adjusted to work in real circumstances.  A non-coding architect's idea for a system is not a design. It is merely a guess, or perhaps a dream.&lt;br /&gt;&lt;br /&gt;If code has a &lt;b&gt;perfect design&lt;/b&gt; for a given set of tradeoffs, then it will work perfectly for that given set of tradeoffs. If it must run on windows and use sql server, then it will work as well as possible under those conditions.  It may fail because of supporting systems, or because IE/ISS ate all the cpu and ram, or because it is interrupted, or starved out by virus checkers, etc. For where it lives, and what it does, it will work great... provided the code is written to use the design.&lt;br /&gt;&lt;br /&gt;Side note: I'm not saying that a design can be devised up front that will be perfect, or even that a design can be evolved to perfection (necessarily). I do not think that a perfect design is possible when working in a waterfall manner, and am firmly convinced that "perfect" is a concept that wiggles -- it changes meaning as a system and its environment evolve.  If there are ever moments of perfection in design, they are brought about through incremental change, and are eventually spoiled by changing requirements and systems. But bear with me, and assume that there are possible moments of perfection.  &lt;br /&gt;&lt;br /&gt;Perfect test coverage would be an automated suite of tests that exercise and evaluate every possible behavior of a software system.  That would be every logic branch of every component of the system under every set of circumstances.  It doesn't happen in practice, but that's not because it's impossible but because it is costly.  &lt;br /&gt;&lt;br /&gt;If perfect test coverage and perfect design are not possible, it is mainly because we don't know how to do them in a cost-effective manner. As a result, users are comfortable with a certain amount of slop provided it does not prevent them from getting work done and living meaningful lives. Some users are used to more slop than others, since some will reboot their machines a few times a day and others scream if they have to reboot once a year.  Some will retry a task in several different ways, others will throw up their hands. Bugs are tolerated if their frequency and consequence are slight.&lt;br /&gt;&lt;br /&gt;So lets draw this an an extreme set of opposites, in a quadrant. &amp;nbsp;Realize that most code is either mostly tested or mostly untested, and either good or not-so-good, but a discussion of extremes helps to clarfiy our thinking about software defects.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" frame="box" rules="all"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Tested&lt;/td&gt;&lt;td&gt;NotTested&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Perfect&lt;/td&gt;&lt;td align="center"&gt;1&lt;/td&gt;&lt;td align="center"&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Imperfect&lt;/td&gt;&lt;td align="center"&gt;3&lt;/td&gt;&lt;td align="center"&gt;4&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Quadrant 1 (tested, perfect) code is as good as it gets. Q1 code is blameless. Though the system around it may misbehave and cause ill effects, Q1 code does the best possible job in its environment. All code wants to be Q1 code, and all users want to think they're purchasing an all-Q1 system. All programmers would prefer to work in a Q1 system, because it is easier and more rewarding to do so. This is the holy grail, but is rare due to perfectly legitimate organizational priorities that prevent the creation of such perfect systems. Sometimes customers and markets don't *really* want perfect systems, if it means not having some other feature that is attractive. Tradeoffs are made.&lt;br /&gt;&lt;br /&gt;In Quadrant 2 (untested, perfect code) there are no currently-known defects and the system seems to operate perfectly. This is a mysterious place to be, because defects can arise at any time since the software system and its business and technical environments will change over time. When defects appear in quadrant 2 they will be discovered in the wild, not in the lab. Q2 is comprised of code that is at risk. The best we can say of supposed Q2 code is that it has not yet proven to be Q4 code. &lt;br /&gt;&lt;br /&gt;Quadrant 3 is comprised of discovered defects. Some of these will be fixed before release, and those whose effect and frequency are slight may be deferred to future releases.  Tests on known bugs-of-little-effect will tend to be ignored or disabled (effectively moving the defect to Q4) until the flaw becomes interesting enough to resolve.&lt;br /&gt;&lt;br /&gt;Quadrant 4 primarily is the result of irresponsible development or intentionally ignored known defects (see Q3). The design flaws are not well-understood or demonstrated in automated tests. Running code that is imperfect and untested is rather a crapshoot. Users are essentially alpha testers, and should not expect consistently good experiences. Trying to fix defects in Q4 code is a nightmare and fraught with disappointment. The best way to fix Q4 code is to move it first to Q3, then try to move it to Q1. The worst way to fix it is to try to push it up into Q2.&lt;br /&gt;&lt;br /&gt;Almost all software systems in existence have some Quadrant 4 code and some Quadrant 3 code.  TDD systems are mostly Q1 and Q3, but legacy systems all have some Q4 code and might have some Q2 code (not that we could tell).&lt;br /&gt;&lt;br /&gt;Software that doesn't work is in Q4. &amp;nbsp;If you have hundreds of bug reports, then you have hundreds of lines of code in Q4, where it's not very good code and you don't have good testing. Your bugs tell you that your code base needs some unit testing goodness applied. &amp;nbsp;If you simply fix the bugs without putting testing around the site of the defect, you are playing catch-and-release in Q4 and nothing is really going to get better for your product or your organization.&lt;br /&gt;&lt;br /&gt;The goal for software developers should be to move code from Q2 and Q4 through Q3 to Q1.  I can see hardly any reason why developers in 2010 would even consider working in Q2/Q4, and I particularly cannot see why organizations would believe that group of people with mixed experience and skill sets would consistently perform in Q2.&lt;br /&gt;&lt;br /&gt;Q2 is essentially a myth. Your Q2 software is probably Q4 in reality.  Maybe you should start investing in the move to Q3. &amp;nbsp;Stop playing catch-and-release&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-6404271390039932024?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/6404271390039932024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/07/your-quadrant-2-software-is-myth-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6404271390039932024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/6404271390039932024'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/07/your-quadrant-2-software-is-myth-and.html' title='Stop Playing Catch And Release In Quadrant 4.'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-3734780875092981697</id><published>2010-06-24T18:16:00.000-07:00</published><updated>2010-06-24T18:16:01.302-07:00</updated><title type='text'>Two Year In, Looking for the Goodies</title><content type='html'>This week I wrote a useful utility and taught some Python to a peer, attended a really great work session and a rough estimating session. I did some WIP management activities with my team, I broke the application, I worked with some awesome partners, went on a bit of a refactoring binge, devised (with partner) a grand strategy, and got stuck on tiny little problems I couldn't see over. This has been an awesome week. &lt;br /&gt;&lt;br /&gt;We have been doing some big refactorings, moving big and critical chunks from one module to another, and dealing with the fallout. I don't know how to tell you how important the tests in our code base have been. I would have spent all day lost without them.  We would move a component, build, resolve build troubles, rinse and repeat. Finally, at end of day, I got all unit tests and fitnesse tests turning green, EXCEPT for a few that won't test because they do horrible things and need remediation. When our tests failed, it was not because the tests were bad (exception, one was pretty iffy) but because something was wrong. The compiler and tests made our work less scary and troubling.  It was still scary and troubling, but would have been overwhelming otherwise.&lt;br /&gt;&lt;br /&gt;I and some of my colleagues transitioned this team to Agile only 2 years ago. It is amazing how deeply some of the team members grok Agile now, and a little frustrating how some people and some circumstances have not really come up to the same level. Frustration is not failure, though. There is light bursting through here and there.&lt;br /&gt;&lt;br /&gt;I've also been checking in as a coach, testing the prevailing winds, looking for the problems that keep us down, looking for the ways to improve our work system, looking for moods issues. We're in a pretty good place, actually, by numeric measures. Some parts of the code base are very well-tested and quite simple, and others are becoming so. There is still some amount of legacy code produced every day, though, and that is a bit disheartening to those who really want to see only improvement (I'll cop to being one of them).&lt;br /&gt; &lt;br /&gt;Our biggest challenge is that there is some big work coming to some ticklish areas of the code, and we'll be under pressure to deliver. This is our first real chance to test our Agile mettle against a really formidable foe. &lt;br /&gt;&lt;br /&gt;Jeff and I just released the "Why Agile" card at &lt;a href="http://agileinaflash.com/2010/06/why-agile.html"&gt;AgileInAFlash&lt;/a&gt;. Two years into the transition, I want to make some comparisons on how we rate today v the original situation.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Improve Customer Involvement&lt;/b&gt; has improved the least. We have a great guy playing the role of Customer, but largely the representatives for the customer don't join the team.  Some of them have found more engaging ways to provide specs (screenshots, videos, etc), and have made themselves more available for discussion. It is still not what it could be. With one notable exception, our Customer players are all surrogates. All but one of the surrogates live on the other side of the building, across a hallway from the developers, and are not really involved in daily work. This is actually a problem that affects morale and development performance. Finding a way to bring us all together would bring profound changes to the product, I have no doubt.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Increase Quality&lt;/b&gt; has come a long, long way. Like any SAAS player we always want better performance, and like any SMB growing larger we have a few issues from time to time, but overall quality is way up and the testing practices are better all the time. When I ask product management or sales or support, they tell me that it is a whole different world from the product of 2008. We haven't reached the "everybody loves us" stage yet, but we have come a long way.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Simplify Releases&lt;/b&gt; is happening. They used to have nightmares about release nights, and now they're more like annoyances.  We still have code freeze and pre-release ceremonies, but we're not 100% covered in tests yet, and we put a lot of features in each month. We will continue to need some regression testing and some exploratory testing for a while yet. Issues that made code hard to deploy keep getting eliminated. It's a new world compared to our starting position.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Increase Operational Awareness&lt;/b&gt; this one hasn't come so far. We don't have the information radiators I would like to see, but the card wall is being used, and people tend to have a pretty good sense of what is in progress, finished, or unstarted. The big priorities are posted on pillars and doors so we can see them. Stand-up meetings help us keep track of each other. It could be better, but it is a good start. Actually, the operations staff have herereally smoked us in this regard. We know more about servers and their problems than ever before. We have moving graphs and charts updating constantly on large-screen displays in the office. There are alerts in email, and people stopping by the developer pairing stations. They're doing a tremendous job.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Drive Down Risk&lt;/b&gt; could be better. We tend to fall back to producing whole big features, rather than staying incremental as we should. I know, breaking down stories into valuable verticals is tough business, but all-or-nothing leaves a strong chance of "nothing." Our demos do collect feedback, and often are valuable working sessions (ours was this week). Testing and pairing also help reduce developer myopia and its resulting code diseases. But still, we're not incremental as we should be, and that leaves us at risk more often than I'd like.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Reconnect With Geek Joy&lt;/b&gt; is there, but we still wrestle with this. Sometimes we don't feel better, even though we are better. A times wrestling with legacy code (even new legacy code) frustrates us. Sometimes we don't have the level of success we might like. Yet I am so encouraged when we can do big things under sufficient tests, and when we find people making far-ranging improvements, when we have consensus on big design changes, and when we demonstrate working code. There is energy around performance and quality. We enjoy solving problems, and we enjoy cleaning code, and we take pride in not leaving silly duplication behind. I enjoy this job, and am happy to be doing it. We are making a difference to each other and serving customers as better than we could before. This job improves me, and that's joyful.&lt;br /&gt;&lt;br /&gt;I know, my readers may want to hear how I totally transformed the company and how all of our problems vanished in 6 weeks or less, but that's not always how it goes. Real change takes time, and not everyone "gets it" all at the same time. New hires, old cliques, old barriers, old policies, old politics, new features, new customers, and new technology keep things challenging. Pressure to release pushes people back into old bad habits. There is a swirling cloud of chaos, but it keeps moving in a desirable direction overall.  &lt;br /&gt;&lt;br /&gt;Maybe we're still struggling a bit, but that's what growth is like. Watch this space. Maybe next year I'll show you how much further we've come.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-3734780875092981697?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/3734780875092981697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/06/two-year-in-looking-for-goodies.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3734780875092981697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3734780875092981697'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/06/two-year-in-looking-for-goodies.html' title='Two Year In, Looking for the Goodies'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4524660446333851149</id><published>2010-06-22T19:29:00.000-07:00</published><updated>2010-06-22T19:29:54.080-07:00</updated><title type='text'>Do You Want Us To Think Or Not?</title><content type='html'>To make software, you need people who are skilled, creative, quick-learning, thoughtful, and engaged. You might be able to skimp on 'skilled' if the rest of your team provides a social learning system (via pair programming, test-driven development, book and link sharing, impromptu teaching, design talks, etc). You cannot really skimp on the characteristics of being creative, thoughtful, and engaged.&lt;br /&gt;&lt;br /&gt;If you tell someone that you don't care how they feel, they will work in an unfeeling way.  If you tell them that you don't care what they think, they will work unthinkingly. If you tell them not to participate, they will disengage. This (IMHO) is why use of corporate software is so often without soul and without joy.  If one self-important side tells the other to shut up, or to stop asking questions, or to leave the decision-making process, then he has switched off an important piece of capital equipment.  &lt;br /&gt;&lt;br /&gt;If you treat a knowledge worker as a drudge, she will turn off her brain and trudge. Unsurprisingly, she will lose energy, become uncaring toward the product, and start phoning in her minimal-thought hacks while polishing off her resume.  It is hard to keep good people in a system that doesn't really value them.&lt;br /&gt;&lt;br /&gt;In an Agile company, we expect customers (or a reliable surrogate) to team up with developers. We expect to have a two-way flow of communication. Each side asks questions, provides answers, researches, considers. Each side teaches and learns. In time the whole team (customers+developers) will take on creative problem-solving, will improve the user experience, will make the product data-center-friendly and user-friendly, and will produce truly valuable work. &lt;br /&gt;&lt;br /&gt;All of the software development roles are creative. All of them have issues and difficulties that the other roles may not understand initially. But if we're going to do good work, we have to learn to listen to each other.  All it takes to destroy the magic is for one to devalue the contributions of the other.&lt;br /&gt;&lt;br /&gt;A few resources:&lt;br /&gt;From Agile Software Development, an article on &lt;a href="http://agilesoftwaredevelopment.com/xp/values/respect"&gt;respect&lt;/a&gt;.&lt;br /&gt;Esther Derby's &lt;a href="http://www.cio.com/article/123406/Stop_Demotivating_Me_"&gt;Stop Demotivating Me&lt;/a&gt; from CIO magazine.&lt;br /&gt;Daniel Pink's talk &lt;a href="http://agileotter.blogspot.com/2010/06/your-reward-system-doesnt-work.html"&gt; via my blog&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4524660446333851149?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4524660446333851149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/06/do-you-want-us-to-think-or-not.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4524660446333851149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4524660446333851149'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/06/do-you-want-us-to-think-or-not.html' title='Do You Want Us To Think Or Not?'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7764843974981756167</id><published>2010-06-18T13:09:00.000-07:00</published><updated>2010-06-18T13:09:59.096-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='meddling'/><category scheme='http://www.blogger.com/atom/ns#' term='agile manager'/><category scheme='http://www.blogger.com/atom/ns#' term='oversight'/><category scheme='http://www.blogger.com/atom/ns#' term='failure'/><category scheme='http://www.blogger.com/atom/ns#' term='agile coach'/><title type='text'>Meddling, Oversight, and Agile, Oh My!</title><content type='html'>A friend of mine (Hi George D) suggested that this would make a good poster,&lt;br /&gt;but all I have is a couple of blogs, so here is the message that inspired&lt;br /&gt;my buddy.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;My experience is that the less well a team has done in the past,&lt;br /&gt;the more oversight is piled on, and that oversight reaches higher&lt;br /&gt;and higher levels.  There really is no legitimate reason for the&lt;br /&gt;CEO to want to know which programmer 5 or more levels below was&lt;br /&gt;assigned to a particular task and if he's behind schedule by a&lt;br /&gt;week or so.&lt;br /&gt;&lt;br /&gt;In healthier organizations, the groups and managers that interface&lt;br /&gt;with the development group tend not to have the same meddlesome urges.&lt;br /&gt;&lt;br /&gt;In our transitions, the biggest problem we face tends to be peeling&lt;br /&gt;back the expensive and unnecessary oversight.  If the team can be&lt;br /&gt;rebooted and work with a single stream of smaller, simpler stories&lt;br /&gt;(rest of agile practices included) then they can win over the&lt;br /&gt;rest of the org in relatively short order.  Sometimes in only a&lt;br /&gt;year or two, sometimes in less than 6 months.&lt;br /&gt;&lt;br /&gt;It's hard to overcome meddlesome urges, especially when they are in&lt;br /&gt;reaction to difficult past history (and moreso if there is competition&lt;br /&gt;among the meddlers to get their work done).&lt;br /&gt;&lt;br /&gt;Tools play into that. People want tools partly so that they can&lt;br /&gt;pile on too much work (more than fits in a head or on a board)&lt;br /&gt;and partly so that they can meddle from the comfort of a remote&lt;br /&gt;office.&lt;br /&gt;&lt;br /&gt;Agile is, among other things, a very intense and orderly way to&lt;br /&gt;get work done. It's just hard to get the focus of a conflicted&lt;br /&gt;organization on getting work done in an intense and orderly way.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7764843974981756167?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7764843974981756167/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/06/meddling-oversight-and-agile-oh-my.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7764843974981756167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7764843974981756167'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/06/meddling-oversight-and-agile-oh-my.html' title='Meddling, Oversight, and Agile, Oh My!'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-3765077162359827922</id><published>2010-06-18T08:10:00.000-07:00</published><updated>2010-06-18T08:10:04.912-07:00</updated><title type='text'>Only Quality Matters</title><content type='html'>If your code doesn't really work, then it doesn't matter how quickly you wrote it.&lt;br /&gt;&lt;br /&gt;Abandoning quality in pursuit of speed is a fool's errand. It has been discussed plenty of times in about any management book you want to look at, and especially by the brilliant minds like Deming.&lt;br /&gt;&lt;br /&gt;If you write your code badly, you can release it without awareness of bugs, and that takes it off of your plate. You may be rewarded or recognized for your quick work. It feels good today. Your team is recognized for being heroes within the company because you are smart, and get things done. &lt;br /&gt;&lt;br /&gt;But tomorrow a customer tries to use it and it fails.  The customer is no longer happy that the feature was delivered, because it's junk.  In fact, as far as the customer is concerned the whole product is now junk, your company is junk, and the developers are pure rubbish.  Loss of good will. Think how you feel when you get the Fail Whale, and you are a friendly customer and unusually forgiving. How do you feel when your cable provider or cell phone service has a hiccup, or when your windows mobile phone has to be rebooted. Normal people are much less forgiving.&lt;br /&gt;&lt;br /&gt;Now that failure is reported (if you're lucky) and someone in product support hears about it.  They feel less proud of their affiliation. They push to get a change made, but the programmers 1) are busy on something else, and 2) take a long time to find the bug.  The product support queue grows. People are employed now to track mistakes and to try to run interference with unhappy customers.&lt;br /&gt;&lt;br /&gt;The failure isn't just reported to the vendor, but to all the customer's bosses, who begin to question their vendor relationships. A few bugs now and then, they might be able to tolerate. but constant performance and behavioral bugs will have them holding the contract in one hand and a lighter in the other.&lt;br /&gt;&lt;br /&gt;People are employed to fix the bugs, and to test the code to be sure the bug is gone.  A few tests written TDD-style would have saved a lot of work, money, and hard feelings.  But you were in a hurry.&lt;br /&gt;&lt;br /&gt;If the code doesn't really work, then it does not matter how quickly you wrote it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-3765077162359827922?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/3765077162359827922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/06/only-quality-matters.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3765077162359827922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3765077162359827922'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/06/only-quality-matters.html' title='Only Quality Matters'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4581239958233632541</id><published>2010-06-15T14:46:00.001-07:00</published><updated>2010-06-15T14:46:35.931-07:00</updated><title type='text'>Software Like Building A House</title><content type='html'>After arguing for decades that it is not so, I find out that I'm wrong. This is from a &lt;a href="http://www.constructionbusinessowner.com/topics/general-management/lean-construction-maximize-value-and-eliminate-waste.html"&gt;2007 article&lt;/a&gt; on construction.&lt;br /&gt;&lt;blockquote&gt;1. If it takes six months to build a house, then 85 percent of the time is spent on two activities: waiting on the next trade to show up and fixing mistakes.&lt;br /&gt;&lt;br /&gt;2. Clemson's Professor Roger Liska conducted an analysis of productivity on the construction industry and found that the average construction worker operates at only 40 percent efficiency.&lt;br /&gt;&lt;br /&gt;3. Critical shortages exist in qualified, skilled workers and labor issue futurist Roger Herman predicts the situation is only going to get worse.&lt;br /&gt;&lt;br /&gt;4. Business Week's 2007 Investment Outlook Report indicates the return on equity (ROE) for all U.S. industries is 17.9 percent, while the ROE for the construction industry is a mere 9.7 percent, despite the recent construction boom.&lt;br /&gt;&lt;br /&gt;5. Industry customers are frustrated with poor quality, confrontation, excessive change orders in quantity and dollar value, scheduling delays and litigation. &lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4581239958233632541?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4581239958233632541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/06/software-like-building-house.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4581239958233632541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4581239958233632541'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/06/software-like-building-house.html' title='Software Like Building A House'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-1703338939742649686</id><published>2010-06-10T14:42:00.000-07:00</published><updated>2010-06-10T14:58:10.642-07:00</updated><title type='text'>Your Reward System Doesn't Work</title><content type='html'>Presented in the most pleasant way possible, by Daniel Pink &amp;amp; friends:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/u6XAPnuFjJc&amp;rel=0&amp;color1=0xb1b1b1&amp;color2=0xd0d0d0&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/u6XAPnuFjJc&amp;rel=0&amp;color1=0xb1b1b1&amp;color2=0xd0d0d0&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;The whole "purpose maximizers" thing gives me hope in ways that "enlightened self interest" never, ever has.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-1703338939742649686?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/1703338939742649686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/06/your-reward-system-doesnt-work.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1703338939742649686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/1703338939742649686'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/06/your-reward-system-doesnt-work.html' title='Your Reward System Doesn&apos;t Work'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8253525220552598759</id><published>2010-05-11T09:57:00.000-07:00</published><updated>2010-05-12T05:57:24.566-07:00</updated><title type='text'>Mocking Done Badly</title><content type='html'>&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;using(Playback) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; sut.PerformAction(parameter);&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;This is the last part of a common style of mock test. We see the system-under-test (sut) being asked to perform some action, and some parameter is passed to it.&amp;nbsp; We know it's a mock test because of the Playback bit.&amp;nbsp; &lt;br /&gt;What is being tested here? Well something about PerformAction is being tested. Not much there. No clear assert written at the bottom of the test to capture our attention.&lt;br /&gt;Let me narrate as I work through the actual code before me, and maybe the readers can respond to tell me whether this really is mocking done badly, or I'm "just not used to good mocking."&lt;br /&gt;&lt;br /&gt;I struggle not to look at the test name, so the code can speak to me more directly.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The parameter is not interesting, it is just a string.&amp;nbsp;&lt;/li&gt;&lt;li&gt;There is another variable, which is a stub, but it's not used inside playback.&lt;/li&gt;&lt;li&gt;There is a 'record' section, set aside with 'using' and not (thankfully) a #region.&lt;/li&gt;&lt;li&gt;In the record section, we call one function with the parameter string, returning the stub. So there is some kind of look-up method called exactly once. The string is the key, the stub is the result. Looks like database avoidance.&lt;/li&gt;&lt;li&gt;Another function is called, taking the stub returned by the first. It is called exactly once, and returns the number '2'.&lt;/li&gt;&lt;/ul&gt;At this point I've read the whole test. Hmmm... what are we doing here again?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Check the test name: ProcessExactlyOneFooWhenGivenParameterBar.&amp;nbsp; Oh. So maybe the "Repeat.Once()" part of the mock is meaningful. But what's really going on?&amp;nbsp;&lt;/li&gt;&lt;li&gt;I read the neighboring test (there is only one). It calls the same method with the parameter "all", and expects to see a call to a different method underneath, one that collects a list of things to process.&amp;nbsp; Okay, "all" is a magic name that means 'do them all' and it collects the list. That helps a tiny bit. The name of that test reflects that my understanding is right, but I can't really follow the original test much better with that knowledge in hand. &lt;/li&gt;&lt;li&gt;The second-to-last desperate measure is called upon*: I read the code.&amp;nbsp; This is backward. I should never read the &lt;i&gt;production code &lt;/i&gt;to explain the &lt;i&gt;test&lt;/i&gt;. I should read the &lt;i&gt;tests &lt;/i&gt;to explain the &lt;i&gt;production code&lt;/i&gt;. My assumptions hold so far. &lt;/li&gt;&lt;li&gt;The method for actually doing the processing is the one that is expected to be called once, and is to use the stub returned by a look-up method. The return code seems arbitrary. I extract it and call it "arbitraryRecordCount"&lt;/li&gt;&lt;li&gt;Some method renaming is done to make tests more meaningful. I double-check the production code to make sure it reads better too. As is usually the case, the code reads better.&lt;/li&gt;&lt;li&gt;Realize that the logging was redundant and ill-placed, and moved it to a unique and more appropriate spot. This simplifies production code even more, and all tests still pass.&lt;/li&gt;&lt;li&gt;I bring a bit more detail up into to the test in hopes that it will make it more clear. It does, but now I have more setup. There is an urge to break the mock setup into paragraphs, a sure sign I'm gathering cruft.&lt;/li&gt;&lt;li&gt;I realize there is a test missing, one that would have made more sense of some of one existing test. I add it. It duplicates the first test a bit. I extract a little, but worry about making it abstract enough that you can't really follow it.&lt;/li&gt;&lt;li&gt;I set up the original test to be a bit more explanatory.&lt;/li&gt;&lt;li&gt;It is at this point that I realize that the setup for this test fully simulates the sensing and acting of one pass through the SUT's method, if all IF statements are ignored/assumed. It is right, and having read the code I understand why it is right. I see the values threaded from one return to the next call, etc. I fear I've just proven that "IF" works in this language. &lt;/li&gt;&lt;li&gt;Now I see that processing involves doing one look-up, calling a method that does a&amp;nbsp; more detailed look-up, and then using the latter look-up result to perform an update.&amp;nbsp; I can see that this is what the code does by looking at the tests. It's rather non-abstract, and not remotely in business language.&lt;/li&gt;&lt;/ul&gt;I do have to wonder if they have any real value other than cementing the code's current implementation into the test suite.&amp;nbsp; If we extract a method or inline a method, I know that these tests will fail. The new method will not be "incorrect", only "different."&amp;nbsp; It bothers me that the tests will fail if I &lt;i&gt;improve&lt;/i&gt; the structure of the SUT.&lt;br /&gt;This is doing test-last, which is a poor way to do testing.&amp;nbsp; That means  it's most likely a poor way to do mocking. The tests are fast and  decoupled from database, etc.&amp;nbsp;&amp;nbsp; &lt;br /&gt;It takes much longer to write about this than to do it, yet I took the time so that there is some basis for discussion. Is my code conscience overly-sensitive, or does this have several kinds of wrong in it?&lt;br /&gt;Is this mocking done well, or done poorly? You tell me.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;* the last desperate measure is to trace execution with the debugger.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8253525220552598759?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8253525220552598759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/05/mocking-done-badly.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8253525220552598759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8253525220552598759'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/05/mocking-done-badly.html' title='Mocking Done Badly'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8580142181549386672</id><published>2010-05-02T15:06:00.000-07:00</published><updated>2010-05-02T15:06:58.007-07:00</updated><title type='text'>Making Stuff is Making Stuff</title><content type='html'>On the television as I type this is a show called "Amazing Wedding Cakes", which is unsurprisingly about cake making. In the current episode a bride has ordered 190 individual single-serving cakes. The team is struggling with a trade-off between doing the work on time and doing the work really well.&lt;br /&gt;&lt;br /&gt;We all do that. Software is so very much the same. We simply don't have time to obsess on every detail, but we also can't skimp on essential details. We need to make both radial and linear improvement, but we can't abandon our charter to deliver quality.&lt;br /&gt;&lt;br /&gt;This has been a running meme this week, whether one can afford quality and whether skimping quality will help a team go faster. &amp;nbsp;I've gone on record enough times saying that I don' think you go faster writing poor code, and I echo Uncle Bob Martin in saying that our most significant impediment is the bad code we have to work in.&lt;br /&gt;&lt;br /&gt;In the end, the boss was pretty angry about the care that was taken with each of the cakes but the work was done on time with pretty high quality. The customers were delighted.&lt;br /&gt;&lt;br /&gt;Of course, while that is a common story, the difference between cakes and software is that cake makers don't have to build all their other cakes by modifying the cake they've just made. &amp;nbsp;If there is an internal defect in one of the mini-cakes, it won't cause the others to fail and it will not cause failures in all of the cakes they make in the future. Wedding cakes are a one-time thing. Software lasts and accrues changes.&lt;br /&gt;&lt;br /&gt;That is not to talk down the cake industry. My wife makes cakes, and I know how much work goes into the structure, flavor, and aesthetics. It's a really cool and really competitive artistic industry.&lt;br /&gt;&lt;br /&gt;The point is just that some things are short-term and highly visible, while others are more long-term and mostly invisible. If we treated cakes like a multi-year investment it would be silly, and it is similarly stupid to treat software as a bunch of one-off, short-term projects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8580142181549386672?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8580142181549386672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/05/making-stuff-is-making-stuff.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8580142181549386672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8580142181549386672'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/05/making-stuff-is-making-stuff.html' title='Making Stuff is Making Stuff'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-2215712756535687328</id><published>2010-04-28T21:51:00.000-07:00</published><updated>2010-04-29T06:05:33.122-07:00</updated><title type='text'>Linear and Radial Progress means Taking The Next Step</title><content type='html'>Today we didn't make a lot of linear progress &lt;br /&gt;&lt;br /&gt;I think of quality in two ways.&amp;nbsp; One is the product quality which users perceive, and the other is the habitability of the code itself. One says whether the function points and UX are well-selected, and the other says whether it is worth your time to try to work in the code.&amp;nbsp; One can have crap code that seems great externally, and one can have beautiful code that doesn't do anything a user is interested in doing (the popularly-presented dichotomy). Likewise one could have poor functionality written poorly, or great functionality written well.&amp;nbsp; Those who consider themselves professionals or craftsmen will desire great functionally written well.&lt;br /&gt;&lt;br /&gt;I often get to work in code that started out as good functionality badly written. I get to work on the teams that clean up the mess and make the system more useful, scalable, and performant. As we work, the code gathers external quality. It becomes increasingly &lt;a href="http://agileinaflash.blogspot.com/2010/02/seven-code-virtues.html"&gt;virtuous&lt;/a&gt;.&amp;nbsp; Smaller, simpler, cleaner code starts to run faster. With less duplication, bugs are fixed once-for-all rather than as buggy duplicates are discovered. This month is better than last month, but next month should be better still. &lt;br /&gt;&lt;br /&gt;Because there are two kinds of quality, and one can make progress on either front, we see two kinds of progress. There is linear progress toward completion of a specific feature, and then there is radial progress which improves the code base overall and makes work easier for many colleagues.&lt;br /&gt;&lt;br /&gt;Developers who make linear progress without radial progress ultimately drive code into an increasingly unliveable state. Eventually bugs are hard to resolve, changes are hard to make, testing is costly, refactoring is painful, and the design is more a collection of warts and hacks than a system any sane beings would have intentionally conceived.&lt;br /&gt;&amp;nbsp; &lt;br /&gt;Radial progress does not contribute much to one's ability to close a particular development request. Instead it improves the&amp;nbsp; ability of the team to complete features next month and the months after that. It tends to affect many source files, so it is uneconomical in projects that don't have a significant investment in automated testing. &lt;br /&gt;&lt;br /&gt;We made a lot of radial progress today. &lt;br /&gt;&lt;br /&gt;We started with a change we wanted to make, but instead of slapdash hacking we took &lt;i&gt;The Next Step&lt;/i&gt; and looked at the tests that covered the area of change. We found the unit tests were poorly written. These tests had poor fault isolation and failed for the wrong reasons. This prompted us to take &lt;i&gt;The Next Step&lt;/i&gt; and make them less fragile so that they would stay 'green'.&lt;br /&gt;&lt;br /&gt;From reverse-engineering the unit tests, we saw that the code under test was nigh indecipherable. It was riddled with poor naming, inconsistency, huge argument lists, lying comments, and slapdash implementation.&amp;nbsp; Support routines did little to clarify the code, and in come cases further obscured its intent. Tests were fragile and indirect.&lt;br /&gt;&lt;br /&gt;We decided to take &lt;i&gt;The Next Step&lt;/i&gt; by refactoring some tests for readability. We replaced some loops with LINQ, after which it was obvious that the code had unnecessary looping. Each readability improvement showed some error in linear thinking that almost certainly slowed initial development of this part of the code base.&lt;br /&gt;&lt;br /&gt;Writing bad tests is hard work. It would have been easier to write them better, or to refactor them as they went, but they were almost certainly more focused on making linear progress than on making the code clean. I can't really blame them. People under pressure cut corners and sometimes "it works" is all they think they can afford. People do the things that make them successful, and sometimes they are rewarded or punished for the wrong things. As is, it suffices to say that they did hard work the hard way, and so we found it in a poor state of development. &lt;br /&gt;&lt;br /&gt;The more we introduced explanatory variables, simplified expressions, and eliminated duplication, the more we could see the next set of flaws to address.&amp;nbsp; We took &lt;i&gt;The Next Step&lt;/i&gt; and started reworking the test harness. Soon we find that there are variables being created and passed from routine-to-routine only to be ignored completely at the lower levels.&amp;nbsp; We cleaned up the Object Mother utility, obviating hundreds (if not thousands) of unnecessary lines of code, and I suppose we should take &lt;i&gt;The Next Step&lt;/i&gt; and remove the unnecessary code from the ObjectMother users.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This sounds like weeks of work, but was only hours. We closed one ticket, opened another, attended a long planning meeting and a lunch-and-learn. We took breaks for all the usual reasons. We broke up our pairing session at 5:00 CDT.&amp;nbsp; We understand the code much better, and the tests explain the code better. &lt;br /&gt;&lt;br /&gt;Sure, the code cleaning could turn into a few man-days of effort, but it is effort that will benefit everyone who wanders into this area of the code in the future.&amp;nbsp; This area of the code base is being actively developed and has outstanding bugs, so we will likely recoup all our investment in the course of completing very few change requests.&amp;nbsp; We are aware that we can't afford to spend time gold-plating this module, but we can make it habitable before we move on.&lt;br /&gt;&lt;br /&gt;On the XP mailing list someone asked what distinguishes a truly great agile development team. Let me offer that the difference is that a great team will take &lt;i&gt;The Next Step&lt;/i&gt; to make the code habitable on the inside in addition to making is useful externally.&amp;nbsp; Because of this tendency, each month gets better, each quarter more productive. Each year, the system requires less patience of all those associated with it, and provides more rewards. &lt;br /&gt;&lt;br /&gt;That, my friends, is &lt;i&gt;great.&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-2215712756535687328?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/2215712756535687328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/04/linear-and-radial-progress-means-taking.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2215712756535687328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/2215712756535687328'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/04/linear-and-radial-progress-means-taking.html' title='Linear and Radial Progress means Taking The Next Step'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-546161302057457289</id><published>2010-04-28T11:03:00.000-07:00</published><updated>2010-04-28T11:03:22.773-07:00</updated><title type='text'>Accept changes, not interruptions.</title><content type='html'>We say "embrace change" and "accept changes to requirements, even late in the process."&amp;nbsp; We also rant about focus and that developers should neither be interrupted nor allowed to multitask.&amp;nbsp; To a lot of people, this sounds just like a contradiction.&amp;nbsp; Are we hypocrites?&lt;br /&gt;&lt;br /&gt;There is no conflict in these statements. The problem is with the organization.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Change In A Change-Resistant Culture&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If, for example, I plan a release in 10 months, and assign each of my developers a ten-month task (or a couple of five-month tasks) then I am not only at capacity, I'm likely well over and don't know it.&amp;nbsp; Now, in month two I have a change I would like to see. I can't get any of my developers to put aside their work and take my task.&amp;nbsp; Those stupid developers!! What's wrong with them?&amp;nbsp; Nothing is wrong with them.&amp;nbsp; They are doing the work they are assigned, and since they have no slack or reserve capacity they know that the new task puts their release in jeopardy.&amp;nbsp; They also know that they are being reviewed, graded, rated, and ordered by their ability to get those assigned changes into the next release.&amp;nbsp; If they drop a task to do the new work, they will fail. If they don't, then they'll be deemed uncooperative which also will possibly cause career damage.&amp;nbsp; They can work overtime to do all the work that they were assigned (which is probably an ambitious goal anyway) and try to absorb the new change by stealing time from their significant others, sleep periods, side projects, and other obligations but this will make them less likely to recognize shoddy work and less eager to correct it. Assigning work this way creates a reserve-free system in which any response to any change is costly both professionally and personally.&amp;nbsp; No wonder developers become demotivated.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Embracing Change In Healthy Organizati&lt;/b&gt;on&lt;br /&gt;&lt;br /&gt;Instead, what if we have a release in 10 months (or so).&amp;nbsp; We break all the features into pieces, where each piece is valuable to the end user, but each one can be completed in a week or two.&amp;nbsp; Maybe there's an admin screen, a data entry screen, and a small bit of processing for the first feature.&amp;nbsp; Rather than assign these to an individual (tying up his next few months), we assign it to the team as a whole.&amp;nbsp; Now each of the people working on this feature will come "free" (ie. have completed a task) in a week or two. They will be able to switch pair programming partners, take on new features, make revisions, etc.&lt;br /&gt;&lt;br /&gt;Now I can introduce changes between tasks, or instead of planned tasks. These task boundaries are frequent, so change is much more welcome. In addition, a developer is only committing to one change or feature at a time, and so only an uncompleted feature is at risk instead of the programmer's career.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;In addition, the code for a completed feature is available much sooner, so that it can be tested, demonstrated, and evaluated.&amp;nbsp; A few months in, it can even enter an alpha-testing program to get end-user feedback and determine the effect of the change on performance and scalability.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Smaller Assignments Are The Secret&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you can't accept change, it is because the work assignments are too large.&amp;nbsp; If you are going to want changes often, then you need to have "change  injection opportunities" more often. If changes are daily, then every  day there should be some programmer(s) coming available to make the  changes.&amp;nbsp; Furthermore, they must be at work in a system that does not punish them (career-wise or by depriving them of the things they hold dear personally) for accepting orders for change.&lt;br /&gt;&lt;br /&gt;You don't have to have an Agile organization or an Agile team to  harness the power of smaller work assignments. There have been many  methodologies, including some from very large contracting companies, who  have long touted "a series of small successes" as the way to best  ensure success of a project. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Early feedback is also known pre-Agile to be important to a good  user experience and to dissolving contract discomfort.&lt;br /&gt;&lt;br /&gt;The trouble is that working this way erodes the strong central authority many managers have enjoyed, and which may have brought them respect as "strong leaders" in the eyes of their managers.&amp;nbsp; That is a topic for a whole different conversation.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If your development organization can't accept change without interruption and multitasking, then:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="text-align: left;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Your work assignments are too large, too personal, and too well enforced.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-546161302057457289?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/546161302057457289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/04/accept-changes-not-interruptions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/546161302057457289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/546161302057457289'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/04/accept-changes-not-interruptions.html' title='Accept changes, not interruptions.'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-262528967051724295</id><published>2010-04-16T05:53:00.000-07:00</published><updated>2010-04-16T06:08:21.852-07:00</updated><title type='text'>Be Careful What You Fix</title><content type='html'>I wake up with odd memories. I think my brain is just getting exercise, staving off senility maybe. &lt;br /&gt;&lt;br /&gt;Yesterday I woke with a memory of a bug fix from long ago, probably 15 years or more.  I was given a project which led me into the permissions-checking code of a billing system.  When I got there, I saw the code was written in such a way as:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   permission* perm = GetPermission(thisPerm);&lt;br /&gt;   if ( perm != null &amp;amp;&amp;amp; perm.Allow == false) {&lt;br /&gt;       return false;&lt;br /&gt;   }&lt;br /&gt;   return true;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I know that's silly, but I am recreating from an old memory, and I remember the code having some silly uses of null &amp;amp; the like.&lt;br /&gt;&lt;br /&gt;I remember noticing right away that if a permission did not exist, it meant that the user can perform the activity.  GetPermission() read from a database table, I think, so that all a user had to do to get unlimited access was to drop records from a table.  Furthermore, if an installation tech didn't deny access to unpaid features, the customer got them for free.&lt;br /&gt;&lt;br /&gt;I don't want to reflect on the validity of the business model here,  whether restricting features and paying for use of them is a good idea  or whatever.  It was a simple code error and a simple code fix to me and I only needed to know if the behavior was intended or accidental.&lt;br /&gt;&lt;br /&gt;I quickly consulted some people who told me that it was not the right behavior. They said that some users had paid extra for features and would be angry if other customers were getting them for free. A little research, and we find that most customers had most features for free.   As requested I fixed the feature so that having no permission meant having no feature. They figured that they were safe since they didn't ship documentation for features that weren't covered in the contract (security by obscurity).  I had approval for the fix, and completed the ticket quickly, and you'd think that was the end of the story.&lt;br /&gt;&lt;br /&gt;To the sales and marketing, however, it was a fiasco. After the next release there were angry people asking why they couldn't do their normal reporting and administrative tasks, why they couldn't do various normal feats that they could do only the week before with no issue.  We had taken back from our users the features that we'd granted.&lt;br /&gt;&lt;br /&gt;People did not rely on the manuals to tell them what the software did. That would be silly. Interfaces are rightly made explorable to people can learn it for themselves. Omitting docs did not lock down features. &lt;br /&gt;&lt;br /&gt;Not testing the permission systems wasn't all that smart either, because nobody realized that it was "in promiscuous mode" until one of us programmers stumbled onto it. &lt;br /&gt;&lt;br /&gt;Maybe the most damning error, though, was taking back what we had given. Whether they were entitled to the extra features or not, they'd had them. The genie was out of the bottle, the toothpaste sans tube. A technical correction was a marketplace error. &lt;br /&gt;&lt;br /&gt;It was a decent lesson to learn, though I soaked the blame for screwing up the customers by fixing the code.  I had permission, had talked it over, and had an approved ticket to fix it, but ultimately it was my fingers typing the code and my hands testing the correction, so I had to wear it.&lt;br /&gt;&lt;br /&gt;I got in more trouble for fixing things than I ever did for breaking them.  There's a lesson in that, too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-262528967051724295?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/262528967051724295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/04/be-careful-what-you-fix.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/262528967051724295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/262528967051724295'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/04/be-careful-what-you-fix.html' title='Be Careful What You Fix'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-7135619505302264491</id><published>2010-03-19T10:34:00.001-07:00</published><updated>2010-03-19T12:57:54.658-07:00</updated><title type='text'>Full Test Access With Data Hiding for Production</title><content type='html'>I'm talking to users of statically-typed languages today.  Functional and dynamic language people, cut them some slack and realize I'm not talking to you.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Breaking with Conventional Wisdom&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are certainly Object-Oriented design pundits who will argue that you should never, ever have public variables in a class.  The reason is good enough, that the object should be responsible for its own state. You should tell it to do things, and it should do them. Likewise you should not manipulate its variables for it, since that requires a strong understanding of valid states for the objects, and this understanding is a strong coupling. Strong couplings between classes are bad things.  All of that wisdom is correct and proven.&lt;br /&gt;&lt;br /&gt;However, many programmers make bean-ish objects where every private variable has a getter and a setter.  This helps to preserve uniformity of access (you can't tell if it's calculated or stored, method or variable), but is otherwise the same as exposing public variables. When uniform access is important, this is a good practice.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Proposal&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When writing tests, data-hiding and uniformity of access are unhelpful. While many say that a class should be tested through the interface it uses in production, we still recognize that testing is improved when there is unimpeded access to a class. How often do you hear of people foregoing tests or adding a "testable" work-around simply because a method is declared protected or private?&lt;br /&gt;&lt;br /&gt;There is a way to harmonize both the desire for object self-management and the need for testing with full access.&lt;br /&gt;&lt;br /&gt;Some (hopefully most) classes are not built to be used directly by other classes, but through interfaces.  A method outside of the interface does not exist to the classes that use the interface.  This invisibility is "data hiding" and is a good thing.  Private methods approximate this invisibility too well, making details of representation invisible to tests as well as to users.&lt;br /&gt;&lt;br /&gt;If we program through interfaces, then we find that adding public methods to classes (not their interfaces) is a non-issue. We are without fear of programmers pillaging our object's state. The non-interface methods do not pop up in the code hints or code completion windows.  They do not exist, and an attempt to call our public non-interface methods are compiler errors. We have the data hiding we need.&lt;br /&gt;&lt;br /&gt;Tests will usually be working against concrete implementations, and are not tied to the small set of methods presented by the interface. Tests automatically have "privileged access" to methods outside the interface of the class. Data hiding therefore can exist alongside full test access.&lt;br /&gt;&lt;br /&gt;Some classes inherit implementation from others.  It's a code sharing mechanism with a long and storied history.  These derived classes will have access to the public methods of their base classes.  So test them well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Side Effects&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is an additional advantage to all classes implementing interfaces, in that interfaces make it easy to build test doubles.  Some languages have facilities for partial-mocking of classes, but an interface only makes the work easier.&lt;br /&gt;&lt;br /&gt;Moreover, most statically-typed languages have IDEs with refactoring support, so that "extract interface" is a relatively trivial thing to do.  If it is easy to make an interface, easy to use an interface, easy to mock an interface, and the interface effectively hides the interface used by testing, it is hard to understand why people do not use them more.&lt;br /&gt;&lt;br /&gt;UI components are a useful class of objects used through interfaces.  They are called by some kind of a UI framework, through interfaces it provides.  The UI framework doesn't know your class from any other class. So why do the UI classes keep private methods and private variables? The only callers of the class cannot call them even if they were made public.  If some other classes in the UI need to use a UI component, let it be used through an interface which constrains the set of usable class features.&lt;br /&gt;&lt;br /&gt;Another instance of classes not needing private variables are test harnesses and test fixtures.  Against whom are they protecting their private state? Against the test runners? Against production programmers? Against other tests? Horse feathers!  There is no real need for tests to preserve their internals.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sound Bite&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;IFF we program to interfaces, THEN private implementation variables and methods are not only redundant but also impede testing.  Let's consider a little shift in our thinking if it will make our work easier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-7135619505302264491?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/7135619505302264491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/03/whats-wrong-with-public-variables.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7135619505302264491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/7135619505302264491'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/03/whats-wrong-with-public-variables.html' title='Full Test Access With Data Hiding for Production'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-8913355647613874993</id><published>2010-03-12T08:03:00.000-08:00</published><updated>2010-03-12T08:35:23.614-08:00</updated><title type='text'>Even simplified, it can be daunting</title><content type='html'>&lt;a href="http://agileinaflash.blogspot.com/2009/03/solid.html"&gt;SOLID&lt;/a&gt; design&lt;br /&gt;&lt;a href="http://agileinaflash.blogspot.com/2009/02/first.html"&gt;FIRST&lt;/a&gt;-rate tests&lt;br /&gt;&lt;a href="http://agileinaflash.blogspot.com/2010/02/seven-code-virtues.html"&gt;Virtuous&lt;/a&gt; code&lt;br /&gt;&lt;br /&gt;I understand the "just get it done mindset" because there is a lot of learning, thinking, and doing behind those three simple links.  It is daunting.  Any developer who can sling code could become considerably better at coding and more desirable as a teammate if he would learn and apply these concepts in his daily work, but it won't happen overnight.&lt;br /&gt;&lt;br /&gt;Jeff and I built these 3x5 cards and simple explanations on the web site, but we don't pretend that you can live on these sound bites alone. The cards tell you what the words mean, and that's a good starting point (better than winging it), but the part that matters most is the part that won't fit on a card, the part where one practices.&lt;br /&gt;&lt;br /&gt;I like the word "practice."  Wherever you are writing code today, it is practice.  You are expected to apply principled development and get better, but even if you are slap-dash hacking things together, you are building your mental habits and your reputation.  You could have a reputation for overdesign, poor quality, quick hacks, and spaghetti coding.  You could choose a reputation for steady progress, high quality, and code that makes next week's programming easier than this week's programming. &lt;br /&gt;&lt;br /&gt;However daunting, it's doable.  If we put a little of SOLID, FIRST, or the Virtues into our work today, we begin practicing principled development.  This practice will deepen our understanding of principles and retrain our mental reflexes.  Eventually our reputations will improve.  We'll have some iffy moments along the way, but becoming a great programmer takes time.&lt;br /&gt;&lt;br /&gt;The exciting part is that it can be done, we can do it, and a bunch of people have spent the time to outline it for us.  This is what excites me about &lt;a href="http://agileinaflash.com/"&gt;agile in a flash&lt;/a&gt;, where we can build references to the works of other software developers to further build our skills.  Feel free to print some of the cards, post them in your workspace, and use them to retrain your programming habits.  Drop us a line to let us know how it's going.&lt;br /&gt;&lt;br /&gt;Even simplifed, it's daunting... but even daunting, it is the way forward.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-8913355647613874993?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/8913355647613874993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/03/even-simplified-it-can-be-daunting.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8913355647613874993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/8913355647613874993'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/03/even-simplified-it-can-be-daunting.html' title='Even simplified, it can be daunting'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-4589886094647881256</id><published>2010-03-10T05:47:00.000-08:00</published><updated>2010-03-10T06:06:06.282-08:00</updated><title type='text'>When The Test Goes Green</title><content type='html'>My assertion today is: If we would read the code we're writing, we wouldn't write the code we're writing.&lt;br /&gt;&lt;br /&gt;We know the red-&gt;green-&gt;refactor cycle, but I find repeatedly that programmers are "optimizing" out that last step.  It tends to run more like red-&gt;green-&gt;next. Perhaps there is confusion over what is supposed to happen when the test turns green.&lt;br /&gt;&lt;br /&gt;The first thing that is supposed to happen is that you read the code you've just written to see if it makes any sense at all. While this sounds perfectly sensible, it often does not happen. Programming is not just typing. It is easy for programmers to rush to complete their assignments and never really examine their work.&lt;br /&gt;&lt;br /&gt;I saw an example recently where the old code said:&lt;pre class="code"&gt;&lt;br /&gt;    DateTime date = DateTime.Parse(datestring);&lt;br /&gt;&lt;/pre&gt;. As a minimal-perturbation change to push to green, the developer changed the code to say &lt;pre class="code"&gt;&lt;br /&gt;   DateTime date = DateTime.Parse(DateTime.Now.ToString());&lt;br /&gt;&lt;/pre&gt;.  Had he or his partner actually read that code they would have realized that it was a little silly, and replaced it with &lt;pre class="code"&gt;&lt;br /&gt;  DateTime date = DateTime.Now;&lt;br /&gt;&lt;/pre&gt;However, I suspect that they never examined it past the green bar.  It worked, and that is a virtue, but it was doing too much and the team would be totally embarassed to see their blunder in print.  I fixed it, and the programmers remain anonymous here. They're good programmers, but this time it seems they sailed past the green bar without a thought.&lt;br /&gt;&lt;br /&gt;When the bar turns green, read your code.  Read the test code, read the code it invokes. It is not at all unusual to find that you have done something short-sighted, complicated, or (God forbid) clever.  That code needs to be cleaned up before your peers see it!&lt;br /&gt;&lt;br /&gt;Once you read the code, you will know what is wrong with it, and then you can use the various refactorings provided by your development tool or outlined in the fine Refactoring book.  You can take your code from one "green" (all tests passing)_ state to another until it is no longer apparent that you ever did anything silly to begin with. &lt;br /&gt;&lt;br /&gt;Be particularly suspicious of any code you've written into your tests or test fixtures that ought to be in the classes you are testing. Tests are meant to be extremely lean and fast-running, whereas business objects are meant to be capable. If you start writing capable test fixtures that call upon lean business objects you know you've gone wrong.  Refactor the code.&lt;br /&gt;&lt;br /&gt;I wish that we could lengthen the sequence to red-&gt;green-&gt;read-&gt;refactor so people would understand the process and apply it.  I suppose that we take too much of "refactor" for granted.  Nevertheless, the secret to TDD is in that third step, and all refactoring begins with reading and evaluating the code we've written.&lt;br /&gt;&lt;br /&gt;After all, a program unexamined is not worth writing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-4589886094647881256?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/4589886094647881256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/03/when-test-goes-green.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4589886094647881256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/4589886094647881256'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/03/when-test-goes-green.html' title='When The Test Goes Green'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-381129527146258002.post-3689373711985052863</id><published>2010-03-08T06:45:00.001-08:00</published><updated>2010-03-08T18:41:24.056-08:00</updated><title type='text'>Motivational Speech</title><content type='html'>My biggest problem with American culture is the concept of "the locker room speech that wins the game".  I don't doubt that people get down and can use encouragement.  A little validation can go a long way, and mistreatment breeds dysfunction. If you treat a winner like a loser, expect to see some losing.  I get all of that (sparing you the painful personal history).  &lt;div&gt;&lt;div&gt;My problem is with the absurdist version of the story: the mythical team that is filled with execution issues, poor teamwork, low degree of individual skill, and an enemy with both superior skill and a history of success.  In this story, it is one stirring talk from the tough-but-beloved coach that turns the team around. They charge the field and play like a commando team, each overcoming all personal skill issues and all of them meshing into a perfect winning machine.&lt;/div&gt;&lt;div&gt;In the real world, it is unlikely that the problems a technical team faces are motivational in nature.  Maybe a team is struggling with technical problems.  Maybe they haven't learned to support each other with their efforts and need some training. Maybe they lack the individual skills necessary for them to do a good job.  Maybe they are skilled, but bound up in organizational boundaries, official roles, rules, and red tape. Maybe there is a very poor system of rewards and compensation, so that they are punished for doing what is best for the company. Commonly (for programming teams) the years of heroic last-ditch efforts have left the code base a non-performant, convoluted, fragile mess of hacks and band-aids.  Maybe they aren't getting access to the Customer that will help them make good decisions.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is ever-so-possible that most people on most teams in most companies are really dealing  with actual problems.  It could be that they're not just slacking or slumping, but that they've hit some walls.  I have never yet seen a slow build, a performance bug, an intermittent failure, or a sloppy code base that yielded to emotional pressure instead of a breakthrough discovery.  I've never seen a team burst through organizational barriers by happy think instead of hammering out working relationships and building a good history of collaboration together one feature at a time.  &lt;/div&gt;&lt;div&gt;The problems our teams face are not all in their heads. The least sympathetic, least effective, least meaningful thing we can do when people are facing real technical or organizational problems is to try to prop them up with positive motivational speeches or "motivate" them with threats and insults.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If we want to be effective we must try giving our people the resources, aid,  and freedom to solve problems. We have to free up some space for the work they have to do, and understand that there is no meaningful way to estimate the time to discovering a problem you do not yet understand. We have to allow them to experiment, make mistakes, learn, discover. I will not be helpful to a struggling team until I drop the motivation and apply some problem-solving or bring in some useful talent to help with the problems.&lt;/div&gt;&lt;div&gt;If we give in to the desire to give a locker room speech and our team succeeds, we have to resist the urge to claim credit. It is their hard work and skills that made it happen. I've been in the technical side of the software business for 30 years, and offer assurance that technical teams succeed &lt;i&gt;despite &lt;/i&gt;these speeches, not &lt;i&gt;because&lt;/i&gt; of them.&lt;br /&gt;Contrary stories are welcome.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/381129527146258002-3689373711985052863?l=agileotter.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://agileotter.blogspot.com/feeds/3689373711985052863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://agileotter.blogspot.com/2010/03/motivational-speech.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3689373711985052863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/381129527146258002/posts/default/3689373711985052863'/><link rel='alternate' type='text/html' href='http://agileotter.blogspot.com/2010/03/motivational-speech.html' title='Motivational Speech'/><author><name>TimOttinger</name><uri>http://www.blogger.com/profile/10773578598860454277</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_WMyCPCNYrhk/Se4O_8ZFOuI/AAAAAAAAAJ4/Bh30Ad2MTbM/S220/headshot2.jpg'/></author><thr:total>3</thr:total></entry></feed>
