<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: Category Tim's Tepid Torrent</title>
    <link>http://blog.objectmentor.com/articles/category/tims-tepid-torrent</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Top Refactorings</title>
      <description>&lt;p&gt;This has been done before by another mentor, and it was fun.  I&amp;#8217;ve been watching my use of refactoring tools, and here is my top five list of seven most-used refactorings:&lt;/p&gt;


&lt;ol&gt;
&lt;li&gt;Rename&lt;/li&gt;
&lt;li&gt;Introduce Variable&lt;/li&gt;
&lt;li&gt;Extract Method&lt;/li&gt;
&lt;li&gt;Inline variable&lt;/li&gt;
&lt;li&gt;Inline method&lt;/li&gt;
&lt;li&gt;Move Method&lt;/li&gt;
&lt;li&gt;Change method signature&lt;/li&gt;
&lt;/ol&gt;

	&lt;p&gt;You might guess that I&amp;#8217;m doing a fair amount of refactoring on legacy code.&lt;/p&gt;


	&lt;p&gt;I was suprised how much I&amp;#8217;m using introduce/inline variable, but quite often I&amp;#8217;m doing that to make a block of code ready for method extraction.  Having broken out small methods, I sometimes find a larger method to extract, and then I inline the use of smaller methods. It&amp;#8217;s sometimes hard to find the right level of generality.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;d have trouble imagining that the first three weren&amp;#8217;t everyone&amp;#8217;s favorite refactorings.&lt;/p&gt;</description>
      <pubDate>Thu, 26 Jun 2008 01:10:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:1b5f9a03-bd7d-49be-a66d-89622e7f60ed</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/06/26/top-refactorings</link>
      <category>Tim's Tepid Torrent</category>
      <category>refactoring</category>
      <category>tool</category>
      <category>rename</category>
      <category>inline</category>
      <category>move</category>
      <category>list</category>
      <category>choices</category>
    </item>
    <item>
      <title>Quality, Timing, and a Clash of Values</title>
      <description>&lt;p&gt;I came across a quote in something I was reading, and I can&amp;#8217;t recall if it was a blog, a cartoon, a book, or what.  A young woman was talking to a politician and asked if he had to make a lot of compromises.  When he admitted that he had to compromise a few times, she shut him down by saying &amp;#8220;you can only compromise your values once, and after that you don&amp;#8217;t have any.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;I had a talk the other day with a fellow mentor, and brought up line only to have it returned to me (with top spin!) when we were talking about when would be the right time to turn on an older suite of tests in CI.&lt;/p&gt;


I finally had a chance to examine the decision point.  Of course, it&amp;#8217;s &lt;strong&gt;always&lt;/strong&gt; the right time to turn on more tests.  When do you not want to know if your code stinks?  On the other hand, I knew: 
&lt;ol&gt;
&lt;li&gt;these forgotten tests were not used by developers, and so are of dubious quality&lt;/li&gt;
&lt;li&gt;the team in the middle of a big stabilization crunch&lt;/li&gt; 
&lt;li&gt;the team is in their final coding week before release.&lt;/li&gt;
&lt;/ol&gt;

	&lt;p&gt;While they need to know their code and test quality soonest (preferably before release) there was emotional foot-dragging on my part.  I knew that they didn&amp;#8217;t have the headroom to even triage the old tests to see if they &lt;strong&gt;should&lt;/strong&gt; pass.&lt;/p&gt;


	&lt;p&gt;The problem was not of compromising my principles so much as choosing which of my principles would have sway.  On one hand, the quality driver knows that we need more tests sooner.  On the other hand, I knew how close the team was to being overwhelmed to the point of shutting down.  My nurturing, coaching &amp;#8220;spider-sense&amp;#8221; kicked in when I wanted to turn on the tests, and my XP quality-driving &amp;#8220;spider-sense&amp;#8221; kicked in when I thought about not turning them on.&lt;/p&gt;


	&lt;p&gt;I decided to wait only a week, and then get the tests turned on.  Was it the right decision? I can&amp;#8217;t tell. I am truly ambivalent; both drawn and repulsed by the decision. Sometimes the good is the enemy of the best and it&amp;#8217;s hard to see which is which.&lt;/p&gt;


	&lt;p&gt;I chose to be the kind of guy who would err on the side of compassion. It&amp;#8217;s the more personal and superior of the two values. Having decided, I move on.&lt;/p&gt;


	&lt;p&gt;But now it&amp;#8217;s time to get those tests running, and sooner is better.&lt;/p&gt;</description>
      <pubDate>Thu, 22 May 2008 22:31:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:70787e9d-db8b-4c8e-b677-0094e67d9e1d</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/05/22/quality-timing-and-a-clash-of-values</link>
      <category>Tim's Tepid Torrent</category>
      <category>compassion</category>
      <category>timing</category>
      <category>values</category>
      <category>Tests</category>
    </item>
    <item>
      <title>Python's Mutable Default Problem</title>
      <description>&lt;p&gt;Today I was perusing &lt;a href="http://www.siafoo.net/article/52"&gt;a very fine python article&lt;/a&gt; all professional python programmers should read. I had to grin when I saw one of my favorite python quirks/flaws.&lt;/p&gt;


Python only evaluates default parameters when it defines a function, leading to surprising side effects &lt;i&gt;(example from saifoo)&lt;/i&gt;:
&lt;pre&gt;
def function(item, stuff = []):
    stuff.append(item)
    print stuff

function(1)
# prints '[1]'

function(2)
# prints '[1,2]' !!!
&lt;/pre&gt;

	&lt;p&gt;The grin on my face was because I was bit by this one again last Tuesday.  You just don&amp;#8217;t want to make a mutable object a default parameter. The solution I used was close to the solution from saifoo:&lt;/p&gt;


Saifoo.net:
&lt;pre&gt;
def function(item, stuff=None):
   if stuff is None:
      stuff = []
   stuff.append(item)
   print stuff
&lt;/pre&gt;
This, of course, gives the correct behavior because it creates a new empty list each time it is called without a second parameter.

	&lt;p&gt;My solution actually combines some advice contained earlier in the article with the solution given for this problem:&lt;/p&gt;


Mine
&lt;pre&gt;
def function(item, stuff=None):
   stuff = stuff or []
   stuff.append(item)
   print stuff
&lt;/pre&gt;

	&lt;p&gt;It&amp;#8217;s not necessarily prettier, and I struggle with whether it is more obvious (to a Python programmer) or not.  I fear it may be &lt;i&gt;clever&lt;/i&gt; (a word I only use in the pejorative sense), but it is also clean-looking to me.&lt;/p&gt;


	&lt;p&gt;The point remains, though, that the mutable default parameter quirk is an ugly corner worth avoiding, and I suspect that any code that purposefully exploits that behavior to populate a structure that persists across calls will run a very real risk of being misunderstood.&lt;/p&gt;


	&lt;p&gt;We all know what happens when the next programmer to touch a program misunderstands it.&lt;/p&gt;</description>
      <pubDate>Thu, 22 May 2008 22:16:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:36360a07-a7f0-4ea1-a246-52ce62b71996</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/05/22/pythons-mutable-default-problem</link>
      <category>Tim's Tepid Torrent</category>
      <category>python</category>
      <category>mutable</category>
      <category>default</category>
      <category>pitfall</category>
    </item>
    <item>
      <title>VIM as a Diff/Merge Tool</title>
      <description>&lt;p&gt;Do you need a really quick, clean, powerful diff/merge tool that you can use in windows, mac, and various Unixen?  As a happy and pround &lt;a href="http://vim.org"&gt;vim&lt;/a&gt; user, I have been enjoying &lt;a href="http://www.vim.org/htmldoc/diff.html"&gt;vimdiff&lt;/a&gt; for a number of years.&lt;/p&gt;


&lt;pre&gt;
        &amp;gt; gvim -d file1 file2
        &amp;gt; vimdiff file1 file2
&lt;/pre&gt;

	&lt;p&gt;(G)vimdiff is wonderful. You can move changes between two versions of a file with
great ease (if you know vim) and amazing speed. It can handle files of any size and does a fine job of syncing up both versions.&lt;/p&gt;


	&lt;p&gt;Vim can do just about anything. I have learned that no matter how much I use and study Vim I still am just scratching the surface of what the editor can do.  I find little tricks and configuration options, new keystrokes, and fun little bits of minutae.  I think it&amp;#8217;s all new.  With my memory, sometimes I just &lt;strong&gt;think&lt;/strong&gt; something is new, and have to go check my &lt;a href="http://tottinge.blogsome.com/use-vim-like-a-pro/"&gt;past notes&lt;/a&gt; to see if I already knew it.&lt;/p&gt;


Today I (re)learned about diffopt, which makes gvimdiff more wonderful. 
&lt;pre&gt;
    :set diffopt=filler
&lt;/pre&gt;
By default, diffopt is set to &amp;#8220;filler&amp;#8221;.  Filler doesn&amp;#8217;t do much, it
just adds vertical spaces to keep the text of the left and right
pane aligned.  It&amp;#8217;s a good setting, and I don&amp;#8217;t much like working
without it.  But there are other settings which are overlooked, 
even by experts.
&lt;pre&gt;
    : set diffopt+=iwhite
&lt;/pre&gt;
My second favorite is &amp;#8216;iwhite&amp;#8217;, which stands for &amp;#8220;ignore whitespace&amp;#8221;.
It makes gvimdiff ignore leading, trailing, and embedded spaces so
that simple acts like retabbing or deleting vertical spaces won&amp;#8217;t 
obscure actual changes.   It really helps you to merge changes in 
situations where you&amp;#8217;ve adopted code that was built to entirely different
standards. 
&lt;pre&gt;
    :set diffopt+=icase
&lt;/pre&gt;
iCase ignores capitalization, which is not as useful as the other options, since programmers are normally interested in case, but it may be handy when someone has corrected and reformatted &lt;span class="caps"&gt;SQL&lt;/span&gt;.  I don&amp;#8217;t expect to use it much.
&lt;pre&gt;
    :set diffopt+=horizontal
&lt;/pre&gt;
The last interesting bit is the choice between vertical splits (the normal case) and horizontal splits (for very long lines on cinema-aspect screens).  I hope to never  need this option again, but I have needed to deal with absurdly long lines.

	&lt;p&gt;If you can use &lt;span class="caps"&gt;VIM&lt;/span&gt; at all, you will find vim&amp;#8217;s diffmode to be a very powerful and  useful tool.  If you can&amp;#8217;t use vim already, then maybe vimdiff will be the reason you will learn vim.&lt;/p&gt;</description>
      <pubDate>Wed, 30 Apr 2008 21:24:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:87ede884-c19a-4ab9-9a04-9b074bb32c86</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/04/30/vim-as-a-diff-merge-tool</link>
      <category>Tim's Tepid Torrent</category>
      <category>vim</category>
      <category>diff</category>
      <category>vimdiff</category>
      <category>diffopt</category>
    </item>
    <item>
      <title>Magic Funnel, Part 3: Covey's Miracle</title>
      <description>&lt;p&gt;We had a team of surrogate stakeholders in the room, and all the very most important stories (as far as we could tell) on a table in front of us.&lt;/p&gt;


	&lt;p&gt;&amp;#8220;These are the most important?&amp;#8221; Heads nodded. &amp;#8220;Then,&amp;#8221; I asked, &amp;#8220;what makes them important?&amp;#8221;  Brows furrowed, and well-considered answers poured forth.&lt;/p&gt;


	&lt;p&gt;I collected their reasons for importance.  Some were about keeping promises, some were about providing increased quality (uptime, correct function), and there were other kinds of importance.  We wrote them on a 3&amp;#215;5 card. Ultimately, we realized that the company&amp;#8217;s reputation is their source of importance.  Users needed to know that the company will do the right things, and provide software that worked and kept them working. I thought it was a good criteria.&lt;/p&gt;


	&lt;p&gt;Next I explained that urgency is different from importance.  There may be a hot demand for some cosmetic changes that don&amp;#8217;t really impact the company&amp;#8217;s reputation one way or another. There may be some changes that in the direction we want to go.  These may be hot topics, but may not be truly important.&lt;/p&gt;


	&lt;p&gt;We could see a difference between the forces of urgency and the force of importance, but there is gray area as a sufficient pent-up demand for otherwise unimportant changes could in fact effect our reputation for service. Still, we could usually see a crisp-enough boundary for any given user story.&lt;/p&gt;


	&lt;p&gt;I then (re-)introduced the team to &lt;a href="http://en.wikipedia.org/wiki/First_Things_First_%28book%29"&gt;Stephen Covey&amp;#8217;s four-quadrant system&lt;/a&gt;.  It has two axes.  The vertical is importance (important at the top, unimportant below).  The horizontal is urgency with urgent things to the left and non-urgent on the right:&lt;/p&gt;


&lt;table border=1px align=center&gt;
&lt;tr&gt;&lt;td&gt;Q1&lt;br&gt;Important and Urgent &lt;/td&gt;&lt;td&gt;Q2&lt;br&gt;Important, not Urgent&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Q3&lt;br&gt;Unimportant and Urgent &lt;/td&gt;&lt;td&gt;Q4&lt;br&gt;Neither important nor urgent&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

	&lt;p&gt;We took our set of cards and the team determined groupings.  Was this a quadrant one activity? Quadrant 3? Quadrant 2?  There were some real surprises, especially when we realized our &amp;#8220;most important&amp;#8221; bit of work was not urgent and should wait until quadrant one activities were finished.&lt;/p&gt;


	&lt;p&gt;Covey&amp;#8217;s recommendation is that we tackle first those items that are both important and urgent.  When we knock that stack down, we move on to those that are important but not urgent.  If we have time left, those non-important-but-urgent items can &amp;#8220;fly standby&amp;#8221; in our sprint.  We reordered the priorities in accordance with Covey&amp;#8217;s recommendation.&lt;/p&gt;


	&lt;p&gt;We had no cards that were both unimportant and non-urgent.&lt;/p&gt;


	&lt;p&gt;At this point in time, we had what looked very much like a magic funnel. Ideas came in from everywhere, and the items that moved from the planning team to the developers came out in the &amp;#8220;magically correct&amp;#8221; order.  We agreed that the selection and the ordering were the best we could do at the time.&lt;/p&gt;


	&lt;p&gt;Our next sprint planning meeting was remarkably efficient.&lt;/p&gt;</description>
      <pubDate>Thu, 17 Apr 2008 22:15:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:92b17688-ec1a-4306-ace5-fe791fb36966</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/04/17/magic-funnel-part-3-coveys-miracle</link>
      <category>Tim's Tepid Torrent</category>
      <category>covey</category>
      <category>FIRST</category>
      <category>Things</category>
      <category>Quadrants</category>
      <category>important</category>
      <category>Urgent</category>
      <category>prioritizing</category>
      <category>magic</category>
      <category>funnel</category>
    </item>
    <item>
      <title>Building Magic Funnels, Part 2: Pragmatic Pedantry</title>
      <description>&lt;p&gt;The middle of the funnel we started on needed work. While it is a simple idea that the single, most important thing in the funnel is the first to emerge from the bottom, it is a multi-flavored affair to try to manage for real.&lt;/p&gt;


	&lt;p&gt;My first strategy was to get the right people in a room and have them fight it out.  I think that the prioritization process should be a lot like local government (maybe a school board?) in that people should argue and complain and push and eventually settle on compromises and deals. Ultimately, I believe that people who have a strong interest in the company can make the right decisions. At least they can be right enough for the next 5 days.  When you have one-week iterations, the next chance to change the agenda is never far away.&lt;/p&gt;


	&lt;p&gt;This first strategy didn&amp;#8217;t work out, and so we went to a backup plan.  &lt;span class="caps"&gt;A C&lt;/span&gt; level manager said he knew what we should do, and so we scheduled an hour or so with him, myself, our priority manager (&amp;#8220;funnel guy&amp;#8221;) and the senior technical developer.&lt;/p&gt;


	&lt;p&gt;Our guys used the sticky post-it 3&amp;#215;5 cards and papered the &lt;span class="caps"&gt;CIO&lt;/span&gt;&amp;#8217;s windows and whiteboards.  They listed the various categories of work from the various stakeholders and pasted them up in priority order.&lt;/p&gt;


	&lt;p&gt;I asked my first pedantic question: &amp;#8220;What is the single most important thing we can work on?  If you had only one story that you knew for sure would be finished this week, which would it be?&amp;#8221;   That led to a nice discussion.&lt;/p&gt;


	&lt;p&gt;When they placed the card on the table, signifying that it was definitely in the build, I asked again if there was any one card anywhere else in the room more important. I asked if that was really the single most important one.&lt;/p&gt;


	&lt;p&gt;When the answer was &amp;#8220;yes, absolutely&amp;#8221; I was ready for my second pedantic question: &amp;#8220;Now that this card is off the board, what is the single most important card left for us to do, if only two stories were guaranteed to be done.&amp;#8221;  Now the pedantry was fully exposed, but the idea had carried.  The team collected all the most important stories and placed them in order on the table.&lt;/p&gt;


	&lt;p&gt;Now I was ready for my next round of pedantry.&lt;/p&gt;</description>
      <pubDate>Thu, 17 Apr 2008 22:00:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ae6af373-160c-4076-9dd4-1c08c43893b2</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/04/17/building-magic-funnels-part-2-pragmatic-pedantry</link>
      <category>Tim's Tepid Torrent</category>
      <category>backlog</category>
      <category>management</category>
      <category>iteration</category>
      <category>planning</category>
      <category>importance</category>
      <category>magic</category>
      <category>funnel</category>
      <category>pedantry</category>
      <category>most</category>
      <category>important</category>
      <category>question</category>
    </item>
    <item>
      <title>Building Magic Funnels, Part 1</title>
      <description>&lt;p&gt;The idea of a magic funnel, as you may remember, is that there is some kind of organizational structure where many ideas and proposals and issues go into the top.  Through some magic, the item that emerges from the bottom of the funnel (to go to the development team) is the single most important thing they could work on next.&lt;/p&gt;


	&lt;p&gt;This is all just backlog management and prioritization, of course. But I think it can be simpler than I&amp;#8217;ve seen it in the past, and that real people working without magic can approximate it.&lt;/p&gt;


	&lt;p&gt;Recently, I&amp;#8217;ve been working to establish another magic funnel. One of the first things we did was to find the person who formerly handed out work to the developers and made him a single point of contact. In our case this is not the scrum master, but is another trusted line-manager type. He has been given a number of people to work with on the Customer side of the house and also works with technical people.&lt;/p&gt;


	&lt;p&gt;We have tried to establish story feeds from all the various stakeholders.  Developers, operations people, technical writers, customers, sales people, marketing people, inside security consultants, and others have been feeding their ideas in to our point-of-contact man.  This part of the funnel is working fairly well.&lt;/p&gt;


	&lt;p&gt;The next thing we have tried to do is to match the feed of work to the rate at which work can be done. This has created a fair amount of back-pressure on the stakeholders (which I believe to be healthy).&lt;/p&gt;


	&lt;p&gt;We have also worked on making the bottom of the funnel narrow, meaning that our guy doesn&amp;#8217;t scatter new work to the team, but feeds it through the scrum master who protects the team&amp;#8217;s productivity and keeps the work flow and tasks visible on the status board. He makes sure that the team is not expected to &amp;#8220;absorb&amp;#8221; changes, but that adding two points of work to the iteration results in two points of unstarted work coming off.  This also creates a healthy back-pressure.&lt;/p&gt;


	&lt;p&gt;As a pun on &amp;#8220;in-flight&amp;#8221;, I named another area of the board &amp;#8220;flying standby&amp;#8221;. This is for stories that aren&amp;#8217;t important enough to swap a story off the board (or for stories that are displaced by more important ones).  If the developers finish more work than they expected, there are stories that can be picked up even though they&amp;#8217;re not a scheduled part of the iteration.  Stakeholders are told that there is no guarantee of these stories being picked up at all in this iteration, but there is some small chance that it could happen if the team discovers that it has overestimated some other stories.&lt;/p&gt;


	&lt;p&gt;The bottom of the funnel is working pretty well.&lt;/p&gt;


	&lt;p&gt;What&amp;#8217;s missing is the &amp;#8220;magic&amp;#8221; bit.&lt;/p&gt;</description>
      <pubDate>Thu, 17 Apr 2008 21:38:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ad130f5c-1cbc-4c34-8f1a-62a84f2a150b</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/04/17/building-magic-funnels-part-1</link>
      <category>Tim's Tepid Torrent</category>
      <category>magic</category>
      <category>funnel</category>
      <category>XP</category>
      <category>agile</category>
      <category>backlog</category>
      <category>management</category>
      <category>negotiation</category>
      <category>planning</category>
    </item>
    <item>
      <title>The Magic Funnel</title>
      <description>&lt;p&gt;At a planning meeting, the developers on the team offer up some amount of work they are able to do. This capacity is termed velocity.  The customer part of the team then selects enough user stories to consume all of the offered capacity. This is simple negotiation, but that hardly tells the story.  What is happening on the customer side is a magic funnel.&lt;/p&gt;


	&lt;p&gt;All kinds of stories come pouring into the customer group.  Some are from actual users in the field who want improvements to existing features. Some suggest entirely new areas of functionality into which the program could expand to good effect.  Some are from the operations group, generally describing ways to make the product more reliable, configurable, or manageable. Some are from the developers who realized that some small changes in code could provide large changed in capability or usability.  Some are from external regulatory bodies, some are from quality control, but for the most part they&amp;#8217;re all good ideas and many have urgency.&lt;/p&gt;


	&lt;p&gt;When the magic funnel is working, we pour all these stories into the top, and the thing that falls out the bottom is the single most important, urgent task we could possibly do.  When it comes time for a new iteration, we fill in our allotted space with whatever comes out the end of the funnel.  Whatever we start doing on Monday, it is the best thing we could possibly start doing.  We know that it is true because it came out of the funnel that way.&lt;/p&gt;


	&lt;p&gt;Sadly, magic funnels are hard to come by.  We approximate them with human beings in multi-disciplinary small groups.  If we leave the funnel purely in the hands of operations, then operational stories are the first to come out.  If we leave the funnel in the hands of marketing people, we tend to do things that are more speculative even though the product users don&amp;#8217;t really need them right now.   If it&amp;#8217;s sales, then whatever will sell more product this month will be the first thing out of the funnel. Give control to customer support and we find ourselves constantly appeasing customers and not moving forward on larger issues. If we leave it to developers, it will tend to turn out those stories that improve the experience of developing the application.  Of course the problem is about conflicting perspectives (all of them right!) with competing desires being processed in fixed time.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m not an expert in creating magic funnels, though it would be a very interesting direction to take at this point in my agile coaching career.  I believe that the answer is ultimately to be found in people working together, well-informed people arguing and debating and even trading favors.&lt;/p&gt;


	&lt;p&gt;I think that part of the answer is Covey-style prioritizing  to select the urgent and important (Q1), then the important items that aren&amp;#8217;t urgent (Q2), and holding all unimportant work until there is nothing better to do.&lt;/p&gt;


	&lt;p&gt;Importance in this case relates to how much the change will affect the future of the product and the company.  This is not just a matter of closing a contract or soothing an angry customer.  It may be that the future is larger and brighter than our immediate concerns.   Immediacy is &#226;&#8364;&#339;urgency&#226;&#8364;&#157;, but the leverage to create a more greater future is &#226;&#8364;&#339;importance&#226;&#8364;&#157;.  I had to read Covey&amp;#8217;s &lt;i&gt;First Things First&lt;/i&gt; several times to really understand the difference, as may the kind reader.  But I did manage to absorb the fact that until you know what you want your future to be, you don&amp;#8217;t know what is important.&lt;/p&gt;


	&lt;p&gt;But imagine how great it will be when you have established your magic funnel, and the work being assigned to each iteration really is the most important and valuable thing that you could do next. Imagine what it would be like if you really were building the future you would like to live in.&lt;/p&gt;</description>
      <pubDate>Wed, 09 Apr 2008 13:18:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:baedf2ab-c088-43c0-bebc-3dc2cf9536cc</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/04/09/the-magic-funnel</link>
      <category>Tim's Tepid Torrent</category>
      <category>planning</category>
      <category>funnel</category>
      <category>coordination</category>
      <category>cooperation</category>
      <category>importance</category>
      <category>urgency</category>
      <category>covey</category>
    </item>
    <item>
      <title>Your Attitude is Affecting Other Departments</title>
      <description>&lt;p&gt;The &lt;span class="caps"&gt;CIO&lt;/span&gt; looked into the eyes of his agile development staff last Friday. &amp;#8220;Your attitude is affecting other departments&amp;#8221; he said.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve heard a lot of department-level speeches start this way, and in relatively small companies it is not unheard-of for a C-level manager to address attitudes of development teams.&lt;/p&gt;


	&lt;p&gt;The group has been working to stabilize and improve a product that was developed by a tiger team of outsider contractors and handed over to the in-house team post-facto. The developers had to overcome many obstacles to come up to speed on the code, to learn the new programming languages and tools, and to try to keep the feature set moving forward.  None of them had been involved in the original design, but it was now their product, and its problems were their problems.&lt;/p&gt;


	&lt;p&gt;At the time of this meeting, I was one part of a coaching team which had introduced a great many changes.   We were trying to help the organization to build a &amp;#8220;whole team&amp;#8221; mentality that encompassed documentation, security, systems administration, QA, customer representatives, and developers alike.  We&amp;#8217;d attacked the problem of matrix management.  We reorganized the seating floorplan.  I think at some point we&amp;#8217;d been an inconvenience to just about everybody. The developers were in the middle of their second two-week iteration.&lt;/p&gt;


	&lt;p&gt;On this occasion, the team was in the midst of a recurring production difficulty, and had been gathered into the &lt;span class="caps"&gt;CIO&lt;/span&gt;&amp;#8217;s office to work through a top-20 list of problems to solve.&lt;/p&gt;


	&lt;p&gt;&amp;#8220;Your attitude has been affecting other departments&amp;#8221;, he said. &amp;#8220;And I want to thank you for it.&amp;#8221;&lt;/p&gt;</description>
      <pubDate>Sat, 05 Apr 2008 21:17:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:293e08d9-74d8-475a-b2aa-a66c2c1a1436</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/04/05/your-attitude-is-affecting-other-departments</link>
      <category>Tim's Tepid Torrent</category>
      <category>Schuchert's Scattered Synapses </category>
      <category>XP</category>
      <category>transitions</category>
      <category>attitude</category>
    </item>
    <item>
      <title>Velocity is Just Capacity</title>
      <description>&lt;p&gt;I don&amp;#8217;t know why, but somehow &lt;i&gt;velocity&lt;/i&gt; as a term really bothers me.&lt;/p&gt;


	&lt;p&gt;We always want higher velocity, and that&amp;#8217;s a good thing.  But with the term velocity, we think that we can create velocity with greater pressure (thrust?).  Doesn&amp;#8217;t it make sense that with a really hard push you can get greater velocity?&lt;/p&gt;


	&lt;p&gt;I guess I get hung up on words.  Essentially, &amp;#8220;velocity&amp;#8221; is fine.  It is the rate at which we&amp;#8217;re &amp;#8220;burning through&amp;#8221; our stories.  We use &amp;#8220;yesterday&amp;#8217;s weather&amp;#8221; to set our level, and we are always seeking any sustainable way to increase our velocity.  Why would we produce only 12 points when we could produce 20?  As motivated developers, we aren&amp;#8217;t yearning to accomplish less. But somehow this doesn&amp;#8217;t tell the right story.&lt;/p&gt;


	&lt;p&gt;When our velocity is decreased, it always seems like a tragedy.  We have all felt it when our 23-point iteration is followed by a 21-point iteration.  We can justify it a lot of different ways, but it always feels tragic.  Worse, hitting any kind of plateau seems frustrating.&lt;/p&gt;


	&lt;p&gt;You increase &lt;i&gt;velocity&lt;/i&gt; by pushing harder. If you push harder, and the numbers come up, then you&amp;#8217;ve successfully increased the velocity and that seems to be intuitively all there is to it.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve reflected about this for a few years before I realized that I really like the term &lt;i&gt;capacity&lt;/i&gt; much more.  It is also accurately describing the rate at which we can truly complete stories.  Since we use yesterday&amp;#8217;s weather, we can even use the term &amp;#8220;proven capacity&amp;#8221; to describe that we&amp;#8217;ve demonstrated the speed. But it also says some other things.&lt;/p&gt;


	&lt;p&gt;Intuitively it seems that we know that you don&amp;#8217;t push your people beyond their capacity to get work done.  Instead, you want to increase their capacity.  When we talk about longer hours, it is still obvious that working people harder diminishes their capacity.  Instead, we want to be working at capacity on the one hand, and increasing our capacity on the other.&lt;/p&gt;


	&lt;p&gt;Increasing the capacity sounds like the right problem.  To improve capacity, you want fresh workers working hard, pairing and communicating, building and/or using better tools (or using tools more capably), using more powerful hardware, learning, and performing the kind of housekeeping that keeps the team productive. Life balance enters into it.  Sufficient team size enters into it so you&amp;#8217;re not so small you&amp;#8217;re short-handed, yet not so plentiful you trip over each other.&lt;/p&gt;


	&lt;p&gt;I don&amp;#8217;t suppose that anyone is going to rename standardized eXtreme Programming terms like &amp;#8220;velocity&amp;#8221; just because some guy from Indiana says to, but I wonder if maybe we can&amp;#8217;t rephrase the problem in such a way that we are intuitively driven toward more reasonable solutions.  Maybe we should explain that velocity is just capacity, and then work from that point onward.&lt;/p&gt;</description>
      <pubDate>Wed, 02 Apr 2008 19:23:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:e325ba21-c7f5-4973-a85f-517ba5c697e1</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/04/02/velocity-is-just-capacity</link>
      <category>Tim's Tepid Torrent</category>
      <category>Velocity</category>
      <category>capacity</category>
      <category>agility</category>
      <category>XP</category>
      <category>balance</category>
      <category>humanity</category>
    </item>
    <item>
      <title>Musing over Mutation</title>
      <description>&lt;p&gt;I read a mailing list entry in which one fellow (who? I can&amp;#8217;t remember!) asked another &lt;i&gt;&amp;#8220;Do you want to get better at what you&amp;#8217;re doing, or find a better way to get the results you want?&amp;#8221;&lt;/i&gt;&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m a sucker for a good one-liner.  That one had me thinking, and as I&amp;#8217;ve had other conversations about innovation, I keep coming back to that line.&lt;/p&gt;


	&lt;p&gt;In our Agile practices, we work really hard for a week or two, and then hold a retrospective.  The purpose of the retrospective is to find ways to work more effectively for the next two weeks. As we develop better software, we also evolve a better team.  We use &amp;#8220;tricks&amp;#8221; such as tracking our velocity and recording blockages on our &amp;#8216;waste snake&amp;#8217; to provide data for our decisions, and we use gut feel to evaluate those things that feel like collateral effort to us.&lt;/p&gt;


	&lt;p&gt;If the practice works, we will see incremental improvement in the team.  We will develop ways of avoiding special variations, and we will learn to accept our normal variations. It will make us better at the way we do things now.&lt;/p&gt;


	&lt;p&gt;XP didn&amp;#8217;t come from a series of incremental improvements to the waterfall technology.  I wasn&amp;#8217;t there when it happened, but it seems that they took on an change in axioms.  They didn&amp;#8217;t strengthen the contracts between groups, but pulled all the decision-makers onto the same team.  They didn&amp;#8217;t find more careful ways to examine the code they were changing, but rather decided to lean radically on volumes of tests.  They didn&amp;#8217;t build practices to improve their anticipatory design, they decided instead not to anticipate at all and simplify their design to allow future change. At the time, this was radical stuff.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m sure there have been many other less-successful process mutations, but there is no evolution without mutation.&lt;/p&gt;


	&lt;p&gt;The man behind the iPod, iPhone, and MacBookPro has had some less-successful product ideas, too.  Some exciting high-concept products didn&amp;#8217;t make it in the wild. But then some new ideas become category killers.&lt;/p&gt;


	&lt;p&gt;How do we learn to make the axiomatic changes that lead us to radically better ways to get what we want?&lt;/p&gt;</description>
      <pubDate>Thu, 20 Mar 2008 22:25:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:aa6972db-849e-4c91-8a47-a2568b8173af</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/03/20/musing-over-mutation</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>TDD on Three Index Cards</title>
      <description>&lt;p&gt;I had the opportunity to talk to a fellow who missed part of a class on &lt;span class="caps"&gt;TDD&lt;/span&gt;. I told him that I could give him a 15-minute overview, and give him all the essentials of &lt;span class="caps"&gt;TDD&lt;/span&gt; on three index cards.&lt;/p&gt;


	&lt;p&gt;Yes, I know that volumes have been written about &lt;span class="caps"&gt;TDD&lt;/span&gt; and &lt;span class="caps"&gt;BDD&lt;/span&gt;, and that it&amp;#8217;s a large topic with many many branches of application, but I didn&amp;#8217;t have time for that. I had time for three index cards.  I figure that an index card is a token, and it represents a conversation, and that one can always dig deeper later.&lt;/p&gt;


	&lt;p&gt;They looked more or less like this:&lt;/p&gt;


&lt;hr&gt;
Card 1: Uncle Bob&amp;#8217;s Three Laws (Object Mentor)
&lt;ol&gt;
&lt;li&gt;Write no production code except to pass a failing test.&lt;/li&gt;
&lt;li&gt;Write only enough of a test to demonstrate a failure.&lt;/li&gt;
&lt;li&gt;Write only enough production code to pass the test.&lt;/li&gt;
&lt;/ol&gt;

&lt;hr&gt;
Card 2: &lt;span class="caps"&gt;FIRST&lt;/span&gt; Principles (Brett and Tim at Object Mentor)
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;F&lt;/i&gt;ast: Mind-numbingly fast, as in hundreds or thousands per second.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;I&lt;/i&gt;solated: The test isolates a fault clearly.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;R&lt;/i&gt;epeatable: I can run it repeatedly and it will pass or fail the same way each time.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;S&lt;/i&gt;elf-verifying: The test is unambiguously pass-fail.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;T&lt;/i&gt;imely: Produced in lockstep with tiny code changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;
Card 3: Flow (using the famous three-node circle diagram) &amp;#8211; origin unknown.
&lt;ul&gt;
&lt;li&gt;Red: test fails&lt;/li&gt;
&lt;li&gt;Green: test passes&lt;/li&gt;
&lt;li&gt;Refactor: clean code and tests&lt;/li&gt;
&lt;/ul&gt;

	&lt;p&gt;Sure there is plenty more, but I didn&amp;#8217;t know how I could provide significantly less. As is, I&amp;#8217;m pretty happy with the exercise. Now I am wondering if I couldn&amp;#8217;t produce most of the important information I wish to convey as a series of index cards. Would that be cool or what?&lt;/p&gt;</description>
      <pubDate>Thu, 06 Mar 2008 19:39:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:a7002e7d-5f30-481f-8792-20f01b2e731f</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/03/06/tdd-on-three-index-cards</link>
      <category>Tim's Tepid Torrent</category>
      <category>testing</category>
      <category>TDD</category>
      <category>three</category>
      <category>index</category>
      <category>cards</category>
      <category>reminders</category>
      <category>simplified</category>
    </item>
    <item>
      <title>Clues For Reading New Code</title>
      <description>&lt;p&gt;Okay, somebody just handed you a new chunk of code to work on.  Your first though on opening the file is &amp;#8220;Why, dear God, why?&amp;#8221;.  How do you get a handle on this masterpiece of clever programming?  Let&amp;#8217;s look for a few clues.&lt;/p&gt;


	&lt;p&gt;Where to start?&lt;/p&gt;


&lt;h2&gt;Documents&lt;/h2&gt;

	&lt;p&gt;Why not look at the documentation? &amp;lt;&lt;strong&gt;laughs&lt;/strong&gt;&amp;gt; Just kidding.  You know there&amp;#8217;s no documentation, and it&amp;#8217;s probably not useful.&lt;/p&gt;


&lt;h2&gt;People and Interactions&lt;/h2&gt;

	&lt;p&gt;You need a partner who is familiar with the code. Having a guide is better than having a map. Not only will you know where to go, but you&amp;#8217;ll know &amp;#8217;&amp;#8217;how&amp;#8217;&amp;#8217; to go and where not to step. Other people are a wonderful resource. Just don&amp;#8217;t settle for someone doing the work in front of you&amp;#8230; the goal is to learn as much as to do.&lt;/p&gt;


&lt;h2&gt;No, really, documents!&lt;/h2&gt;

	&lt;p&gt;&lt;span class="caps"&gt;OTOH&lt;/span&gt;, if you have somethng in the way of a summary or architectural overview, that might help. I&amp;#8217;d read the abstract and look at the pictures.  We&amp;#8217;re after big-picture, so &lt;strong&gt;read&lt;/strong&gt; it only, don&amp;#8217;t &lt;strong&gt;trust&lt;/strong&gt; it. Documents are seldom accurate, and seldom for long.  It might be good preparation for your partner&amp;#8217;s visit.&lt;/p&gt;


&lt;h2&gt;Use The Tests, Luke&lt;/h2&gt;

	&lt;p&gt;Do you have tests?  If you are in a test-driven shop, looking at unit tests is a good idea. If they&amp;#8217;re written well, they are specifications (by example) of the system.  If they&amp;#8217;re written poorly, you know where to start your work at least. Your partner could do a great service by helping clean up the code instead of explaining it.&lt;/p&gt;


	&lt;p&gt;No tests? Uh, oh.  No tests &lt;strong&gt;and&lt;/strong&gt; no doc?  Now you&amp;#8217;re in trouble.&lt;/p&gt;


&lt;h2&gt;Scan the File Space&lt;/h2&gt;

	&lt;p&gt;Are the classes well-named? Do you know where to begin working? If you can find code by looking at file names then you&amp;#8217;ve got the handle you need.  Your partner can help improve file naming if you find the code you&amp;#8217;ve been handed is in ill-named files.&lt;/p&gt;


	&lt;p&gt;So you&amp;#8217;re in a file, you have a mission.  Either you have tests, or you&amp;#8217;re ready to write some.&lt;/p&gt;


&lt;h2&gt;Sense Of Smell&lt;/h2&gt;

	&lt;p&gt;What if the code is still not obvious?  You have one more resource before you have to print out the listing and break out the markers to reverse-engineer your way out of code hell.  You have your nose and your refactoring editor.  You can use refactorings such as &amp;#8216;rename&amp;#8217;, &amp;#8216;extract method&amp;#8217;, and &amp;#8216;introduce variable&amp;#8217; to clarify an existing method. You can spot duplication and eliminate it.  Maybe you can bring it to a point of clarity, and then you will know&lt;/p&gt;


&lt;h2&gt;Deep Code Spelunking&lt;/h2&gt;

	&lt;p&gt;It&amp;#8217;s time to pour a really big cup of tea, get some food, take a couple of preemptive aspirin, and make sure your printer has paper.&lt;/p&gt;


	&lt;p&gt;Sometimes, you will have to reverse-engineer some of the code you were handed. Your only hope may be to rebuild it from the inside-out.&lt;/p&gt;


	&lt;p&gt;You might want to either copy the code to a scratch space to do this.  Maybe you want to branch the project in version control.  You want to be free to dig in an learn this the hard way, and make it better as you emerge from the depths.&lt;/p&gt;


	&lt;p&gt;You still can/must use refactoring tricks to capture the knowledge you gain, but you may need to take the code off line. And look for new partners.&lt;/p&gt;</description>
      <pubDate>Wed, 05 Mar 2008 19:27:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:5a6bcbe7-686d-4cf3-8b45-6eb95e45c65e</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/03/05/clues-for-reading-new-code</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Turn Back The Dial</title>
      <description>&lt;p&gt;The coolest thing just happened! I broke the glass cover off of my watch.  At first I thought it was awful, but then I realized that I could turn the hands.&lt;/p&gt;


	&lt;p&gt;Imagine my joy as I realized that I could make it 11:30 again, and go enjoy another lunch.  Meeting at 3:30? No problem, just turn the hour hand up to 6:00 and go home! I can sleep as long as I want as long as I turn it back to 8:00 when I get to the office. All my work estimates are now &amp;#8220;five minutes&amp;#8221;, and I complete them every time.&lt;/p&gt;


	&lt;p&gt;My coworkers have no idea the awesome power that I&amp;#8217;ve gained with this one happy accident.  They ask &amp;#8220;what time is it?&amp;#8221; and I say &amp;#8220;what time would you like it to be.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Of course the above is a total fabrication. Pretending it&amp;#8217;s 6:00pm when it&amp;#8217;s 8:00am isn&amp;#8217;t going to do anybody any good at all, and is likely to make a mess of things for me.&lt;/p&gt;


	&lt;p&gt;But people still try to mandate velocity.&lt;/p&gt;</description>
      <pubDate>Wed, 05 Mar 2008 19:16:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:3dc25ff8-864f-4286-bafb-0fa71c9895cf</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2008/03/05/turn-back-the-dial</link>
      <category>Tim's Tepid Torrent</category>
      <category>Velocity</category>
      <category>agile</category>
      <category>measurement</category>
      <category>metrics</category>
    </item>
    <item>
      <title>Shoveling Code</title>
      <description>&lt;p&gt;I was ill when the first snow fell last weekend, and didn&amp;#8217;t get out and scrape the drive and sidewalks.  Sadly, neither did I bundle up my kids and send them out with shovels.  As a result, the snow melted and refroze.  When I left home on sunday morning, clearing the snow was frustrated by the presence of hard, packed ice under the snow.&lt;/p&gt;


	&lt;p&gt;Now I have to be very careful when moving in the drive or sidewalk because of the black ice in some places and thick lumpy stuff in others.  I could choose to leave it that way and just walk carefully and try to avoid the area, but I really don&amp;#8217;t want it to be like this all winter.&lt;/p&gt;


	&lt;p&gt;Instead, I bundled up and spent several painful hours trying to clear not only the six to eight inches of new snow, but the ice under it.  Clearing the fresh stuff is tough because the rough and lumpy ice is under it.  The ice snags the shovel and hurts my elbows and shoulders.  I use the metal edge of the shovel to plane off the ice so that it&amp;#8217;s not quite so difficult, and the work gets a little easier.&lt;/p&gt;


	&lt;p&gt;Smooth, planed ice is not a solution.  It is actually going to be more slippery and dangerous when the sun hits it and it melts a little.  It will then refreeze to an even smoother and slicker sheen.  I can&amp;#8217;t ignore the problem, and I can&amp;#8217;t smooth it over and leave it at that.&lt;/p&gt;


	&lt;p&gt;I invested in some complicated salt product to lower the melting point of the ice so I can scrape it away.  It wasn&amp;#8217;t enough, but now there are some safe areas in my driveway.  I continue to scrape it and hope that I can get it all squared away so that my wife and kids have safe passage, though it is tedious and unpleasant work.&lt;/p&gt;


	&lt;p&gt;Yes, it&amp;#8217;s my fault.  I should have bundled up my sick self or my children and taken care of this when the first snow fell, back when it was easy.&lt;/p&gt;


	&lt;p&gt;Then it dawned on me that my driveway is a lot like source code.  If I always take care of it when it&amp;#8217;s relatively easy and not too polluted, it will remain easier to deal with in the longer term.  The more unsafe and ugly it is, the more important it is to clean it up.  It won&amp;#8217;t do to smooth it out a little or to leave it be.  It needs to be safe for me and my team.&lt;/p&gt;


	&lt;p&gt;And I guess that&amp;#8217;s my parable for today.&lt;/p&gt;</description>
      <pubDate>Thu, 06 Dec 2007 12:56:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:ae89090e-70ae-4a59-b25b-befd7ecb2a18</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/12/06/shoveling-code</link>
      <category>Tim's Tepid Torrent</category>
      <category>snow</category>
      <category>code</category>
      <category>cleaning</category>
      <category>smoothing</category>
      <category>avoid</category>
      <category>trouble</category>
      <category>parable</category>
      <category>ottinger</category>
    </item>
    <item>
      <title>Naming: A Word To The Wise</title>
      <description>&lt;p&gt;Please pronounce your variable names as words, even if they are merely abbreviations.  The phonemes indicated by your spelling may correspond to an existing word with an entrenched meaning. It may be one that you do not intend to communicate.&lt;/p&gt;</description>
      <pubDate>Tue, 27 Nov 2007 20:50:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:b90134fd-a901-4af6-91b0-6c4e65e4b5b6</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/11/27/naming-a-word-to-the-wise</link>
      <category>Tim's Tepid Torrent</category>
      <category>naming</category>
      <category>clever</category>
      <category>clear</category>
      <category>code</category>
      <category>style</category>
    </item>
    <item>
      <title>On Being Stupid</title>
      <description>&lt;blockquote&gt;
This was posted originally to a mailing list, but is reproduced here essentially unchanged by request of a friend. 
&lt;/blockquote&gt;

	&lt;p&gt;I frequently see code (written by others) that is completely
double-spaced, heavily commented, loaded with many abbreviated or meaningless variable names, and hundreds of lines long.
In order to read the function and understand what it&amp;#8217;s doing, poor Tim
must wear out a mouse, skip comments, and track the variables on
paper.  A &amp;#8220;smarter&amp;#8221; programmer could just load it into his head, I
suppose, but not the simpleton who writes this email.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m not smart enough to just read it from top to bottom and
understand it. Sadly, when I read through and understand what in the
heck the thxIniFvt variable is doing, I will forget it by the time I
figure out the purpose(es) of pszVbt.  I can spend all day, or even a
few days to figure out a method, and that&amp;#8217;s an admission of
feeble-mindedness to be sure.  I guess I&amp;#8217;m not up to the level of some
of the rapid hackers. That&amp;#8217;s a limitation I face most days.&lt;/p&gt;


	&lt;p&gt;I find that I can sometimes understand a method like that only  if I just delete all the blank lines and comments first, then reformat to break lines, then inline all methods with seven or more parameters, and then start renaming variables, extracting explanatory variables, and
extracting explanatory methods. I may have to break the method into
classes even.   I guess I&amp;#8217;m not one of the smart kids.&lt;/p&gt;


	&lt;p&gt;I used to be one of the smart kids.  I once built a module so complex and fragile that nobody but me could figure out what to do with it.  It was all tables and indicators, and stunningly clever.  I am so ashamed that I wrote it. It was such a mistake that they eventually disabled it rather than field it in such a state. That was years ago, but so memorable to me. Other programmers said it was like the inside of a swiss watch, all
delicate and perfectly balanced, and scary to mess with unless you first knew exactly what each part was doing, and why.&lt;/p&gt;


	&lt;p&gt;I would like to be faster than I am both mentally and in the sense
of quickly producing code. I&amp;#8217;d like to be a little less intimidated at
the start of a project. .But I would not want those things if it meant
building crap that people who are not appreciably more talented than
myself would trip over every day.  Instead, I sometimes wish I could
teach the really fast, smart kids how to dumb down the code for the
rest of us morons to read.&lt;/p&gt;


	&lt;p&gt;The funny thing is that dumbing code to my level doesn&amp;#8217;t make it
harder for the smart kids to use it, and sometimes allows a compiler
to do a better job with it.  I guess stupid isn&amp;#8217;t so stupid after all.&lt;/p&gt;</description>
      <pubDate>Mon, 10 Sep 2007 10:16:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0b06c5f0-9426-40f9-add4-95c9b20a56ac</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/09/10/on-being-stupid</link>
      <category>Tim's Tepid Torrent</category>
      <category>naming</category>
      <category>dumb</category>
      <category>moron</category>
      <category>clever</category>
      <category>refactoring</category>
      <category>comments</category>
      <category>coding</category>
      <category>Fast</category>
      <category>whitespace</category>
      <category>dumbing</category>
      <category>down</category>
      <category>code</category>
    </item>
    <item>
      <title>Not A Task, But An Approach</title>
      <description>&lt;p&gt;Transitions are tough. It seems that lately I&amp;#8217;ve been getting a lot of contact from frustrated people who don&amp;#8217;t really have a good handle on the &amp;#8220;drive&amp;#8221; part of Test Driven Development.  A question heard frequently is: &amp;#8220;I&amp;#8217;ve almost completed the coding, can you help me write the &lt;span class="caps"&gt;TDD&lt;/span&gt;?&amp;#8221;&lt;/p&gt;


	&lt;p&gt;It seems like Test Driven Development is taken backward, that the &lt;em&gt;developers&lt;/em&gt; are &lt;em&gt;driven&lt;/em&gt; to write &lt;em&gt;tests&lt;/em&gt;.  The practitioner winces, realizing that he again faces The Great Misunderstanding of &lt;span class="caps"&gt;TDD&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt; stands for Test-Driven Development, which is not as clear as &lt;span class="caps"&gt;TFD&lt;/span&gt; (Test-First Development). If the consultant would strive to always say the word &amp;#8220;first&amp;#8221; in association with testing, most people would more surely grasp the idea.  In fact, I&amp;#8217;ve begun an experiment in which I will not say the word &amp;#8220;test&amp;#8221; without the word &amp;#8220;first&amp;#8221; in close approximation. I&amp;#8217;ll let you know how that works out for me.&lt;/p&gt;


	&lt;p&gt;If the tests are providing nothing more than reassurance on the tail end of a coding phase, then the tests aren&amp;#8217;t driving the development.  They are like &lt;em&gt;riders&lt;/em&gt; instead of &lt;em&gt;drivers&lt;/em&gt;.  Test-Ridden Development (TRD)[1] would be a better term for such a plan. Even though it is better to have those tail-end tests than to have no automated testing, it misses the point and could not be reasonably be called &lt;span class="caps"&gt;TDD&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;An old mantra for &lt;span class="caps"&gt;TDD&lt;/span&gt; and &lt;span class="caps"&gt;BDD&lt;/span&gt; is &amp;#8220;it&amp;#8217;s not about testing&amp;#8221;. The term &lt;span class="caps"&gt;BDD&lt;/span&gt; was invented largely to get the idea of &amp;#8220;testing&amp;#8221; out of the way.  People tend to associate &amp;#8220;test&amp;#8221; as a release-preparation activity rather than an active approach to programming. &lt;span class="caps"&gt;BDD&lt;/span&gt; alleviates some of that cognitive dissonance.&lt;/p&gt;


	&lt;p&gt;In &lt;span class="caps"&gt;TDD&lt;/span&gt;, tests come first. Each unit test is written as it is needed by the programmer.  Tests are just-in-time and are active in shaping the code. Acceptance Tests likewise tend to precede programming by some short span of time.  [2]&lt;/p&gt;


Through months of repetition I have developed the mantra:
&lt;blockquote&gt;
&lt;span class="caps"&gt;TDD&lt;/span&gt; isn&amp;#8217;t a task. It is not something you do.  It is an approach.  It is how you write your programs.
&lt;/blockquote&gt;

	&lt;p&gt;I wonder if we shouldn&amp;#8217;t resurrect the term Test-First Programming or Test-First Development for simple evocative power. Admittedly there are some who would see that as a phase ordering, but maybe enough people would get the right idea.&lt;/p&gt;


	&lt;p&gt;Brett Schuchert(with some trivial aid from your humble blogger) has worked up an acronym to help socialize the basic concepts which are somehow being lost in translation to the corporate workplace.&lt;/p&gt;


	&lt;p&gt;The teaser:
    Fast, Isolated, Repeatable, Self-validating, and Timely.&lt;/p&gt;


	&lt;p&gt;As a reader of this blog, you are probably very familiar with all of the terminology and concepts behind &lt;span class="caps"&gt;TDD&lt;/span&gt;. I beg of you, socialize the idea that testing comes first and drives the shape of the code.  If we can just get this one simple idea spread into programming dens across our small spheres of influence, then we will have won a very great victory over Test-Ridden Development.&lt;/p&gt;


	&lt;p&gt;&amp;#8220;And there was much rejoicing.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;&lt;small&gt;
1 Jeff Langr will refer to this &lt;span class="caps"&gt;TRD&lt;/span&gt; concept as &amp;#8220;Test-After-Development&amp;#8221;, which he follows with a chuckle and a twinkle, &amp;#8220;which is a &lt;span class="caps"&gt;TAD&lt;/span&gt; too late.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;2 Of course, one still needs QC testing as well, however &lt;span class="caps"&gt;TDD&lt;/span&gt; is about driving development, not testing its quality post-facto.
&lt;/small&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 02 Aug 2007 22:14:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:bd848598-96fa-4e15-84e8-ccba83ab4325</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/08/02/not-a-task-but-an-approach</link>
      <category>Tim's Tepid Torrent</category>
      <category>FIRST</category>
      <category>testing</category>
      <category>mentoring</category>
      <category>TDD</category>
      <category>TRD</category>
      <category>TAD</category>
      <category>Fast</category>
      <category>Isolated</category>
      <category>Repeatable</category>
      <category>Self</category>
      <category>validating</category>
      <category>Timely</category>
    </item>
    <item>
      <title>Tuple Madness and STL in C++</title>
      <description>&lt;p&gt;I have already complained about &lt;a href="http://blog.objectmentor.com/articles/2007/02/13/tuple-madness"&gt;Tuple Madness&lt;/a&gt; with reference to Python and Ruby, and UncleBob has seen &lt;a href="http://butunclebob.com/ArticleS.UncleBob.RubarianNotation"&gt;the same problem&lt;/a&gt; and noted it on the old blog. I have come to realize that the same problems appear in modern C++ code.&lt;/p&gt;


	&lt;p&gt;I have always looked at the &lt;span class="caps"&gt;STL&lt;/span&gt; as a way of implementing a class, but never as a replacement for &amp;#8220;real&amp;#8221; classes with named member values.  In some ways, I think that templates have made our C++ code worse.&lt;/p&gt;


For instance, I need a two-member structure. Say I am going to store Name and Address.  Now, those with C background would immediately think along these lines:
&lt;pre&gt;
    struct name_and_address { char name[34]; struct address address; };
    struct name_and_address get_name_and_address(void);
    // blah blah blah

    struct name_and_address x = get_name_and_address();
    printf("%s", x.name );
    printf("%s", x.address.line1);
    // ... and so on...
    printf("%05d", x.address.zip);
&lt;/pre&gt;

	&lt;p&gt;Got to love those old C programmers. There is a nice, primitive struct, maybe with a nice, primitive struct embedded in it.  Look at the &lt;a href="http://tottinge.blogsome.com/meaningfulnames/"&gt;clear names of those variables&lt;/a&gt;.  It is even pretty efficient to copy these things. With a Plain Old Data Object, the compiler knows what you&amp;#8217;re doing and can do block copies instead of memberwise copies. That can be very efficient, enough that you can often pass structures around by value instead of by reference. That&amp;#8217;s kinda cool. That same efficiency also applies to plain old data classes in C++, but a lot of people don&amp;#8217;t know it.&lt;/p&gt;


	&lt;p&gt;Sadly, a modern C++ developer does what? Yeah, he returns a pair.  This is annoying because when I call my function, I have to know that the name is now called &amp;#8220;first&amp;#8221; and the address is called &amp;#8220;second&amp;#8221;.  But that is only for &lt;em&gt;this&lt;/em&gt; pair-returning function.  In another pair-returning function, &amp;#8220;first&amp;#8221; means birthday and &amp;#8220;second&amp;#8221; is account number.   Of course the prototype is not always in view, so I have to have more tiles in my window to check my work as I code.&lt;/p&gt;


	&lt;p&gt;Pair is named well enough for an arbitrary pair of primitive values, but frankly it makes no sense for x,y coordinates or names and address, or for the rolls of two twenty-sided dice.  Wait.  For the dice, it works just fine.  After all, what would you call them? Dice1 and Dice2?  But I digress.  The point is that for most two-member structures, a two-member structure with named members is probably a better choice.&lt;/p&gt;


Now pair is not alone (oh look, a pun). Even when we are dealing with collections, the interface to a vector, map, or set is unlikely to be the right set of names and semantics for our problem domain objects.  Maybe our property should be listed, and not push_back()-ed.  Maybe we care about a policy, that:
&lt;pre&gt;
        policy.covers(theCar)
&lt;/pre&gt;
Maybe we&amp;#8217;re not so interested in whether list&lt;Insurable&gt; x will:
&lt;pre&gt;
        x.find(z.first) != x.end()
&lt;/pre&gt;

	&lt;p&gt;The fascination with exposing &lt;span class="caps"&gt;STL&lt;/span&gt; containers (combined with unfortunate naming, as given here for effect) is hurting readability. It also is a very unfortunate form of &lt;a href="http://sis36.berkeley.edu/projects/streek/agile/bad-smells-in-code.html#Primitive+Obsession"&gt;primitive obsession&lt;/a&gt; and a violation of the &lt;a href="http://www.google.com/url?sa=t&amp;#38;ct=res&amp;#38;cd=1&amp;#38;url=http%3A%2F%2Fwww.objectmentor.com%2Fresources%2Farticles%2Fdip.pdf&amp;#38;ei=LDGgRr-EDIySgATvodT5DQ&amp;#38;usg=AFQjCNEpBGziZw6APHj0rMG9pp1LJt9FHA&amp;#38;sig2=39HJU1Vlx6jAawt9cM-0zw"&gt;Dependency Inversion Principle.&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;The people who work on your code with you should not have to &lt;em&gt;reverse&lt;/em&gt; &lt;em&gt;engineer&lt;/em&gt; your work in order to add new features or correct  bugs.  The code should be written so clearly that mistaken assumptions will be more obvious. They should not have to chase down typedefs and keep notes on paper to keep track of your structures. They should especially not have to look for data in obliquely named pairs of pairs (x.second.first means &amp;#8220;price&amp;#8221;? Or was that x.first.second? Or&amp;#8230;).&lt;/p&gt;


	&lt;p&gt;If you write your code with a pair programming partner, you should get plenty of feedback about the readability of your code.  Even if you do not work in pairs, you should read your tests when you get back from lunch or a meeting, and you should see if primitive containers, primitive member functions,  and template syntax are obscuring their purpose.  If your tests don&amp;#8217;t speak clearly, then none of the other users of your class can speak clearly.  Get the syntax out of their way by giving them reasonable wrapper functions.&lt;/p&gt;


	&lt;p&gt;You might think that wrapping your containers will cost you performance by adding dispatch here and there, but you might be surprised to find out that not wrapping it may cost you far more by concealing bugs and obscuring functionality than it ever save you in performance. A better policy is to keep your code obvious and simple, and try a little profiling and optimization where it really matters.&lt;/p&gt;


	&lt;p&gt;Of course, if one was worried about the cost of one dispatch for a named method v. an exposed container, there is always the option to build an inline member function in the header.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m mindful that this is not the time for me to rant about C++ programmers who never profile, and who manage performance by rule of thumb and old wives&amp;#8217; tales.  There are more of them than us, my dear reader, and I fear their wrath.  Maybe some day later, when I&amp;#8217;m feeling brave.&lt;/p&gt;


	&lt;p&gt;My roots run pretty deep into C++, and I appreciate how hard it is to produce a system.  I just want the guys who are now running with the ball right now to realize that it is far more valuable to be clear and obvious than they appreciate, and it is far less expensive to do so than they fear.&lt;/p&gt;


	&lt;p&gt;I guess the points are:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Don&amp;#8217;t be afraid to write small classes and structs.&lt;/li&gt;
		&lt;li&gt;Don&amp;#8217;t be afraid to wrap your containers.&lt;/li&gt;
		&lt;li&gt;Don&amp;#8217;t be afraid to use abstraction.&lt;/li&gt;
		&lt;li&gt;Everything does not have to be written in templates.  &lt;/li&gt;
		&lt;li&gt;Be afraid to write test code that doesn&amp;#8217;t tell a story.&lt;/li&gt;
		&lt;li&gt;Be afraid to give too much access to your data by exposing containers.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Adjust your values accordingly.&lt;/p&gt;</description>
      <pubDate>Thu, 19 Jul 2007 22:21:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ceb08ca2-cc05-4ebb-b74d-d0be19b32d26</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/07/19/tuple-madness-and-stl-in-c</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Testing Will Challenge Your Conventions</title>
      <description>&lt;p&gt;If you are doing test-first development, you are likely to find your old coding conventions are no longer valid.  There are a few changes you will need to make to your coding standards and practices.&lt;/p&gt;


	&lt;p&gt;1. Interfaces suddenly seem like a really good idea when you have to start introducing test doubles of various flavors (mocks, etc).  You will find yourself creating interfaces in places where you probably would not have created them before.  You&amp;#8217;ve always known that you shouldn&amp;#8217;t depend or derive from concrete classes, and now you are feeling the pain of non-trivial concrete classes. You are forced, more or less, to comply with the Dependency Inversion Principle. Abstraction becomes a way of life.&lt;/p&gt;


	&lt;p&gt;2. Singletons and static methods no longer seem like a great way to do work (esp in C++) because you can&amp;#8217;t easily isolate a module that makes use of them.  The exception is when a static method is totally self-contained and testable, and does not use resources like a database, file system, etc. Only the very trivial can be static. Test doubles matter that much. Suddenly substitutability is a primary measure of code goodness.&lt;/p&gt;


	&lt;p&gt;3. Private makes less sense than it used to.  You can&amp;#8217;t test anything that&amp;#8217;s private.  You need to have ways to sense that your tests are working as intended, and you have to be able to test any method that is interesting. That means less private and more accessors.  Get used to living in a more public world.  If you need to hide something from users, don&amp;#8217;t include it in the interface or abstract base class. &amp;#8220;Implements&amp;#8221;/&amp;#8221;public inheritance&amp;#8221; is the new &amp;#8220;private&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;4. You need to be able to pass a class everything it might need at construction time, so that you can pack it a stubbed logger and a faked database access  module. Otherwise, you will not have the isolation you need to write good unit tests. Calling a concrete class constructor inside the body of a method now makes you cringe, because you realize you&amp;#8217;ve missed an opportunity for abstraction, and limited the isolation of your method.   The fat constructor argument list is a concession to the need for isolation and testing with mocks (and fakes, and stubs).&lt;/p&gt;


	&lt;p&gt;5. Smaller methods are the norm. It is hard to test a two-hundred line method.  It&amp;#8217;s far harder than testing a many smaller, equivalent methods. Whatever is easier to test is easier to write. Large is bad. This has always been so, since optimizers love simple functions, but now it&amp;#8217;s real to you as well.&lt;/p&gt;


	&lt;p&gt;6. You hate inheriting code without tests, because you don&amp;#8217;t want to reverse-engineer what the other programmer was thinking.  In fact, you find yourself looking at tests before you look at code, because you know the tests are better than comments. Testing becomes a kind of &amp;#8220;code clarity&amp;#8221; mechanism.  The profound bit is that code is more clear if it is more testable, even if you have to &amp;#8220;pollute&amp;#8221; the class to make it testable by moving variables and methods out of the private space or by creating interfaces, or by using fat constructor argument lists.  Testability is the new legibility.&lt;/p&gt;


	&lt;p&gt;7. Hard-to-use class interfaces are now hard for you to use, not just hard for other people. You have to write the tests, so you have to use the class. Usability determines how much you will like your own code, not cleverness.&lt;/p&gt;


	&lt;p&gt;8. Performance management by old wives tales is dead.  You will build for testability, and then use measurement tools to improve performance.  This is what the wizened greybeards have been telling us for a lot of years, and with &lt;span class="caps"&gt;TDD&lt;/span&gt; you start listening.  You stop avoiding trivial issues like copying &lt;span class="caps"&gt;PODS&lt;/span&gt; and virtual dispatches.  You pay attention to more important issues.  With optimization, &lt;span class="caps"&gt;YAGNI&lt;/span&gt; applies until it doesn&amp;#8217;t, and when it doesn&amp;#8217;t you need to know why and where.&lt;/p&gt;


	&lt;p&gt;9. You care deeply how long it takes to run the tests because you need to be able to run all of the tests all the time, after only a few lines of code are written, and after each refactoring.  If it&amp;#8217;s taking more than 20 or 30 seconds to run all your unit tests, you start looking for ways to speed it up.  You must maintain test performance, because it is key to productivity.&lt;/p&gt;


	&lt;p&gt;10. Dependency hurts.  You can&amp;#8217;t afford &amp;#8216;god classes&amp;#8217; and &amp;#8216;global hubs&amp;#8217;.  If test setup becomes a chore, you immediately start reaching for the axe.  You have to keep your modules isolated better than ever before.  Of course, you should have done this all along, but you never felt it this keenly.&lt;/p&gt;


	&lt;p&gt;11. &amp;#8220;Clever&amp;#8221; is dead. Clever is hard to refactor. Clever is hard to isolate, hard to internalize, hard to phrase in tests.  One point of &amp;#8220;obvious&amp;#8221; is worth two hundred points of &amp;#8220;clever&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;12. Your &lt;span class="caps"&gt;IDE&lt;/span&gt; is good to the extent that it allows you to do quick write/build/test cycles.  You need to do several per minute.&lt;/p&gt;


	&lt;p&gt;For the most part, &lt;span class="caps"&gt;TDD&lt;/span&gt; forces you to start doing the things you always should have done, though it signals a change in values that should be reflected in your coding standards.&lt;/p&gt;


	&lt;p&gt;Maybe you should get a highlighter and mark each section of your coding standard  or architectural document that encourages any practice that in turn discourages testability.  The world has changed, values have shifted,  and your style guide needs to change if it is to remain relevant.&lt;/p&gt;</description>
      <pubDate>Tue, 17 Jul 2007 22:28:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:b84c2373-e256-429f-a7c2-2e16528c9d81</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/07/17/testing-will-challenge-your-conventions</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>What I Don't Like About Python</title>
      <description>&lt;p&gt;I love &lt;a href="http//python.org"&gt;python&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I love the simplicity, the nice data types, the strong dynamic typing, the significant indentation, the runtime flexibility, the list comps, the generators, they way that I can get work done in Python. I love the built-in help. I dig the Tao of Python.&lt;/p&gt;


	&lt;p&gt;There are still a few bits that seem artificial and clumsy.  I was told that you don&amp;#8217;t really know a language if there are not five things you hate about it. I have more than five, but these will do for now:&lt;/p&gt;


&lt;ol&gt;
&lt;li&gt;&lt;b&gt;&lt;dir&lt;/b&gt; Dir is not a very good name for the method that dumps the contents of an object.  I don&amp;#8217;t like the ruby alternative, where methods and members are separate, but I just don&amp;#8217;t like the naming here. A change would be possible. It would have to be grandfathered in, but it could happen.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;double-underscores&lt;/b&gt; annoy me.  I would like to see some other way of denoting operators and other magic functions. I suppose one could grandfather-in a decorator-based trick for defining operators. It would be a real compatibility breaker, but I really feel that &amp;#95;&amp;#95;getitem&amp;#95;&amp;#95; is probably not the best naming our guys could come up with.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;#95;&amp;#95;name&amp;#95;&amp;#95;&lt;/b&gt; has always felt like a hack to me. Try explaining it to a novice programmer, or worse to someone who programs in perl or ruby or java for a living.  Comparing the magic variable &amp;#95;&amp;#95;name&amp;#95;&amp;#95; to the magic constant &amp;#8221;&amp;#95;&amp;#95;main&amp;#95;&amp;#95;&amp;#8221; feels doubly so.  I would rather have a convention such as naming a method &amp;#8220;main&amp;#8221; or maybe decorating with @script_main now that we have decorators.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Blocks&lt;/b&gt; give me of ruby envy or smalltalk envy.  I like local functions. Love them.  I tolerate lambda.  But I really, really would like to see a more rubyesque iterator setup where we pass a callable to the list, and the callable can be defined free-form inline. Python doesn&amp;#8217;t really do that and so it&amp;#8217;s less of a language lab than I might like.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Properties&lt;/b&gt; are unattractive, partly because of blocks being absent.  I don&amp;#8217;t really want to define a named parameter (with double-underscores, most likely) and then two named functions, and &lt;span class="caps"&gt;THEN&lt;/span&gt; declare a property.  That seems like so much work for such a simple situation. It is something I will only do if all other methods fail me, or if all other methods are overriding &amp;#95;&amp;#95;setattr&amp;#95;&amp;#95; and &amp;#95;&amp;#95;getattr&amp;#95;&amp;#95;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Lack of recognition&lt;/b&gt; just kills me.  This is a wonderful little language with great libraries and tremendous capability.  Google, Eve, Nasa, a great many scientific efforts, a bunch of web sites, and a lot of Linux installers and configuration tools use python.  A number of very nice distributed version control tools are written in it. But still people seem to go deaf if anyone mentions python, as if we&amp;#8217;d mentioned &lt;span class="caps"&gt;JCL&lt;/span&gt; or something.  I don&amp;#8217;t get that.&lt;/li&gt;
&lt;li&gt;There is a very ugly &lt;b&gt;mutual-inclusion design bug bug&lt;/b&gt;. I spent time on it once and was very unhappy.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Self&lt;/b&gt; loathing takes over in my functions. I wish that I could refer to member variables without saying &amp;#8220;self.&amp;#8221; first. Testing would be easier if I could just import all my fixture variables into my local namespace&amp;#8212;or better if it were done for me automagically.  Typing &amp;#8220;self.&amp;#8221; doesn&amp;#8217;t kill me, but it doesn&amp;#8217;t help me.  Yes, I have an abbreviation in my editor, but it still bugs me.&lt;/li&gt;
&lt;/ol&gt;

	&lt;p&gt;Don&amp;#8217;t put me down as a complainer.  I really, really love working in python. But  There&amp;#8217;s a lot more love than hate here.&lt;/p&gt;


	&lt;p&gt;PS: Is it uncommonly sensible that &amp;#8220;not&amp;#8221; is spelled &amp;#8220;not&amp;#8221;, &amp;#8220;and&amp;#8221; is spelled &amp;#8220;and&amp;#8221; and &amp;#8220;or&amp;#8221; is spelled &amp;#8220;or&amp;#8221;?  I think so.  &amp;#38;&amp;#38; I&amp;#8217;m ! just kidding || something.&lt;/p&gt;</description>
      <pubDate>Tue, 17 Jul 2007 21:41:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0709a2f0-37ac-4cec-b4ed-6b48b6098d9f</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/07/17/what-i-dont-like-about-python</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Dependency Broadcaster</title>
      <description>&lt;p&gt;I&amp;#8217;m not sure if there is already a code smell name for this situation. The idea is rather like &amp;#8220;Large Class&amp;#8221; or &amp;#8220;God Class&amp;#8221; but isn&amp;#8217;t really related to behaviour.  It&amp;#8217;s just a matter of dependency.&lt;/p&gt;


	&lt;p&gt;Michael Feathers refers to &amp;#8220;horrible include dependencies&amp;#8221;, and that&amp;#8217;s the right idea.&lt;/p&gt;


	&lt;p&gt;So what if you have a class file that includes (or forward-declares) a few hundred other classes, and that class is used by almost every other class in the system?&lt;/p&gt;


	&lt;p&gt;This is perhaps what comes from writing a very class-rich architectural layer as a single class.&lt;/p&gt;


	&lt;p&gt;Mainly the idea is that the class takes a lot of ugly dependencies and spreads them evenly over the application.  I would call that &amp;#8220;broadcasting&amp;#8221; although the correct agrarian term is &amp;#8220;manure spreader.&amp;#8221;  I will stick with the less evocative &amp;#8220;dependency broadcaster.&amp;#8221;&lt;/p&gt;</description>
      <pubDate>Mon, 16 Jul 2007 20:34:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:6cf4342a-6506-4112-b624-995e27368fc4</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/07/16/dependency-broadcaster</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Use VIM to do TUT Unit Testing</title>
      <description>&lt;p&gt;I&amp;#8217;m not crazy about &lt;span class="caps"&gt;TUT&lt;/span&gt;, but a customer is using it on a project and wanted to get a little assist from &lt;span class="caps"&gt;VIM&lt;/span&gt;.  I don&amp;#8217;t blame him. It&amp;#8217;s a pain to keep track of your test number and there&amp;#8217;s always more testing that we&amp;#8217;d like in our test frameworks.&lt;/p&gt;


	&lt;p&gt;So I scribbled up a little &lt;span class="caps"&gt;VIM&lt;/span&gt; script to handle some of the light housekeeping.  It&amp;#8217;s not a wonderful script, and I&amp;#8217;m betting the readers can give me some pointers (I&amp;#8217;ve only written a few other vimscripts ever). I&amp;#8217;m sure that I could do better if I reflected and refactored, but I haven&amp;#8217;t yet.&lt;/p&gt;


	&lt;p&gt;Maybe you know a good way to unit test vim scripts?.&lt;/p&gt;


	&lt;p&gt;My script hijacks your F5 key. You can change that easily enough.  Maybe I should have mapped it to \nt for &amp;#8220;new test&amp;#8221; or something.  Anyway, enjoy and comment please:&lt;/p&gt;


&lt;pre&gt;

function! NewTutTest()
    let s:testNumber = 0
    let s:newNumber = 0
    " Seek a higher number
    let s:list = getline("1","$")
    for s:line in s:list
        if s:line =~ 'test&amp;lt;'
            let s:newNumber =  0 + matchstr(s:line, '\d\+')
            if s:newNumber &amp;gt; s:testNumber
                let s:testNumber = s:newNumber
            endif
        endif
    endfor

    "Increment (tests are 1..n)
    let s:testNumber = s:testNumber + 1

    "Output the test values
    let s:line = line(".")
    let s:indent = repeat(" ", &amp;#38;shiftwidth)
    let result = append(s:line, s:indent . "template&amp;lt;&amp;gt;")
    let s:line = s:line + 1
    let result = append(s:line, s:indent . "template&amp;lt;&amp;gt;")
    let s:line = s:line + 1
    let result = append(s:line, s:indent . "void object::test&amp;lt;" . s:testNumber . "&amp;gt;()")
    let s:line = s:line + 1
    let result = append(s:line, s:indent . "{" )
    let s:line = s:line + 1
    let result = append(s:line, repeat(s:indent,2) )
    let s:line = s:line + 1
    let result = append(s:line, s:indent . "}" )
    call cursor(s:line, (&amp;#38;shiftwidth * 2))

endfunction

" Paste a version of this line into .vimrc to assign a keystroke (in this case F5)
" Comment-out this version if you do
" --------------------------------
map &amp;lt;F5&amp;gt; :call NewTutTest()&amp;lt;CR&amp;gt;Aset_test_name(" 

" Some helpful macros for command mode. Press \ten and it opens a new line
" and types ensure(" so you can fill in the string and the parameters.
" Overall, not too shabby.
map \tn oensure(" 
map \te oensure_equals(" 
map \td oensure_distance(" 
map \tf ofail(" 

" Abbreviations to help you in insert mode. Type the 
" two-letter name, followed by a quote.
ab tn ensure(
ab te ensure_equals(
ab td ensure_distance(
ab tf fail(

&lt;/pre&gt;</description>
      <pubDate>Wed, 11 Jul 2007 09:47:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:59fa76b6-51eb-4607-ad92-82e21bd54a70</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/07/11/use-vim-to-do-tut-unit-testing</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Revisit: The common subgroups</title>
      <description>&lt;p&gt;In cleaning up the code, I simplified the algorithm a very little and improved performance considerably.  Amazing how that works, how simpler equals faster for so much code.  Adding simple data structures, local explanatory functions, and the like often make code much faster.&lt;/p&gt;


	&lt;p&gt;What I&amp;#8217;m hoping is that I will use this in a few different and useful ways.&lt;/p&gt;


	&lt;p&gt;The first way is to look for interfaces where concrete classes are being used from many other classes.  You need to add an interface, but don&amp;#8217;t know who needs which part. The goal is to figure out a relatively small number of interfaces that satisfy a number of clients in a module.&lt;/p&gt;


	&lt;p&gt;The second use would be to look for common clumps of parameters when I&amp;#8217;m working in a large code base where the average number of arguments per function call does not remotely approach one.  I suspect that there are clumps of similarly-named variables being passed around, and that these are likely &amp;#8220;missed classes&amp;#8221;.  Sometimes these are obvious, but it would be good to see them in a nice list spit out from a nice tool.&lt;/p&gt;


	&lt;p&gt;So this is a hopeful start on a series of useful tools.&lt;/p&gt;


	&lt;p&gt;Code follows.&lt;/p&gt;


&lt;pre&gt;
import shelve
import sys

def find_groups(input):
    """ 
    Exhaustively searches for grouping of items in a map, such
    that an input map like this:
        "first":[1, 2, 3, 4],
        "second":[1,2,3,5,6],
        "third":[1,2,5,6]
    will result in:
        [1,2,3]: ["first","second"]
        [1,2]: ["first","second","third"]
        [5,6]: ["second","third"]

    Note that the return value dict is a mapping of frozensets to sets,
    not lists to lists as given above. Also, being a dict, the results
    are effectively unordered.
    """ 
    def tupleize(data):
        "Convert a set or frozenset or list to a tuple with predictable order" 
        return tuple(sorted(set(data)))

    def append_values(map, key, *values):
        key=tupleize(key)
        old_value = map.get(key,[])
        new_value = list(old_value) + list(values)
        new_value = tupleize(new_value)
        map[key] = new_value
        return key, new_value

    result = {}
    previously_seen = {}
    for input_identity, signatures in input.iteritems():
        input_signatures = set(signatures)
        for signature_seen, identities_seen in previously_seen.iteritems():
            common_signatures = set(signature_seen).intersection(input_signatures)
            if len(common_signatures) &amp;gt; 1:
                known_users = list(identities_seen) + [input_identity]
                append_values(result, common_signatures, *known_users)
        append_values(previously_seen, signatures, input_identity)
    return filter(result)

def filter(subsets):
    filtered = {}
    for key,value in subsets.iteritems():
        if (len(key) &amp;gt; 1) and (len(value) &amp;gt; 1):
            filtered[key] = set(value)
    return filtered

def display_groupings(groupings):
    "Silly helper function to print groupings" 
    keys = sorted(groupings.keys(), cmp=lambda x,y: cmp(len(x),len(y)))
    for key in keys:
        print "\n","-"*40
        for item in key:
            print item
        for item in sorted(groupings[key]):
            print "     ",item
        print

&lt;/pre&gt;</description>
      <pubDate>Tue, 03 Jul 2007 10:43:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:bda9c375-df64-42f1-9fe3-627b9d354ec1</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/07/03/revisit-the-common-subgroups</link>
      <category>Tim's Tepid Torrent</category>
      <category>python</category>
      <category>algorithm</category>
      <category>optimized</category>
      <category>clean</category>
    </item>
    <item>
      <title>Python Subgroup Detection and Optimization</title>
      <description>&lt;p&gt;I had a moderately interesting customer problem to work on.  I got acquainted with a bit of legacy code that is seriously in need of some interface segregation.  It&amp;#8217;s an entirely concrete class and used from all over the code base. The question is how to segregate, and that depends on what methods are called from which programs. We ran &amp;#8216;nm&amp;#8217; to extract the link table from our object files, saving me the trouble of parsing C++ (a scary thought) All that remained was for me to compare the method prototypes used by the object files and find the common sets.&lt;/p&gt;


	&lt;p&gt;Lacking better ideas, I decided to do this exhaustively in a brute-force kind of way.  It is only a few hundred files, so it shouldn&amp;#8217;t take too long. I was very wrong. It took a long time and eventually failed.&lt;/p&gt;


	&lt;p&gt;I had &lt;span class="caps"&gt;TDD&lt;/span&gt;-ed the code, so I had tests of correctness, and I relied on these as I added optimizations, but of course the performance problem occurred only under a real load.&lt;/p&gt;


	&lt;p&gt;I could have run a profiler on it (and probably should have) but instead I simply monitored my computer. I quickly saw that my time was going into memory allocation, which is also the reason it died after many minutes When I have python performance problems, this is usually the reason, and almost never &amp;#8220;interpreter drag&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;My friend Norbert (a gentleman of many programming languages, including ruby) suggested that I wasn&amp;#8217;t interning my strings, and of course I was not.  I switched to interning strings, and noticed a little improvement which meant the program ran &lt;em&gt;longer&lt;/em&gt; before failing from memory problems. Well, the tests still passed, so I knew at least that the logic was still good even if the algorithm was primitive and Occam was spinning in his grave.&lt;/p&gt;


	&lt;p&gt;Next I realized that I am dealing with a lot of small groups of strings, and in a leap of optimism/faith/stupidity I decided to intern groups of strings. That helped very little, but it did help since my program was now running for the better part of an hour (!!!) and then failing. &amp;#8220;More of same&amp;#8221; without measurement is hardly a good recipe for optimization.&lt;/p&gt;


	&lt;p&gt;This is when I realized that I shouldn&amp;#8217;t be storing sets or frozensets, which are pretty heavyweight data structures. I had chosen them because I was really working with set intersections, but hadn&amp;#8217;t counted the in-memory storage cost. I converted the data structure used by the algorithm and added a local function to make tuples out of the sorted sets.&lt;/p&gt;


	&lt;p&gt;I was very glad to have my tests to catch me when I had some typing mistake or sloppy conversion.  My tests had to be edited, but the changes there were very lightweight, and caused me to abstract out some data comparisons that were (admittedly) repeated. It was all good.&lt;/p&gt;


	&lt;p&gt;When I ran the full program it completed so quickly that I was sure I&amp;#8217;d broken it.  It was running with sub-second time, including gathering data from various text files (nm output files).  I did a few spot-checks, and determined that it was indeed doing the right thing (as far as I know).&lt;/p&gt;


	&lt;p&gt;The data is moderately interesting, and I will be able to pick out some useful interfaces.  Better yet, I have a program that can pick out all the uses of my big, fat class and recommend interfaces to me.  This is all good.&lt;/p&gt;


Lessons learned:
&lt;ul&gt;
&lt;li&gt;The tests gave me peace of mind as I worked.  I would so hate to have done this &amp;#8220;naked&amp;#8221;.&lt;/li&gt;
&lt;li&gt;Python&amp;#8217;s speed is fine (even startling) if you aren&amp;#8217;t doing something wasteful and heavy-handed like storing hundreds or thousands of non-interned strings and heavyweight data structures&lt;/li&gt;
&lt;li&gt;I could have been done sooner if I&amp;#8217;d measured with hotshot instead of guessing. This is very clear to me, and I won&amp;#8217;t think I&amp;#8217;m too clever or my problem is too simple to do this ever again.&lt;/li&gt;
&lt;li&gt;Keep some ruby friends on hand. They come in handy.&lt;/li&gt;
&lt;li&gt;I didn&amp;#8217;t really need a cooler algorithm.  Brute force is sometimes enough.&lt;/li&gt;
&lt;/ul&gt;

	&lt;p&gt;I want to build a new wrapper for this code to compare parameter lists, to help find unrecognized classes in these same programs.  It shouldn&amp;#8217;t be too hard, but it will be a larger data set so I will probably need some more optimization or a cooler algorithm later. I think I see some waste in it now, but I guess I&amp;#8217;ll have to fix that after blogging.&lt;/p&gt;


	&lt;p&gt;Of course, I&amp;#8217;m not done learning.  I am sure there are a lot of ways to improve the core code. I also believe in other people, that I should make it available to criticism and suggestions.&lt;/p&gt;


	&lt;p&gt;Here it is:&lt;/p&gt;


&lt;h3&gt;Tests&lt;/h3&gt;
(Which, embarassingly, could use more refactoring)
&lt;pre&gt;
import unittest
import clumps

def keySet(someMap):
    return set(someMap.keys())

class ClumpFinding(unittest.TestCase):
    def testNoGroupsForSingleItem(self):
        input = { "OneGroup": [1,2] }
        actual = clumps.find_groups(input)
        self.assertEquals({}, actual)

    def testNoOverlapMeansNoGroups(self):
        input = {
            "first": [1,3],
            "second": [2,4]
        }
        actual = clumps.find_groups(input)
        self.assertEquals({}, actual)

    def testIgnoresSingleMatches(self):
        input = {
            "first": [1,3],
            "second": [1,4]
        }
        actual = clumps.find_groups(input)
        self.assertEquals({}, actual)

    def testTwoInterfaceMatches(self):because of
        group = (1,2)
        names = ("first","second")
        input = dict( [(name,group) for name in names])

        actual = clumps.find_groups(input)

        self.assertEquals(1, len(actual))
        [key] = actual.keys()
        self.contentMatch(group, key)
        self.contentMatch(input.keys(), actual[key])

    def contentMatch(self, left,right):
        left,right = map( frozenset, [left,right])
        self.assertEquals(left,right)

    def testFindsThreeGroupsMatchingExactly(self):
        group = [1,3,8]
        names = "one","two","three" 
        input = dict( [(name,group) for name in names ] )

        actual = clumps.find_groups(input)

        self.assertEquals(1, len(actual))
        [clump_found] = actual.keys()
        self.contentMatch(group, clump_found)
        self.contentMatch(names, actual[clump_found])

    def testFindsPartialMatchInThreeGroups(self):
        input = {
            "a":[1,2,3,4,5],
            "b":[1,4,5,6,8],
            "c":[0,1,4,5]
        }
        target_group = frozenset([1,4,5])
        names = input.keys()

        actual = clumps.find_groups(input)

        [key] = actual.keys()
        self.contentMatch(target_group, key)
        self.contentMatch(names, actual[key])

    def testFindsMultipleMatches(self):
        input = {
            "a":[1,2,3,4,5],
            "b":[1,4,5,6,8],
            "c":[0,1,4,5],
            "d":[1,2,3],
            "e":[1,3]
        }

        actual = clumps.find_groups(input)
        keys = actual.keys()

        self.assertEqual(3, len(actual))

        grouping = (1,2,3)
        referents = set(["a","d"])
        self.assert_(grouping in keys, "expect %s in %s" % (grouping,keys) )
        self.assertEqual(referents, actual[grouping])

        grouping = (1,4,5)
        referents = set(["a","b","c"])
        self.assert_(grouping in keys)
        self.assertEqual(referents, actual[grouping])

        grouping = (1,3)
        referents = set(["a","d","e"])
        self.assert_(grouping in keys)
        self.assertEqual(referents, actual[grouping])

if __name__ == "__main__":
    unittest.main()
&lt;/pre&gt;

&lt;h3&gt;The Code&lt;/h3&gt;

&lt;pre&gt;
import sys

def find_groups(named_groups):
    """ 
    Exhaustively searches for grouping of items in a map, such 
    that an input map like this:
          "first":[1, 2, 3, 4],
          "second":[1,2,3,5,6],
          "third":[1,2,5,6]
    will result in:
        [1,2,3]: ["first","second"]
        [1,2]: ["first","second","third"]
        [5,6]: ["second","third"]

    Note that the return value dict is a mapping of frozensets to sets,
    not lists to lists as given above. Also, being a dict, the results
    are effectively unordered.
    """ 
    def tupleize(data):
        "Convert a set or frozenset or list to a tuple with predictable order" 
        return tuple(sorted(list(data)))

    result = {}
    for name, methods_called in named_groups.iteritems():
        methods_group = frozenset(methods_called)
        methods_tuple = tupleize(methods_group)
        for stored_interface in result.keys():
            key_set = frozenset(stored_interface)
            common_methods = tupleize(key_set.intersection(methods_group))
            if common_methods:
                entry_as_list = list(result.get(common_methods,[]))
                entry_as_list.append(name)
                entry_as_list.extend( result[stored_interface] )
                result[common_methods] = tupleize(entry_as_list)

        full_interface_entry = result.setdefault(methods_tuple, [])
        if name not in full_interface_entry:
            full_interface_entry.append(name)
    return filter(result)

def filter(subsets):
    # Apology: I'm betting I can do this in a functional way.
    filtered = {}
    for key,value in subsets.iteritems():
        if (len(key) &amp;gt; 1) and (len(value) &amp;gt; 1):
            filtered[key] = set(value)
    return filtered

def display_groupings(groupings):
    "Silly helper function to print groupings" 
    keys = sorted(groupings.keys(), cmp=lambda x,y: cmp(len(x),len(y)))
    for key in keys:
        print "\n","-"*40
        for item in key:
            print item
        for item in sorted(groupings[key]):
            print "     ",item
        print

&lt;/pre&gt;</description>
      <pubDate>Wed, 27 Jun 2007 23:23:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:5615a4c9-4a82-447e-92e1-ff331d47a48f</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/06/27/python-subgroup-detection-and-optimization</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>The Things That Pass For Simple I Can't Understand</title>
      <description>&lt;p&gt;(with apologies to Steely Dan for the nearly-lyrical title)&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve noticed that &amp;#8220;Do the simplest thing that might possibly work&amp;#8221; gets universal agreement in principle, and great divergence in practice.&lt;/p&gt;


	&lt;p&gt;Is a set of variables related by name prefix simpler than a named class containing the same variables?  In the &amp;#8220;fewest number of the fewest things&amp;#8221; sense, I see a group of variables as a lot more to manage than a class.  I can&amp;#8217;t understand why some people pass the same group of loose variables to a number of methods. Isn&amp;#8217;t a seven-argument method &amp;#8220;complex&amp;#8221;?&lt;/p&gt;


	&lt;p&gt;Is a custom exception &amp;#8220;fancy&amp;#8221; or &amp;#8220;trivial&amp;#8221;?  I&amp;#8217;ve had that discussion recently.  Some feel one way, some the other.  Is it more complex to throw a standard exception type and then try to figure out what it means elsewhere?&lt;/p&gt;


	&lt;p&gt;Is event-handling simpler than polling?  I&amp;#8217;ve heard this one too.  I don&amp;#8217;t know how other people see it.  I think events have more complex plumbing, but that polling has a greater run-time complexity because of failure modes (periodicity issues, race conditions, etc).  I think that it is simpler if you have fewer problems to look out for.&lt;/p&gt;


	&lt;p&gt;If you need a fixed set of java instances, is an enum simple or fancy?  Here you have a newer language feature, but it exists to simplify the management of a fixed set of instances, so it leaves you less to deal with, no?&lt;/p&gt;


	&lt;p&gt;Is &amp;#8220;more primitive&amp;#8221; simpler? How about if you use arrays and integer indices into a string rather than a list of strings? Is that simpler or more complex?  Is the Bowling Game &amp;#8220;simple&amp;#8221; because it uses a primitive array and a separate array counter instead of custom objects?&lt;/p&gt;


	&lt;p&gt;In C++, is it simpler to have a struct that contains two data members or to use the pair&amp;lt;&amp;gt; template?  Is it &amp;#8220;simpler&amp;#8221; that you have to refer to them as &amp;#8220;first&amp;#8221; an &amp;#8220;second&amp;#8221;?  Or is that just more obscure?  I think that &amp;#8220;obvious&amp;#8221; is more simple.&lt;/p&gt;


	&lt;p&gt;I am not sure how other people judge simple.  I think &amp;#8220;simple to use&amp;#8221;, &amp;#8220;less bookkeepping&amp;#8221;, &amp;#8220;harder to mess up&amp;#8221;, &amp;#8220;less setup to call&amp;#8221;, &amp;#8220;fewer parameters&amp;#8221; are simpler.  Other people seem to have contrary thoughts.&lt;/p&gt;


	&lt;p&gt;Clearly simple involves more than &amp;#8220;least thought&amp;#8221; or &amp;#8220;most primitive data components&amp;#8221;.  It should have something to do with the lack of effort in using something and the ease with which things can be used correctly.  Well, clearly to me.   And it should have to do with the least difficulty in reading the resulting code, and the least difficulty in changing it.&lt;/p&gt;


	&lt;p&gt;Unrelated to this, I find some tools that others find simple to be baffling, and some tools that are complex to others seem pretty easy to use to me.  I suppose that&amp;#8217;s a kind of &amp;#8220;personal taste&amp;#8221; but is there a more reliable rule to base &amp;#8220;simple&amp;#8221; on than personal choice? There should be if the rule is for us all to do the simplest thing that works, and to maintain the simplest design we can afford to build.&lt;/p&gt;


	&lt;p&gt;But I have unique viewpoints sometimes, and maybe simple to you isn&amp;#8217;t simple to me.  Personally, some of the things that are simple to you may be all but inscrutable to me.  I guess that happens.&lt;/p&gt;</description>
      <pubDate>Thu, 14 Jun 2007 00:19:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:38d1dd7b-6090-4f9d-aff6-f0ece6016e14</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/06/14/the-things-that-pass-for-simple-i-cant-understand</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Collateral Effort Revisited</title>
      <description>&lt;p&gt;One of the things I love about &lt;span class="caps"&gt;TDD&lt;/span&gt; is that it takes all the scaffolding and collateral effort for creating a class, all indications of bad coupling, and makes them entirely visible. This is also one thing that makes it very hard to start &lt;span class="caps"&gt;TDD&lt;/span&gt; in legacy system.&lt;/p&gt;


	&lt;p&gt;When you realize that it&amp;#8217;s very hard to test a class out-of-context, the right answer is to start decoupling each class so it can be run out-of-context. When we are successful here, tests run very very fast and are easily self-verifying and isolated.  It is a beautiful thing even if it follows many ugly hours of painstaking work.&lt;/p&gt;


	&lt;p&gt;The wrong answer, I&amp;#8217;m convinced, is to build a mega-framework for testing that allows you to test in-context. This type of framework typically creates a totally realistic runtime environment (complete with database, configuration files, directories, etc).  This approach allows you to think that you can ignore your dependency nightmare. You really can not Mega-test-frameworks take a such a long time to run that developers stop running all the tests all the time.  This is a far worse problem than breaking dependencies because it breaks the whole process.  Mega-frameworks don&amp;#8217;t solve the problem, they only defer the solution until the problem gets worse.&lt;/p&gt;


	&lt;p&gt;When you are faced this kind of collateral effort, the answer is to work through it, not to sweep it under a rug.  Working through it is work, indeed, but this is about doing the right thing not doing the easiest thing.&lt;/p&gt;</description>
      <pubDate>Mon, 11 Jun 2007 20:36:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:925c8e61-d709-4523-adaf-b2646602d831</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/06/11/collateral-effort-revisited</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/8778</trackback:ping>
    </item>
    <item>
      <title>The Myth of  Learning Compression</title>
      <description>&lt;p&gt;There is an odd idea that learning is compressible, that any training course of any length can be squeezed into a very small time box and delivered to any large number of people without significant loss.&lt;/p&gt;


	&lt;p&gt;As an educator and as a guy who has a pretty big learning load at any time, I know that this is a myth.  I can cover any topic much better if I am working with a handful of individuals over the course of a week or two.  If you double the number of attendees, then the interactivity is highly degraded, and discussions become time sinks.  If you half the time, then interactivity is likewise degraded, and material that might have been covered must be skipped or skimmed.&lt;/p&gt;


	&lt;p&gt;I have a joke with my coworkers that the ideal environment for some large corporations would be a three-train roller coaster.  The participants would buy a ticket, climb on board, sail past the materials at speeds in excess of 60 miles per hour, and would collect their certificate at the other end.  As one train is unloading, another is loading, and another is in progress so that we could cover many hundreds or thousands of students per day.  Of course, they would learn next to nothing and would not really participate at all.&lt;/p&gt;


	&lt;p&gt;But I respect my corporate customers, including the fact that they have much to do, and cannot easily afford a one-week work-stop for each dozen team members, all with consultant/trainer fees.  Some large organizations would have us on-site for years in a row before all their developers would be trained in any technology.  It&amp;#8217;s just not reasonable, and they push for a more feasible schedule.&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s a rock and a hard place, and people on both sides understand that it is so.&lt;/p&gt;


	&lt;p&gt;The good news is that compressibility is not a total myth.  There are techniques and tools that can make the training more effective, so that less time is necessary in class.  There is the idea of a jump-start, where a topic is introduced and discussed in a short time and students are given materials on which they can continue via self-training.  The compressibility myth drives us to more dense and useful presentation.   It is a valuable spur.&lt;/p&gt;


	&lt;p&gt;It also has the advantage of the time box.  If you have only three days to teach someone how to &lt;span class="caps"&gt;TDD&lt;/span&gt;, you have to choose the three most important days-worth of material to teach.  This kind of prioritization is the same thing that we demand of our product owners in a scrum, and is perfectly fair and reasonable.&lt;/p&gt;


	&lt;p&gt;Even though compressibility is a myth, it is a useful myth.&lt;/p&gt;


	&lt;p&gt;The only mythological part of the compression myth is the idea that it is lossless.   It is lossy compression.  But as is the case with audio and visual compression, compressed learning can be &amp;#8220;good enough.&amp;#8221;   If that&amp;#8217;s what we&amp;#8217;re after, it&amp;#8217;s all good.&lt;/p&gt;</description>
      <pubDate>Thu, 24 May 2007 13:56:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:c23ca614-9695-4be6-bcd7-1b698ceb5040</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/05/24/the-myth-of-learning-compression</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Unit Tests Coverage: Less Is More</title>
      <description>&lt;p&gt;In &lt;span class="caps"&gt;TDD&lt;/span&gt; a unit test has to be very small to isolate failures.  This does funny things to code coverage as a metric.  Each test should have a very small area of effect, and so each unit test should have a negligible effect on the overall code coverage statistic.  Bear with me here, see where I&amp;#8217;m missing out.&lt;/p&gt;


	&lt;p&gt;Say you have an existing (legacy) system with no coverage at all.  Zero percent.  If you start doing &lt;span class="caps"&gt;TDD&lt;/span&gt; today, the overall coverage percentage should barely change at all. If only the new code is test-driven, then the old code is not gaining coverage except where tests are necessary to ensure that the new code is being called.  The low coverage per test is a good thing because it shows that the unit tests have good isolation.  In such a situation, code coverage is really telling you the ratio of new code to old code.  Again, this is so obvious and logical to me that I must be missing some cool subtleties.&lt;/p&gt;


	&lt;p&gt;If all the code was test-driven from the beginning, you should have a very high coverage number, and writing a new unit test &lt;strong&gt;before&lt;/strong&gt; you add code should not impact that number.  You only write enough code to pass the test, so again you aren&amp;#8217;t getting much in the way of uncovered code. A lowering of the ratio might indicate a problem with test-to-production-code ratio.  This seems pretty simple and logical, so I&amp;#8217;m sure I&amp;#8217;m missing some interesting corner cases.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;OTOH&lt;/span&gt;, system tests and integration tests paths through many components at once, and should have a more significant effect on coverage in a previously-untested system, though their job is to prove function points, not to raise the metrics.  These non-unit tests are the thing that boost your coverage of old code. That is also a good effect, because it is the goal of the system test to ensure that the parts work together.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m not saying that code coverage should be low, only that as we move incrementally, the unit tests we write should individually have negligible effect on our overall code coverage numbers&amp;#8230; a thought that intrigues me.&lt;/p&gt;</description>
      <pubDate>Mon, 07 May 2007 08:06:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:1bd6fe5d-c5ff-4269-a20d-87e7d57443d8</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/05/07/unit-tests-coverage-less-is-more</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>CppUnit and Vim </title>
      <description>&lt;p&gt;I&amp;#8217;m playing with ways to make &lt;span class="caps"&gt;CPPUNIT&lt;/span&gt; and &lt;span class="caps"&gt;VIM&lt;/span&gt; a bit more agile for my C++ teams.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve been hearing about great lengths people go to, flipping back and forth between .h and cpp for the tests or writing perl scripts to coalesce them together. I&amp;#8217;m too simple-minded for that.  I figure nobody wants to #include my tests, so I don&amp;#8217;t need a .h.  I do it all in the .cpp file, all inline.  It works fine.  This way, everything is in one place.  I don&amp;#8217;t have to jump up to the header file to add a protoype and then down to the implementation to add the &lt;span class="caps"&gt;CPPUNIT&lt;/span&gt;_TEST line, and then back down to my code to enter it.  I have no .h, so no prototype.  Inline makes it a bit more like pyunit or junit.&lt;/p&gt;


	&lt;p&gt;I grokked the CompilerOutputter  pretty quick.  If you use the quickfix mode (and esp if you use :cw) you will definitely want the CompilerOutputter.  I like the way it helps me move from testing error to testing error (err.. if there were ever more than one), just as it does with compile errors (errr.   if they happen.  They do).  I set up my makefiles to run the tests, so there&amp;#8217;s no additional step required.  That&amp;#8217;s handy.  I also have the makefile run ctags to make my navigation nice and easy.&lt;/p&gt;


	&lt;p&gt;Still, adding and removing tests takes some effort.  I figure &lt;span class="caps"&gt;VIM&lt;/span&gt; can take up the slack. I have macros to start up a new test file (F2), to add a test class(F11), to register a function(F12), and to delete a function and its &lt;span class="caps"&gt;CPPUNIT&lt;/span&gt;_TEST line (F9) .&lt;/p&gt;


	&lt;p&gt;I also abbreviate most of the macros that I would otherwise have to type.  I am thinking about remapping them maybe to more memorable values, but it helps.&lt;/p&gt;


	&lt;p&gt;There are probably a lot more elegant ways to do this.  I can&amp;#8217;t wait to hear about them.&lt;/p&gt;


&lt;pre&gt;
 " Add methods to help create CPPUNIT classes
function! NewCppUnitFile()
    call NewCppUnitClass()
    0r~/.cppunit_file_template.vim
endfunction

function! NewCppUnitClass() 
    r~/.cppunit_class_template.vim
    let name = input("Name your new test class: ")
    exec "%s/@@@NAMEHERE@@@/" . name . "/g" 
endfunction

nmap &amp;lt;F2&amp;gt; :call NewCppUnitFile()&amp;lt;CR&amp;gt;
nmap &amp;lt;F9&amp;gt;  ^f(b*ddN0d/{&amp;lt;CR&amp;gt;d%
nmap &amp;lt;F11&amp;gt; G:call NewCppUnitClass()&amp;lt;CR&amp;gt;
nmap &amp;lt;F12&amp;gt; ebmz"zyw?CPPUNIT_TEST_SUITE_END(&amp;lt;CR&amp;gt;OCPPUNIT_TEST(&amp;lt;C-R&amp;gt;z);&amp;lt;ESC&amp;gt;'z

" CPPUnit abbreviations
ab cas CPPUNIT_ASSERT
ab cam CPPUNIT_ASSERT_MESSAGE
ab cfa CPPUNIT_FAIL
ab caf CPPUNIT_FAIL
ab cae CPPUNIT_ASSERT_EQUAL
ab cat CPPUNIT_ASSERT_THROW
ab cde CPPUNIT_ASSERT_DOUBLES_EQUAL
&lt;/pre&gt;

	&lt;p&gt;The current rhythm is to open a new file and press F2.  F2 calls NewCppUnitFile, which sucks in my file header template.  It&amp;#8217;s pretty bare, but it can be edited to taste.  Mostly it helps me remember what to include.&lt;/p&gt;


&lt;pre&gt;
    #include &amp;lt;cppunit/TestFixture.h&amp;gt;
    #include &amp;lt;cppunit/extensions/HelperMacros.h&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;Then I give the name of my first test class.  I get a starter class.  I can then add it to the makefile (note to self: automate the makefile bit).  the starter template I have has a dummy test, so  I can run it and see if it fails.  Failing means it&amp;#8217;s being built and run.&lt;/p&gt;


&lt;pre&gt;
    class @@@NAMEHERE@@@: public CPPUNIT_NS::TestFixture {
        CPPUNIT_TEST_SUITE(@@@NAMEHERE@@@);
        CPPUNIT_TEST(shouldFailAsEvidenceThisMethodIsRegistered);  // DELETEME?
        CPPUNIT_TEST_SUITE_END();

        public:
            void setUp() {
            }
            void tearDown() {
            }
        protected:
            void shouldFailAsEvidenceThisMethodIsRegistered() { // DELETEME?
                CPPUNIT_FAIL("This function is registered and can be deleted");
            }
    };
    CPPUNIT_TEST_SUITE_REGISTRATION(@@@NAMEHERE@@@);

&lt;/pre&gt;

	&lt;p&gt;Substitution is automagical.  the &lt;code&gt;@@NAMEHERE&lt;/code&gt;@@ is the magic pattern being replaced with test names.&lt;/p&gt;


	&lt;p&gt;A nice thing about macros is that they&amp;#8217;re atomic.  If I hate the name I gave my test, I press &amp;#8216;u&amp;#8217; for undo, and it vanishes.  Back to empty file. :-)&lt;/p&gt;


	&lt;p&gt;If the &amp;#8221;:mak&amp;#8221; works and I get the inevitable failure in the &amp;#8220;shouldFail&amp;#8221; method, I put my cursor on the &amp;#8220;void shouldFail&amp;#8230;&amp;#8221; line and press F9.  In the wink of an eye, the method and its &lt;span class="caps"&gt;CPPUNIT&lt;/span&gt;_TEST line both vanish.  Again, macros are atomic, so if I delete the wrong thing, I just press &amp;#8216;u&amp;#8217; for undo and both the function and its registration reappear.&lt;/p&gt;


	&lt;p&gt;No flipping between files, no scrolling up and down.  We have software to do that now.&lt;/p&gt;


	&lt;p&gt;I add a method under &amp;#8220;protected&amp;#8221;.  I put the mouse on the method name and press &lt;span class="caps"&gt;F12&lt;/span&gt; to add the &lt;span class="caps"&gt;CPPUNIT&lt;/span&gt;_TEST for it above.  I add some more text.  When I get to the part where I need to assert, I use one of the abbreviations.  If I&amp;#8217;m in insert mode and type &amp;#8220;cae(&amp;#8221; I get &amp;#8220;CPPUNIT_ASSERT_EQUALS(&amp;#8221;.  I don&amp;#8217;t have to remember whether it ends in an S or not.  I actually struggle with that, sad thing that I am.&lt;/p&gt;


	&lt;p&gt;I can press &lt;span class="caps"&gt;F11&lt;/span&gt; to create more test classes.  I like to keep a test class for every circumstance (setup) I am using.  I don&amp;#8217;t mind at all having multiple tests per .cpp file.   I like to group the tests together in files.  After all, quickfix knows where the code is.  This is actually one of the reasons I like to keep using CppUnit.   I&amp;#8217;ll have to tell the others someday.&lt;/p&gt;


	&lt;p&gt;Well, that&amp;#8217;s how I do it.  You don&amp;#8217;t have to, but you could try it.  If you find any errors, or glaring omissions, please mail them to me or comment here.  In return, I will claim my &lt;strong&gt;actual&lt;/strong&gt; scripts are perfect and blame it on the web master. ;-)&lt;/p&gt;</description>
      <pubDate>Thu, 03 May 2007 21:54:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:e25e9bd8-0a88-4875-8896-bcceff23ff03</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/05/03/cppunit-and-vim</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>What Cant Who Do? </title>
      <description>&lt;p&gt;I have a fresh idea.  When someone is supposed to change their workstyle to do &lt;span class="caps"&gt;TDD&lt;/span&gt;, and they say &amp;#8220;we can&amp;#8217;t do that&amp;#8221;, how about we assume they&amp;#8217;re telling the truth.&lt;/p&gt;


	&lt;p&gt;The first word is &amp;#8220;we&amp;#8221;.  It may well be that the speaker and the people he represents might not be able to do the work.  They&amp;#8217;re not saying that it can&amp;#8217;t be done.  They&amp;#8217;re only saying that &lt;strong&gt;they&lt;/strong&gt; can&amp;#8217;t do it.&lt;/p&gt;


	&lt;p&gt;The next word is &amp;#8220;can&amp;#8217;t&amp;#8221; and that&amp;#8217;s an interesting word, too.  It might mean that they lack the ability or knowledge.  That&amp;#8217;s ideal, because such things can be taught and can be led. The other sense is that they are not allowed.   If it&amp;#8217;s like that, then there is going to be some political work going on.  But at least you know what you&amp;#8217;re getting into.&lt;/p&gt;


	&lt;p&gt;The other tell is the word &amp;#8220;that&amp;#8221;.  Maybe they should describe what it is that they can&amp;#8217;t do, and you can tell if the thing they can&amp;#8217;t do is the same thing that you are wanting them to do.   Sometimes it is not.&lt;/p&gt;</description>
      <pubDate>Tue, 01 May 2007 21:55:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:e4c17889-ba01-4ce2-8bf0-24bc5c2345af</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/05/01/what-cant-who-do</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Coercive Immediacy</title>
      <description>&lt;p&gt;I have been thinking a lot about the &amp;#8220;short reach&amp;#8221; idea, and tryng to reach beyond it to capture the thing that the good agile project teams have and several others are missing.  At the same time, I&amp;#8217;ve been reading up on some agile tools (including &lt;a href="http://explainpmt.com/"&gt;one by a guy I know&lt;/a&gt;) in my spare time.  In addition, I am on a mailing list for multisite agile development.  Finally, I have been pondering how to work this agile stuff when the developers cannot be co-located due to shortage of office space or shortage of common areas.&lt;/p&gt;


	&lt;p&gt;I realized that the whole &amp;#8220;short reach&amp;#8221; thing creates a kind of coercive immediacy.&lt;/p&gt;


	&lt;p&gt;The corkboard with all the story cards in their four columns has that kind of immediacy.  I can&amp;#8217;t walk past it without assessing how far we are in the current iteration.  I can certainly ignore a web page, or a display in some application on my computer.  I can&amp;#8217;t walk into the common area past that board without thinking.&lt;/p&gt;


	&lt;p&gt;Likewise, I could ignore an app that holds story status and backlog, but the cork board is where I go to show that I&amp;#8217;ve completed a task and to get the next task.  If my stories were assigned to me (rather than allowing self-organization) then I could neglect the corkboard too.  I would not have to look at it or think about it.  I could hold &amp;#8220;my&amp;#8221; story card at &amp;#8220;my&amp;#8221; desk until I decided I was done.  When we are self-organizing, we are always thinking about who could help us, when we can get done, and what is the best way to truly complete this story and move on.&lt;/p&gt;


	&lt;p&gt;A partner has coercive immediacy.  When you are programming in pairs, you don&amp;#8217;t answer the phone unless you have to.  IM and mail can wait.  Interruptions are less welcome.  Having two people on the story pushes one to focus.  Also, the pair partner is always there to catch the sloppy shortcut, the poor naming, the ill-considered algorithm.&lt;/p&gt;


	&lt;p&gt;The customer team member also participates, and both feeds and feels the coercive immediacy of the team.  Rather than make a guess, the programmer feels the nearness of the customer, and it&amp;#8217;s much easier to ask than guess.&lt;/p&gt;


	&lt;p&gt;I think that &lt;span class="caps"&gt;TDD&lt;/span&gt; shows this most of all.  I can&amp;#8217;t choose to ignore the red bar. I write a line of code or two, and now my tests pass. The immediacy would be gone with it, except that I know I have some cheesy, minimal-effort code and I can&amp;#8217;t leave it that way.  I need a better test.  When a test fails in some area where I&amp;#8217;m not working, I feel the immediacy.&lt;/p&gt;


	&lt;p&gt;With distribution, multi-site, tools, and the rest I fear that we lose the coercive immediacy of Agile development.  If we don&amp;#8217;t have a partner in our way/face, then we lose something.  If the status board is a tool somewhere, even a really nice tool, but I have to remember to ask for it to see it, then it is not in my way.  It doesn&amp;#8217;t inspire me.&lt;/p&gt;


	&lt;p&gt;My thought now is that an agile management tool won&amp;#8217;t help unless it is something we have to live with all the time, during pairing, as part of the test/code/refactor cycle.  It has to be in our faces, over our heads, and not just tickling the edge of our awareness like a more polite version of &amp;#8220;clippy&amp;#8221;.&lt;/p&gt;</description>
      <pubDate>Tue, 01 May 2007 20:13:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:210121b7-7793-4a88-9423-291ca8b069d5</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/05/01/coercive-immediacy</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Short Reach</title>
      <description>&lt;p&gt;I&amp;#8217;m always trying to find newer, better, shorter, more powerful ways to explain what Agile is about.  I suppose I&amp;#8217;m some kind of obsessive about expressive power and economy.&lt;/p&gt;


	&lt;p&gt;Finally I decided that Agile, as I understand it today, is about the &lt;i&gt;short reach&lt;/i&gt;.&lt;/p&gt;


	&lt;p&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;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The customer/analyst is keep in the same room, in the same short reach.&lt;/li&gt;
		&lt;li&gt;We feed back the iterations to the customer/analyst so that his every decision has a shorter reach. &lt;/li&gt;
		&lt;li&gt;We do iterations to ensure our planning has short reach.&lt;/li&gt;
		&lt;li&gt;We keep our teammates very close, in the same room, so that it&amp;#8217;s a shorter reach to them.&lt;/li&gt;
		&lt;li&gt;The test is written first, so that implementation has shorter feedback on correctness.&lt;/li&gt;
		&lt;li&gt;We compile/test frequently because our code time should have a short reach.&lt;/li&gt;
		&lt;li&gt;We pair so that our code is instantly vetted through a peer.  We don&amp;#8217;t pile it up and review it after the tests pass. &lt;/li&gt;
		&lt;li&gt;Our planning is based on &amp;#8220;yesterday&amp;#8217;s weather&amp;#8221;, data collected a very short time ago.&lt;/li&gt;
		&lt;li&gt;We don&amp;#8217;t plan the team structure and the assignments, we self-organize so that tasks are waiting for the shortest time possible.&lt;/li&gt;
		&lt;li&gt;We talk face-to-face, not across chat and email and official company documents.&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.&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. &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.&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&amp;#8217;t have to wait until the week before integration when the &amp;#8220;real&amp;#8221; tests are run.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&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 &amp;#8220;point of contact&amp;#8221; and &amp;#8220;official channels&amp;#8221;, and where the developers are not placed in a common work area agility is very difficult.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m not saying that agile techniques can&amp;#8217;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 &amp;#8220;agilist&amp;#8221; 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;/p&gt;


	&lt;p&gt;At least that&amp;#8217;s my half-baked observation of the day.  Let me know if I&amp;#8217;m wrong here. Or if I&amp;#8217;m more right than I think I am.&lt;/p&gt;</description>
      <pubDate>Mon, 23 Apr 2007 15:33:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:d2b41a9d-04ef-4fec-9e4c-332c956369cf</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/04/23/short-reach</link>
      <category>Tim's Tepid Torrent</category>
      <category>agile</category>
      <category>short</category>
      <category>reach</category>
      <category>philosophy</category>
    </item>
    <item>
      <title>Using VIM</title>
      <description>&lt;p&gt;It isn&amp;#8217;t done yet, but I figured I would post my work in progress in the meantime for feedback.  It&amp;#8217;s a little article about the &lt;a href="http://tottinge.blogsome.com/use-vim-like-a-pro"&gt;proper use of the &lt;span class="caps"&gt;VIM&lt;/span&gt; editor&lt;/a&gt;.  I tried to mix in some keystroke quick-reference with the philosophy of the tool in a way that might make it a bit more accessible.&lt;/p&gt;


	&lt;p&gt;When it&amp;#8217;s done (Ha!) I will probably find new places to store it, but for now it&amp;#8217;s at my personal blog.&lt;/p&gt;


	&lt;p&gt;Don&amp;#8217;t be afraid to offer corrective assistance, or to recommend sections.&lt;/p&gt;</description>
      <pubDate>Fri, 20 Apr 2007 01:19:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f0b91d0a-527e-42b4-8579-781bb91ec465</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/04/20/using-vim</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>The Two Things Agile</title>
      <description>&lt;p&gt;For Agile, maybe the &lt;a href="http://www.csun.edu/~dgw61315/thetwothings.html"&gt;Two Things&lt;/a&gt; are:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;We can do better/faster this week.&lt;/li&gt;
		&lt;li&gt;And this way next week will be better yet.&lt;/li&gt;
	&lt;/ul&gt;</description>
      <pubDate>Mon, 16 Apr 2007 22:07:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:c785d99a-bc43-49b6-9299-0d0340922748</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/04/16/the-two-things-agile</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Code is a Liability</title>
      <description>&lt;p&gt;I have thought for a long time that code is  liability, and that viewing code as a liability has the power to transform our art.  I read articles about code-as-a-corporate-asset and most of them are pretty good articles about wringing the value from the code you have, but I still feel that there&amp;#8217;s something essentially wrong about it.&lt;/p&gt;


	&lt;p&gt;Programs are a great means to an end. Don&amp;#8217;t get me wrong, I&amp;#8217;m in favor of having software and I&amp;#8217;m greatly in favor of writing software. I think we would be in pretty poor shape without it.  But I can&amp;#8217;t call code an asset.&lt;/p&gt;


	&lt;p&gt;Functionality is clearly an asset. When we can inter-operate with various services (possibly even web services) our businesses produce more business results more quickly. We use software to control machines and to increase public safety in more ways than most of us know (talk to the guys who write the software that controls your car, the over-the-road trucks, forklifts, industrial robots, and aircraft).  Software makes our life better and it&amp;#8217;s a wonderful thing.  I&amp;#8217;m all in favor of software functionality and you have to write code to get it.&lt;/p&gt;


	&lt;p&gt;Our bosses and clients will pay good money to get the functionality they want, and they want it right now!  If we could give them what they want without writing a line, it would be a tremendous win.  If we could do it with one line or two lines of well-considered code, we would be heroes!  Why is doing less so valuable if code is an asset? Clearly less code is better.&lt;/p&gt;


	&lt;p&gt;Sadly, most companies have to deal with heaping, shaggy mounds of code.  Code takes up time and space. It has to be managed. It has to be versioned.  It hast to be tracked, and planned. It has to be updated, and packaged, and revised. It needs backup to save us from having to reproduce it by hand.  It has to be reviewed (hopefully in an efficient way like pairing).  It often drives companies to expand staff and dedicate people to manage it (version control administrators, managers, build czars, consultants, contractors, metric-gathering tool specialists, etc).&lt;/p&gt;


	&lt;p&gt;Old code gets in the way of new code.  Having more code will typically slow development, and will certainly reduce your ability to incorporate new programmers.  Of course you&amp;#8217;ll need more programmers because you have all this code to deal with.  Size has a cost.&lt;/p&gt;


	&lt;p&gt;The problem doesn&amp;#8217;t go away if you artificially reduce the code.  Folding a lot of effects into few lines of code makes the code worse. Adding voluminous documentation makes the code worse.  Moving it into metadata and models and other forms doesn&amp;#8217;t make it any smaller, and often makes it worse.  Hand-crafted code is almost always more readable, smaller, more optimal, more focused, more literary in its style than generated code or funky data tables.  Since there has to be code, it might as well be the best code we can write. Coding well takes human beings who value minimalism.&lt;/p&gt;


	&lt;p&gt;It seems that the trick with the functionality/code game is in trying to maintain a positive balance.&lt;/p&gt;


	&lt;p&gt;We reach a point on some projects where we are producing a positive number of functions with a net loss in lines of code.  That&amp;#8217;s a wonderful time.  We reduce the line count by simplifying the code and eliminating duplication.  Sometimes we refactor our code into a more compact form and then only add a very few lines of code to produce a change. If code were an asset, then those moments would be failures instead of triumphs.&lt;/p&gt;


	&lt;p&gt;Code size reduction is a very good thing.  I want the simplest, the smallest, the least code possible, with the least risk of breaking something else in the system. I don&amp;#8217;t want big functions that touch everything in sight. I don&amp;#8217;t want long complicated blocks of if/else statements. I don&amp;#8217;t want monster functions which conglomerate dozens of operations in a single, fat interface.  Shallow is good. Short is good. Less code is good. More code is a liability. This isn&amp;#8217;t about typing less, it&amp;#8217;s about &lt;strong&gt;owning&lt;/strong&gt; less.&lt;/p&gt;


	&lt;p&gt;This is the point of view that makes test-first (TDD) so important.  &lt;span class="caps"&gt;TDD&lt;/span&gt;/BDD has us encode the functionality (the asset) first, and then write minimal code to realize the specified feature.  If code is a liability, and function is an asset, this is exactly the right way to do things.&lt;/p&gt;


	&lt;p&gt;And maybe, just maybe, it might explain why one might open-source less-important useful systems.&lt;/p&gt;</description>
      <pubDate>Mon, 16 Apr 2007 21:10:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0af14e78-464c-4950-8e14-9a7b46ca08bd</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/04/16/code-is-a-liability</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>It's a Poor Coach Who Slaps The Kids</title>
      <description>&lt;p&gt;Today I was remembering a bit of advice I received back in the late 80s when I started trying to work with people more.  I&amp;#8217;d been a programmer for a while, and mainly survived by reading a lot and practicing what I read.  I taught myself most of all the programming I knew (I did have some good mentoring peers). I wasn&amp;#8217;t much of a people person.&lt;/p&gt;


	&lt;p&gt;A fellow named Kevin worked on a project with me in the DC area.  One day he had the kindness to take me aside. He explained to me how to work with people.  He taught me that when someone had an error in their understanding I shouldn&amp;#8217;t tell them they were wrong, but rather tell them they were right &lt;strong&gt;except&lt;/strong&gt; for the part where there was an error.  He helped me more than he knows.  We only had the one project together, and he went on to a different employer and I went on to become me.&lt;/p&gt;


	&lt;p&gt;He told me that a good coach doesn&amp;#8217;t tear down his kids.  He doesn&amp;#8217;t tell they they stand like a sissy or throw like a girl.  Instead, a good coach will let them know what&amp;#8217;s right and what&amp;#8217;s valuable about what they&amp;#8217;re doing, and then explain what to add to their technique to get better results. And he doesn&amp;#8217;t tell them everything all at once.&lt;/p&gt;


	&lt;p&gt;Now I&amp;#8217;m a coach. I teach development methods, including agile methods, including &lt;span class="caps"&gt;TDD&lt;/span&gt;.  I  now work with people more than technology.  I also work with a lot of other coaches from time to time.  The best ones seem to intuitively understand when to criticize and how, and when to hold their tongues.&lt;/p&gt;


	&lt;p&gt;In the warm rush of enthusiasm and passion for the art of development, we coaches have to continually remind ourselves that it&amp;#8217;s the poor coach indeed who slaps the kids around.  We have to instead meet them where they are and look for ways to help them get the results they want.&lt;/p&gt;


	&lt;p&gt;Kevin&amp;#8217;s lesson continues to teach.&lt;/p&gt;</description>
      <pubDate>Mon, 16 Apr 2007 21:01:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:09d75df6-fcda-4c7d-9c54-467f1a357865</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/04/16/its-a-poor-coach-who-slaps-the-kids</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Single Ownership in C++ (intro to auto_ptr)</title>
      <description>&lt;p&gt;I find a lot of C++ programmers experience memory management differently than I do.  I used to have the same kinds of problems that they have, but I learned an important rule:  &lt;strong&gt;every heap object has exactly one owner, and &lt;i&gt;n&lt;/i&gt; borrowers.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;The way that I realize this is using reference types.  Of course, all good  C++ programmers write their functions to use the canonical &amp;#8220;const T&amp;#38;&amp;#8221; parameters whenever possible.  Using a reference means that we have an actual object and not a null reference (side effect: no null checks) and we have simple dot notation (side effect: less typing), but I also use this to mean that we are borrowing the object, not owning it.   Likewise, if we have to drop the &amp;#8216;const&amp;#8217;, we are still borrowing.&lt;/p&gt;


What about passing by pointer? I only do that if I absolutely must accept 0 (null) as a possible value.  I always hate to do that.  I would rather have an object outright than a pointer that I dereference.  If the function is being called by a framework, I don&amp;#8217;t get a choice.  I might do something like this:
&lt;pre&gt;
     void functionName(const Snorkle* snorkleWithNull) {
             if (0 == snorkleWithNull) { 
                  throw SomeIdiotPassedMeANull();
            const Snorkle&amp;#38; snorkle = snorkleWithNull;

           // ... work with snorkle, ignore snorkleWithNull ... 

     }
&lt;/pre&gt;
However sick that seems (and it does) it reverts back to the const reference case quickly and I&amp;#8217;m left with a reference to a real object.   It keeps me from forgetting to dereference when I&amp;#8217;m in a hurry, and keeps me from casting.  I have to work extra-hard to do bad things, and that&amp;#8217;s a good thing.  On the other hand, in modern &lt;span class="caps"&gt;TDD&lt;/span&gt; style, with refactoring, it can double the length of a function (hence feeling sick).

	&lt;p&gt;Either way, if you are a borrower, you have no right to delete the object.  You can reference it for the duration of your function, or (if the intent is that you will have a short-lived object) for the duration of the object lifetime, but no ownership is given by pointer or reference.  Remember that we still have a risk of the pointer being dangled, so holding a reference/pointer for longer than a method call should be considered fairly dangerous and must be done rather intentionally.&lt;/p&gt;


	&lt;p&gt;But what about transfer of ownership? That&amp;#8217;s what the auto_ptr in &amp;lt;memory&amp;gt; is for.   Yes, it&amp;#8217;s a template.  If I can&amp;#8217;t use templates, I&amp;#8217;ll make up something new that acts roughly the same.    The auto_ptr is the one structure in C++ that undeniably says &amp;#8220;owner&amp;#8221;.  When I receive an object via auto_ptr, I am now the owner.  When I return an auto_ptr from a function, I&amp;#8217;ve clearly given up ownership.&lt;/p&gt;


	&lt;p&gt;The recipient of the auto_ptr has to do something with the referenced object, or else it will be deleted when the auto_ptr passes out of scope.  If the recipient decided to &lt;strong&gt;release&lt;/strong&gt; the auto_ptr, they can keep a normal pointer or reference in whatever structure pleases them.  They can make a copy and delete the original (remember the warning about dangling).&lt;/p&gt;


	&lt;p&gt;The trick is to remember that 99% of the time, you want to be a borrower, and that any class that is going to hold a borrower&amp;#8217;s reference to an object needs an algorithmic guarantee that the referenced object will outlive the reference.&lt;/p&gt;


	&lt;p&gt;The scary part is for an object to have a large number of long-term borrowers, because there is the constant fear that one might outlive the owner.  In that case, you need to hang the auto_ptr on the shelf and go get some bigger magic.  You might actually need the smart pointer.    I have created reference-counting pointer templates in several projects, which  will cause C++ to act more like a garbage-collecting language. I know that there are 3rd-party libraries for garbage-collecting.  If I find myself in a situation where there are a number of long-term borrowers, I will definitely move in one of these directions again.  It is too important to leave object ownership up to chance or naming convention.&lt;/p&gt;</description>
      <pubDate>Fri, 30 Mar 2007 10:48:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:af181d4b-afe1-43ce-9287-6646801e9745</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/03/30/single-ownership-in-c-intro-to-auto_ptr</link>
      <category>Tim's Tepid Torrent</category>
    </item>
    <item>
      <title>Solution Probleming</title>
      <description>&lt;p&gt;I&amp;#8217;ve been fortunate enough to have spent most of the past three weeks teaching advanced Object-Oriented Design with patterns.  The students have been wonderful and helpful and brilliant, so the classes have gone very well.&lt;/p&gt;


	&lt;p&gt;As I introduced students to Visitors, Adaptors, Chain of Responsibility, and mult-level State patterns, I was reminded of the problem that was rampant in the 90s: Having learned a catalog of patterns, many OO designers could not wait to put them into practice.   Rather than using patterns to solve problems, they began to look for ways to apply these pattern solutions.&lt;/p&gt;


	&lt;p&gt;I call it &amp;#8220;solution probleming&amp;#8221;, which is of course the opposite of &amp;#8220;problem solving.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;It wasn&amp;#8217;t just the patterns community, it was software tools and it was frameworks and languages.  A company I know used to say &amp;#8220;I don&amp;#8217;t know what the problem is, but the solution is &lt;span class="caps"&gt;DB2&lt;/span&gt;, CICS, and &lt;span class="caps"&gt;COBOL&lt;/span&gt;.&amp;#8221;  That&amp;#8217;s solution probleming.  It&amp;#8217;s one of the reason that so many of us strive to not be product-based consultants.  We want to solve problems, not just shoehorn prefab solutions into people&amp;#8217;s applications.&lt;/p&gt;


	&lt;p&gt;I think any well-developed software developer&amp;#8217;s immune system should be wary of the smell of solution probleming.  It&amp;#8217;s one of the best ways I know to overcomplicate and overengineer a solution &lt;del&gt;-&lt;/del&gt; which is one of the worst ways to develop software.&lt;/p&gt;</description>
      <pubDate>Fri, 23 Mar 2007 11:07:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:236750c7-e455-40bd-a917-a4221e8c0925</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/03/23/solution-probleming</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/6110</trackback:ping>
    </item>
    <item>
      <title>Many</title>
      <description>&lt;p&gt;We&amp;#8217;ve talked about Zero, and One, so all that&amp;#8217;s left of the big Three Numbers is &amp;#8220;many&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;Many is more than one. More than one object that must be used in the same way, more than one implementation of an algorithm, more than one implementation of an interface.  An &lt;span class="caps"&gt;API&lt;/span&gt; wrapper implemented once for production, and once for testing is Many.  One real object and one mock is Many.&lt;/p&gt;


	&lt;p&gt;Many gives power to the Liskov Substitution Principle.  If there are many (more than one) objects to be used in the same way, then it is imperative that an interface is created for them so that they may be used interchangeably (transparently) by the client.&lt;/p&gt;


	&lt;p&gt;Many objects of the same interface (&amp;#8220;type&amp;#8221;) may be used one-at-a-time (by reference) or in groups (containers and loops).  We don&amp;#8217;t write code that calls A and B and C in the same way because that would be &amp;#8220;three&amp;#8221; and we don&amp;#8217;t believe in 3.  We believe in Many.  It&amp;#8217;s a loop over a list.   If we&amp;#8217;re treating the objects similarly, we should exalt the similarity by putting them in a loop, rather than stress individuality by coding two statements for making the call.&lt;/p&gt;


	&lt;p&gt;By the way, don&amp;#8217;t confuse Many with &amp;#8220;two things with similar structure&amp;#8221;.   Many refers to &amp;#8220;more than one thing with similar usage&amp;#8221; in the &lt;span class="caps"&gt;LSP&lt;/span&gt;-compliant sense. It doesn&amp;#8217;t demand that you create base classes to capture some essential similarities, only that you create interfaces and loops as required.&lt;/p&gt;


	&lt;p&gt;In a multi-generational GC, the theory is that some things by nature have short lifespans, and others by nature have long lifespans.  Most objects are created and deleted, and a few may make it to the third-generation cache where they&amp;#8217;re almost never examined (comparatively) for collection.  Many has a similar theory.  Objects that occur once are singular things, but once they start to multiply they are expected to multiply more in the future.  Not only does the &amp;#8220;interfaces &amp;#38; loops&amp;#8221; keep the code clean, it recognizes the Many things as an extension point in the code.  That&amp;#8217;s double-benefit if we listen to our code as it goes from one to many.&lt;/p&gt;</description>
      <pubDate>Fri, 23 Mar 2007 11:01:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ae4739e7-8fe9-45b8-85ae-bbfdcf718d64</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/03/23/many</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/6108</trackback:ping>
    </item>
    <item>
      <title>Zero</title>
      <description>&lt;p&gt;Clarity of code is a signal-to-noise ratio.  We need our code to be as concisely meaningful as possible (not as cramped and crowded as possible, and not unnecessarily spread out over many pages).  Whatever size provides the most accurate and quickest reading for trouble-shooting and enhancement is the best size.&lt;/p&gt;


	&lt;p&gt;On one of my past projects, we found ourselves able to remove a lot of dead code and as we added new features we were also able to simplify a lot of existing code.  This is a very good thing, since code is a liability and functionality is an asset (I&amp;#8217;ll elaborate more on that at a later date).&lt;/p&gt;


	&lt;p&gt;However, my manager was secretly reporting our progress in terms of lines of code/week.  I was called on the carpet after some very productive weeks of producing unusually clean code.  My manager&amp;#8217;s problem was that we had been averaging over 200 lines &lt;strong&gt;less&lt;/strong&gt; per week. By making the system cleaner and smaller, we were being reported as making negative progress, and were ordered to stop!&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s just another &amp;#8220;bad metrics&amp;#8221; story, but it underscores an unspoken assumption that code should always grow bigger over time.&lt;/p&gt;


	&lt;p&gt;One non-zero-respecting practice is that of commenting-out code and leaving it.  people have to scroll around the code, reading bits above and below, and so it is really just a speed bump for those who are trying to learn.  It&amp;#8217;s worse if the code is inside some nested level of a function than if  an entire function is commented out.   This is unnecessary, because a version control system holds the old code and can restore it if you really need it again (if not, consider a new &lt;span class="caps"&gt;VCS&lt;/span&gt;).  Commented code is redundant with the &lt;span class="caps"&gt;VCS&lt;/span&gt;, in addition to being a nuisance.&lt;/p&gt;


	&lt;p&gt;Zero isn&amp;#8217;t all really about comments, but about noise in general.  Systems often have &amp;#8216;dead code&amp;#8217;, code which is never used but never deleted.  When there are insufficient tests, one is unsure of coverage and cannot tell if a piece of code is being used or not.  That means that code with zero use may have non-zero occurrences.  In such systems, it can be very dangerous to remove code at all.  Since the rule of zero is not respected, code accumulates.&lt;/p&gt;


	&lt;p&gt;Zero also will have us remove abstractions and interfaces when we no longer need them.&lt;/p&gt;


	&lt;p&gt;Zero tells us to remove tests when they&amp;#8217;re no longer valuable.&lt;/p&gt;


	&lt;p&gt;Zero is a good idea.&lt;/p&gt;


	&lt;p&gt;I just located an old &lt;a href="http://www.extragroup.de/weblog/hmk/archives/003824.html"&gt; Jeff Atwood quote&lt;/a&gt; that lights up a few of the same synapses.&lt;/p&gt;</description>
      <pubDate>Thu, 22 Mar 2007 12:23:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:27952b15-e337-46f3-8d9d-95d02be51d61</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/03/22/zero</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/5717</trackback:ping>
    </item>
    <item>
      <title>One</title>
      <description>&lt;p&gt;I posted earlier about the three numbers of software design (zero, one, many).  Zero and Many are numbers we see pretty often, but the rise of &lt;span class="caps"&gt;TDD&lt;/span&gt; has made &amp;#8220;one&amp;#8221; just a little bit lonelier. I wanted to say that one is the loneliest number, but David Chelimsky beat me to it several months ago, and I would just feel like a copycat.&lt;/p&gt;


	&lt;p&gt;When we&amp;#8217;re test-driving an application into existence, we tend to create mock objects.  The presence of one mock object in addition to one real object places is firmly in the design space of &amp;#8220;many&amp;#8221;, and so interfaces  become the rule of the day.&lt;/p&gt;


	&lt;p&gt;In addition, we have dependency management to deal with.  In order to reduce the D metric on a package, we find ourselves often breaking a class into an interface (increasing A) and an implementation that depends upon it (increasing I) in a separate package.&lt;/p&gt;


	&lt;p&gt;Of course, the &amp;#8220;other question&amp;#8221; is volatility.  If we have one implementation of something small and simple in a domain that is very stable then we don&amp;#8217;t need any interface and &amp;#8220;one&amp;#8221; takes center stage.  This is true for whole value objects (fowler) in general.  If the class is more complex, or dependent on special hardware or changing algorithms, then we end up creating a mock (driving us back to &amp;#8220;many&amp;#8221;).&lt;/p&gt;


	&lt;p&gt;But the number one is becoming more and more rare in our design world.&lt;/p&gt;</description>
      <pubDate>Wed, 21 Mar 2007 09:17:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ed167d57-6430-4d3b-a15d-b622216c33a5</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/03/21/one</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/5209</trackback:ping>
    </item>
    <item>
      <title>The Three Numbers</title>
      <description>&lt;p&gt;There are only three numbers that are truly meaningful in software design.  The numbers are the same as the numbers in relational database design: zero, one, and many.&lt;/p&gt;


	&lt;p&gt;Zero: if a condition, circumstance, requirement does not exist, then no code should exist (commented or uncommented) to deal with it.  This is true for requirements we haven&amp;#8217;t seen (future proofing), but is also true for requirements which have some and gone.  When a test, function, variable, or class has zero uses, it must be deleted.  Recognizing the power of zero helps us keep our code clean.&lt;/p&gt;


	&lt;p&gt;One: A condition or class, event or circumstance, role or behavior exists, and so we must code for it.  There is a limit on how much insulation and abstraction is needed.  We can keep things very simple.  Moving from zero to one (adding a requirement) is the typical operation, but moving from one to zero also happens.&lt;/p&gt;


	&lt;p&gt;Many: More than one is &amp;#8220;many&amp;#8221;.  You might as well consider adding a list and/or interfaces.  In design, some things repeat and some do not.  Those that repeat are likely to continue repeating.  Therefore, &lt;strong&gt;many&lt;/strong&gt; is represented first by the value of two.   Where there are many, there needs to be some insulation.  The open-closed principle tells us that we should open the system for extension.  The usual case in design is moving from one to many, but sometimes one will move in the opposite direction by removing interfaces or lists.&lt;/p&gt;


	&lt;p&gt;The transitions in either direction are important design events.&lt;/p&gt;</description>
      <pubDate>Tue, 20 Mar 2007 11:27:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:e05f29e8-2d86-4ef0-8be4-292c8096aa5f</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/03/20/the-three-numbers</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/4478</trackback:ping>
    </item>
    <item>
      <title>It's All Iterative</title>
      <description>&lt;p&gt;People say &amp;#8220;we don&amp;#8217;t do iterative&amp;#8221;.  Sometimes it is a prideful thing, more often a kind of self-effacing confession.  However, you and I know that it&amp;#8217;s not true.  All software development is iterative, it&amp;#8217;s a matter of granularity.&lt;/p&gt;


	&lt;p&gt;When working on the very first 1.0 release of a product, developers and managers may think that they&amp;#8217;re not doing iterative work, but any idiot knows that they&amp;#8217;re not writing all the code at once.  They couldn&amp;#8217;t possibly.  They&amp;#8217;re not releasing yet, but they&amp;#8217;re appending functionality every day.&lt;/p&gt;


	&lt;p&gt;They try to design all at once, but that&amp;#8217;s just for 1.0.  Software is like a plan: it never survives contact with the real world unscathed.&lt;/p&gt;


	&lt;p&gt;After 1.0 do we cancel the project? If so, it&amp;#8217;s a failure.  After 1.0 is 1.0.1 or 1.1 or 2.0.  The project continues and continues to receive new appendages and improvements.  Isn&amp;#8217;t the whole idea of &amp;#8220;next release&amp;#8221; an iteration?&lt;/p&gt;


	&lt;p&gt;Since you&amp;#8217;re really iterating anyway, why not capture the data that iterating produces, and why not take advantage of the integration and testing opportunities that iterating will give us? And why not have useful feedback loops?  And why not measure our progress as we go?    And for that matter, why &lt;strong&gt;not&lt;/strong&gt; go for smaller measured periods so we can judge trends more reliably?&lt;/p&gt;


	&lt;p&gt;When we say &amp;#8220;it isn&amp;#8217;t an incremental and iterative effort&amp;#8221; we are really saying that we&amp;#8217;re denying a basic truth, and choosing not to use the data it produces for us.  Not intentionally, but almost certainly.&lt;/p&gt;</description>
      <pubDate>Fri, 16 Mar 2007 09:38:55 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:26adf6fa-35a6-492d-b98b-1593716f941a</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/03/16/its-all-iterative</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/3362</trackback:ping>
    </item>
    <item>
      <title>Outliving The Great Variable Shortage</title>
      <description>&lt;p&gt;One of the more annoying problems in code, confounding readability and maintainability, frustrating test-writing, is that of the multidomain variable.&lt;/p&gt;


	&lt;p&gt;I suppose somebody forgot to clue me in to the Great Variable Shortage that is coming.  I have seen people recycling variables to mean different things at different times in the program or different states of the containing object.   I&amp;#8217;ve witnessed magic negative values in variables that normally would contain a count (sometimes as indicators that there is no count, much as a &lt;span class="caps"&gt;NULL&lt;/span&gt;/nil/None would).  I might be willing to tolerate this in programming languages where a null value is not present.&lt;/p&gt;


	&lt;p&gt;Yet I have seen some code spring from multidomain variables that made the code rather less than obvious.  I think that it can be a much worse problem than tuple madness.&lt;/p&gt;


	&lt;p&gt;I have a rule that I stand by in OO and in database design, and that is that a variable should have a single, reasonable domain.   It is either a flag or a counter. It is either an indicator or a measurement.  It is never both, depending on the state of something else.&lt;/p&gt;


	&lt;p&gt;It is sort of like applying Curly&amp;#8217;s law (Single Responsibility Principle) to variables.  A variable should mean one thing, and one thing only.  It should not mean one thing in one circumstance, and carry a different value from a different domain some other time.  It should not mean two things at once.  It must not be both a floor polish and a dessert topping.  It should mean One Thing, and should mean it all of the time.&lt;/p&gt;


	&lt;p&gt;Surely I&amp;#8217;ll take a shot from someone citing the value of a reduced footprint, and I won&amp;#8217;t argue very long about the value of usinge only as much memory as you must. In C++ I was a happy advocate of bitfields.  I haven&amp;#8217;t been overly vocal about using various data-packing schemes, but I think that it can be a reasonable choice for compressing many values into a smaller space, but I will maintain that multipurpose variables are a bad idea, and will damage the readability of any body of code.&lt;/p&gt;


	&lt;p&gt;I suggest, in the case of constrained footprint where there truly is a Great Variable Shortage (&lt;acronym title="tm"&gt;GVS&lt;/acronym&gt;) that &lt;strong&gt;if&lt;/strong&gt; (and that&amp;#8217;s a big &lt;strong&gt;if&lt;/strong&gt;) the author absolutely &lt;span class="caps"&gt;MUST&lt;/span&gt; repurpose variables on the fly that it is the lot of that programmer to make sure that users of the class/struct never have to know that it is being done. Never.  Including those writing unit tests.  The class will have to keep data-packing and variable-repurposing as a dirty secret.&lt;/p&gt;


	&lt;p&gt;Perhaps a strong statement or two in rule-form should be made here:&lt;/p&gt;


&lt;ol&gt;
&lt;li&gt;A variable should have a &lt;span class="caps"&gt;SINGLE DOMAIN&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;One must &lt;span class="caps"&gt;NEVER GET CAUGHT&lt;/span&gt; repurposing a variable.&lt;/li&gt;
&lt;/ol&gt;

	&lt;p&gt;We don&amp;#8217;t have to make do with the smallest number of variable &lt;strong&gt;names&lt;/strong&gt; possible. Try to learn to live in plenty: use all the variables you want.  For the sake of readability, consider having a single purpose for every variable not only at a given point in time, but for the entire program you&amp;#8217;re writing.&lt;/p&gt;</description>
      <pubDate>Mon, 26 Feb 2007 23:07:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:034f8e03-88f4-441e-8619-91698d8c9c61</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/02/26/outliving-the-great-variable-shortage</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/275</trackback:ping>
    </item>
    <item>
      <title>PySweeper: Un-refactoring, Tuple Madness, and Injection</title>
      <description>&lt;p&gt;&lt;p&gt;I figure that to understand the code before me, I need to
  start testing. I&amp;#8217;ll start with the constructor. The
  constructor actually is doing a lot of work. In order to test out
  my refactoring tools, I recklessly broke out two routines without
  adding any testing. I don&amp;#8217;t recommend that on any project that
  needs to work, but I also don&amp;#8217;t recommend using a real product to
  learn your tools.&lt;/p&gt;

&lt;p&gt;Today, the constructor looks something like this:&lt;/p&gt;
&lt;pre&gt;
    def __init__( self, rows = 16, cols = 16, mines = 10): # 40 ):
        """Initialize the playing field.

        This function creates a playing field of the given size, and randomly
        places mines within it.

        rows and cols are the numbers of rows and columns of the playing  field, respectively.  
        mines is the number of mines to be placed within the field.
        """ 
        self._validate_parameters( rows, cols, mines )

        self.rows = rows
        self.cols = cols
        self.mines = mines
        self.cleared = 0
        self.flags = 0
        self.start_time = None

        minelist = []
        self.freecoords = {}
        for col in range( cols ):
            self.freecoords[col] = range( rows )

        self._place_mines( mines, minelist )

        self.board = []
        for col in range( cols ):
            self.board.append( [( -2, 0 )] * rows )
            for row in range( rows ):
                if ( row, col ) in minelist:
                    self.board[col][row] = ( -1, 0 )

    def _validate_parameters( self, rows, cols, mines ):
        for var in ( rows, cols, mines ):
            if var &amp;lt; 0:
                raise ValueError, "all arguments must be &amp;gt; 0" 
        if mines &amp;gt;= ( rows * cols ):
            raise ValueError, "mines must be &amp;lt; (rows * cols)" 

    def _place_mines( self, mines, minelist ):
        while mines &amp;gt; 0:
            y = random.choice( self.freecoords.keys() )
            x = random.randrange( len( self.freecoords[y] ) )
            minelist.append( ( self.freecoords[y][x], y ) )
            del self.freecoords[y][x]
            if not self.freecoords[y]:
                del self.freecoords[y]
            mines = mines - 1
&lt;/pre&gt;

&lt;p&gt;I feel a little guilty for breaking out functions without
testing them. I start to write tests for
&lt;code&gt;_validate_parameters&lt;/code&gt;, but I cannot call it
in isolation. I have to have an instance of Field to call it, and
it is also called in Field&amp;#8217;s constructor.  I can&amp;#8217;t test weird values
as easily as I&amp;#8217;d like. I need something like a static method (c++/java).
I add the &lt;code&gt;@classmethod&lt;/code&gt; decorator and I can
call it freely from my unit tests.&lt;/p&gt;

&lt;p&gt;I remind the reader that the game runs and is playable, so the
addition of tests should pretty much be a bit of pedantic
formalism in preparation for refactoring. However, look at the
code carefully and see if you can see a loophole:&lt;/p&gt;
&lt;pre&gt;
    @classmethod
    def _validate_parameters( self, rows, cols, mines ):
        for var in ( rows, cols, mines ):
            if var &amp;lt; 0:
                raise ValueError, "all arguments must be &amp;gt; 0
        if mines &amp;gt;= ( rows * cols ):
            raise ValueError, "mines must be &amp;lt; (rows * cols)" 

&lt;/pre&gt;
&lt;p&gt;A perceptive reader will realize that the code is checking that the
value is &lt;em&gt;less than&lt;/em&gt; zero, but reporting that it must be &lt;em&gt;greater
than&lt;/em&gt; zero. I found this with tests before it jumped out at me
visually.&lt;/p&gt;

&lt;p&gt;I write and run several tests and then get a nag from PyDev.
I guess somehow I missed the part where PyDev told me it was not
free software. The nag messages tells me I&amp;#8217;m in a  trial period
and I&amp;#8217;m expected to eventually buy or quit. Bummer.  PyDev is
not expensive. I just have to decide if I want to afford it.&lt;/p&gt;
&lt;p&gt;I am also playing with
&lt;a href="http://www.die-offenbachs.de/detlev/eric.html"&gt;Eric3&lt;/a&gt;
which is a python-specific &lt;span class="caps"&gt;IDE&lt;/span&gt; with refactoring, and it seems to
have better integration with PyUnit. It is not as nice in terms
of automatic completion and seems to have trouble with the context
menu for refactoring. I immediately miss the cool way that PyDev would
stick the word &amp;#8220;self&amp;#8221; in so I didn&amp;#8217;t have to type it.&lt;/p&gt;

&lt;p&gt;In the last installment, I extracted a method called &lt;code&gt;_place_mines&lt;/code&gt; but
it&amp;#8217;s a bit hard to test.  It&amp;#8217;s actually a very poor refactoring, done to test a 
tool and not really to improve the code. As is, it wants to muck about with an &lt;a href="http://tottinge.blogsome.com/2007/02/12/the-unspoken-parameter/"&gt;
unspoken parameter&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;
    def _place_mines( self, mines, minelist ):
        while mines &amp;gt; 0:
            y = random.choice( self.freecoords.keys() )
            x = random.randrange( len( self.freecoords[y] ) )
            minelist.append( ( self.freecoords[y][x], y ) )
            del self.freecoords[y][x]
            if not self.freecoords[y]:
                del self.freecoords[y]
            mines = mines - 1  

&lt;/pre&gt;

&lt;p&gt;It&amp;#8217;s small, but not obvious. Nor is it tested. It is using
&lt;code&gt;freecoords&lt;/code&gt; rather heavily. Breaking out
that method was a mistake, and I put it back inline. It seems that
&lt;code&gt;freecords&lt;/code&gt; is a list of all the positions in the grid that do
&lt;em&gt;not&lt;/em&gt; contain mines. It is only used in the constructor
and one other place.  In the other place, it&amp;#8217;s used and then
deleted from the object.&lt;/p&gt;

&lt;p&gt;The names of variables &lt;code&gt;mines&lt;/code&gt; and
&lt;code&gt;minelist&lt;/code&gt; aren&amp;#8217;t helpful because the names mean the
same thing, even though the variables do not. They each mean
&lt;em&gt;more than one mine&lt;/em&gt;, but one is an integer count and the
other is a list of the coordinates of the mines. That should
change right away. I rename the integer to &lt;code&gt;numberOfMines&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;__init__&lt;/code&gt; reconstituted, I notice that I
don&amp;#8217;t even keep the minelist. It&amp;#8217;s discarded at the end of the
&lt;code&gt;__init__&lt;/code&gt;method. Maybe I can do this more simply.&lt;/p&gt;

&lt;p&gt;I realize now that the code suffers from &lt;em&gt;Tuple
Madness&lt;/em&gt;. The cells are represented by two-tuples. The first 
and second item are not distinguished by a name, only by subscripts 0 and
1. There can hardly be anything less descriptive of the content.
The initial values are (-2,0), but sometimes they are replaced 
with (-1,0). The code gives no obvious guidance to the significance 
of the first parameter versus the second parameter, and no real 
guide to the meaning of the integer-coded values. If one were 
going to document this code, it would be helpful to explain the
use of anonymous data structures. Of course, that&amp;#8217;s selfish because
my goal is to obviate any comments I find.  I just want it to be
easy.&lt;/p&gt;

&lt;p&gt;I dig in and discover that subscript
zero really is the count of adjacent cells with mines.  Since 
you can&amp;#8217;t have less than zero mines, the number -2 tells us that
we&amp;#8217;ve not counted yet. The number -1 is a code telling us that
the cell itself contains a mine. I&amp;#8217;ll want to split these out
later into named attributes.&lt;/p&gt;

&lt;p&gt;Tuple Madness is such an easy trap to fall into with Python or Ruby
(and I&amp;#8217;m told Lisp as well).
Each has such great native tuple and list types that we may 
forget to create real data structures for small data sets. I&amp;#8217;ve 
done it, the PySweeper author fell into it, and so have my
coworkers. If we had n-tuples in C, the resulting code would have
been so inscrutible that the software practice might never have
recovered. Yet two-tuples can be very good things. Just not here. 
I vow to create a data structure for the
cell as soon as I have this body of code sufficiently under test.&lt;/p&gt;

&lt;p&gt;As I learn about the two-tuples I write a couple of tests,
as if there were more descriptive functions.  I write calls to
such functions as &lt;code&gt;hasAMine()&lt;/code&gt; to check if subscript
zero has a -1 value, and &lt;code&gt;cellAt&lt;/code&gt; to get a cell at a 
given location, etc. Explanatory functions are a powerful documentation
technique 
&lt;pre&gt;
    def cellAt(self, x, y):
        return self.board[x][y]

    def isOpened( self, x, y ):
        return self.cellAt(x, y)[1] == -1

    def countAt(self, x,y):
        result = self.cellAt(x,y)[0]
        if result &amp;lt; 0:  result = None  # indicator value
        return result

    def hasMine(self, x,y):
        return self.cellAt(x,y)[0] == -1
  &lt;/pre&gt;
I have a small-but-growing body of tests. I should soon 
have enough confidence to do bigger refactorings.&lt;/p&gt;

&lt;p&gt;Note the ugly comment in &lt;code&gt;countAt&lt;/code&gt;. This is variable
reuse.  Rather than have a separate indicator (another element in
the tuple maybe), one element is serving double-duty.  It is too 
entrenched right now, so I&amp;#8217;ll work on making it obvious and easier
to separate later. Soon my body of explanatory methods will compose 
an opaque interface, and  there will be little or no upset when I 
change the implementation of those methods.&lt;/p&gt;

&lt;p&gt;Note also that we&amp;#8217;re in violation of the &lt;span class="caps"&gt;SRP&lt;/span&gt;. The class has methods
related to the field and also to specific cells in the board.  Maybe
I will eventually have classes for the cells, the game, and the board.&lt;/p&gt;

&lt;p&gt;Time to stop reading and do more testing. I did learn enough
to know that the game tries to be &amp;#8220;fair&amp;#8221;.  If there is a mine
on the very first square you select, it moves it out of the 
way. My &amp;#8220;gaming the system&amp;#8221; gene took over. I should be able 
to fill a three-by-three grid with eight mines, and then 
click (open) the center square.  That should guarantee me that
I have this structure:
&lt;table&gt;
    &lt;tr&gt;&lt;td&gt;mine&lt;/td&gt;&lt;td&gt;mine&lt;/td&gt;&lt;td&gt;mine&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;mine&lt;/td&gt;&lt;td&gt;empty&lt;/td&gt;&lt;td&gt;mine&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;mine&lt;/td&gt;&lt;td&gt;mine&lt;/td&gt;&lt;td&gt;mine&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
The more astute reader knows that this disregards
the first rule of testing: &lt;em&gt;Control The Environment&lt;/em&gt;.  I 
should take control of the placement of mines rather than testing
the system with random mine placement.&lt;/p&gt;

&lt;p&gt;Sure enough, I find that the routine
that moves the mine to a new spot is not working quite as expected.
Now I have a failing test which allows me to make changes to the 
randomizer. I fix it, and then decide to pull the random chooser into 
a separate class. It will behave according to the &lt;code&gt;iterator&lt;/code&gt; 
protocol in Python so I can pass a simple array of (col,row] pairs to 
the constructor as a testing stub/mock/thing.&lt;/p&gt;

  &lt;p&gt;Now the top of my file has the random cell chooser.  There are some named constants, the 
  still-busy &lt;code&gt;__init__&lt;/code&gt; method, the now-tested &lt;code&gt;_validate_parameters&lt;/code&gt;
  method, and then other code we&amp;#8217;ve either talked about already or haven&amp;#8217;t touched yet.&lt;/p&gt;  
&lt;pre&gt;

random.seed()

class random_cell_chooser(object):
    def __init__(self, columns, rows):
        self.choices = [ (x,y) for x in range(columns) for y in range(rows) ]
    def next(self):
        if len(self.choices) == 0:
            raise StopIteration, "Out of free cells" 
        item = random.choice(self.choices)
        self.choices.remove(item)
        return item

INITIALLY_EMPTY = ( -2, 0 )
INITIALLY_MINED = ( -1, 0 )

class Field:
    """Provide a playing field for a Minesweeper game.

    This class internally represents a Minesweeper playing field, and provides
    all functions necessary for the basic manipulations used in the game.
    """ 
    def __init__( self, rows = 16, columns = 16, numberOfMines = 40, chooser=None):
        """Initialize the playing field.
        """ 

        self._validate_parameters( rows, columns, numberOfMines )

        self.rows = rows
        self.cols = columns
        self.mines = numberOfMines
        self.selector = chooser or random_cell_chooser(columns,rows)
        self.cleared = 0
        self.flags = 0
        self.start_time = None

        self.board = []
        for col in range( columns ):
            self.board.append( [INITIALLY_EMPTY] * rows )

        for counter in range(numberOfMines):
            (col,row) = self.selector.next()
            self.board[col][row] = INITIALLY_MINED

    @classmethod
    def _validate_parameters( self, rows, cols, mines ):
        for var in ( rows, cols, mines ):
            if var &amp;lt; 0:
                raise ValueError, "all arguments must be &amp;gt; 0" 
        if mines &amp;gt;= ( rows * cols ):
            raise ValueError, "mines must be &amp;lt; (rows * cols)" 

  &lt;/pre&gt;

&lt;p&gt;An engineer friend of mine is fond of saying &amp;#8220;suspenders 
and belt&amp;#8221;, referring to having redundant safety mechanisms.
I&amp;#8217;m appreciating the value of both a good version control system 
and a growing set of tests.  I am aware of the quality of the code
I&amp;#8217;m modifying (whether it passes all the tests) and that I can 
always abandon a change I&amp;#8217;m making if it gets messy. 
&lt;/p&gt;

&lt;p&gt;My little test is building that three-by-three grid and playing
 a very simple game to completion by opening the middle square. 
 I am testing setup and a bit of gameplay. I&amp;#8217;ll put a better test
 in tomorrow.&lt;/p&gt;

&lt;p&gt;It is a simple thing to extract the method for placing the mines
and pass it to the constructor for &lt;code&gt;Field&lt;/code&gt;.  Now I can 
set the mines just where I want them, giving me total control of the
field constructor.  I make it act like an iterator so my tests can 
pass a list iterator to the constructor:
&lt;pre&gt;

class random_cell_chooser(object):
    def __init__(self, columns, rows):
        self.choices = [ (x,y) for x in range(columns) for y in range(rows) ]
    def next(self):
        if len(self.choices) == 0:
            raise StopIteration, "Out of free cells" 
        item = random.choice(self.choices)
        self.choices.remove(item)
        return item

  &lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;Because the tests are new and few, I&amp;#8217;m also playing (losing) a game 
of minesweeper every so often so that I know that it still beats me in
reasonable ways.  I can&amp;#8217;t wait until I can depend entirely on automated
tests. Maybe in this way, it would have been better to have some basic
acceptance tests before working in unit tests. It&amp;#8217;s a thought.&lt;/p&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 17 Feb 2007 13:02:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:ab049910-92f7-40e5-9825-ab1c4fa5ee0f</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/02/17/un-refactoring-tuple-madness-and-injection</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/187</trackback:ping>
    </item>
    <item>
      <title>PySweeper: Python test collector</title>
      <description>&lt;p&gt;I wrote a number of separate test files for the pysweeper refactoring exercise, and very quickly got tired of running them all individually.  I created a stupid test composite tool and I run this one instead.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s what it is looks like right now.&lt;/p&gt;


&lt;pre&gt;
import os
import unittest
import sys

def collect_tests(directoryName):
    """Gather all tests matching "test*.py" in the current directory""" 
    alltests = []
    for filename in os.listdir(directoryName):
        if filename.startswith('test') and filename.endswith('.py'):
            module = __import__(filename.replace(".py",""))
            for item_name in dir(module):
                item = getattr(module,item_name)
                if isinstance(item,type) and issubclass(item,unittest.TestCase):
                    test = unittest.makeSuite(item)
                    alltests.append(test)
    return alltests

def suite():
    "Collect all local tests into a monster suite" 
    suite = unittest.TestSuite()
    here = os.path.dirname(sys.argv[0]) or os.getcwd()
    alltests = collect_tests(here)
    suite.addTests(alltests)
    return suite

if __name__ == "__main__":
    tester = unittest.TextTestRunner()
    tester.run(suite())
&lt;/pre&gt;

	&lt;p&gt;Thre may be easier ways or better ways, but right now I don&amp;#8217;t know them. I figure it will be good enough until I learn something cooler.  I can think of several ways to extend it, but don&amp;#8217;t need them.&lt;/p&gt;</description>
      <pubDate>Sat, 17 Feb 2007 12:00:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:0db095b1-a599-42ec-81d7-0a82ed28bbfc</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/02/17/pysweeper-python-test-collector</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/186</trackback:ping>
    </item>
    <item>
      <title>Seed-And-Harvest Considered Harmful</title>
      <description>&lt;p&gt;Quite a while back I complained that a class is not a &lt;span class="caps"&gt;BASIC&lt;/span&gt; program, and more recently I blogged on my personal site about The Unspoken Parameter, but on further consideration I realize that these are both aspects of larger, well-known problem that vexes developers.&lt;/p&gt;


	&lt;p&gt;The real problem is the idea of seeding a function&amp;#8217;s input in various places and then calling the program, and then harvesting the function&amp;#8217;s results from the surrounding environment.  This indirect access to input and output is troublesome and frustrates maintenance.&lt;/p&gt;


	&lt;p&gt;Seed-and-harvest programming was common in &lt;span class="caps"&gt;BASIC&lt;/span&gt; &amp;#8220;gosub&amp;#8221; programming, and I see it in some command line programs too.  I see it in classes where methods take no parameters and have no return values and you must seed and harvest the object&amp;#8217;s fields to make a successful test.  I see it happening in poorly extracted test methods. I see it in java programs where you have to have a host of environment variables and files and command line parameters all set up to be harvested by the program.&lt;/p&gt;


	&lt;p&gt;Seed-and-harvest is daft.  Every program is composed of input, process, output. We try to simplify and focus processing, but still I find code that does not take the same degree of care with input and output.&lt;/p&gt;


	&lt;p&gt;Since seed-and-harvest are bad, the degree to which the input and output are formal and direct is a goodness.  It isn&amp;#8217;t the only measure of goodness, but it is a goodness.&lt;/p&gt;


	&lt;p&gt;If I can call a function, passing everything it needs to know, and it returns a value indicating everything it has done for me, then I have an optimally direct and formal interface.  Barring foolish and meaningless naming (or personal inability), I should be able to understand what it does fairly easily and without error.  It is also far more likely to work in multithreaded environments, by the way.&lt;/p&gt;


	&lt;p&gt;If I must set environment variables or manipulate global data stores or even local data structures in order to call a function, then I have diluted the interface by relying on input seeding.&lt;/p&gt;


	&lt;p&gt;After calling a function, if I must to collect its output from the environment, global data structures, or local data structures, or various fields of the function&amp;#8217;s object/class/module then the interface is diluted by harvesting.&lt;/p&gt;


	&lt;p&gt;An example of good here is a sensor object that emits a reading.  The method to get a reading is obvious, clean, and likely to be thread-safe.  A less good solution would leave the reading data in data fields of the sensor to be collected by a series of accessor calls.  It defocuses the class re: &lt;span class="caps"&gt;SRP&lt;/span&gt;, while creating risk of update anomalies. It requires more effort from its clients than if it returned a reading.&lt;/p&gt;


	&lt;p&gt;This principle leads to other well-known principles. Dependency injection is a solution to a problem of indirectness. The Law of Demeter makes sense in the sense that it reduces the degree a method must reach to collect its input and to place its output.&lt;/p&gt;


	&lt;p&gt;In OO programs, static functions often have the most direct and formal interfaces since they can&amp;#8217;t rely on instance variables.  We know that static functions have problems with regard to substitutability in &lt;span class="caps"&gt;TDD&lt;/span&gt;, so we may make them non-static functions by moving them to a class or passing them by reference (closures and blocks). But we can see how much easier it is to read static functions than members, since we seldom have to read their code to understand what they are doing (though we may open them up to see &lt;em&gt;how&lt;/em&gt;).&lt;/p&gt;


	&lt;p&gt;Objects with fields will exhibit some seed-and-harvest behavior to manage state and change of state, but we can preserve an otherwise direct formal interface with reference to callers of the object&amp;#8217;s methods. We should not have to call a function to cause an effect and then call a number of accessors to get the results, as this would indicate we&amp;#8217;ve diluted the interface with harvesting.  We need to understand and bear in mind that we&amp;#8217;re trading off some directness for convenience and encapsulation. If we know that we&amp;#8217;re making that tradeoff then we are better equipped to do it well.&lt;/p&gt;


	&lt;p&gt;In end-user experience, this becomes more important. Plenty has been said by others about &amp;#8220;direct manipulation&amp;#8221;.  They were wiser and earlier on the scene than myself; when it comes to &lt;span class="caps"&gt;UI I&lt;/span&gt; am still but an egg.&lt;/p&gt;


	&lt;p&gt;This concept is nothing new, even to me. I&amp;#8217;m not saying it because I think it is something new.  I&amp;#8217;m saying it because I think people need to keep hearing it. It is simple but also profound.&lt;/p&gt;</description>
      <pubDate>Thu, 15 Feb 2007 14:28:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:79f72241-637c-40f6-bd9c-5b70ca30df3a</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/02/15/seed-and-harvest-considered-harmful</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/178</trackback:ping>
    </item>
    <item>
      <title>Tuple Madness</title>
      <description>&lt;p&gt;If there is a downside to modern OO languages like Python and Ruby it is the great built-in list types.  They&amp;#8217;re wonderful, but they&amp;#8217;re tempting.&lt;/p&gt;


	&lt;p&gt;Today I had my fourth or fifth encounter with tuple madness.  It seems that the siren song of &amp;#8220;free&amp;#8221; data structures with unnamed members is just too much to resist.   I&amp;#8217;ve decided to call it Tuple Madness.  An example is:
     x = (2,3,-1)
Could one be less descriptive? Probably not.&lt;/p&gt;


	&lt;p&gt;I came across some code which uses two-tuples where both values are encoded integer values.  It&amp;#8217;s a pain to figure out.&lt;/p&gt;


	&lt;p&gt;In a previous job, a coworker would write his python entirely as filters on n-tuples so that figuring out what his code was doing was really painful.  A function would take a sequence of n-tuples, and return a sequence of n-tuples where some of the values were preserved (though reordered) from the input, and the rest were transformations on the input + some local data.  It was really tough to read a program where the data structures had unnamed elements and only existed between the return of one function and the invocation of the next.&lt;/p&gt;


	&lt;p&gt;At least one of my colleagues has blogged about suffering from Tuple Madness as well.&lt;/p&gt;


	&lt;p&gt;I don&amp;#8217;t think that &amp;#8220;magic tuples&amp;#8221; are always evil, only that they&amp;#8217;re no substitute for proper objects and meaningful data structures.&lt;/p&gt;</description>
      <pubDate>Tue, 13 Feb 2007 12:07:16 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:b18fdea8-0e28-4e06-a14d-2d778d940afe</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/02/13/tuple-madness</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/169</trackback:ping>
    </item>
    <item>
      <title>PySweeper: Digging In</title>
      <description>&lt;p&gt;In the last installment I got the source and started up the
  development environment.Now I start to play with the tools.&lt;/p&gt;

  &lt;p&gt;I start to peruse the source. Python programs are written a
  mix of paradigms, and this is something I love about it. Every
  variable is a first-class object, but not all methods have to be
  members of a class. You can have global functions (well,
  module-scoped) which are themselves first-class objects capable
  of having multiple methods and member variables, all
  participating in reflection/introspection. As such, some will
  describe the use of non-class-bound methods as &amp;#8220;procedural&amp;#8221;, and
  I suppose it&amp;#8217;s technically a fair cop. Some of the program is
  written in class-free functions, mostly the bits that are used to
  initialize the application.&lt;/p&gt;

  &lt;p&gt;Python also has a number of functional programming features,
  but I suspect that the 2002 copyright predates list
  comprehensions and generators, so I don&amp;#8217;t see them represented
  here. I will be using some of those techniques to simplify code
  that had to be written in loops and nested loops before. It
  should shorten a number of methods.&lt;/p&gt;

  &lt;p&gt;The PyGame UI and business logic (guts) of the code are
  separate modules with a protocol for communicating between the
  two. I was afraid that I would find them all intermingled, and
  was delighted to see separate modules. The core of the game
  itself is only a few hundred lines of code if I include comments,
  docstrings, and whitespace.&lt;/p&gt;

  &lt;p&gt;I know that the first order of business is to get some testing
  started, but I want so badly to to take Eclipse PyDev for a spin
  that I&amp;#8217;m having an impulse control problem. I think the code is
  formatted reasonably, but I use the Eclipse feature to reformat
  the code to see if it works. I&amp;#8217;m rewarded with equally attractive
  code. No damage is done!&lt;/p&gt;

  &lt;p&gt;The outlining feature works fine, and so does completion. I
  scribble a little and delete it. It&amp;#8217;s looking good so far. I
  notice that the &lt;code&gt;Run As..&lt;/code&gt; menu has options to run
  Python, Jython, PyUnit, Python coverage and more. It&amp;#8217;s looking
  good.&lt;/p&gt;

  &lt;p&gt;What of refactoring? Sure enough I find that I can rename,
  extract and inline variables, and extract and inline functions.
  Those are the biggies. I scroll into the constructor of the
  &lt;code&gt;Field&lt;/code&gt; class. The &lt;code&gt;Field&lt;/code&gt; represents the
  playing field of the game, the grid of bombs and clues. In the
  constructor are various paragraphs of code that help set up the
  class. I pick the section that adds mines, move some of the
  constants out of the way by extracting local variables, and then
  extract that portion of the function as
  &lt;code&gt;_place_mines&lt;/code&gt;. In Python no functions are private, so
  the standard protocol is to use an underscore prefix as a &amp;#8216;wart&amp;#8217;
  to tell other authors that it&amp;#8217;s not really part of the formal
  interface, just a convenience function for the class. Love it or
  hate it, that is just how it&amp;#8217;s done.&lt;/p&gt;

  &lt;p&gt;I do the same with the paragraph that validates the parameters
  (ie there are more than zero rows, columns, and mines, and that
  there are not more mines than cells in the grid). This becomes
  &lt;code&gt;_validate_parameters&lt;/code&gt;, and is called from the
  constructor (in Pythonese the constructor is a function named
  &lt;code&gt;__init__&lt;/code&gt;).&lt;/p&gt;

  &lt;p&gt;I find eight instance variables in &lt;code&gt;__init__&lt;/code&gt;.
  That&amp;#8217;s quite a few. I pledge to look for violations of the Single
  Responsibility Principle later.&lt;/p&gt;

  &lt;p&gt;It dawns on me that Eclipse doesn&amp;#8217;t know my current version
  control selection, &amp;lt;a href=
  &amp;#8220;http://en.wikipedia.org/wiki/Bazaar_(vcs)&amp;#8221;&amp;gt;bazaar.&lt;/a&gt; This
  distresses me, because all the Team features of Eclipse are lost
  to me. I won&amp;#8217;t be able to do all my checkin/update/diff functions
  from within the &lt;span class="caps"&gt;IDE&lt;/span&gt;. I vow to look for a plugin soonest. That&amp;#8217;s
  two promises, two items of debt so far. I will keep going
  today.&lt;/p&gt;

  &lt;p&gt;For now, I see a function called &lt;code&gt;_get_adjacent&lt;/code&gt;.
  It has a pretty simple function, but it looks like this:&lt;/p&gt;
  &lt;pre&gt;

    def _get_adjacent(self, x, y):
        """Provide a list of all tiles adjacent to the given tile.

        This function takes the x and y coordinates of a tile, and returns a
        list of a 2-tuples containing the coordinates of all adjacent tiles.

        x and y are the x and y coordinates of the base tile, respectively.
        """ 
        adjlist = [(x - 1, y - 1), (x, y - 1), (x + 1, y - 1),
                   (x - 1, y), (x + 1, y),
                   (x - 1, y + 1), (x, y + 1), (x + 1, y + 1)]
        rmlist = []
        for adjpair in adjlist:
            for value, index in [(-1, 0), (-1, 1), (self.cols, 0),
                                 (self.rows, 1)]:
                if adjpair[index] == value:
                    rmlist.append(adjpair)
                    break
        for item in rmlist:
            adjlist.remove(item)
        return adjlist

&lt;/pre&gt;It looked pretty heavy to me, for the small amount of work
it&amp;#8217;s doing. Ah, it had to use nested loops instead of list
comprehensions, and it&amp;#8217;s adding unnecessary rows only to remove
them later. I think I could do better if I had a body of tests to
protect me.

  &lt;p&gt;I figure it&amp;#8217;s time to try PyUnit inside Eclipse. I create a
  new file called testPysweeper.py. I hate the name, and again go
  against my better instincts by leaving it that for a while. That
  would be yet another promise, and I&amp;#8217;m running out of patience
  for procrastination.  I rename it &lt;code&gt;testAdjacency.py&lt;/code&gt;. 
  I feel an instant sense of relief and go on to write a
  series of tests of the existing &lt;code&gt;_get_adjacent&lt;/code&gt;
  method. It is&lt;/p&gt;

  &lt;pre&gt;
        class PySweeperTest(unittest.TestCase):
            def parentSetup(self, columns, rows, mines, target):
                target_column, target_row = target
                self.game = pysweeper.Field(columns,rows,mines)
                self.target = (target_column,target_row)
                self.result = self.game._get_adjacent_cells(*self.target)
                self.result.sort()

        class CellsAdjacentToCol2Row2(PySweeperTest):
            """Expecting a circle of squares around the target cell""" 
            def setUp(self):
                self.parentSetup(5,5,0, (2,2))
            def testShouldFindEightCells(self):
                assert len(self.result) == 8
            def testShouldNotIncludeCol2Row2(self):
                assert self.target not in self.result
&lt;/pre&gt;These are not highly imaginative, and continue with several
different scenarios. I test a normal &amp;#8220;middle&amp;#8221; cell, one against an
edge, the top left and bottom right corners, etc. &lt;/p&gt;

  &lt;p&gt;You&amp;#8217;ll notice the base class &lt;code&gt;PySweeperTest&lt;/code&gt;. I didn&amp;#8217;t have that to start with
  but added it to reduce duplication, and I named it badly.  These
  are not general PySweeper tests, but they are specific cell adjacency tests.  Naming is easily fixed.
  &lt;/p&gt;
  &lt;p&gt;  A cool thing happens.  I rename it &lt;code&gt;AdjacencyTest&lt;/code&gt; and 
  Suddenly all the test names become redundant and silly.  I 
  start renaming them, and 
  &lt;pre&gt;
  class CellsAdjacentToCol0Row0(PysweeperTest):
  &lt;/pre&gt;
  becomes
  &lt;pre&gt;
  class Column0Row0(AdjacencyTest):
  &lt;/pre&gt;
  On further reflection, this becomes:
  &lt;pre&gt;
  class UpperLeftCorner(AdjacencyTest):
  &lt;/pre&gt;
  It&amp;#8217;s amazing how wrong my first instinct can be.  The test is so much more
  obvious now, and the conditions make so much more sense.  I smile in mild
  self-derision, but I&amp;#8217;m happy to have cleaned it up quickly.  The PyDev 
  refactoring tools feel pretty comfortable to me now.  One goal of the exercise
  is being met.
  &lt;/p&gt;

  &lt;p&gt;
  The tests run for the old routine, and I write a new routine.
  &lt;/p&gt;

  &lt;p&gt;I hit my next snag trying to run the python unit test. I have 
  always done python from the
  command line, and would run my tests as if they were any other
  python program. I never did them as:&lt;/p&gt;
  &lt;pre&gt;
        python -m unittest filename.testname

&lt;/pre&gt;I think that this must be what Eclipse wants to do. I can use
the option to &lt;code&gt;Run as.../Python run&lt;/code&gt; but I cannot use
the option to &lt;code&gt;Run as.../Python unit-test&lt;/code&gt;. When I try I
get the following error:
  &lt;pre&gt;
  Finding files... ['/home/tottinge/Projects/Pysweeper-1.0/testAdjacency.py']
  done.
  Importing test modules... done.

  ----------------------------------------------------------------------
  Ran 0 tests in 0.000s

&lt;/pre&gt;It found the right test file, but either it didn&amp;#8217;t import it,
or else it imported it and somehow didn&amp;#8217;t recognize any tests. I
added a print line to the file so I could see it, and got nothing.
Why would it find my file and not import it? This is something that
requires a little google..&lt;/p&gt;
&lt;p&gt;It doesn&amp;#8217;t work when I use the &lt;code&gt;python -m unittest blah&lt;/code&gt;
either.  Maybe the problem isn&amp;#8217;t that I&amp;#8217;m not used to PyDev, but that
I don&amp;#8217;t know enough about PyUnit?  I put this off, since I have a
reasonable workaround for now. This is &lt;em&gt;another&lt;/em&gt; bit of debt
to work off.  I&amp;#8217;m unhappy at how fast it piles up.&lt;/p&gt;

  &lt;p&gt; The old version of &lt;code&gt;_get_adjacent&lt;/code&gt; was about 21 lines 
  with loops and local variables. Here is a smaller 
  version using list comprehensions:&lt;/p&gt;
  &lt;pre&gt;
   def _get_adjacent(self, x, y):
        """Provide a list of all tiles adjacent to the given tile.""" 
        columns = (x-1,x,x+1);
        rows = (y-1,y,y+1);
        adjacent_pairs = [ (col,row)  for col in columns 
                                      for row in rows 
                                      if 0&amp;lt;=row&amp;lt;self.rows and 0&amp;lt;=col&amp;lt;self.cols]
        adjacent_pairs.remove( (x,y) )
        return adjacent_pairs

&lt;/pre&gt;

  &lt;p&gt;A list comp is very simple. The one above returns a list of &lt;code&gt;(row,column)&lt;/code&gt;
  pairs by iterating over &lt;code&gt;columns&lt;/code&gt; and &lt;code&gt;rows&lt;/code&gt;, and only returns a pair if the
  &lt;code&gt;row&lt;/code&gt; and &lt;code&gt;column&lt;/code&gt; are both on the grid. But it doesn&amp;#8217;t look that simple above.
  My spider sense buzzes.  I immediately worry that the list comp is too complex.
  The filtering is too deep in the list comprehension and is too far from the initialization of
  &lt;code&gt;rows&lt;/code&gt; and &lt;code&gt;columns&lt;/code&gt;. A quick modification and retest.&lt;/p&gt;
  &lt;pre&gt;
    def _get_adjacent_cells( self, x, y ):
        """Provide a list of all tiles adjacent to the given tile.""" 
        columns = [ col for col in ( x-1, x, x+1) if 0&amp;lt;=col&amp;lt;self.cols ]
        rows = [ row for row in (y-1, y, y+1) if 0&amp;lt;=row&amp;lt;self.rows ]

        adjacent_pairs = [ ( col, row )  for col in columns for row in rows ]
        adjacent_pairs.remove( ( x, y ) )

        return adjacent_pairs  
&lt;/pre&gt;

  &lt;p&gt;The tests all pass, and the code is more obvious to me. I have no teammate
  to correct me, so I leave it as-is.&lt;/p&gt;

  &lt;p&gt;One more feature to look at today, and that&amp;#8217;s the
  &lt;code&gt;compare with local history&lt;/code&gt;. It&amp;#8217;s a beautiful thing.
  Eclipse is becoming a very good friend to me.&lt;/p&gt;</description>
      <pubDate>Sat, 10 Feb 2007 21:44:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:412dba24-24df-4e5f-8dff-87133f58bc6d</guid>
      <author>tottinger</author>
      <link>http://blog.objectmentor.com/articles/2007/02/10/pysweeper-digging-in</link>
      <category>Tim's Tepid Torrent</category>
      <trackback:ping>http://blog.objectmentor.com/articles/trackback/158</trackback:ping>
    </item>
  </channel>
</rss>

