<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'><id>tag:blogger.com,1999:blog-6488575</id><updated>2008-04-29T15:42:35.530-05:00</updated><title type='text'>Jeff's Blog</title><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/blog.shtml'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default?start-index=26&amp;max-results=25'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml'/><author><name>Jeff L.</name></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>84</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6488575.post-7044494957367332846</id><published>2008-04-28T22:49:00.004-05:00</published><updated>2008-04-29T15:42:35.566-05:00</updated><title type='text'>Revisiting BDD in Java</title><content type='html'>&lt;p&gt;My initial reaction a few years ago to BDD implementations in Java was less than stellar. Since then, I revisited them a couple times, and now I'm digging into them again. They're still around, so someone must be getting value out of them. I certainly have gotten some mileage around naming and organizing my tests in a more BDD fashion.
&lt;/p&gt;
&lt;p&gt;
Right now, I'm being lazy, and haven't done diligent research. But my initial internet searches suggest that there are a handful of tools, none of them the de facto standard. I remember my doctor once saying, "We have about a hundred ways to treat this [a plantar wart]. Usually when there are so many ways, it means we don't know what we're doing."
&lt;/p&gt;
&lt;p&gt;
I started looking at one framework in more depth, and coded some straightforward examples. Didn't seem so bad, until I looked to code a more involved assertion. Here's one (contrived but simple) example:
&lt;pre&gt;
Ensure.that(name, and(contains("Langr"), startsWith("J")));
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
One of the core principles of BDD is "getting the words right." I think this example demonstrates that sometimes we try too hard, and perhaps this construct isn't a great idea for Java. The "classic" approach is easily more expressive:
&lt;pre&gt;
assertTrue(name.contains("Langr") &amp;&amp; name.startsWith("J"));
&lt;/pre&gt;
or better...
&lt;pre&gt;
assertTrue(name.contains("Langr")
assertTrue(name.startsWith("J"));
&lt;/pre&gt;
or even...
&lt;pre&gt;
assertFirstInitialAndLastName(name, "J", "Langr");
&lt;/pre&gt;
I suppose my complaint could be tempered with the fact that these kinds of compound assertions don't occur so frequently.
&lt;/p&gt;
&lt;p&gt;
Yes, sure, the failure messages are better. That's not significant to me, given that I don't drive my development off of failure messages. Sure, all tests fail at least once, but I usually know why they're failing the first time, so I don't need that message initially. Later, when they fail for unknown reasons, more information might be useful (sometimes it is, not always), but if I need that, I just enhance the assertion I already have and rerun the tests. No big deal.
&lt;/p&gt;
&lt;p&gt;
Writing custom "matchers" is also an example in ugliness, given the limitations of Java. (I need to speed up my move to Groovy or Ruby, so I can stop whining about Java so much...)
&lt;/p&gt;
&lt;p&gt;
I won't give up on the Java BDD tools completely, but I'm not much happier now than I was three or so years ago.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/04/revisiting-bdd-in-java.html' title='Revisiting BDD in Java'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=7044494957367332846&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7044494957367332846'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7044494957367332846'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-8132879652948808518</id><published>2008-04-23T13:29:00.002-05:00</published><updated>2008-04-23T15:03:30.219-05:00</updated><title type='text'>What's the Next Test?</title><content type='html'>&lt;p&gt;I coded the "Roman numeral &lt;a href="http://codekata.pragprog.com/"&gt;kata&lt;/a&gt;" for the first time last night. I thought it was a reasonably straightforward exercise, but then I looked at the solutions of others by searching the web.
&lt;/p&gt;&lt;p&gt;
In agile, there's this notion of "doing the simplest thing that could possibly work," and I think it applies to TDD just fine. It helps keep me in the red-green-refactor rhythm. More importantly, it prevents me from pre-building complexity. It also keeps me in a mode of extreme incrementalism: DSTTCPW keeps teaching me how to truly grow a system incrementally, as agile demands.
&lt;/p&gt;&lt;p&gt;
From looking at the solutions on the web, however, I suspect that some people translate "do the simplest thing" to "don't think at all." Specifically, I'm referring to their progression of tests. At all times, once I complete a single test method, I spend some time &lt;em&gt;thinking&lt;/em&gt; about what the next test should be. I don't spend too much time, but nor do I blindly jump into the next apparently obvious test.
&lt;/p&gt;&lt;p&gt;
The task in the Roman numeral kata is to convert a positive integer to a Roman numeral. Doing this kata in a TDD fashion, the first test is converting 1 to I, which is a hard-coded return. The second test is converting 2 to II, which is simply done with an if statement. One might refactor at this step to a loop/count construct, or one might wait until 3 (III).
&lt;/p&gt;&lt;p&gt;
From 3, though, I noted that many of the coders insisted on jumping directly to 4 (IV). Certainly, this works, but most of the solutions I saw derived in this fashion either ended up more complex, or resulted in a fairly excessive solution that scaled back dramatically with some last-step refactoring.
&lt;/p&gt;&lt;p&gt;
One could argue that this is in the true spirit of incrementalism. After all, we should be able to tackle requirements in any order. Perhaps we need only support the numbers 1 through 4 initially, and later someone will insist on adding 5+.
&lt;/p&gt;&lt;p&gt;
An argument currently brewing on the &lt;a href="http://groups.yahoo.com/group/extremeprogramming"&gt;XP list&lt;/a&gt; goes into the whole YAGNI thing, with one poster suggesting that if you have comprehensive information, there is nothing wrong with taking that into account. Kent Beck subsequently &lt;a href="http://tech.groups.yahoo.com/group/extremeprogramming/message/141881"&gt;updated his take&lt;/a&gt; on YAGNI: "Here's what I do: consider &lt;em&gt;[forthcoming feature]&lt;/em&gt; a little, but try not to get so caught up in it that I freeze."
&lt;/p&gt;&lt;p&gt;
In a similar fashion, TDD doesn't mean "don't think." Determining the next test to write should incorporate some thought about what represents the simpler path to a more complete solution. Sometimes this is a guess, but with more experience, the wiser choices are more apparent. Sometimes you make the wrong choice, but you can still end up in the right place, particularly if you refactor with diligence.
&lt;/p&gt;&lt;p&gt;
With respect to the Roman numeral solution, the better answer is, try 5 (V) before 4 (IV). Then add combinations of V and I (6, 7); then finalize this logic with X, which pretty much demands a table-driven solution.
&lt;/p&gt;&lt;p&gt;A last intuitive leap can dramatically improve the solution, but is not essential: Table entries don't have to represent a single Roman letter. Thus you end up with an entry in the table for 4 (IV), 9 (IX), 40 (XL), 90 (XC), and so on. The logic stays clean and simple:
&lt;/p&gt;&lt;pre&gt;
import java.util.*;

public class Roman {
  private final int number;
  private final TreeMap&amp;lt;Integer, String&amp;gt; digits = new TreeMap&amp;lt;Integer, String&amp;gt;();
  {
     digits.put(1, "I");
     digits.put(4, "IV");
     digits.put(5, "V");
     digits.put(9, "IX");
     digits.put(10, "X");
     digits.put(40, "XL");
     digits.put(50, "L");
     digits.put(90, "XC");
     digits.put(100, "C");
     digits.put(400, "CD");
     digits.put(500, "D");
     digits.put(900, "CM");
     digits.put(1000, "M");
  }

  public Roman(int number) {
     this.number = number;
  }

  @Override
  public String toString() {
     StringBuilder roman = new StringBuilder();
     int remaining = number;
     for (Map.Entry&amp;lt;Integer,String&amp;gt; entry: digits.descendingMap().entrySet()) {
        int decimalDigit = entry.getKey();
        String romanDigit = entry.getValue();
        while (remaining &amp;gt;= decimalDigit) {
           roman.append(romanDigit);
           remaining -= decimalDigit;
        }
     }
     return roman.toString();
  }
}
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;
If you don't make the intuitive leap, the final solution is a bit more muddy (as I saw in a few solutions out there). But you have a second chance: Since you have all those wonderful tests, you can refactor the heck out of your muddy solution, looking for a more concise expression, and often you'll find it.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/04/whats-next-test.html' title='What&apos;s the Next Test?'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=8132879652948808518&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/8132879652948808518'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/8132879652948808518'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-7064422857053953442</id><published>2008-04-08T22:25:00.002-05:00</published><updated>2008-04-08T22:32:22.164-05:00</updated><title type='text'>Clean Code</title><content type='html'>&lt;p&gt;Uncle Bob Martin just completed a draft of &lt;a href="http://blog.objectmentor.com/articles/2008/04/08/clean-code-whew"&gt;Clean Code&lt;/a&gt;, which the publisher site lists as being available August 22, 2008. The book is a code-intensive collection of thoughts on how to keep, well, your code clean. I was honored to submit two chapters, one on "clean classes" and one on emergent design. Uncle Bob got the last word, putting in even more code than I'd laid out on these chapters. 
&lt;/p&gt;&lt;p&gt;
Many of the chapters are contributions by other current-and-ex-Object Mentors, but Bob put in a significant effort to go through the compiled book as a whole, to make sure everything coheres well and put his personal stamp on it.
&lt;/p&gt;&lt;p&gt;
The announcement got me stoked again about writing. &lt;a href="http://developer.com"&gt;Developer.com&lt;/a&gt; is also looking to compile an e-book of my many articles on design patterns (most with a TDD bent), so look for that in the near future. Still, I think it's time I went back and started on a whole, real book of my own. The C++ tome is still a potential if Mr Koss and I can find mutual time together for it.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/04/clean-code.html' title='Clean Code'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=7064422857053953442&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7064422857053953442'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7064422857053953442'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-9122130608111233726</id><published>2008-04-03T16:30:00.003-05:00</published><updated>2008-04-03T16:51:45.983-05:00</updated><title type='text'>Open Source Pairing Scheduler</title><content type='html'>&lt;p&gt;Rather than whine about not having enough good pairing experiences, I've decided to do something about it. Recently I've had a few pairing sessions online, and I decided that the software to build would start around the simple notion of scheduling online pairing sessions.&lt;/p&gt;
&lt;p&gt;The idea is to slowly start building an online pairing community. I imagine there are many kinds of participants, people who want to:
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;build quality software via pairing and TDD&lt;/li&gt;
&lt;li&gt;promote their services and ability to mentor via pairing&lt;/li&gt;
&lt;li&gt;get some work done on a real product&lt;/li&gt;
&lt;li&gt;get in touch with other members of the agile community&lt;/li&gt;
&lt;li&gt;learn about either pairing or TDD&lt;/li&gt;
&lt;li&gt;learn about the effectiveness of distributed pairing&lt;/li&gt;
&lt;li&gt;learn a specific technology (Java, Rails, JMock, RSpec, etc.)&lt;/li&gt;
&lt;li&gt;improve their Ward number for bragging purposes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope that the scheduler software will be all that and many more. Initially, I created a wiki (see http://jlangr.wiki.zoho.com/) as a scratch pad area, to help set up sessions, to hold an initial backlog of stories around the scheduler itself, and to record experiences.&lt;/p&gt;
&lt;p&gt;
I chose Java, but only because of interests in my pairing partner. I'm not sure that the pairing scheduler should be Java, but for now it is. If Java, what represents the best choice for front end (web) technologies?
&lt;/p&gt;
&lt;p&gt;
Please feel welcome to join up and post your recommendations and experiences at the wiki site. Interested developers should send me an email with their intents, and I'll set up their SourceForge account to have appropriate access.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/04/open-source-pairing-scheduler.html' title='Open Source Pairing Scheduler'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=9122130608111233726&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/9122130608111233726'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/9122130608111233726'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-3086537850392991884</id><published>2008-03-31T08:54:00.002-05:00</published><updated>2008-03-31T09:15:19.910-05:00</updated><title type='text'>Upside-Down Problem Solving</title><content type='html'>&lt;p&gt;
In doing Sudoku puzzles, most of the time the next solution is staring you in the face. But you can't see it for all the other numbers in the way.
&lt;/p&gt;
&lt;p&gt;
I got stumped on a puzzle Saturday, one that I'd stared at for about ten minutes without success. I have a ten-minute rule, so it was time for a new tack. (Others might call this ADD, but I follow Weinberg's Bolden Rule: "If you can't fix it, feature it.") I turned the book around to let my son look at it, but continued to look at the upside down numbers. Thirty seconds later, the very obvious solution almost started blinking at me. Duh.
&lt;/p&gt;
&lt;p&gt;
Often, all we need is a different perspective on the problem. Many of us have experienced code enlightenment when having someone read over our shoulder. The usual explanation is that we're now trying to perceive how others are reading our code. Another thought: Sometimes I suspect that a very brief mental break is all that's needed.
&lt;/p&gt;
&lt;p&gt;
But maybe it's just that we're shifting in our chair and catching the code at an odd angle. :-) Next time I'm stumped on code, perhaps I'll invert my display. Or change my font.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/03/upside-down-problem-solving.html' title='Upside-Down Problem Solving'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=3086537850392991884&amp;isPopup=true' title='2 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/3086537850392991884'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/3086537850392991884'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-5071707280967958249</id><published>2008-03-23T08:06:00.003-05:00</published><updated>2008-03-23T08:15:57.010-05:00</updated><title type='text'>Dogs and Bugs</title><content type='html'>&lt;p&gt;My dog kept wandering around the neighborhood, so I recently put up a fence around my back yard. Now I'm experiencing some regret: after all that expense and effort, the dog no longer gets out of the yard! &lt;a href="http://tech.groups.yahoo.com/group/agile-testing/message/13412"&gt;Was it all a waste of time?!!?&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
(I think Ward Cunningham puts it much more nicely, but hey, I'm not Ward and will never be. Ward says, "&lt;a href="http://tech.groups.yahoo.com/group/agile-testing/message/13415"&gt;How about FIND BUGS PROMPTLY?&lt;/a&gt;")
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/03/dogs-and-bugs.html' title='Dogs and Bugs'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=5071707280967958249&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/5071707280967958249'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/5071707280967958249'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-7520890464175470130</id><published>2008-03-04T20:43:00.006-06:00</published><updated>2008-03-05T10:24:28.401-06:00</updated><title type='text'>TDD Hype</title><content type='html'>&lt;p&gt;
A trend I've noticed in the software development community is that there are a large number of developers who resist the new wave. Many of those who spent their formative development years doing procedural development went kicking and screaming into the OO age; some suggested that it was an inappropriate tool for many problems. Many C++ developers looked at Java as a toy, not useful for any real work. And I've met enough Java developers who thought that Java was the last word in programming languages.
&lt;/p&gt;
&lt;p&gt;
Certainly we should question newfangled tools and techniques, and insist on putting them through their paces. OO is &lt;em&gt;not&lt;/em&gt; the best tool for every problem, Java did suck big time when it first came out, and yet there are now some significant advantages to continue doing business with it. Challenges ultimately help the tools &amp; techniques improve.
&lt;/p&gt;
&lt;p&gt;Experimentation and innovation is at the heart of the software industry, not active resistance. But it's far easier to sit in a corner and make as many possible excuses for not doing something. I know, because I've done so myself. There are plenty of jobs out there using old technologies, and places where people are happy with the status quo.
&lt;/p&gt;
&lt;p&gt;
So, TDD. Some of us strongly believe in it, only because we've seen benefits firsthand--not just from toy Stack examples, but from working on systems that range from tens of thousands, to hundreds of thousands, and millions of lines of code. Ahh, but the stack example is all the people sitting in the corner see, because that's all they want to believe is behind TDD.
&lt;/p&gt;
&lt;p&gt;
I agree with the vocal dissenters that TDD should not always be used, but not for the lame list of excuses they often come up with. Primarily, the reason is that the typical American software team just isn't that good. TDD is a reasonably tough discipline to get a handle on, and most developers are still struggling with OO, language, and tool basics.
&lt;/p&gt;
&lt;p&gt;What's interesting is that TDD would ultimately help these people the most--some of its best potential is its use as a learning tool. The vocal dissenters, on the other hand, are usually reasonably sharp developers who already have a good notion of design. Thus they can't quite understand why a technique that promotes more decoupled and cohesive designs is important--"duh, we already get it." Particularly, for example, if they don't happen to work with lots of typically underachieving coders.
&lt;/p&gt;
&lt;p&gt;
Is TDD overhyped? Not a chance. There are still mountains worth of learning that TDD will promote in the minds of the majority of the developers out there. For those who don't want to do TDD, don't do it.
&lt;/p&gt;
&lt;p&gt;
Can TDD be dangerous, and lead to disasters? Yes. This is true for any tool in the wrong hands. &lt;b&gt;That also includes insisting on emphasizing test-after--I've seen that lead to plenty of failures and wasted time.&lt;/b&gt; TDD, like OO or any other tool/technique, is not for everyone or every project. But in the &lt;em&gt;right&lt;/em&gt; hands, I've seen TDD work wonders on software projects.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/03/spurning-hype.html' title='TDD Hype'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=7520890464175470130&amp;isPopup=true' title='8 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7520890464175470130'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7520890464175470130'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-3071626894077559503</id><published>2008-03-02T15:14:00.003-06:00</published><updated>2008-03-02T15:30:55.447-06:00</updated><title type='text'>Choices, Choices</title><content type='html'>&lt;p&gt;
Who else has this quandary?
&lt;/p&gt;&lt;p&gt;
I'm long, long weary of Java and C++ (which I thought I had been weary of over well over a dozen years ago, but here I am again struggling with it). Where next? Sure, I've been looking at Ruby for over five years now, and Rails a bit as well, but I've not had an opportunity to put it to any real use in a production environment (except for an odd pairing session here and there).
&lt;/p&gt;&lt;p&gt;
Recently I've also looked at D, Erlang, and Scala. "Looked at" means that I've downloaded it, gotten it running, run through at least a tutorial or two, maybe read the book, and then moved on to experimentation, perhaps starting to re-implement pieces of systems.
&lt;/p&gt;&lt;p&gt;
Seems like the most interesting stuff happening is going on in Ruby--it's a rapidly maturing environment. There are things going on around the other three languages I mentioned, but it doesn't to be nearly as much. Maybe when they've reached "critical mass," there will be more going on around them.
&lt;/p&gt;&lt;p&gt;
In any case, there are scads of new languages and tools vying for attention. It seems like there are more than ever, making for an exciting time. It also means that my stack of what I don't know keeps piling up. I think I need to pick one and invest some real, significant effort into it.
&lt;/p&gt;&lt;p&gt;
So, the decision: ride on the bandwagon, or blaze a trail? What are your reasons for putting your money where it currently is? What else should I be looking at that I'm not?
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/03/choices-choices.html' title='Choices, Choices'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=3071626894077559503&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/3071626894077559503'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/3071626894077559503'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-7324025437633498598</id><published>2008-02-07T16:02:00.000-06:00</published><updated>2008-02-07T16:23:08.594-06:00</updated><title type='text'>Pair Programming Withdrawal</title><content type='html'>&lt;p&gt;
Once again, I find myself without peers. I'll spare the details, but I used to work with some great agile technical mentors. I had some (never enough) opportunities to just sit and pair on a solution, not as a mentor, but as a peer on a programming effort. Unfortunately they've all disappeared, one way or another.
&lt;/p&gt;&lt;p&gt;
I'm reminded of my feelings when I left a 7-month programming gig a few years ago. During that seven months, I paired almost continually. I looked forward to going to work every morning. There's a significant social aspect to pairing, but mostly I looked forward to learning new things.
&lt;/p&gt;&lt;p&gt;
Some of my favorite pairing sessions in the past half-year were with &lt;a href="http://tottinge.blogsome.com"&gt;Tim O.**&lt;/a&gt;, and more recently with a guy named Rick. I learned, and I think they may have learned too. I improved in capability and thus effectiveness on vi while working with Tim. With vi, a very powerful editor, I think there are a number of rungs: 1, where it just beeps at you, 2, where you've figured out how to survive, 3, where you're reasonably proficient, 4, where you know quite a bit and are very effective, and 5, a true master that knows everything in there. Tim is certainly at 4 and approaching 5 (there were a few things he had to look up). The nice thing about our pairing sessions is that Tim helped me to step up from rung 2 to 3.
&lt;/p&gt;&lt;p&gt;
Now, I'm all alone (*sob*). Sympathy cards are welcome, but smacks upside the head for my whining are also welcome. The way I look at it is that every day that I'm &lt;em&gt;not&lt;/em&gt; pairing, there are many, many things that I could be learning that I'm not. That's a shame. I now second-guess my work. "This sucks. There has to be a better way. Is there a better way?" I'm pretty sure that I also develop more slowly.
&lt;/p&gt;&lt;p&gt;
As an aside, I've heard suggestions that expert-to-expert pairings are a waste of time. That's absolutely not true. A good tennis player and friend once told me that the best way to hone your game and take it to the next level is to play with someone as good as you or better. It works in programming, too.
&lt;/p&gt;
&lt;p&gt;
**Tim is an Object Mentor consultant who coaches agile teams in just about everything. I think he'd like it that I added this information.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/02/pair-programming-withdrawal.html' title='Pair Programming Withdrawal'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=7324025437633498598&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7324025437633498598'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7324025437633498598'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-4023902065592543820</id><published>2008-01-30T10:11:00.000-06:00</published><updated>2008-01-30T10:41:48.148-06:00</updated><title type='text'>Stories and Code Quality</title><content type='html'>&lt;p&gt;
(See also &lt;a href="/blog/2008/01/stories-and-tedium-of-iteration.html"&gt;Stories and the Tedium of Iteration Planning Meetings&lt;/a&gt;.)
&lt;/p&gt;&lt;p&gt;
Doling stories out to individual developers not only makes for more boring iteration planning meetings, but it also impacts the system's overall quality.
&lt;/p&gt;&lt;p&gt;
One of the most overlooked practices in software development today is review. If you don't pair, then you really must find a way to consistently review work product. Unfortunately, most companies pay the cost of not doing this: code that is increasingly more difficult to maintain, and solutions that are questionable at best.
&lt;/p&gt;&lt;p&gt;
Insisting that a team finish a story every couple of days or fewer will often mean that two or more developers must collaborate on a story. In order to collaborate, they must agree on some part of the design and a plan to implement it. The developers will need to continue talking as the implementation progresses. That's a good thing. Much of the resulting design won't be one developer's wonderfully clever or woefully inadequate brainchild.
&lt;/p&gt;&lt;p&gt;
Such collaboration brings a bunch of siloed developers one step closer to being a true team. Initially, velocity will decrease a bit: developers will have to learn how to talk to each other and coordinate things. Developers will learn more about other parts of the system, increasing their value to the project as well as their personal worth. It's not quite as good as pairing, but it does go to the heart of agile.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/01/stories-and-code-quality.html' title='Stories and Code Quality'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=4023902065592543820&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/4023902065592543820'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/4023902065592543820'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-6195901025359780444</id><published>2008-01-25T10:35:00.000-06:00</published><updated>2008-01-25T11:05:16.649-06:00</updated><title type='text'>Stories and the Tedium of Iteration Planning Meetings</title><content type='html'>&lt;p&gt;
In "&lt;a href="http://www.developer.com/tech/article.php/3707701"&gt;Tools, Iterations, and Stories&lt;/a&gt;," I said you should "focus on implementing and completing stories, not iterations. If your iteration is 10 days, and you have 10 stories of 1 point each, you should have delivered one story by the end of the first day, and two stories by the end of the second day, and so on."
&lt;/p&gt;&lt;p&gt;
Then, in a blog post titled "&lt;a href="/blog/2007/12/stories-and-tedium-of-daily-standups.html"&gt;Stories and the Tedium of Daily Standups&lt;/a&gt;," I talked about how a focus on completing stories, not tasks and iterations, would make daily stand-ups interesting enough to bother with (anew--since many teams that initiate daily stand-ups often find them boring and thus slowly stop doing them).
&lt;/p&gt;&lt;p&gt;
There's another important side-effect of organizing an iteration around incrementally completing stories: Iteration planning meetings are more interesting.
&lt;/p&gt;&lt;p&gt;
Implicitly, to be able to complete stories as an iteration progresses requires team members to actually collaborate on a story. Imagine that. It's at the heart of the emphasis on continual communication in agile, yet many teams tend to miss this key point. In my next blog posting I'll talk about the side-effect of improved quality. For now, I'll restrict my thoughts to the impact of story planning on iteration planning meetings.
&lt;/p&gt;&lt;p&gt;
If an iteration planning covers four stories to be implemented by a team of four developers, there are two primary ways this meeting could go: 1) The customer details each story by focusing on each individual that will work it, or 2) The customer details all stories, discussing them with all four team members. The downside of option #2 is that it will probably take a little longer to work through all the stories. In fact, if you went with option #1, you really wouldn't need a team meeting. The customer could just meet individually with each developer.
&lt;/p&gt;&lt;p&gt;
Effectively, what you have with option #1 is a meeting in which 3 out of 4 developers have little interest in the story discussion at any given point in time. Information about other developers' stories is mental clutter, and consciously or subconsciously, each developer will tune out to some extent for 75% of the meeting. They will view iteration planning meetings as mostly a waste of time.
&lt;/p&gt;&lt;p&gt;
In contrast, option #2 requires everyone to be attentive. We all have to understand every story, and we most certainly have to start figuring out how each one breaks up. We probably need to do a little bit of design. People attending these sorts of iteration planning meetings are engaged. They leave the meeting with the impression that it held considerable value for them.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/01/stories-and-tedium-of-iteration.html' title='Stories and the Tedium of Iteration Planning Meetings'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=6195901025359780444&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/6195901025359780444'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/6195901025359780444'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-6861083723148543925</id><published>2008-01-24T20:36:00.001-06:00</published><updated>2008-01-24T20:41:14.904-06:00</updated><title type='text'>Blocked!</title><content type='html'>&lt;p&gt;Jerry told me about frustrations at his new company. Here's a possible conversation from my next interview (if there ever is one):
&lt;/p&gt;&lt;p&gt;
Jeff: Do you block web sites or other things like IM?&lt;br/&gt;
Interviewer: We filter on naughty words, we block web mail, and we also disallow use of instant messaging.&lt;br/&gt;
Jeff: Interesting. Why do you block web mail and IM?&lt;br/&gt;
Interviewer: Because we've found that some people tend to abuse it at the office. They also raise some concerns with respect to security.&lt;br/&gt;
Jeff: So you also block phone calls, then?&lt;br/&gt;
Interviewer: Of course not.&lt;br/&gt;
Jeff: Why not?&lt;br/&gt;
Interviewer: Well, people have legitimate business reasons to make phone calls.&lt;br/&gt;
Jeff: OK, first, there are legitimate business reasons to use IM. Second, you could block calls to individuals' homes if you really wanted to.&lt;br/&gt;
Interviewer: Sometimes employees have legitimate need for personal calls. We find that's ok if they don't abuse the "privilege."&lt;br/&gt;
Jeff: So, if talking on the phone all the time was a problem, a manager might intervene and have a discussion with the employee. That seems reasonable. It also seems reasonable that an employee might have a similar, legitimate need for personal emails from time to time.&lt;br/&gt;
Interviewer: But we block webmail.&lt;br/&gt;
Jeff: Thank you, and have a nice day.&lt;br/&gt;
&lt;p&gt;Let's face it, companies rarely change abusive policies like these. Sometimes, the best we can do is voice our disapproval and vote with our feet.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/01/blocked.html' title='Blocked!'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=6861083723148543925&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/6861083723148543925'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/6861083723148543925'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-7916067708114750432</id><published>2008-01-02T10:41:00.000-06:00</published><updated>2008-01-02T11:15:06.372-06:00</updated><title type='text'>Test-First vs. Test-After, Round 4</title><content type='html'>&lt;p&gt;
I submit two articles per month to &lt;a href="http://developer.com/"&gt;Developer.com&lt;/a&gt;. It's often tough coming up with new article ideas, so coming up with a theme that will produce a long stream of ideas is always a good idea (as long as the publisher is willing to accept it). Design patterns is something I've done about a dozen articles on.
&lt;/p&gt;
&lt;p&gt;
Over the nice, long Christmas holidays (vacation for me), I started writing an article featuring the memento design pattern. For me, the hardest part of writing any of these articles is coming up with a good example. I try to avoid the common examples that are already out there, and I don't think abstract examples are very useful. In any case, once I've thought of and coded an example, the article almost writes itself.
&lt;/p&gt;
&lt;p&gt;
Right now, I'm on my third example attempt for memento, which for me is a fiasco. I've probably burned eight hours on something that usually only takes me a few. Memento is not something I've (explicitly) used, so that's not helping.
&lt;/p&gt;
&lt;p&gt;Each example attempt has been centered around the typical use of memento, to support undo/redo capability. I floundered through two examples, discarding each in turn when I decided that it wasn't a good representation of "real" use of memento.
&lt;/p&gt;
&lt;p&gt;
The other real problem was that I figured I'd wing it. I've coded the examples for every other design pattern article using TDD. But over the holidays, I guess I got lazy. For memento, I banged out a solution and figured I'd refactor to something that I could easily unit test after the fact if I felt compelled to.
&lt;/p&gt;
&lt;p&gt;
It's been a while since I've lazed off and not done TDD. As usual, it was a good reminder that it's just a crappy, less-effective way of working. The code I produced was a mess, with logic entwined in the UI class, as tends to happen when there's no interest in unit testing. Worse, I kept getting stuck on a problem with BigDecimal and scaling that wouldn't have given me such trouble had I used TDD.
&lt;/p&gt;
&lt;p&gt;
Maybe I'm just not a very good developer, after all. Or maybe, just maybe, test-after is a less mature way to code.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2008/01/test-after-vs-test-first-part-4.html' title='Test-First vs. Test-After, Round 4'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=7916067708114750432&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7916067708114750432'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7916067708114750432'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-7820875241608381326</id><published>2007-12-21T09:30:00.000-06:00</published><updated>2007-12-21T10:03:53.991-06:00</updated><title type='text'>Test-First vs. Test-After, Round 3</title><content type='html'>&lt;p&gt;
I post occasionally to JavaRanch, a "friendly" forum (it's policed by moderators who cleanse any material deemed offensive). JavaRanch features a book-of-the-week discussion and giveaway. This week, it's a pitch for the book, &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321503104/langrsoftware-20/"&gt;Next Generation Java Testing&lt;/a&gt;. The book so far appears to largely be a pitch for TestNG and an expected couple of rants against JUnit (version 3.8, for whatever odd reason, and not version 4) and TDD. I stopped reading it for now (I'll finish it later) because I found Lasse Koskela's book &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/1932394850/langrsoftware-20/"&gt;Test Driven&lt;/a&gt; more useful.
&lt;/p&gt;&lt;p&gt;
As expected, the JavaRanch discussions contain &lt;a href="http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&amp;amp;f=68&amp;amp;t=001672"&gt;some allusions&lt;/a&gt; to the fact that it doesn't matter whether or not you write (unit) tests first or last. I've written elsewhere on this subject many times, so I'll add only a brief thought or two here.
&lt;/p&gt;&lt;p&gt;
I suppose it doesn't matter, from a conceptual standpoint, if you do test firsts or tests after if you are an experienced professional developer. If you are good at design and structuring your code well, then there's no reason you shouldn't be able to write as many useful tests after you've already built the code.
&lt;/p&gt;&lt;p&gt;
But that's not what really happens. In the real world**, 8 out of 10 developers aren't so experienced or professional, and so most don't care enough or know enough about design to structure their system right. And as soon as someone says, "you don't really have to write tests for everything, and they can break and that's ok," the 80% end up thinking that these unit tests are largely a waste of time. So they--the developers and the tests--don't get better.
&lt;/p&gt;&lt;p&gt;
The other reality is of course time. Without a disciplined approach, deadlines always get in the way of tests. Interruptions push unit tests outward, and they just don't get done.
&lt;/p&gt;&lt;p&gt;
I believe that test-after is only for the true software development master who is close to expert level. For anyone else, it's a recipe for wasted time and frustration. A better investment would be in automating your acceptance criteria.
&lt;/p&gt;&lt;p&gt;
That's opinion. Test-after is unscientific and undisciplined, and that's fact. I'm willing to accept that there may be something better, but test-after when-you-feel-like-it-and-can-figure-out-how-to-do-it is not it, and TDD is closer to following a scientific method. That too is fact. I'd rather look to advance the craft than make excuses why I'm too set in my ways to change.
&lt;/p&gt;
&lt;p&gt;** Sorry Tim.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/12/test-first-vs-test-after-round-3.html' title='Test-First vs. Test-After, Round 3'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=7820875241608381326&amp;isPopup=true' title='2 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7820875241608381326'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/7820875241608381326'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-2773135505107423259</id><published>2007-12-06T19:29:00.000-06:00</published><updated>2007-12-06T20:04:48.141-06:00</updated><title type='text'>Stories and the Tedium of Daily Standups</title><content type='html'>&lt;p&gt;In "&lt;a href="http://www.developer.com/tech/article.php/3707701"&gt;Tools, Iterations, and Stories&lt;/a&gt;," I talked about how you should "focus on implementing and completing stories, not iterations. If your iteration is 10 days, and you have 10 stories of 1 point each, you should have delivered one story by the end of the first day, and two stories by the end of the second day, and so on."
&lt;/p&gt;&lt;p&gt;
Today I helped deliver training on agile estimation and planning. One topic that arose was the daily stand up. We quickly surmised, no surprise, that this group's experiences with daily standups were negative. We discussed some of the reasons why these meetings might be so poorly received. As typical, their standup meetings went on much longer than 5-10 minutes. Reasons? Also typical: people didn't literally stand up, the meetings lacked focus, and people tried to use them to solve problems instead of just identify them. Most people, rightly so, viewed these meetings as very costly. 
&lt;/p&gt;&lt;p&gt;
In response, we talked about why daily standups might be useful. We discussed the importance of getting the entire team to communicate more frequently. Daily should be a bare minimum!
&lt;/p&gt;&lt;p&gt;
The other part of our discussion was around what should be said during a standup. One of the complaints was that the standups were boring and tedious. The teams were using the typically recommended elements: what did I accomplish, what am I working on, what might I need help with? You know the drill. 
&lt;/p&gt;&lt;p&gt;
Then it struck me: a focus on completing iterations, not stories, was part of the problem, contributing to the tedium.
&lt;/p&gt;&lt;p&gt;
The classic mistake in an initial stab at doing agile is to treat each iteration as a mini-waterfall. Spend a day discussing requirements, spend a day or two on design, code it, then test it, then integrate it. A team will open most of its stories on day one, and on the last day of the iteration, most of these same stories will still be open. The team will struggle to close them out prior to iteration end. The article I wrote (see link above) talks about a better approach: initiate work on one or two stories, and move on only after these stories are completed. That allows for incremental delivery of business value throughout the iteration, and usually minimizes the amount of work at risk for the iteration.
&lt;/p&gt;&lt;p&gt;
A team following the first approach, where an iteration is a mini-waterfall, will have very little useful information to say during a daily standup:
&lt;ul&gt;
&lt;li&gt;"What did you work on yesterday?"&lt;/li&gt;
&lt;li&gt;"The flim flam widget."&lt;/li&gt;
&lt;li&gt;"Is it going ok?"&lt;/li&gt;
&lt;li&gt;"Sure, I guess so."&lt;/li&gt;
&lt;li&gt;"What are you doing today?"&lt;/li&gt;
&lt;li&gt;"Same thing as yesterday. Probably tomorrow, too."&lt;/li&gt;
&lt;/ul&gt;
Zzzz. The daily standup is drudgery, because not much is changing, and none of the information is reliable anyway. When asked where they're at, a developer uses the old 80/20 rule. Week one in a two-week iteration, they're probably 20% done, and week two, they're 80% done. And during week one, most developers have the confidence that they'll be done in time, even if they're stumbling. We won't find out that there are real problems with their commitment until (too) late in week two.
&lt;/p&gt;&lt;p&gt;
In contrast, here's how a standup might go in a team that looks to complete stories, not iterations:
&lt;ul&gt;
&lt;li&gt;"What did you work on yesterday?"&lt;/li&gt;
&lt;li&gt;Joe: "I started on the frizzbang story."&lt;/li&gt;
&lt;li&gt;"That's supposed to be done sometime today, right? Are you on target?"&lt;/li&gt;
&lt;li&gt;"Well, maybe not, I'm stuck on a strange exception. I could use help from someone who's worked in this area."&lt;/li&gt;
&lt;li&gt;Jane: "OK, well, I helped complete the flim flam widget by finishing the GUI component, so I'm available."&lt;/li&gt;
&lt;li&gt;"So the flim flam is ready for testing?"&lt;/li&gt;
&lt;li&gt;"Yup. Today I'll go work with Joe, before I start on the festivus tool."&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;&lt;p&gt;
The more I do agile, the more I find that a primary focus on (really) completing stories is the best path to success.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/12/stories-and-tedium-of-daily-standups.html' title='Stories and the Tedium of Daily Standups'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=2773135505107423259&amp;isPopup=true' title='3 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/2773135505107423259'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/2773135505107423259'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-4588937971011719378</id><published>2007-12-05T14:37:00.001-06:00</published><updated>2007-12-06T19:28:30.276-06:00</updated><title type='text'>Testing Getters and Setters?</title><content type='html'>&lt;p&gt;You've heard many developers claim they don't test getters and setters. Correct--you should probably not write direct tests for these things. The primary reason is that they do not (usually) represent behavior; a setter or getter is (usually) just a means of exposing an attribute.
&lt;/p&gt;
&lt;p&gt;
Let me touch on a few points.
&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;"Getters and setters can't possibly break." Wrong! Been there done that. Try misspelling the formal argument name in a setter, e.g. "X" instead of "x." &lt;code&gt;this.x = x;&lt;/code&gt; will compile (you might get a warning), but it will do nothing on execution. If you &lt;em&gt;assume&lt;/em&gt; that this sort of code can never break, you will spend lots of time looking elsewhere for the problem--been there done that! :-) Still, this isn't a compelling reason to write a &lt;em&gt;direct&lt;/em&gt; test.&lt;/li&gt;
&lt;li&gt;"Don't test getters and setters" should probably be quantified with "directly." More or less everything, in effect, should be test-driven. That is, code should not come into existence without first having a failing test. So, perhaps tests against a method in another class drive the need for the getter, and that's fine. But you should never blindly add getters/setters to a class without a reason. (The code generator utilities in Eclipse and other tools should probably be painful to use, to dissuade you, and they sort of are.) If you use a dumb framework that insists on you creating getters/setters that aren't directly called by your code, consider a better framework.&lt;/li&gt;
&lt;li&gt;Many getters have interesting logic (e.g. lazy initialization), as do setters (although this is often a riskier design choice). I'm a firm believer in verifying that these "trivial" idioms actually work; I've seen enough broken initialization attempts. You should test-drive these, and probably directly so (and maybe even ensure they are comprehensively re-tested within the context that they are used).&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I always write tests for constructors, for a few reasons. First, it's a good, simple place to start. It allows you to get a quick test in place and build an instantiable class within a minute or two. Second, a class without tests often suggests to other developers that maybe we don't need to worry about writing &lt;em&gt;any&lt;/em&gt; tests for that class. "Oh yeah, I guess we need to &lt;em&gt;add to&lt;/em&gt; the tests for this class." Third, having to write constructor tests can discourage people from putting any complex logic in constructors, something that's not usually a good thing to do. :-) Fourth, and most importantly, tests for constructors document all of the possible means of creating instances of a class, information that can be difficult to derive otherwise. You're cheating your fellow developers by skimping on these tests.&lt;/p&gt;
&lt;p&gt;Having tests for my constructors means that I effectively test-drive getters, as they are the best means to verify construction.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;So, should you test-&lt;em&gt;drive&lt;/em&gt; getters and setters into existence? Yes, usually indirectly. As long as they get test-driven into existence, you'll eventually find the problem if they hide a defect. Directly, only if the getters and setters are interesting.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/12/testing-getters-and-setters.html' title='Testing Getters and Setters?'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=4588937971011719378&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/4588937971011719378'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/4588937971011719378'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-3044704520625621186</id><published>2007-11-26T11:30:00.001-06:00</published><updated>2007-11-26T11:45:04.612-06:00</updated><title type='text'>Agile and PHBs</title><content type='html'>&lt;p&gt;
We all think Scott Adams has worked in our offices, given how often conversations between Dilbert, his co-workers, and his PHB (pointy-haired boss) seem like conversations we've just had. I remember some discussions with management about metrics; the very next Dilbert strip read like someone had recorded our conversation.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://dilbert.com/comics/dilbert/archive/images/dilbert2666700071126.gif"&gt;Today&lt;/a&gt;, Dilbert's PHB paraphrases agile programming to mean "no more planning and no more documentation." The PHB directs the team to "just start writing code and complaining." 
&lt;/p&gt;
&lt;p&gt;
That's precisely what many people think agile to be. It's why I often curse the notion of big-A "Agile." Buzzwords almost always end up suggesting equally succinct negative connotations. I spoke recently at a BA conference, and my audience quickly confirmed their perception of agile met these the big myths: no planning and no documentation.
&lt;/p&gt;
&lt;p&gt;
I won't belabor an argument. Basically, to do agile well, you must plan all the time. And with respect to documentation, agile generally says that documentation is a cost that must be recognized. It doesn't say don't do it; it says prioritize documentation with respect to its business value.
&lt;/p&gt;
&lt;p&gt;
In the final panel of today's strip, the PHB says to Dilbert, "That was your training." In fact, that's often all training is nowadays. A concept is distilled into an article, or even two sentences, and the corporation feels that it's done its adequately trained its people. I've actually heard management suggest that its people should be smart enough to seek out and understand new concepts completely on their own. 
&lt;/p&gt;
&lt;p&gt;
Yes, agile is a fairly simple concept. Yes, training courses only provide so much value. But there's enough in agile to get wrong and misinterpret that you'd be a PHB were you to ignore the need to properly train your teams.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/11/agile-and-phbs.html' title='Agile and PHBs'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=3044704520625621186&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/3044704520625621186'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/3044704520625621186'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-5286873849493884726</id><published>2007-11-15T21:18:00.000-06:00</published><updated>2007-11-15T21:21:45.967-06:00</updated><title type='text'>A Case for Pairing: Open Workspaces and Distractions</title><content type='html'>&lt;p&gt;I currently work as part of an agile mentoring team in a large organization. Up until recently, we shared a project room. At any given point in time, there might have been one of four to six or seven team members (including a manager), plus one to three people that we were working with. On average there were four people in the room at any given time.
&lt;/p&gt;&lt;p&gt;
Up until this experience, I had always had positive sentiments about open workspaces and team rooms. In this current setting, I did benefit significantly from getting to converse frequently with all of the other people in the room. I learned things I probably would never have learned otherwise. And, I had a grand old social time.
&lt;/p&gt;&lt;p&gt;
But I also found that I wasn't getting much work done when I had things I need to concentrate on. It seemed like I could be guaranteed a distraction at least every five minutes. Either someone was asking a question, or I was overhearing something that I felt compelled to respond to. It got to the point where if I had to find a couple hours to work on something (such as preparing training material), I ended up leaving the open workspace to find somewhere quiet.
&lt;/p&gt;&lt;p&gt;
The problem wasn't the open workspace, it was the fact that none of us were really working on the same thing. The other mentors were usually working on a different project than I was. And my manager, well, you know how managers are, there's always something they want you to pay attention to right away.
&lt;/p&gt;&lt;p&gt;
Escaping the room on occasion was an adequate solution, but the better solution ended up being pairing. I noted that as soon as I found a partner to help build a solution, or someone that I was mentoring, the distractions disappeared. I surmise two reasons: first, as a pair we were focusing on a problem. That meant I was no longer listening to any external conversations. Second, people are more reluctant to interrupt two people that they see obviously engaged in a conversation or task.
&lt;/p&gt;&lt;p&gt;
As I've paired more and have worked with teams employing pairing, I've grown a long list of benefits that I've seen accrue from the practice. My experience here adds a new bullet item: pairing minimizes distractions.&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/11/case-for-pairing-open-workspaces-and.html' title='A Case for Pairing: Open Workspaces and Distractions'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=5286873849493884726&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/5286873849493884726'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/5286873849493884726'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-5913506744046837968</id><published>2007-11-09T17:04:00.001-06:00</published><updated>2007-11-09T17:05:32.551-06:00</updated><title type='text'>If You're Not Pair Programming...</title><content type='html'>... what do you call it? "Solo programming," I've heard. My preferred term is "isolation-based programming." So, sure, pairing up seems like a dumb idea. So does programming in isolation. Yeah yeah, it's not really isolation. May as well be.</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/11/if-youre-not-pair-programming.html' title='If You&apos;re Not Pair Programming...'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=5913506744046837968&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/5913506744046837968'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/5913506744046837968'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-6725822087626778432</id><published>2007-11-09T14:23:00.000-06:00</published><updated>2007-11-09T16:41:37.786-06:00</updated><title type='text'>Function Points are a Crock</title><content type='html'>&lt;p&gt;
Every once in a while, someone will ask about the value of incorporating function points. For those under, say, the age of 40, function points were something that were devised in the late 1970s in order to come up with a consistent metric for estimating the size of a software system.
&lt;/p&gt;
&lt;p&gt;
Sure, function points can end up being fairly accurate from time to time. They may help in terms of comparing efforts on two software projects.
&lt;/p&gt;
&lt;p&gt;The problem is the investment required to derive function points. Function point analysis is expensive (albeit there have been several initiatives to try and simplify the effort). In order to be useful across projects, a metric has to be consistently calculated. In the case of function points, consistently calculating them is a meticulous effort. Generally, you need an "expert" in order to do well with function points. 
&lt;/p&gt;
&lt;p&gt;
Fortunately, to save the day, we have &lt;a href="http://www.softwaremetrics.com/"&gt;high-priced consultants&lt;/a&gt; that can come in and explain why (a) agile sucks and (b) why they are the one who can do these ridiculous calculations.
&lt;/p&gt;
&lt;p&gt;
Horse hockey. I've seen as good or better results from agile estimating and planning techniques. Or, agile aside, from notions that are much simpler to calculate ("how many screens are there?"). These techniques, which come more cheaply, are far less onerous, and anybody can quickly learn how to do them without hiring an overpriced consultant (or "software economist").
&lt;/p&gt;
&lt;p&gt;
Should you trust me, a "high-priced consultant" myself to tell you function points are dead? Look around. There's a good reason why most organizations have moved off of such heavyweight nonsense. All of these wondrous efforts and calculations make managers and executives feel good. Function points look like a lot of effort went into them, and fancy looking calculations back this effort up. But that's about it. They don't really add value to a project. What adds value is getting quality product in front of a customer on a &lt;em&gt;consistent&lt;/em&gt; basis, giving them what they ask for and expect.
&lt;/p&gt;
&lt;p&gt;
A good consultant will teach you how to start solving your own problems. A questionable one will sell you complexity you don't need.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/11/function-points-are-crock-every-once-in.html' title='Function Points are a Crock'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=6725822087626778432&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/6725822087626778432'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/6725822087626778432'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-4949717734751726775</id><published>2007-11-06T16:54:00.000-06:00</published><updated>2007-11-09T15:59:43.016-06:00</updated><title type='text'>On Striking</title><content type='html'>&lt;p&gt;
I just did a google search, looking for something on the agile catchphrase of "Done Done." The first hit was &lt;a href="http://www.jamesshore.com/"&gt;James Shore's site&lt;/a&gt;. I clicked on the link, expecting useful information, but received propaganda instead:
&lt;em&gt;
&lt;p&gt;In the United States, power flows from the people. We grant our power to representives [sic] on the first Tuesday of November.&lt;/p&gt;
&lt;p&gt;In the last six years, that trust has been betrayed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Torture&lt;/li&gt;
&lt;li&gt;Extraordinary Rendition&lt;/li&gt;
&lt;li&gt;Engaging in War Under Deceptive Pretences&lt;/li&gt;
&lt;li&gt;Suspension of Habeus Corpus&lt;/li&gt;
&lt;li&gt;Imprisonment Without Trial at Guantanemo [sic] Bay&lt;/li&gt;
&lt;li&gt;Warrantless Wiretapping&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are not American values.&lt;/p&gt;
&lt;p&gt;I am on strike today in protest of these actions.&lt;/p&gt;
&lt;p&gt;Next year on the first Tuesday of November please join me in removing those responsible.&lt;/p&gt;
&lt;/em&gt;
&lt;/p&gt;&lt;p&gt;I applaud Mr Shore for being courageous enough to mix his politics with his business. I choose to minimize my commentary to places like this blog, where my personal beliefs shouldn't be enough to dissuade someone from doing business with me. Of course, that still may happen, but it's far less likely to happen than if I choose to shut down access to information and commerce on my site in order to push my personal belief system.&lt;/p&gt;
&lt;p&gt;Perhaps if more people were to take a stand, like Mr Shore, we'd be better off. I'll take my small stand: most of what Mr Shore says is correct, with the exception of the part about the "last six years." The unfortunate part is that these activities aren't just part of the current administration, they've existed in virtually every administration since Abraham Lincoln (who used just about all of these tactics), up to Clinton and of course Bush II. It's just that sometimes the American people have been gullible enough to swallow the rationales and excuses, or worse, have been willing to be complicit because their party happens to be the offender.
&lt;/p&gt;
&lt;p&gt;
I recommend that the American voters remove everyone responsible next year. That includes those in Congress who swallowed the lies as well as those who made the lies--the threat of WMDs, even if real, was not an excuse to invade another country. That's pretty much everyone in Congress. If only we had the courage.
&lt;/p&gt;
&lt;p&gt;
I am neither Republican, Democrat, socialist, or Libertarian. I no longer believe that voting contributes to solving any problem (in fact, I believe that voting is implicitly an act of force). But if I were to vote, I'd say that the only hope for the future of the U.S. lies in someone who actually believes in the U.S. Constitution, and not someone who believes in only parts of it (Republicans or Democrats). That one person is Ron Paul. Do your research.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/11/on-striking-i-just-did-google-search.html' title='On Striking'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=4949717734751726775&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/4949717734751726775'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/4949717734751726775'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-708060112352859601</id><published>2007-10-31T18:12:00.000-05:00</published><updated>2007-11-09T16:00:57.228-06:00</updated><title type='text'>Comments and Footnotes</title><content type='html'>&lt;p&gt;
Will I ever stop railing on about comments? I don't think so. As long as it's possible to write code in a less than clear manner, people will always be compelled to explain their coding deficiencies. And I will always be compelled to resist.
&lt;/p&gt;
&lt;p&gt;
As a writer, I try to ensure that the main text in a book or article is clear to the reader. Every rare once in a while (perhaps a couple dozen times in a book), I feel compelled to write extra information, something that supplements the text. I do so in the form of a footnote. The footnote provides non-essential information. It's something that might help add some insights to what I just wrote, perhaps, or a humorous but otherwise distracting note.
&lt;/p&gt;
&lt;p&gt;
My editors would never let me use footnotes to re-explain a passage of text. A coder attempting to salvage bad code with comments is like me adding footnotes to try and explain poorly written text. If the mainline text didn't explain it well, why should a footnote explain it any better?
&lt;/p&gt;
&lt;p&gt;
Footnotes and comments are ultimately a distraction. Ever try to read a book with footnotes on almost every page (and I'm not talking citations or references)? You may as well be reading two books, in some cases. As writers, we owe it to our readers write more clearly and to minimize these distractions.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/10/comments-and-footnotes-will-i-ever-stop.html' title='Comments and Footnotes'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=708060112352859601&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/708060112352859601'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/708060112352859601'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-1334366507780512204</id><published>2007-10-23T21:44:00.000-05:00</published><updated>2007-11-09T16:10:35.618-06:00</updated><title type='text'>Krakow</title><content type='html'>&lt;p&gt;
I visited a number of development teams (both C++ and Java) in Krakow, Poland over the prior two weeks. I also had an opportunity to speak at the Agile Poland Users Group (see the slides in the &lt;a href="/resources.shtml"&gt;resources section&lt;/a&gt; for the topic). Overall, I enjoyed my visit, but was as always most thankful to return home. The Polish developers were mostly very good and interested in improving upon themselves. I learned a few things from them, and I hope they learned from me.
&lt;/p&gt;
&lt;p&gt;
For many, not all, of the developers, I could offer only "the little things," as they seemed to have solid basic knowledge. Mostly, I worked with them on improving the readability and maintainability of their tests. I think this refactoring of tests is where the real money proposition can start coming into play--until tests are of high quality, they will continue to be costly to maintain. I hope the developers took "the little things" to heart, because I think attention to them is what distinguishes a journeyman from a master.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/10/krakow-i-visited-number-of-development.html' title='Krakow'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=1334366507780512204&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/1334366507780512204'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/1334366507780512204'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-3323168140611466146</id><published>2007-10-02T22:25:00.000-05:00</published><updated>2007-11-09T16:11:09.401-06:00</updated><title type='text'>Certification and the Agile Alliance</title><content type='html'>&lt;p&gt;
I attended a panel presentation, "To Certify or Not to Certify," at Agile 2007 in Washington, D.C. The presenters included several esteemed members of the agile community, including (but not limited to!) Ron Jeffries, Michael Feathers, Mike Cohn, and Angela Martin. I thought the panelists offered some interesting but far from comprehensive thoughts on certification. The panel deliberately avoided "hot" or contentious questions, in favor of a subdued give-and-take on the topic.
&lt;/p&gt;
&lt;p&gt;
What I heard was essentially this message: "certification is inevitable, so we should try to beat those other guys (whoever they are) to the punch." Presumably, the interest would be to build good certification, so good that those greedy other guys don't come up with poor certification. (The Agile Alliance issued a position paper on what they thought the value proposition was for certification; it can be found &lt;a href="http://www.agilealliance.org/show/1796"&gt;here&lt;/a&gt;.)
&lt;/p&gt;
&lt;p&gt;
Shortly after the conference, I was invited to and joined an online action/discussion forum consisting of some of the aforementioned panel members. I asked for some goals for certification, thinking that there are many paths to many different kinds of certification. The first step toward any solution is knowing what the problems are, and how much of each problem you're trying to solve.
&lt;/p&gt;
&lt;p&gt;
If there is a discussion forum metaphor for blank stares, that's what I got with my posts. A different action group formed, one where a decision was already made to build some sort of trust network (based on a notion similar to Google page ranks). I wasn't so warmly invited to this second group. Perhaps my pointed posts helped kill the first certification forum.
&lt;/p&gt;
&lt;p&gt;
Never one to be subdued by rejection, my response is to move forward on my own and establish a basis for a certification program for test-driven development (TDD). My intent is to produce a skill-based TDD curriculum, one about as rigorous as a typical university course. Is there a test? Is there a certificate? That's probably not something I can build as a sole proprietor, but I'm open and ready to work on creating a standards body for TDD certification.
&lt;/p&gt;
&lt;p&gt;
What are my motivations? They of course include profit, but they also include my strong interest in improving the level of professionalism in software development. While some decry profit motivations based on their belief system, certification schemes are primarily about profit, and I believe competition usually drives improvement. Let's get competing!
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/10/certification-and-agile-alliance-i.html' title='Certification and the Agile Alliance'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=3323168140611466146&amp;isPopup=true' title='6 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/3323168140611466146'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/3323168140611466146'/><author><name>Jeff L.</name></author></entry><entry><id>tag:blogger.com,1999:blog-6488575.post-1806858024823654496</id><published>2007-09-27T16:35:00.000-05:00</published><updated>2007-11-09T16:11:41.628-06:00</updated><title type='text'>Agile Doesn't Work If...</title><content type='html'>&lt;p&gt;
... you think it's stupid. Or if you don't want to do it. It should be obvious, but to truly succeed with something in life, you have to truly believe it's worth doing.
&lt;/p&gt;
&lt;p&gt;
As such, I'm going to suggest something to all the people out there who don't think agile is a good idea: don't do it. Please, find something better. Maybe you'll hit across something we can all learn from. I'll be happy to move on from agile once I see something better. Just remember that saying "I'll do these kinds of things when I feel like it" isn't agile.
&lt;/p&gt;</content><link rel='alternate' type='text/html' href='http://www.langrsoft.com/blog/2007/09/agile-doesnt-work-if.html' title='Agile Doesn&apos;t Work If...'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6488575&amp;postID=1806858024823654496&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://www.langrsoft.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/1806858024823654496'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6488575/posts/default/1806858024823654496'/><author><name>Jeff L.</name></author></entry></feed>