Exploring Solution Spaces © Copyright 2003-2006, by C. Keith Ray
   


About
Exploring Solution Spaces, Keith Ray's blog on Software development and other topics.

Send comments to:
keithray@mac.com

For Agile Training, eLearning, or Coaching contact:
Industrial Logic, Inc.
866-540-8336 (toll free)
510-540-8336 (Berkeley, California)

Links
xpminifaq
Résumé
“Adopting XP” Article 2002 (pdf)
“ Refactoring” Article 2006
AYE Conference
Lucien W. Dupont
Elisabeth Hendrickson
Johanna Rothman's Managing Product Development
Brian Marick's Exploration Through Example
Esther Derby's Insights You Can Use
Laurent Bossavit's Incipient(thoughts)
Dale Emery's Conversations with Dale
Martin Fowler's Bliki
Creating Passionate Users

Archives

  • 2003
  • 2004
  • 2005
  • 2006
  • 2007
  • 2008
  • Subscribe
    RSS Exploring Solution Spaces XML


           
    2005.Dec.17 Sat

    On Looking for the Next Microsoft

    A good tidbit a long piece by Paul Graham.

    ... When we were making the rounds of venture capital firms in the 1990s, several told us that software companies didn't win by writing great software, but through brand, and dominating channels, and doing the right deals.

    They really seemed to believe this, and I think I know why. I think what a lot of VCs are looking for, at least unconsciously, is the next Microsoft. And of course if Microsoft is your model, you shouldn't be looking for companies that hope to win by writing great software. But VCs are mistaken to look for the next Microsoft, because no startup can be the next Microsoft unless some other company is prepared to bend over at just the right moment and be the next IBM.

    It's a mistake to use Microsoft as a model, because their whole culture derives from that one lucky break....

    [/docs] permanent link

    2005.Dec.14 Wed

    Minimal To Humane

    A bit more on the Humane Interfaces and Minimal Interfaces debate that I blogged about previously. Some people think XP's "YAGNI"(You Aren't Going to Need It) rule that prevents unnecessary work means XPers are in favor of Minimal Interfaces, but that is only to start with. Refactoring away code duplication (and other code smells that the Simplicity Rules are against) tends to create Humane Interfaces.

    For example, if I was doing test-driven development in an environment that didn't already have a list class, and one was needed, I would test-drive a minimal implementation: maybe all it has to start with is list.size(), list.at(int index), list.add(object), and list.removeAt(int index). However, as the list gets used, I would look for duplicate code. If I refer to the first element using list.at(0) in more than one place, adding list.first() to the list class would remove duplication (the OnceAndOnlyOnce part of the Simplicity Rules). If I have code like this...

    x = nil;
    if ( list.size > 0 )
        x = list.at( list.size() - 1 );
    

    ... I don't even need duplication to want to refactor that piece of code into a method of the list class. You'll note those three lines of code have the code smell "Many messages to the same object from the same method" (3 is "many" here), or "asking instead of telling" (we need some pithy standardized names for code smells). Refactoring that code into "list.last()" follows the Simplicity Rule "Expresses every idea that we need to express" (aka "Self Documenting Code", aka "Intention-Revealing Code"). Similarly if I search the list, enumerate the list, and so on, the rules of Simple Design would require that I move those features into the list class as well to clearly express intention and avoid duplication.

    So as the project progresses, the list class moves from being a very minimal interface to being a humane one, without ever having a method that isn't used in the project.

    Library(framework) design often starts in a vacuum, but wise people recommend using the library in three non-trivial applications before publishing it, precisely so that these kinds of refactorings can "tune" the library into something people will want to use, before publishing it.

    [/docs] permanent link

    2005.Dec.07 Wed

    Minimal versus "Humane" Class API Design

    Interesting stuff about class API design:

    good: HumaneInterface.html

    doesn't get that intention-revealing interfaces are good, "tell, don't ask" is good, and code duplication is bad: cafeaulait

    reaction to the above: cincomsmalltalk.com/blog/ Don't forget to read the comments. My comment:

    You just know that because Java's List class doesn't have a "last" method, that everyone who needs to access the last element is going to have to write "alist.get( alist.size() - 1 ) WHICH IS DUPLICATED CODE. (And buggy as well, failing if the list is empty.)

    Duplicated code is a sign of bad design, and leads to bugs. There's probably been a million bugs where someone coded alist.get( alist.size() ) attempting to get the last element (which will instead throw an exception), and no doubt less that 80% of those bugs have been fixed.

    It wouldn't be so bad if Java programmers could extend existing classes (Like Cocoa programmers and Smalltalk programmers).

    more reactions:

    simplicity rules in the right place

    java net style vs smalltalk ruby style (though I'm not sure I agree with 437 methods for Smalltalk's Object Class!)

    [/docs] permanent link

    2005.Dec.04 Sun

    Test Duration < Iteration Length

    Extreme Programming is built on the assumption that completely testing the product under development can be done within a single iteration. If manual testing is the only method of testing, the test-duration will get longer every iteration until it can't be done within a single iteration. This is why automated testing is so important on an XP project. In well-run XP projects, automated testing covering every feature can be executed, at worse, overnight or in one or two days, and at best, as quickly as 20 minutes or faster. And that's two layers of automated tests: programmer/unit tests, and customer/acceptance tests.

    The reason XP has iterations and automated testing is to increase the speed of feedback on the design. On a large project, a design that meets all the requirements is going to require a long time to be developed. No person or team can come up with an "instant" design for all the requirements. In a phasist approach, a team might spend a long time coming up a design that they think will meet all the requirements, and not have any real feedback on the goodness of that design until they start implementing it and testing it. If it turns out the design is bad, the project may not have enough time to fix the design before shipping deadline.

    Contrary to some popular misconceptions, XP team do design, but they do it incrementally, creating tests for that design in each iteration. The implementation for that design isn't considered complete until it passes all the tests that the programmers (doing test-driven development) and the testers (creating customer/acceptance tests) think up. Most importantly, refactoring is design, as the design that was appropriate for the last iteration is changed to be appropriate for the current iteration.

    Fortunately for people doing incremental design work with refactoring, most automated tests do not have to change when the code is changed. The tests are acting as executable specifications for the requirements, so if the requirements haven't changed, then the tests should not have to change. Of course, when the tests are very close to the implementation, they do sometimes need to be change, but the majority of tests should not change when someone need to alter the design to handle requirements being address in the current iteration.

    If someone is making changes to the code, and the tests fail, or the code isn't even executable or compilable any more, they are not doing refactoring. They are doing something else, like rewriting, Stop them. Teach them how to do refactorings that are in Martin Fowler's book: each refactoring is a small behavior-preserving change that keeps the code and tests working. Run the programmer tests after each refactoring for assurance that no behaviors have been changed unintentionally. Many people are using refactoring tools that can do refactorings that are almost always error-free, though running the tests is still recommended, just in case. Manual refactoring is more prone to error, so be careful and work slowly in order to avoid mistakes (and therefore go faster). Make sure the whole team knows the direction the refactorings are headed in, so you don't get into cycles where one developer undoes the refactorings of another developer and vice-versa.

    Teams that haven't gotten their specification and testing processes firmly in place will experience what Michael Feathers calls iteration slop and "trailer-hitched QA":

    When your team does trailer-hitched QA the developers work until the last possible moment within the iteration and when the iteration ends, they hand off to the QA team. The QA team gets the "final" build and they work with it for a while, running more automated and manual tests. Often this takes close to the length of an iteration. [...] Effectively, trailer-hitched QA doubles the amount of time that it takes for a team to really know that they finished an iteration. It can work, but it is kind of counter-productive in a process which aims to shorten the amount of time it takes to get feedback.

    What happens when there are conflicting requirements? In a large project, it's often hard to detect conflicting requirements because you just can't hold them all in your head at the same time. You could spend some time comparing every requirement to every other requirement, but that's tedious and you're still likely to miss the conflicting requirements -- particularly when some requirements are (as yet) unwritten and/or "derived" requirements.

    On projects without fast automated tests, conflicting requirements show up as a cycle of bug reports, often with long delays between bug reports. Fixing one bug causes another bug to show up, perhaps weeks later when testing gets to that conflicting requirement. Fixing that other bug causes the original bug to re-occur -- but it may be flagged as a new bug if no one reviews the old "fixed" bugs before filing a new bug report.

    When every high-level requirement is written as an automated customer/acceptance test, and every low-level requirement is written as a programmer/unit test something interesting happens: getting one conflicting requirement/test to pass will cause another test to fail. Getting that other one to pass will cause the original one to fail. If you run all the tests often, and they run quickly, it becomes pretty obvious that a cycle is going on.

    Many XP teams create new tests whenever they are going to fix a bug. The test fails because of the bug, and will pass when the bug is fixed. In practice (particularly with legacy code), this can be very difficult because to write a failing test, you first have to find the buggy code. However, having that test in place will help detect conflicting requirements if you later fix a bug and cause the previous bug-detecting-test to fail again.

    What do you do with legacy code? You can segregate it: do test-driven development on new code, avoid changing the old code, move old features into the new tested-code gradually until the legacy code disappears. This assumes the legacy code is mostly bug-free. If you have to fix bugs in legacy code often, your best strategy is to put the old code under test, starting with the parts you are about to modify for bug-fixes. See Working Effectively With Legacy Code by Michael Feathers for techniques on how to introduce testability into legacy code. You will also have to spend more time on manual testing, and probably have to have longer iterations in which to do it.

    [/docs] permanent link

    2005.Dec.03 Sat

    Science Life

    "Some of my smartest graduate students get freaked out when they discover what our lives are really like. [...] They think science is about asking questions and devising experiments that answer them. They think there is a map to knowledge they can follow by just working hard. But the truth is that we often don't even know what the right questions are. There is no map. Some of my students get so disoriented by this that they have to quit and do something else." -- Jerry Leob, quoted in Rebuilt: how becoming part computer made me more human by Michael Chorost.

    [/docs] permanent link

    2005.Dec.01 Thu

    Medicatiboons

    The title of this post is taken from a spam - I thought it sounded like it should be a real word: medication + boon.

    Check out Kevin Lawrence's tale of a class that "just" was going to represent a class-name, and became so much more. He titled his post "Fight Complexity with Complexity" but by creating an abstraction that centralizes stuff that was spread out everywhere, he actually simplified the code -- according to two of Kent Beck's rules of simplicity: "no duplicate logic" and "expresses the programmer's intentions".

    All the time we thought of a class name as just a string, it had no behavior. Once we created a type for it - once we reified it - we realized that class names had a lot of rules and behavior that had previously been distributed throughout the codebase. We had added a little complexity and were rewarded with less complexity overall.

    [/docs] permanent link

    Utility Functions as a Code Smell

    Bunches of utility functions, whether bunched together in a "utility class" or not, are often a sign that code isn't object-oriented enough. For example, in Apple's Cocoa implementation, there are a bunch of utility methods for filename-manipulation, in class NSString:

    - (unsigned)completePathIntoString:(NSString **)outputName caseSensitive:(BOOL)flag matchesIntoArray:(NSArray **)outputArray filterTypes:(NSArray *)filterTypes

    - (const char *)fileSystemRepresentation

    - (BOOL)getFileSystemRepresentation:(char *)buffer maxLength:(unsigned)maxLength

    - (BOOL)isAbsolutePath

    - (NSString *)lastPathComponent

    - (NSArray *)pathComponents

    - (NSString *)pathExtension

    - (NSString *)stringByAppendingPathComponent:(NSString *)aString

    - (NSString *)stringByAppendingPathExtension:(NSString *)ext

    - (NSString *)stringByDeletingLastPathComponent

    - (NSString *)stringByDeletingPathExtension

    These path-component methods are actually added to the class NSString via a class category, but are viewed as members of the NSString in the documentation and usage.

    My point here, with this example, is to raise the question: what are these "path" and "path component" methods doing in class NSString? Perhaps they should be members of a PathName or PathComponent class. (And by the way, pathnames in MacOS X not just unicode, they are "decomposed" unicode, so don't forget to call decomposedStringWithCanonicalMapping; a PathName class would take care that of that for you.)

    Like pathnames, URLs are strings with rules for how they are formatted, encoded, etc., so you might expect that Cocoa deals with them using a bunch of utility methods in NSString. But, being a later addition to Cocoa, they are actually their own class: NSURL. This class encodes the requirements of RFCs 1808, 1738, and 2732. It provides methods to access host, get the base URL, test if the URL refers to a file, get absolute and relative forms of an URL, and so on. Apple is moving to using NSURLs instead of pathnames in various Cocoa APIs, and beginning to deprecate the pathname-based APIs, since NSURLs can refer to local files as well as remote web-based resources.

    If you've got a bunch of utility methods, look at their names and behaviors to see if they really belong to one or more new classes. If they conceptually belong to an existing class that you can't edit, Objective-C gives you the option to extend that class via a class category.

    In other languages, you might have to make a subclass, or in the worst case, leave them as utility methods, but put them together in a class that reflects where you would rather put them. For example, if you write a bunch of string utilities in Java, you can't extend the java.lang.String class, so put them as static methods into your own com.yourcompany.StringExtras class. But first, consider if they are actually representing a concept that deserves to be its own class, like Apple did with URLs.

    [/docs] permanent link

    Kent Beck Podcast/Interview

    Kent Beck Podcast/Interview here 21 minutes.

    [/docs] permanent link

    2005.Nov.28 Mon

    Story Card to FIT tests

    This is an partial example of how a story-card might be 'translated' into FIT tests -- this example is paraphrased from the middle chapters of "FIT for developing software" by Mugridge & Cunningham.

    Here's a story card:

    +--------------------------------------------------------+
    |  CreateRentalTemplate                                  |
    |                                                        |
    |  A rental template defines a list of rental items. The |
    |  template specifies the proportion of each item per    |
    |  person. The user can select a template and specify the|
    |  number of people to rent those items.                 |
    |                                                        |
    +--------------------------------------------------------+
    

    To accompany the story, there is discussion (verbal, spoken) between the programmers, testers, and the person that understands the requirements: the "Customer" in XP terminology, "Product Owner", "Domain Expert", etc. I'll leave out estimation and scheduling of stories, which are taken care of by Release Planning and Iteration Planning.

    In the case of this story, there is discussion of how rounding-up will occur when the number of people specified doesn't exactly match the proportions in the Rental Template, so the test is written to use numbers that test the rounding-up.

    Using FIT or Fitnesse, one acceptance test for CreateRentalTemplate would look something more or less like this:

    --------------------------------------------------
    | Create rental template | Coffee break          |
    --------------------------------------------------
    | one | coffee dispenser    | for | 20  | people |
    --------------------------------------------------
    | one | coffee table        | for | 40  | people |
    --------------------------------------------------
    | one | cup                 | for | 0.9 | people |
    --------------------------------------------------
    
    --------------------------------------------------------
    | begin transaction for client | Joanna                |
    --------------------------------------------------------
    | fill template | Coffee break | for | 21 | people     |
    --------------------------------------------------------
    | pay cash | 65.00                                     |
    --------------------------------------------------------
    | end transaction                                      |
    --------------------------------------------------------
    | rentals of client | Joanna  |
    -------------------------------
    | rental item         | count |
    -------------------------------
    | coffee dispenser    | 2     |
    -------------------------------
    | coffee table        | 1     |
    -------------------------------
    | cup                 | 24    |
    -------------------------------
    

    The code to make this work would involve implementation various kinds of fixture classes, that will be instantiated by the FIT framework, and which in turn call the model objects to exercise the application. Initially the FIT tests will fail because the model objects do not exist or do not yet have required functionality. Use test-driven-development to create the model objects with the required behaviors. Then the FIT tests should pass.

    See http://fit.c2.com/ for info about FIT, see http://fitnesse.org/ for info about Fitnesse.

    [/docs] permanent link

    2005.Nov.12 Sat

    AYE 2005

    I'm back from the AYE conference. Very informative. Very interesting (people and sessions). Very intense. Very tiring. Veni Vidi Very. I came back with new books, lots of hand-outs, notes, and a head-cold. No t-shirt. I will be blogging about the sessions and the books as I recover.

    [/docs] permanent link

    2005.Nov.11 Fri

    Gates vs Jobs in Slide Presentations

    Comparison of Steve Jobs's and Bill Gates's slide presentations compared here:

    Steve Jobs, allows the screen to fade completely empty at appropriate, short moments while he tells his story. In a great jazz performance much of the real power of the music comes from the spaces in between the notes. The silence gives more substance and meaning to the notes....

    Mr. Gates needs to read Cliff Atkinson's Beyond Bullet Points, ironically published by Microsoft Press. Atkinson says that "...bullet points create obstacles between presenters and audiences." He correctly claims that bullets tend to make our presentations formal and stiff, serve to "dumb down" our points, and lead to audiences being confused...and bored.

    With pictures. Check it out.

    [/docs] permanent link

    2005.Nov.06 Sun

    Motivation

    Quotes from Lasse Koskela:

    In my job as a TDD coach (among other things), the hardest but also biggest win is to convince a strong, self-confident individual to give it a shot...

    A couple of years ago, I was convinced that "selling" agile methods to management was the most difficult part... Boy was I wrong about all that.

    ... what are the drivers regarding the change from management's point of view? Profit. Higher quality, faster lead times, less operational costs. All that equals higher profit.

    Now, think of the developer in that same organization. What are the drivers she's affected by...? It's not profit, that's for sure.

    Safety. I have come to believe most developers' biggest issue with, say, TDD is not whether it's more productive or not. I believe that most of the time the biggest issue is that of insecurity... Insecurity of not knowing whether you will be able to learn a new trick. Insecurity of not knowing whether you'll suddenly become the other end of a pecking order.

    [/docs] permanent link

    2005.Nov.04 Fri

    Health

    In pursuit of better health, I have spent literally hours today waiting for a doctor, a chiropractor, a lab tech, and a pharmacist to do what they do, and even more hours driving from one place to another. The doctor was a last-minute appointment, and the lab work required a waiting period to measure certain biological processes correctly. Also if the prescription had been faxed to the pharmacy like usual, there would have been less of a wait there.

    There was also some time spent looking for an certain doctor-recommended over-the-counter medicine at a combined grocery store/drug store, which didn't carry it, and at a "real" drug-store, which did carry it.

    Each place I visited may have been very efficient from their own perspective, but all these wait, search, and transit times are signs of inefficiency from my perspective. (See "Theory of Constraints" for more on that.) This situation is not likely to change as long each of these functions is an independently-owned enterprise, and our laws and traditions will work to preserve this independence at a cost of (my) efficiency. If I valued choice less and efficiency more, I suppose a good HMO (or equivalent) with centralized infrastructure would make for a better experience. (Or maybe not.)

    [/docs] permanent link

    2005.Oct.27 Thu

    The Return of Freedom of the Press

    Today's quote on my google home page is "Freedom of the press is limited to those who own one." - AJ Liebling. In the days of the USA's founding fathers, anyone who wanted to get their views across to other people would hire a press, or rent or buy one, and print their own pamphlets and broadsides to distribute or sell. It was fairly democratic for that time.

    In the days of television, only a very few could afford to buy television time. Broadcasters could refuse to show material they disagreed with. The common people had to resort to creating newsworthy "demonstrations", marches, speeches, etc., and hope that a sound-byte would be get broadcast by a news organization. Writing to newspapers and magazines also depends on the whim of editors as to whether your views get published.

    Now just about anyone can buy or rent a web-page, or even get a free page for a blog, to get across their views. Popular or controversial content shows up on search-engines if enough people agree or disagree with it and link to it. We aren't dependent on the whims of TV or newspapers editors anymore. Power to the people! Yay!

    You know, we ought to have a national holiday to celebrate our freedoms of speech and press.

    [/docs] permanent link

    2005.Oct.26 Wed

    Microsoft Mind-Rot

    Quotes from Charles Petzold's Does Visual Studio Rot the Mind?: (bold-facing is my emphasis)

    ... NET Framework 2.0. Tabulating only MSCORLIB.DLL and those assemblies that begin with word System, we have over 5,000 public classes that include over 45,000 public methods and 15,000 public properties, not counting those methods and properties that are inherited and not overridden.... 60,000 properties and methods...

    ... Like other addictive technologies, I have a love/hate relationship with IntelliSense, and the more I despise it, the more I use it, and the more I use it, the more disgusted I am at how addicted I’ve gotten, and the more addicted I get, the more I wish it had never been invented... IntelliSense is also dictating the way we program.

    ... for many years programmers have debated whether it’s best to code in a top-down manner, ... or, alternatively, the bottom-up approach ... In order to get IntelliSense to work correctly, bottom-up programming is best. IntelliSense wants every class, every method, every property, every field, every method parameter, every local variable properly defined before you refer to it ... But the implication here is staggering. To get IntelliSense to work right, not only must you code in a bottom-up structure, but within each method or property, you must also write you code linearly from beginning to end... It’s not that IntelliSense is teaching us to program like a machine; it’s just that IntelliSense would be much happier if we did. And I think it’s making us dumber... So I don’t think IntelliSense is helping us become better programmers. The real objective is for us to become faster programmers, which also means that it’s cheapening our labor.

    Take a look at some of the sample code that comes out of Microsoft. There you’ll see button1, button2, button3, label1, label2, label3, etc. Any yet, everyone agrees that one of the most important elements of writing self-documenting code is giving your variables and objects meaningful names.

    If Visual Studio really wanted you to write good code, every time you dragged a control onto your form, an annoying dialog would pop up saying “Type in a meaningful name for this control.” But Visual Studio is not interested in having you write good code. It wants you to write fast code.

    Another problem with Visual Studio’s generated code is that every control is made a field of the class in which it is created. This is a hideous programming practice, and it really bothers me that programmers may be looking at the code generated by Visual Studio to learn proper programming technique, and this is what they see.... Global variables are basically gone in object-oriented programming, except that fields are now the new global variables, and they can be abused just as badly.

    [/docs] permanent link

    2005.Oct.24 Mon

    Write GUI Code Last

    The most common attitude about test-driven development and user-interface code is that the two don't combine well. I have only attempted a small amount of test-driven UI code - on MacOS Carbon and Java Swing - and didn't find it terribly helpful. I may try again with Cocoa and see how that works out.

    The danger of having GUI code as a coding-area designated "not to be test-driven" is the temptation to write the GUI code first, and to mix in business logic code with the GUI code. Avoid that temptation.

    Your business logic could have multiple user-interfaces: a Mac UI, a Windows UI, a Unix/Linux UI, a command-line interface, a scripting UI via COM on Windows or AppleScript on MacOS X, or an embedded scripting language, and even a web-interface. Using FIT/Fitnesse means that you also have an acceptance-testing interface.

    Keep the UI from mixing with the business logic by test-driving the business logic first. This makes writing portable, multi-platform code much easier since UI code is very often single-platform. Even if you don't plan on writing portable code, TDD-ing the business logic before coding the UI still provides a separation of concerns that is a hallmark of good design, and allows better re-use of the business logic within the same project or different projects.

    Therefore, to avoid mixing business business logic with the GUI code and thus creating code that's unnecessarily coupled and non-cohesive, test-drive the business logic code first, and write the GUI code last. Sometimes a spike might be necessary to find out what the GUI framework requires. Don't forget to throw away the spike code after you discover what you need to learn.

    [/docs] permanent link

    2005.Oct.17 Mon

    False Dichotomies

    BDUF (big design up front) is not the "opposite" of incremental design, it's part of the continuum of how much design precedes coding/refactoring. In a blog entry where Joel wrote a specification up-front contrasting it with his straw-man view of XP's incremental development, he called what he did BDUF, but it was neither Design (it was specification), nor was it big; he was not doing BDUF, and he was doing something many agile methods promote: creating a specification of the requirements before development. In XP the details of the specification would be delayed until later, but the overall requirements are needed to estimate the Release Plan.

    Waste does not mean failure. Advocates of incremental design say that too much design up-front is wasteful, but that doesn't mean up-front design can't be part of a successful project.

    BDUF is not the same as "too much" design up-front, so stop saying BDUF when you mean TMDUF (too much design up-front).

    [/docs] permanent link

    2005.Oct.10 Mon

    Uncle Bob 3

    Robert C. Martin writes on the benefits of TDD-style unit tests (bold-facing is my emphasis):

    Have you ever integrated a third party library into your project? You got a big manual full of nice documentation. At the end there was a thin appendix of examples. Which of the two did you read? The examples of course! That's what the unit tests are! They are the most useful part of the documentation. They are the living examples of how to use the code. [...]

    [...] I had been a programmer for nearly thirty years before I was introduced to TDD. I did not think anyone could teach me a low level programming practice that would make a difference. Thirty years is a lot of experience after all. But when I started to use TDD, I was dumbfounded at the effectiveness of the technique. I was also hooked. I can no longer concieve of typing in a big long batch of code hoping it works. I can no longer tolerate ripping a set of modules apart, hoping to reassemble them and get them all working by next Friday [...]

    [/docs] permanent link

    Uncle Bob2

    Robert C. Martin compares test-driven development to double-entry bookkeeping:

    Software is a very sensitive domain. If a single bit of a 100MB executable is wrong, the entire application can be brought to it's knees. Very few other domains suffer such extreme sensitivity to error. But one very important domain does: Accounting. A single digit error in a massive pile of spreadsheets and financial statements, can cost millions, and bankrupt an organization.

    Accountants solved this problem long ago. They use a set of practices and disciplines that reduce the probability that errors can go undetected. One of these practices is Dual Entry Bookkeeping. Every transaction is entered twice; once in the credit books, and once in the debit books. The two entries participate in very different calculations but eventually result in a final result of zero. That zero means that the all the entries balance. The strong implication is that there are no single digit errors. [...]

    We in software have a similar mechanism that provides a first line of defense: Test Driven Development (TDD). Every intention is entered in two places: once in a unit test, and once in the production code. These two entries follow very different pathways, but eventually sum to a green bar. That green bar means that the two intents balance, i.e. the production code agrees with the tests. This is not perfect, and other controls are necessary; but there can be little doubt that TDD vastly decreases the defect load in software projects. [...]

    [/docs] permanent link

    Uncle Bob

    Robert C. Martin reminds us:

    When tests are ugly, maintaining them is hard; and that makes maintaining the production code hard because the tests have to be maintained along with the production code. [...] If you want your production code to be easy to maintain, you must keep your tests easy to maintain. [...] The tests need to be well structured, well designed, and well coded. They need to be readable, understandable, and flexible. Duplication must be eliminated from them. [...]

    Test code is what we depend upon for design documentation, correctness verification, design support, and so many other things. Our tests support our refactoring. Our tests give us the courage to make changes. Our tests tell us what has gone wrong whenever we break something. Given that we depend on our tests for so much; doesn't it make sense to treat them well?

    [/docs] permanent link

    2005.Oct.06 Thu

    Unpalatable Advice

    The few people who were doing Waterfall development successfully were offended when proponents of Agile methods attacked the usual attempts at a process also called Waterfall as being unworkable. Both sides were using the same name, but for the most part were talking about different things.

    Now Ken Pugh's book Prefactoring is out, and he does the same thing: attacking something that many inexpert teams do, but which experts don't (usually) do: stopping progress in a project in order to do a large redesign. He calls that refactoring, a term commonly mis-used for that very thing, but which doesn't fit the definition of refactoring as understood and practiced by the experts. Recall that the first XP project with Kent Beck and Ron Jeffries did the same thing: they spent a week or two with acceptance tests failing as they stopped progress to change a core part of their design. It seems like every team doing XP has to learn the hard way that refactoring has to be done as a continuous process, otherwise code-debt piles up until a big overdue change has to be done.

    Looking at the sample chapter available from O'Reilly, I see Ken advocating the same care with domain-driven design that many agile experts have advocated. Compare this with, for example, what Kevin Rutherford writes: "One of my current bug-bears is the lack of design done by agile teams. I know we all chant 'design is good, so we design all the time', but in reality it just doesn't happen. Switching from legacy habits into test-first thinking and good object design is a really hard jump." And John Roth: "...the fundamental language types, and the basic language libraries, do not, and let me repeat that, do not represent any concepts that your application actually needs. At best they represent bizzare oversimplifications of those concepts that can't be told apart by the type checking mechanism.".

    Ken Pugh, in this book, wrote: "...avoid using primitive data types. Pretend that ints or doubles do not exist.... Items are priced in Dollars.... The time for a single song... could be stored in a TimePeriod.... A U.S. Zip Code is not just a CommonString either. You can describe it as a NumericString.... as a FormattedString.. or as a ZipCode data type. If any combination of digits was valid, using NumericString or FormattedString might be appropriate. However, declaring the attribute as a ZipCode type allows us to abstract away its actual representation.... Do not combine classes simply for implementation purposes. You can define both SocialSecurityNumbers and PhoneNumbers as strings of digits with two dashes. That does not make them equivalent.... You would never send a Social Security number to be dialed, nor would you attempt to record payroll taxes against a phone number."

    I had the opportunity to review a draft of Ken's book early this year, but lost track of it with my new job and all sorts of things. I will not judge his book by the cover, but by its content, which seems to have some uncommon "common sense".

    [/docs] permanent link

    2005.Oct.04 Tue

    Agile Specifications

    Automated acceptance tests are specifications in an agile method. Check out Dave Churchville's blog entry on this subject. Quote:

    ... Now, for the next iteration, Bill gets a little preoccupied with some nuisance lawsuit, and isn't able to spend as much time with the developers. Since they can't really talk to him, they make some educated guesses about the features, and try to keep it simple.

    So Bill has asked for some online help in the next iteration. Our cheerful developers build a maniacal animated paperclip, which certainly fulfills the high level story. Millions of innocent people are made to suffer needlessly.

    What if Bill had just written some acceptance tests to clarify things?...

    [/docs] permanent link

    BDD

    Since TDD - Test-Driven Development - is a design-implement technique that happens to produce suites of automated tests, people often think it all about testing. BDD - Behavior-Driven-Design - attempts to correct this by using different terminology. See Elizabeth Keogh's blog entry on this. Quotes:

    ..."Test", in Test Driven Development, encapsulates the idea of specification, design, verification of implementation and the ability to confidently refactor....

    I find that using the word "should" helps me [...]. I find it helps me consider the roles and responsibilities of the class, and the class's interaction with others. I find it keeps me away from that distracting, misleading, misnomer: "Test".

    [/docs] permanent link

    2005.Oct.02 Sun

    Fighting Urban Legends about Garbage Collection

    Urban performance legends, revisited, by Brian Goetz. Quotes:

    The common code path for new Object() in HotSpot 1.4.2 and later is approximately 10 machine instructions ..., whereas the best performing malloc implementations in C require on average between 60 and 100 instructions per call... many real-world C and C++ programs, such as Perl and Ghostscript, spend 20 to 30 percent of their total execution time in malloc and free -- far more than the allocation and garbage collection overhead of a healthy Java application...

    ... The malloc/free approach deals with blocks of memory one at a time, whereas the garbage collection approach tends to deal with memory management in large batches, yielding more opportunities for optimization...

    ... you can see why copying collectors enables such fast allocation -- allocating a new object is nothing more than checking to see if there's enough space left in the heap and bumping a pointer if there is. No searching free lists, best-fit, first-fit, lookaside lists -- just grab the first N bytes out of the heap and you're done.

    ... for most objects, the direct garbage collection cost is -- zero. This is because a copying collector does not need to visit or copy dead objects, only live ones... the vast majority of objects in typical object-oriented programs (between 92 and 98 percent ...) "die young," which means they become garbage shortly after they are allocated, often before the next garbage collection... Therefore, not only is allocation fast, but for most objects, deallocation is free.

    [/docs] permanent link

    2005.Sep.30 Fri

    Coupling

    Object-Oriented programming, and design patterns in particular, help us get away from the morass of spaghetti-code from olden days of yore (before OO and design patterns). Imagine a ball of tangled cooked spaghetti that's cooled and congealed and maybe has been sleeping in the freezer for a long while, and you want to remove one stand without breaking any other strands or even moving them too much. You can't: that's tightly-coupled.

    Here are a few things that couple code: global variables, global functions, concrete classes that refer directly to each other, code duplication, data duplication, C/C++ include files. And "manifest types". That last one is where your programming language requires you to declare type for each member variable, parameter, function result, local variable, etc. And then the compiler checks them. Sometimes you know more than the compiler does and therefore you have to use type-casts to tell the compiler the correct type.

    The worst of manifest typing and "include files" often goes together. You change the return type of a method from "unsigned short" to "short" (or vice versa), perhaps by changing a typedef for that return-type in a header file. Now every source file that includes that header file has to be recompiled, even if they didn't use that type or that method. Also, every method that overrides or calls that method has to be recompiled - and the rest of each class's code gets to be recompiled as well, even though other methods in the class might not be affected. Every class that has a member variable of that typedef has to be recompiled. Every other method that has parameter or local variable of that typedef has to be recompiled. In this case, the size of the type hasn't changed, the operations that legal for that type haven't changed, and though the range of values used for that variable have changed, almost all the code involving that type will not have to change, but massive recompiled has been forced on you.

    The same kinds of cascades of recompiling can occur when changing a method's argument type to 'const', or changing from one container type like 'list' to 'vector', or many other things that you would hope would have only minor effects. On large projects, those recompiles can cost hours each day.

    David Buck talks about this on this blog. He references Local Change / Local Effect Principle and Domino Effect.

    [/docs] permanent link

    2005.Sep.28 Wed

    Filters

    I once needed to make three "filters" works. They each took an image file and several parameters as input, and produced an output PDF file. For most manual tests for various parameter settings, they did not produce correct output. So I refactored the big filter function to do the filtering in two steps (two subroutine calls).

    The first subroutine works on the parameters to compute the values needed to be passed into the image processing library, and the second subroutine calls the image processing library with the input image, those computed values, and produces the output image.

    Then I wrote a parameterized unit test that took all the parameters as input to the first subroutine, also took into expected output values, and asserted that the actual output values were equal to the expected output values.

    Then I wrote 900 one-line unit tests to this parameterized unit test with the various permutations of the input parameters and expected output values. (I actually worked in a spreadsheet for a while and copied-pasted from the spreadsheet to the unit test source code.) The test would also generate the output PDF file, which I could visually examine

    About 80% of the tests failed.

    Then I started working on the first subroutine to fix its problems. I got to where only 60% of the tests failed, then only 50%, 30%, 25%, 10%, the only 2 failures, and then 100% passing. Sometimes a change causes more tests to fail than before, and I could examine my latest modification and fix it, or undo it to try something else.

    That was the first of the three filters.

    The other two were similar, but with fewer parameters and options, each of those only needed about 600 one-line unit tests. Note that I didn't test EVERY combinations of options and settings. That would have required several billion test cases. By making an intelligent selection of the "input space" I could exercise the filter algorithm along all of its dimensions with a minimum of effort.

    Fixing all three filters with the aid of automated tests only took a few days each. Trying to make the algorithm work with manual testing would have taken months or years.

    [/docs] permanent link

    Blocks

    Ruby, calling a method with a block argument:

    
        anObject.methodTakingBlock { someObj.doSomethingHere }
    
    

    or

    
        anObject.methodTakingBlock do
            someObj.doSomethingHere
        end
    
    

    Smalltalk, calling a method with a block argument:

    
        anObject methodTakingBlock: [ someObj doSomethingHere ].
    
    

    Ruby, implementing a method that takes a block argument (the lack of a named block variable and the "yield" keyword are a bit confusing, particularly if you associate "yield" with threads, which are not in play here.)

    
        def methodTakingBlock
            yield
        end
    
    

    Smalltalk, implementing a method that takes a block argument.

    
        methodTakingBlock: aBlock
            aBlock value.
    
    

    Ruby, calling a method with a block argument that takes two argument itself:

    
        anObject.methodTakingBlock { 
            |aVar, bVar| someObj.doSomethingHere(aVar, bVar) }
    
    

    or

    
        anObject.methodTakingBlock do |aVar, bVar|
            someObj.doSomethingHere(aVar, bVar)
        end
    
    

    Smalltalk, calling a method with a block argument that takes two arguments itself:

    
        anObject methodTakingBlock: [ :aVar :bVar | 
            someObj doSomethingHere: aVar andHere: bVar ].
    
    

    Ruby, implementing a method that takes a block argument, giving the block the values 12 and 13 for the block's own arguments.

    
        def methodTakingBlock
            yield 12, 13
        end
    
    

    An Ruby alternative syntax where the block argument is converted to a Proc object and is accessible via a named parameter:

    
        def methodTakingBlock(&aProc)
            aProc.call(12,13)
        end
    
    

    Smalltalk, implementing a method that takes a block argument, giving the block values 12 and 13 for its own arguments.

    
        methodTakingBlock: aBlock
            aBlock value: 12 value: 13.
    
    

    [/docs] permanent link

    2005.Sep.24 Sat

    Dear Wil Wheaton (an Open Letter)

    I've enjoyed your books, your blog, and your performances on Star Trek Next Generation. In Dancing Barefoot I particularly enjoyed the story of "William F-ing Shatner" and everything that led up to your epiphany at the Las Vegas Star Trek Experience.

    In the course of that writing, you mention that Deep Space Nine is not one of your favorite Star Trek series [please don't stop reading yet]. I suggest this may be, at least in part, because you are viewing that show as a Star Trek fan. If you view it as a writer and actor, you may see more value to that series. The meat and potatoes for writers and actors is conflict, drama, and comedy. The setting and cast of DS9 is just full of opportunities for conflict, drama, and comedy. The original Star Trek and Star Trek: The Next Generation were more about exploration and sense of wonder (and there's nothing wrong about that). All of the Star Trek shows (except for the Original Series) took at least two seasons to find their "tone", so please don't judge DS9 from its earliest episodes, which may have started even rockier than the others.

    DS9 has conflicts in its initial setting: The Bajorans, who were until recently oppressed by Cardassians, have to rebuild the world and rebuild their world-view. They still must interact with Cardassians, and each race hates each other, but in many episodes they have to work with each other, and sometimes even come to love each other. Neither race particularly likes the Federation. Many of the Bajorans now involved with governing the planet and the space station were, quite frankly, terrorists during the Cardassian occupation. I sometimes wonder how this show would play in the Middle East if translated into Arabic, Farsi, etc. Would the viewers think of the Cardassians as representing the United States and/or Israel? I imagine they would identify with the Bajorans to some degree. What would the Federation, with its acceptance of tolerance and diversity, represent to them? Watching the show with those ideas in mind provides a twist quite lacking in most episodes of other Star Trek series.

    Ben Sisco, the Federation man in charge of the space station, considers himself a man of science, and yet finds himself thrust into the role of the Bajoran "Emissary of the Prophets", a religious figure of much importance, in the first episode. During the seven years of the series, he grows into that role. In the early seasons, he calls the mysterious occupants of the wormhole, the "wormhole aliens," and in later seasons more and more often refers to them using the Bajoran term "the Prophets". His dual 'roles' provide conflicts on both professional and personal levels.

    Like Wesley Crusher on ST:TNG, there is a child growing up on the show: Jake Sisco. Unlike Wesley, he's something of an under-acheiver. Jake has a particularly moving episode in Season 4 where he loses his father to a "wormhole inversion"; he spends his life trying to retrieve his father from this anomaly, and as an old man, realizes that to save his father, he has to kill himself the next time his father temporarily re-appears. And he does! This resets time back to the original incident and Ben Sisco is able to avoid getting trapped in the time-vortex the "second time" around.

    Nog, other 'child' on the show (which under the makeup I think was played by an adult), starts outs as a truant who often gets Jake into trouble, and ends up becoming an over-enthusiastic Star Fleet cadet and ensign. He has a episode that is also a good character study in Season 7 where he has to come to terms with losing his leg in the war. You don't really see this kind of character growth in individual episodes; you have to view each season as if you're reading a novel.

    The best dramatic Season 6 episode shows us what life as black science fiction writer of the 1950's might have been like. Avery Brooks portrays a man with a dream, nearly broken by racism, so well that I'm getting misty-eyed just remembering it. Far Beyond The Stars should have won mainstream awards for best TV series dramatic episode, but of course it wasn't considered because it was "just" a science fiction show. :-(

    There are too many good dramatic episodes to list (poor Chief O'Brien, the "everyman" character: he gets himself wrung through the wringer many times ), but I also love the comedic episodes. The Ferengi, who are mostly used for comedic episodes, poke fun at our capitalistic society. The season 6 episode, The Magnificent Feregni , is one of the funniest because they try to act all macho, which is out of character for their kind (though Quark, Rom and Nog demonstrate honor and quiet bravery in many dramatic episodes). The House of Quark in Season 3 , where Quark temporarily marries a Klingon and saves her house through good accounting and Klingon-esque bravery, is also particularly good.

    Perhaps the best comedic episode of all builds on the Original Star Trek's The Trouble With Tribbles : Trials and Tribble-ations . For a Star Trek fan, this episode is a must-see because of how detailed their recreations of the original ship model, sets, costumes, and props are. Watch the DVD's "making of" extras to see how much love went into the making of that episode. DS9 probably brought back more actors reprising the characters from the original series than any other. (But they were all Klingons!) "Darvin" from Tribbles, "Kor", "Kang", and "Koloth" in other episodes.

    So there something there for a Star Trek fan, as well as for someone who appreciates comedy and drama. Check it out. :-)

    Sincerely, C. Keith Ray

    [/docs] permanent link

    2005.Sep.19 Mon

    Using Cocoa's Reflection APIs for Reading/Writing an SQL Database

    CoreData is probably doing something like this already. If you don't like CoreData's use of sqlite3/XML or being limited to the Tiger version of MacOS X, you can probably use these APIs to implement your own object-to-database mapping. If you want to work with a database schema that doesn't map simply to your classes, look elsewhere. Also: I'm just getting to know SQL-based databases, so I may be mis-using SQL/DB terminology or concepts.

    Writing to the database:

    1. Call the method "className" to get the object's class-name and map that to a database table. You probably also want to map object addresses to a unique id in that database table.

    2. Calls these methods to find keys of the object and map those to column-names (and possibly foreign keys to other tables): "attributeKeys", "toOneRelationshipKeys", "toManyRelationshipKeys"

    3. Get values for keys by calling "valueForKey:" or "dictionaryWithValuesForKeys:". There's also "mutableArrayValueForKey:" for dealing with to-many relationships.

    4. Assemble SQL from the classname/tablename, key-names/column-names, and values gotten above, and use that to write to the database. You'll probably need to write multiple rows to multiple tables to persist a complex aggregate object, thus you need to use techniques common to object-serialization to detect cycles and avoid writing an object to the db more than once. One of the PLoP books had a good discussion of serialization.

    Reading from the database is pretty much the reverse of the above, but getting to the class from a classname/tablename requires calling NSBundle's "classNamed:" method or some other method or function I haven't found in my quick search using AppKiDo while writing this. Once you have the values and key-names, set them with the method "setValue:forKey:" or "setValuesForKeysWithDictionary:".

    Cocoa has bunches of interesting methods like "classForArchiver" and "replacementObjectForArchiver:" that are probably used behind the scenes for implementations of Distributed Objects, reading/writing NIB files (in various NIB file formats, which recently included XML, I believe), and more recently, Core Data. Maybe someday I'll get more familiar with these. Oh, I haven't actually done this (yet), so don't ask me for help if you get stuck. :-)

    [/docs] permanent link

    2005.Sep.09 Fri

    Heard...

    Really cool, funny book teaching Ruby here. Funner than "Mr. Bunny's Guide to Java" and actually educational.

    Cutter IT Journal apparently published a study "What Metrics Say About XP" by Michael Mah where five XP projects were compared to five waterfall-style projects inside a medical devices company. The XP projects completed 25-30% sooner and had one fourth the defects of the traditional-style projects.

    John Roth provides an idea to force programmers to create abstractions (hopefully appropriate for their application's domain). Quote:

    Provide a switch that causes a compile error if any of the fundamental types or fundamental libraries are used without the "private" scope.

    It's that simple: the fundamental language types, and the basic language libraries, do not, and let me repeat that, do not represent any concepts that your application actually needs. At best they represent bizzare oversimplifications of those concepts that can't be told apart by the type checking mechanism.

    [/docs] permanent link

    2005.Sep.08 Thu

    The Simplest and Yet a Very Effective Feature Request tracking tool

    One that works well for small, co-located teams is the index card for small features/stories.

    Particularly nice if you are doing iterative development and you can put the index cards on the wall, partitioning the wall in designated areas: "this iteration's stories" (aka "front burner"), "next iterations stories" ("back burner"), other future stories ("refrigerator"), and not-to-be-done-this-release ("the freezer"). A project might have 100 to 200 stories (or more), but only a dozen or two are on the wall, in the 'active' state, at any time.

    (Kitchen metaphor names courtesy of Net Objective's Alan Shalloway, see http://www.netobjectives.com/events/specific/pr_nca_2005_08_xbrfasd.htm Slides in pdf form here)

    Bugs can be considered small features/stories as well, and tracked using index cards and the wall as well. Some teams use red index cards for bugs. If you have so many bugs that you need a database... you have too many bugs.

    It's really nice to take a bug-report-on-paper, talk to the QA tester about the bug, take it to my computer, fix the bug (writing notes on that paper if I need to), and then take the paper to the QA tester and talk to him about the bug and its fix, leaving it for him to verify. It can then go back on the wall with a mark on it indicating that bug-fix is completed, or go back to me for additional work.

    For remote employees, I've used a wiki to list stories, track who is working on them and when they're completed.

    [/docs] permanent link

    2005.Aug.27 Sat

    Lots of Design All The Time

    Big Design Up-Front (BDUF) supporters claim that XP doesn't do enough design. See Agile Modeling for the opposing view. That book is naming all the kinds of designing (other than test-driven-design) that XP projects do.

    We need a new acronym for XP's design practices: not SDUF (Small Design Up-Front), even though that's kinda true, but LoDAtT: Lots of Design All the Time.

    [/docs] permanent link

    2005.Aug.17 Wed

    Are Your Lights On?

    I've been re-reading the book Are Your Lights On? How to figure out what the problem REALLY is by Donald C. Gause and Gerald M. Weinberg. This is the book that should have become popular instead of "Who Moved My Cheese?". It doesn't talk down to the reader, and it's fairly light-hearted. (Of course, it's not the same subject as the Cheese book, but that's besides the point.) [Problem: a bad book like Cheese was popular, but a good book like this isn't (in comparison). We are the Solution: buy it, and blog about it. Tell all your friends. Get your CEO or CIO or the HR department to buy it in bulk.]

    Sometimes the problem not considered when coming up with solutions is "whose problem is it?". This book considers that question several times in various real-world situations... such as landlords versus tenants, university president versus professors versus students, competing businesses and government regulators, bureaucrats and travelers.

    In the area of agile programming practices, and their acceptance or lack of acceptance within an organization, consider who "owns" a problem before trying to solve it. If you are considering automated acceptance tests, what problems are they solving? (And, what problems are they creating?) Are people who feel the pain the most solving their own problem?

    You can also consider this book as an informal prequel to the more serious book Exploring Requirements: Quality Before Design by Gause and Weinberg. Buy both.

    [/docs] permanent link

    2005.Aug.13 Sat

    Essays

    Essays by Scott Berkun, author of a project management book, The Art of Project Management, about which Kent Beck said "Reading this was like reading the blueprint for how the best projects are managed at Microsoft. I wish we always put these lessons into action!"

    "How to learn from your mistakes" quotes: You can only learn from a mistake after you admit you’ve made it. ... The larger your ambitions, the more dependent you will be on your ability to overcome and learn from your mistakes. ... success in learning from mistakes often requires involvement from other people, either for advice, training or simply to keep you honest. ... when you can laugh at your own mistakes you know you’ve accepted it and no longer judge yourself on the basis of one single event. Reaching this kind of perspective is very important in avoiding future mistakes. Humor loosens up your psychology and prevents you from obsessing about the past. It’s easy to make new mistakes by spending too much energy protecting against the previous ones.

    Why smart people defend bad ideas" quotes: ... one thing I did learn after years of studying advanced logic theory is that proficiency in argument can easily be used to overpower others, even when you are dead wrong. ... The problem with smart people is that they like to be right and sometimes will defend ideas to the death rather than admit they’re wrong. ... if they got away with it when they were young ... they’ve probably built an ego around being right ... Until they come face to face with someone who is tenacious enough to dissect their logic, and resilient enough to endure the thinly veiled intellectual abuse they dish out during debate ... they’re never forced to question their ability to defend bad ideas.

    Check them out.

    [/docs] permanent link

    2005.Aug.04 Thu

    [no] Change in the Boardroom

    Seth Godin blogs:

    There’s no point whatsoever in having a meeting designed to elicit change if the attendees are insulated against changing their minds. ...

    Ironically, the setting and tone of a conference room work to create precisely the opposite effect. Business meetings (and sales calls) are custom-made for failure. People walk in and are reminded (in an overwhelmingly Proustian way) that this is the place to stand your ground, this is the place where good arguments carry the day and build careers, and weak-kneed flip-floppers hurt their careers. When was the last time you changed your mind in a conference room?

    ...Well, you can argue against human nature or you can follow a two part strategy:

    1. sell to people in the mood to flip. ...

    2. Start a cascade of small flips....

    [/docs] permanent link

    2005.Aug.02 Tue

    Good Stuff on "Blaming Organizations" here:

    Beyond Blaming: Congruence in Large Systems Development Projects by Jean McLendon and Gerald M. Weinberg (See also www.satir.org and www.geraldmweinberg.com)

    It is a fairly long article, here's a few small snips:

    "...Propose to an Englishman any principle, or any instrument, however admirable, and you will observe that the whole effort of the English mind is directed to finding a difficulty, a defect, or an impossibility in it. If you speak to him of a machine for peeling a potato, he will pronounce it impossible; if you peel a potato with it before his eyes, he will declare it useless, because it will not slice a pineapple.... Charles Babbage, 1852

    "As early as 1852, Charles Babbage could see symptoms of decay and infer from them a vision of future performance. In so doing he provides a perfect description of the blaming style of communication, which emerges in 'decaying' organizations--be they nations or software engineering organizations. What is a "blaming style of communication," and why is it important in systems development?...

    "Achieving Congruence

    "When Deming said, "Drive fear out of the workplace," we think he was talking about changing the blaming organization to the congruent organization. This kind of change is made by one person at a time--hopefully starting at the top--and one step at a time. The steps can be broken down into six 'A's', as follows: Awareness, Acceptance, Authorship, Articulation, Application, Activism. Let's look at how each of these steps takes place in the context of an individual trying to change a blaming organization.

    "...Activism says, "Now that I can make a difference in myself and my most familiar world, I'm going to help spread this throughout the organization." Activism is applied leadership, starting at the point at which you have enough competence at being congruent to reach out and be proactive--anticipating, initiating, instigating--but not inflicting. You cannot operate from an incongruent position and force other people to be congruent..."

    [/docs] permanent link

    What would it take for a new language to impress me?

    1. painless interoperability with other languages: C in particular, Objective-C, C++, Python, Java, Ruby, SQL, etc. Objects in this new language should be able to use and/or be proxies for objects in other languages. The language should be usable for shared libraries, plugins, device-drivers, and so on, as well as applications and scripting.

    2. support for threads and inter-thread / inter-process communication. Java had "synchronized" but that wasn't enough (and maybe not even the right thing to have). Cocoa's Distributed Objects turn out to be fairly easily used for both inter-thread / inter-process communication, and Cocoa also has support for other ways of synchronous/asynchronous communication, but much of Apple's Cocoa isn't thread-safe. Make it easy to use operating-system threads. Also, make it easy for a programmer to set up a million thread-like objects that don't harm each other and which don't thrash a CPU to death.

    3. garbage collection. Look to modern Smalltalk environments for how to do it right. Be able to turn it off for specific objects, etc.

    4. work with programmer's weaknesses: many programmers forget to initialize local and member variables... make it easy to init them to a good value, and default to initializing them a zero, null, or default-constructor. Also put in warnings for some other common problems.

    5. avoid other language/system weaknesses: learn from common problems areas in Java for example: classpath and class-loaders.

    6. consider Objective-C's "message-eating null" -- many people who've never used it expect it to cause problems, but it actually makes programming easier and simpler. Only very rarely do you need to check if a variable is null... and you never get "Null Pointer Exceptions" halting your program.

    7. and while you're at it, I'd like to use a debugger that understands objects: let me set breakpoints on ONE specific object: any methods (or any methods that I select) called on that object break into the debugger. Let me add logging of all state-changes to an object, or class of objects, while I'm in the debugger, without writing any code. If I set a break point on a method, let me specify which classes that applies to, if the method is inherited by more than one class. Let me browse all instances of a class (or all classes), and optionally find out where each one was created.

    Note that I don't talk about syntax, or dynamic-type-checking versus static-type-checking (versus type-inferencing). A correct program is correct in spite of the kind of type-checking that a compiler might enforce. I would want help from the compiler, but not hindrances. I've seen a lot of varieties of syntax. I would want something readable (and I don't consider Lisp and Perl - as usually written - to be readable). Pascal might be considered verbose these days, but it was designed for readability and simplicity (a parser for Pascal would be pretty simple, very simple compared to a C++ parser). Smalltalk is very simple, and pretty readable. Objective-C is "unusual" for those used to C++, but it is powerful, and pretty painless in integrating with other languages. I wonder what a combination of Pascal and Objective-C would look like?

    [/docs] permanent link

    2005.Jul.27 Wed

    Pair Programming Paper

    From a paper by Alistair Cockburn and Laurie Williams:

    Economics. A recent controlled experiment found only a small development cost for adding the second person. However, the resulting code also had fewer defects. The defect removal savings should more than offsets the development cost increase.

    This paper sites IBM's finding that defects released to end-users cost an average of $8000 to fix. The lower defect rate more than makes up the slightly higher cost of development. Another quote: we zoomed through QA with hardly a hitch. Everyone, myself included, was amazed that it didn't take weeks to debug, especially given that one of the trees had recently spent SIX WEEKS in QA hell. It was obvious that the pairs had dramatically reduced the defect rate.

    Other effects of pair programming:

    Pair relaying ... pairs consistently report that they solve problems faster, and that it is different from improving design quality, or detecting typing errors, or brainstorming. By "problem solving", we refer to when the two are puzzled as to why something doesn't work as expected, or simply can't figure out how to go forward.

    ...I encouraged the developers to think out loud (what Ward Cunningham calls reflective articulation). This did the trick. They actually began to work together, not just take turns coding...

    Line of sight learning... successful apprenticeship environments is that the novice work in a "line of sight" of the expert, that expertise is transmitted, in part, through the ongoing visual (and auditory) field. They describe successful apprenticeship learning in both tailors and Navy signalmen where "line of sight" is available. The beginner explicitly picks up skills from hearing and/or seeing the expert.

    Use Expert In Earshot when novices are not learning good techniques and habits very well, but you don't want to turn the expert into a full-time teacher. Put the expert or leader in the same workspace as the more novice workers, so that the novices can learn by watching and listening, while the expert does his or her usual work....

    Note also that experts can learn from their non-expert partners:

    I was sitting with one of the least-experienced developers, working on some fairly straightforward task. Frankly, I was thinking to myself that with my great skill..., I would soon be teaching this young programmer how it's really done. We hadn't been programming more than a few minutes when the youngster asked me why I was doing what I was doing. Sure enough, I was off on a bad track. I went another way. Then the whippersnapper reminded me of the correct method name for whatever I was mistyping at the time. Pretty soon, he was suggesting what I should do next...

    [/docs] permanent link

    2005.Jul.07 Thu

    What TDD is Really About

    Quoting Dave Astels on Test-Driven Development (aka Behaviour Driven Development):

    So if it’s not about testing, what’s it about?

    It’s about figuring out what you are trying to do before you run off half-cocked to try to do it. You write a specification that nails down a small aspect of behaviour in a concise, unambiguous, and executable form. It’s that simple. Does that mean you write tests? No. It means you write specifications of what your code will have to do. It means you specify the behaviour of your code ahead of time. But not far ahead of time. In fact, just before you write the code is best because that’s when you have as much information at hand as you will up to that point. Like well done TDD, you work in tiny increments… specifying one small aspect of behaviour at a time, then implementing it.

    Brian Marick has been calling this Example-Driven Development.

    [/docs] permanent link

    2005.Jul.06 Wed

    Recommended Book and Videos

    Inside Intuit: How the Makers of Quicken Beat Microsoft and Revolutionized an Entire Industry Notice how the founders got requirements from their potential customers before writing and releasing Quicken.

    Wonderfalls - The Complete Series "The funniest show you've never seen." Killed by Fox after showing only 4 episodes, the DVD set has the entire first season of 13 episodes. It's what "Joan of Arcadia" might be if that series was a romantic comedy and a lot less self-important. Quoting a review: "What sets it apart from other series is the surreal touch and wicked sense of humor. It's never made clear why Jaye hears toys and bookends talking cryptically to her -- is it God? Aliens? Her own mind?" This DVD set is available only because of a letter-writing campaign organized at http://www.savewonderfalls.com/. Go to that site for links to interviews with the cast, episode guide, scripts (which make good reading), etc.

    [/docs] permanent link

    2005.Jul.02 Sat

    Cut Your Car Refueling Costs in Half

    According to what I've read here, Brazil lessened its dependency on foreign oil by converting, over the course of the last three decades, to gas-alcohol mixtures. Their "flex-fuel" cars and trucks can run on pure gasoline, pure alcohol or a mixture. Currently alcohol fuel in Brazil, made from local sugar-cane, is half the price of pure gas, and 40% of the vehicles are running on it.

    Most American cars can run on mixture of up to 10% alcohol without modification. There are perhaps 5 million "flex-fuel" vehicles in the U.S. that can burn a mixture as high as 85 percent ethanol. Unfortunately few gas stations can handle "E85" fuel. Adding ethanol to gas has been called a ploy for farm-subsidies, but if the U.S.A committed to it, we could seriously reduce our fuel prices, reduce pollution, and reduce our dependance on foreign oil.

    If we also gradually convert to hybrid gas-electric cars that can optionally be plugged in for recharging, we further reduce our dependance on oil. Eventually more electric power-plants would be needed for overnight recharging, but few or no power-plants depend on oil. New plants will be more efficient (and thus less polluting) than old ones, so this path will also lead to eventual reductions in pollution.

    [/docs] permanent link

    "One Best Way" versus "Options"

    A book I have talks about preferences for 'one best way' (also called 'process') versus 'options'. 'Process' people want one way to do things, want to be told how to do it that way, and want to be told that it is the 'best' or 'right' way.

    'Options' people always want to invent a better way. If they're told 'x process' is the 'best way', they'll try to find a better. Options people are good at inventing processes, but not so good at following them.

    When talking to 'process' people, if you can establish your credentials as someone who should know the 'best' way, explain how following the process of test-code-refactor insures good design. Explain the rules of good design (modularity, encapsulating behavior, cohesiveness, low levels of coupling, etc.) and give examples of how following the test-code-refactor process produces code that meets those criteria and how design-code-(maybe-test) so often fails to produce code that meets those criteria.

    If you are talking to options people, you can mention how a whiteboard design session before TDD can let you explore options in the design, and how the rules of good design creates flexible code - allowing more options on how to use the code in the future.

    To get 'process' people to consider options, repeat this phrase:

    "One choice is not a choice, it is a trap;
    two choices is not a choice, it is a dilemma;
    three choices is a choice."
    (I believe I got that saying, perhaps worded slightly differently, from Jerry Weinberg.)

    Repeat this saying often. Establish it as a process to follow to avoid traps and dilemmas.

    [/docs] permanent link

    2005.Jun.27 Mon

    Code Smells - Long Method

    Introduction One

    Over recent years, in mailing lists and newsgroups, a conversion about refactoring is repeated many times which goes something like this:

    A: "Refactoring is [gold-plating | rewriting | unnecessary ]"
    B: "No, refactoring is improving the design without changing the functionality."
    A: "Ungh. I don't have time for that. The code is good enough as it is. "

    and so on... and sometimes...

    B: "Of course you'll want to have an automated test-suite to insure your refactorings don't accidentally change the intended behavior.
    A: "I certainly don't have time to write tests!

    Introduction Two

    Textbooks and courses try to teach good design, almost never show examples of bad design. The only examples I know of are the excellent books Refactoring by Martin Fowler, Refactoring to Patterns by Joshua Kerievsky and Working Effectively With Legacy Code by Michael Feathers. Code smells (names for various categories of bad design) has a chapter in "Refactoring" but could just as easily have a whole series of books.

    This essay is an attempt to describe one code smell, and how to correct it. The code smell is known as "Long Method" (or Long Function in a non-object oriented language.)

    The long method represents a lack of proper encapsulation -- it does too much itself, and doesn't delegate that work to the proper authorities. The irony here is the young coders sometimes think putting everything in one method or in one class is encapsulation. A long method often has varying levels of abstraction within a single block of code.

    Besides having "too much information" in one place, long methods prevent appropriate code re-use: they encourage cut-and-paste code duplication instead of re-use by calling methods and instantiating classes. Long methods are hard to understand. Hard to debug. And they are very hard to test.

    Here's an example - a 284-line function from an unnamed open-source project:

    In this example, the first block of code after the variable declarations starts with a comment "Remove all carriage returns". Any time you see a block of code within a long method that tells what that code is doing, that's a candidate for an Extract Method refactoring. We extract out that code, and use the comment as the name of the extracted method. In this example, 21 lines of code in this method are now replaced with one line of code. And you can bet that somewhere else in our project, we will also want to do something like this - if not removing carriage returns, then maybe removing some other character. This extracted method is also easy to test.

    The next comment in the code is "Trim all trailing white space" but unfortunately the code to do that is intermingled with code performing other activities. If the original programmer had been programming by intention, he would have created a method named TrimWhiteSpace, which would have been simple to write and simple to test. In this example, understanding this intermingled code and extracting out the TrimWhiteSpace code is going to be difficult enough that I would postpone that refactoring... getting other cleanup done may allow this refactoring to be easier to do, later.

    Even if you can't get the code as clean as you would like in one pass, doing small amounts of refactoring every day will help increase your productivity, code reuse, and testability

    See also:

    [/docs] permanent link

    2005.Jun.14 Tue

    Keeping the Design Good

    It's long been accepted that software inevitably degrades until it has to be re-written. Advocates of refactoring and iterative/incremental design/implementation reject that idea. Software doesn't degrade unless acted upon by an outside force (most often, programmers).

    Here's an example of a new requirement, and two ways to satisfy that requirement. One way creates an unsafe "lump" of bad design. The other way modifies the existing design so that the solution-code for the new requirement continues to meet the criteria for good design.

    The new requirement, for Apple MacOS X developers using Metrowerks PowerPlant, is Intel support/Universal Binaries. Specifically, the PowerPlant resource files that are in PowerPC (Motorola byte-order) need to work on Intel (Intel byte-order) as well as PowerPC, preferably without modification. These resources are called Ppob resources, and the are stored in binary form.

    Apple provided a lump of code that flips the bytes in Ppob resources here. Notice how the function _FlipPPob depends on the layout of almost every PowerPlant view/control class. Notice the big switch statement. Note the tons of duplicated code, such as calls to FlipViewData.

    One unsafe aspect of this _FlipPPob function is that it attempts to work with every view/control class, but there's a danger in that it doesn't really work with every view/control class. The author of this code may have left some view/control classes out, and of course programmers can (and do) define their own subclasses of PowerPlant view/control classes.

    Let's re-examine the existing design. Ppob resource reading is invoked by UReanimator. It reads enough to identify a view/control class, and creates an instance of that class via a set of nifty templatized factory objects. By using the factory objects, the UReanimator class does not depend on any concrete view/control classes. To read the PPob resource, UReanimator creates an instance of LDataStream, that it passes into the view/control object, which reads the Ppob data from that stream (typed as LStream, the abstract parent class of LDataStream). Each view/control class knows how to read its own data layout from the stream.

    While we could modify every view/control class to byte-swap the data it reads from the LDataStream, that would be duplicated code. The place to put the byte-swapping is in LDataStream, LStream, or a byte-swapping subclass of LDataStream or LStream. If we are running on an Intel platform, UReanimator can instantiate the new byte-swapping LStream-derived class (or pass in a parameter to LDataStream) The method that reads an int can be transformed from something like this:

    LStream & LStream::operator >> (UInt32 & outNum)
    {
        ReadBlock(& outNum, sizeof(outNum));
        return (*this);
    }
    

    to something like this:

    LStream & LStream::operator >> (UInt32 & outNum)
    {
        ReadBlock(& outNum, sizeof(outNum));
        if ( mByteSwapping )
        {
            outNum = ByteSwapUInt32( outNum );
        }
        return (*this);
    }
    

    Instead of a lump of poorly designed code (780 lines worth), we have a change in the UReanimator class (probably a one-line change) and a few changes to a existing LStream class; probably less than 100 lines of new code. The new changes are localized. They are not dependent on all the existing PowerPlant view/control classes. Any view/control class that we didn't plan for will still work. We have modified the code to handle a new requirement, without degrading the design.

    [/docs] permanent link

    2005.May.30 Mon

    Agile Acceptance Tests

    Quoting Lisa Crispin's

    Although our [automated acceptance] tests have found regression bugs, over and over the biggest value comes when we (testers and customers) collaborate with the programmers to create the tests. 9 times out of 10, there is a misunderstood assumption or overlooked scenario.

    Writing those tests before implementing the code to pass the tests helps flesh out those assumptions and scenarios before coding... saving time and avoiding re-work.

    The tests codify the requirements much better than non-executable documentation does, simply because it can be quickly executed to show if the product is in compliance, whenever the team needs that assurance.

    [/docs] permanent link

    2005.May.26 Thu

    Changing Your Compiler

    Since the Smalltalk compiler is just another set of classes within the Smalltalk environment, you can change it if necessary. David Buck shows the the simple changes he made in VisualWorks Smalltalk to enable programmers to write 45200000000 (45.2 billion) as 45.2b, 3000000 (3 million) as 3m, 60000 as 60k and so on. Check it out.

    [/docs] permanent link

    2005.May.24 Tue

    Outsourcing on its way Out

    Quoting Enterprise Systems/Stephen Swoyer:

    A recent study from professional services giant Deloitte Consulting found that many one-time outsourcers are bringing it all back home, so to speak. The Deloitte study, "Calling a Change in the Outsourcing Market," found that 70 percent of survey participants reported having negative experiences with outsourcing projects. Almost half (44 percent) didn’t realize the expected cost savings, and a majority (62 percent) found that outsourcing requires a greater-than-expected degree of management and oversight.

    As a result, Deloitte says, fully 25 percent of one-time outsourcers are bringing applications and services back in-house.

    [/docs] permanent link

    "Bugs" Versus "Defects" and "Issues"

    Johanna Rothman, on her blog, recently wrote "I suggested that my client change his naming of 'bug' to 'defect.'" She got several opposing responses. Interestingly, I think one opposing response may have been from a maker of a bug-databases that uses "bug" in the name of its product. The commenters said things like "bug is just a synonym for defect" and "changing the terminology has no benefit".

    One response said "what would we call the act of removing the defects? Dedefect?". This reveals the idea that the only way to handle bugs is to remove them after-the-fact. Replacing "debugging" with "defect detection and removal" may be wordier, but it provides a different mindset; it allows thinking about "defect prevention" and different ways to do "defect detection" (such as automated tests and other tools in addition to manual debugging). I almost never hear the phrase "bug prevention" but I've heard "defect prevention" fairly often. And we can use the term "defect injection" to talk about how defects get into the code in the first place.

    Johanna isn't the first to recommend using the term 'defect'. Her most recent blog entry has comments identifying several sources. Another term that can be used instead of "bug" is "issue", as in an "issue-database" instead of a "bug-database". An issue may be a misunderstanding of the requirements. Usually this gets called an "invalid bug", which can be quite discouraging to whomever raised the issue. An issue is something that still needs some resolution, even if it doesn't identify a code defect. In the case of a misunderstood requirement, the resolution may point to the need for better communication and/or better documentation.

    If I recall correctly, in one of the four volumes of Quality Software Mangement by Gerald M. Weinberg, Jerry recommended both a defect-database and an issue-database, because one issue could be caused by many defects, and one defect could cause many issues. That implies a database that tracks many-to-many relationships between issues and defects. (There probably isn't a commercial product that does this, though the better bug-databases at least allow linking issue-reports to each other.)

    Extreme Programming aims at keeping defects (and issues) so low that a database isn't necessary. Instead of creating an issue report, an XP team might create a failing automated test. Such as test is better than a simple database entry because: (1) writing automated tests is a way to flush out understanding of the features. (2) A test that is failing because of code defects should start passing when the code defects are fixed. (If not, then this provides feedback that not all of the defects associated with an issue have been fixed yet.) And (3), being automated, that test can be run many times in the future to detect a recurrence of that issue.

    [/docs] permanent link

    2005.May.23 Mon

    "Can do" not "Have to do"

    There's an idea that XP is only useful for frequently-released projects, and not so useful for projects that ship annually or less often. I would say that XP is useful for both. Because XP brings up the quality levels for for those teams who adopt practices like automated acceptance tests, test-driven-development, and pair programming, and drives down the numbers of defects produced, XP projects are able to ship more frequently than once a year. (They don't have to.) They're able to release more often because the members of the team and their users can be more confident that what they ship to the user has useful features and few defects.

    There's an idea that XP is useful only for projects where the requirements are frequently changing. I assert that our understanding of requirements and of the design is frequently changing even on those projects that seem to have "stable" requirements. All the tools of XP can help a project with stable requirements deliver a superior-quality product.

    "Stable" waterfall projects often don't "demo" or test their features until the end, at which time they don't have time to accept the changes that the users may want: that's an artificial freezing of the understanding of requirements. "Oh well, those changes will have to go into version 2."

    Iterative/incremental projects demo and test their features as they are implemented, which allows the users (or user-proxy "project managers", testing staff, and the programmers) to update their understanding of the requirements against the functioning code.

    [/docs] permanent link

    Google's Map-Reduce

    I went to Google's open house on May 5 (which happened to be 5/05/2005, but that's probably not significant) and listened to a very interesting set of lectures (and a genuine professional "Engineer/Comedian"). One of the interesting bits is a simple algorithmic infrastructure that Google uses for the index of web-pages, and some other purposes: the "MapReduce" programming model.

    Google indexes the web using a sequence of 24 MapReduce operations. These operations are specified by a custom high level interpreted programming langauge, and distributed across thousands of rack-mounted dual-processor PCs. Using their fault-tolerant parallel processing infrastructure (implemented in C++).

    The input data is a few thousand terabytes of data represented as files in Google's custom distributed/fault tolerant file system. The output and intermediate output data are several hundred terabytes.

    As you might expect, the system is i/o bound -- disk i/o and network i/o. Thus the overhead of an interpreted language for map-reduce operations is not the constraint when doing these big jobs. They have to build their own custom gigabit ethernet switches to handle a thousand (or more) rack-mounted PCs -- commercial ethernet switches top out at 64 PCs and cost too much.

    Their system has to be fault tolerant, since having at least one PC die (or otherwise go out of commission) each day is not unusual for each of their data-centers.

    [/docs] permanent link

    2005.May.21 Sat

    Offering Appreciations

    Quoting The Appreciation Gap by Esther Derby:

    A recent Gallup Poll report quoted this statistic: “…the number-one reason people leave organizations is that they don't feel appreciated, notes the U.S. Department of Labor.”

    Read the rest of her article on how to offer appreciations, and how not to screw it up. Don't do a praise sandwich or a cheap gift in place of a sincere verbal appreciation.

    [/docs] permanent link

    2005.May.10 Tue

    Fearless Commerce

    Seth Godin asks the question "why haven’t you and your team launched as many Purple Cows as you’d like?" and answers it: "Fear". People would rather do the familiar things, and have an acceptable way of failing than risk blame for failing with something different. (Ironic that "fear" only appears once in the wiki page AnAcceptableWayOfFailing that I just linked to. Go to FindPage and search for pages containing the word 'fear'.)

    Ricard Semler's Semco does everything that other companies fear: there have no managers and no official hierarchy, employees set their own salaries and hours, there is no "core business". Semler says that sticking to a "core business" artificially limits where they can find profits. (Why do most companies avoid branching out into multiple fields? Fear.)

    Seth writes books about marketing. He champions creating cheap but thoughtful innovations in products, services, and marketing that customers appreciate. But the interesting thing about his book Free Prize Inside! is that half of the book is teaching you, the reader, how to be a change agent in order to get your marketing ideas accepted within your own company. Get this book to learn how to get your company beyond the fear of the new and unfamiliar.

    [/docs] permanent link

    2005.May.01 Sun

    A Big Change for a Sustained Change

    Quoting Fast Company's "Change Or Die" by Alan Deutschman :

    [...] many patients could avoid the return of pain and the need to repeat the surgery -- not to mention arrest the course of their disease before it kills them -- by switching to healthier lifestyles. Yet very few do. "If you look at people after coronary-artery bypass grafting two years later, 90% of them have not changed their lifestyle, [...] Even though they know they have a very bad disease and they know they should change their lifestyle, for whatever reason, they can't."

    The conventional wisdom says that crisis is a powerful motivator for change. But severe heart disease is among the most serious of personal crises, and it doesn't motivate -- at least not nearly enough. [...] What is it about how our brains are wired that resists change so tenaciously? Why do we fight even what we know to be in our own vital interests?

    Kotter has hit on a crucial insight. "Behavior change happens mostly by speaking to people's feelings," he says. [...] In highly successful change efforts, people find ways to help others see the problems or solutions in ways that influence emotions, not just thought."

    Unfortunately, that kind of emotional persuasion isn't taught in business schools, and it doesn't come naturally to the technocrats [...] who pride themselves on disciplined, analytical thinking.

    [Dr. Dean] Ornish published studies [...] showing that his holistic program, focused around a vegetarian diet [...] can actually reverse heart disease without surgery or drugs. [...] Researchers took 333 patients with severely clogged arteries. They helped them quit smoking and go on Ornish's diet. The patients attended twice-weekly group support sessions led by a psychologist and took instruction in meditation, relaxation, yoga, and aerobic exercise. The program lasted for only a year. But after three years, the study found, 77% of the patients had stuck with their lifestyle changes -- and safely avoided the bypass or angioplasty surgeries that they were eligible for under their insurance coverage. And Mutual of Omaha saved around $30,000 per patient.

    [...] For a few weeks after a heart attack, patients were scared enough to do whatever their doctors said. But death was just too frightening to think about, so their denial would return, and they'd go back to their old ways.

    [...] instead of trying to motivate them with the "fear of dying," Ornish reframes the issue. He inspires a new vision of the "joy of living" -- convincing them they can feel better, not just live longer. That means enjoying the things that make daily life pleasurable, like making love or even taking long walks without the pain caused by their disease. "Joy is a more powerful motivator than fear," he says.

    [...] George Lakoff, a professor of those two disciplines at the University of California at Berkeley, defines frames as the "mental structures that shape the way we see the world." Lakoff says that frames are part of the "cognitive unconscious [...]

    The big challenge in trying to change how people think is that their minds rely on frames, not facts. "Neuroscience tells us that each of the concepts we have -- the long-term concepts that structure how we think -- is instantiated in the synapses of the brain," Lakoff says. "Concepts are not things that can be changed just by someone telling us a fact. We may be presented with facts, but for us to make sense of them, they have to fit what is already in the synapses of the brain. Otherwise, facts go in and then they go right back out. They are not heard, or they are not accepted as facts, or they mystify us: Why would anyone have said that? Then we label the fact as irrational, crazy, or stupid." [...]

    Reframing alone isn't enough, of course. That's where Dr. Ornish's other astonishing insight comes in. Paradoxically, he found that radical, sweeping, comprehensive changes are often easier for people than small, incremental ones. For example, he says that people who make moderate changes in their diets get the worst of both worlds: They feel deprived and hungry because they aren't eating everything they want, but they aren't making big enough changes to quickly see an improvement in how they feel, or in measurements such as weight, blood pressure, and cholesterol. But the heart patients who went on Ornish's tough, radical program saw quick, dramatic results, reporting a 91% decrease in frequency of chest pain in the first month. "These rapid improvements are a powerful motivator," he says. "When people who have had so much chest pain that they can't work, or make love, or even walk across the street without intense suffering find that they are able to do all of those things without pain in only a few weeks, then they often say, 'These are choices worth making.' "

    While it's astonishing that most patients in Ornish's demanding program stick with it, studies show that two-thirds of patients who are prescribed statin drugs (which are highly effective at cutting cholesterol) stop taking them within one year. What could possibly be a smaller or easier lifestyle change than popping a pill every day? But Ornish says patients stop taking the drug because it doesn't actually make them feel any better. It doesn't deal with causes of high cholesterol, such as obesity, that make people feel unhealthy. The paradox holds that big changes are easier than small ones.

    Check it out, and the blog that referred me to this essay: Creating Passionate Users: Change — or lose you mind.

    This is why I think that an incremental approach to adopting agile practices is less likely to work: people who make partial changes in their work environment can get the "worst" of the agile and non-agile work experiences instead of seeing improvements; it will not encourage them to go further with adopting new practice.

    [/docs] permanent link

    2005.Apr.29 Fri

    Intuit Quickbooks

    I never blog about where I work, but I'll make an exception today. I'm working at Intuit, on QuickBooks for Macintosh. You can buy the 2005 version at Amazon. I can't say what will go into next year's version, but I assure you, that if you need small-business accounting software on MacOS X, it will be worth the purchase or upgrade price.

    [/docs] permanent link

    2005.Apr.23 Sat

    Modifying the Rules

    We all have various rules in our heads, acquired on our life journey from many sources. Learning new techniques sometimes involves "unlearning" (or modifying) some of those rules. On April 5, 2005, in the XP mailing list, Dale Emery wrote of an example of this. He and Elisabeth Hendrickson were teaching a class on unit testing. He wrote:

    We ran an exercise where people track down a defect using only unit tests. As part of locating the defect, people end up writing tests for four or five different methods. Some of the methods are private, and in order to test them, you gotta make them public. Some people are queasy about making stuff public just so you can test it.

    To surface what rules are in play here, Dale asked a "why" question thusly: "What concerns do you have about making methods public?"

    "Well, then we lose control of the methods."

    "What do you mean when you say that you lose control?"

    "Other people might call the methods."

    "And if people were to call the methods, what concerns you about that"? (Another "why" question)

    "Suppose you need the methods to be called in a certain order. If people call them out of order, it might mess up the object."

    As we explored in this way, the concern became clear: Exposing the methods might make the object's integrity vulnerable.

    We asked a lot more questions in a similar style, and got several flip charts full of concerns. We summarized these down to these key concerns: Making private methods public:

    • Exposes the object to security violations
    • Makes the integrity of the object vulnerable
    • Inflates the class's interface:
      • Commits the class to responsibilities we don't want to commit it to
      • Confuses users ("which method should I call?")

    It seems to me that any one of these is a damned good reason not to make a method public.

    So I said, "What if we could make the method public without any of these bad effects? Would you still feel queasy about that?"

    "Probably not, but you'll have to show us first."

    Having gotten their permission, Dale and Elisabeth demonstrated the refactorings Extract Class and Move Method... creating a new class, and moving those private static methods into the new class, making them public along the way. The original class would contain a local or private member variable of the new class type, and would call those public methods using that new local or member variable.

    Now, as I understand it, the code being used in the training class didn't have security concerns. And, as it turns out, the private methods were static, so they did not mess with the object-state, and therefore making them public would not make the integrity of the object's state vulnerable to misuse. So the last issue of making these private static methods public was that they would "inflate" the class's interface/responsibilities...

    We also offered the idea that if exposing a method inflates the class's interface to include responsibilities we don't want to commit the class to, that may be a hint that the responsibilities belong elsewhere. Moving the method actually makes the original class more understandable by getting that "non-core-responsibility" code out of the class. So we not only avoided that concern, but actually improved things.

    Dale and Elisabeth didn't invalidate the rules these people had about private methods, but added a refinement to them... the idea that private methods can be a "design smell" indicating a class has too many responsibilities. Dale sums up:

    By eliciting peoples concerns fully, we were able to show how we could make the code testable AND address their concerns. And in order to understand their concerns, we asked various forms of "why" questions (but none that began with "why").

    Michael Feathers has an article dealing with a similar situation - code that seemed well-designed, but was not testable. Making it testable improved the design: beforeClarity.pdf

    [/docs] permanent link

    2005.Apr.12 Tue

    Objective-C++

    I used to be a master of C++, even serving as a team's C++ "language lawyer"... As the language has become more esoteric, I have purposefully avoided getting into the rat-hole of meta-programming in favor of "real" programming.

    Now that I'm back on the Mac doing Cocoa programming, I'm getting more work done with less keyboarding because I can use Objective-C in combination with C++. Objective-C has more run-time power and flexibility than C++.

    Patrick Logan reminds us how easy it is to integrate Objective-C's first-class objects with Python, Ruby, Java, Smalltalk/Fscript... integration that does not require, for the most part, the massive amounts of code-generation that integrating C++ objects to other systems would require.

    Smalltalk and Ruby's "blocks" (closures) provide a lot of power in a much more simple manner than C++ metaprogramming provides... besides passing a block around to classes and methods, you can implement new methods on blocks, to provide new control structures. This provides some sample of blocks.

    Smalltalk, Ruby, Python, and Objective-C have ways for a class to intercept "invalid" method calls and do useful things with them - such as forwarding the call over a network (a network-proxy via a single method). To do network proxies in C++ requires code-generation or extensive amounts of template programming. See these Smalltalk examples for a lot of other interesting things that can be done with this interception capability that would require re-writing the compiler in another language.

    I have been doing some meta programming in Objective-C this weekend. Unlike in C++, meta-programming is done in the same syntax as regular programming. Starting with the Objective-c proxy example here, I'm creating a class to log calls into an object's methods. This involves decoding the method signatures in order to log the arguments. I will be able to do something like this:

    someObj = [ [ LoggingProxy alloc ] init: someObj ];
    

    to take an existing object and start logging calls to it -- no recompilation of the sources of someObj's class would be needed. I might even be able to call this code from gdb, so my choice to start logging an object could be made at run-time when debugging.

    Some parts of Aspect Oriented Programming are doable in Objective-C without using a pre-parser/code-generator, by using the forwarding/proxy and introspection features of the language.

    Apple's Objective-C++ lets me use straight C, Objective-C objects/syntax, and C++ objects/syntax, and mix them in the same source files. (With some care due to differences in object-allocation and exception-handling.) Objective-C++ lets you Alternative Hard(fast) and Soft(slow) Layers within the same language.

    Apple made their modifications of gcc available to the maintainers of gcc (and the sources are probably on http://developer.apple.com/darwin/ or opendarwin.org), but the last time I checked, the maintainers of gcc declined to accept those changes and make those modifications available on other platforms. If you want the power of Objective-C++, but you're not using MacOS, ask the gcc maintainers to accept Apple's mods -- or buy a Mac. :-)

    [/docs] permanent link

    2005.Apr.08 Fri

    Unit Test Patterns

    Gerard Meszaros seeks feedback here: http://tap.testautomationpatterns.com:8080/index.html:

    Much of the material on this site is destined for a book to be published by Pearson Education (Addison Wesley). Feel free to comment on the Book Outline or to volunteer to be a reviewer (whether official or otherwise.)

    Quoting Using Test Doubles:

    Note to reviewers: A key purpose of publishing these patterns is to give everyone a common vocabulary for talking about test design. Current usage of terms such as Mock Object, Stub, Fake and Dummy Object are used in many different ways with the meaning of each term becoming very ambiguous. I have tried to standardize on the most common or most correct (as defined in related literature) usage. I invented the name Test Double as the generic name for Dummies, Stubs, Fakes and Mock Objects. Feedback on this proposal for standardized terminology is earnestly requested!

    Types of Test Doubles

    A Test Double is any object or component that we install in place of the real component specifically so that we can run a test. Depending on the reason for why we are using it, it can behave in one of four basic ways:

    A Dummy Object is a placeholder object that is passed to the SUT as a parameter but is never actually used.

    A Test Stub is an object that is used by a test to replace a real component on which the SUT depends so that the test can control the indirect inputs of the SUT. This allows the test to force the SUT down paths it might not otherwise exercise. A more capable version of a Test Stub, the Recording Test Stub can be used to verify the indirect outputs of the SUT by giving the test a way to inspect them after exercising the SUT.

    A Mock Object is an object that is used by a test to replace a real component on which the SUT depends so that the test can verify its indirect outputs. Typically, the Mock Object fakes the implementation by either returning hard-coded results or results that were pre-loaded by the test.

    A Fake Object (or just "Fake" for short) is an object that replaces the functionality of the real depended-on component with an alternate implementation of the same functionality.

    Check out the nice diagram on that page, which includes "Eager Mock Object", "Lazy Mock Object", and "Recording Test Stub", as well as the other types of dummy objects mentioned above.

    [/docs] permanent link

    2005.Apr.07 Thu

    Introducing Agile to a Legacy Code Project

    Brian Marick writes:

    I'm almost always contacted about testing in an Agile project. [...] But some people I talk to are just starting with Agile, working on a legacy code base that really needs cleaning up, and don't have much in the way of testing. [...] My talking points follow. [...]

    Have at least half the programmers read Michael Feathers' wonderful Working Effectively with Legacy Code. [...]

    Be wary of large-scale code cleanups. Ron Jeffries has an excellent analogy: cleaning up legacy code is like cleaning up a horrendously messy kitchen. You can set aside a day, work like a dog, and leave it pristine. Great. What happens next? It gets dirty again, dish by dish. You don't have the habits that help you keep it clean.

    [...] Being a good Agile programmer means learning how to incrementally grow a good design while at the same time doing something else (like adding features). [...]

    [...] I've come to believe the test-writing part of TDD is actually easier to learn than the refactoring part. A surprising number of programmers have no visceral dread of duplication, [...] So the team has to commit to learning those and other similar things. The project has to explicitly become a learning project. I recommend pair programming and colocation as ways of spreading learning quickly. Use Big Visible Charts to nudge people toward more learning. [...]

    [...] Testing should belong to everyone on the team, and everyone should be willing and able to add new tests. All the programmers should be ready to extend the test harness or other test support code.

    There's more good advice there. Check it out.

    [/docs] permanent link

    2005.Apr.02 Sat

    April Fools

    Quoting the Google Gulp Faq:

    7. How can I get my hands on a Google Gulp?

    This "limited release" beta product is available to anyone who turns in a used Google Gulp bottle cap at any local retailer. If you don't have any Gulp caps, ask a friend to give you one.

    8. What if none of my friends have a Gulp cap to give me? Can't you just give Google Gulp to anyone who wants it?

    Well, we're thinking about it, but, um, you have to understand that there are many considerations which go into deciding how to distribute

    9. I mean, isn't this whole invite-only thing kind of bogus?

    Dude, it's like you've never even heard of viral marketing.

    [/docs] permanent link

    2005.Mar.30 Wed

    Response to 'Toyota, XP and Slack'

    Isaac Gouy emailed to me:

    I'll resist the temptation to beat-on-you for drawing overly detailed conclusions from a tour of the NUMMI plant, and instead point to a couple of articles ;-)

    Spear, Steven J. (May 2004). "Learning to Lead at Toyota." Harvard Business Review, 78-86.

    Spear, S. and Brown, H.K. (September-October 1999). "Decoding the DNA of the Toyota Production System." Harvard Business Review, 97-106.

    (Harvard Business Review seems to be available in most public libraries.)

    Here's an excerpt:

    "...Toyota's real achievement is not merely the creation and use of the tools themselves; it is in making all its work a series of nested, ongoing experiments, be the work as routine as installing seats in cars or as complex, idiosyncratic, and large scale as designing and launching a new model or factory.

    "...standardization - or more precisely, the explicit specification of how work is going to be done before it is performed - is coupled with testing work as it is being done. The end result is that gaps between what is expected and what actually occurs become immediately evident."

    Those articles really are worth reading - I see way to many folk referencing the old James Womack or Taiichi Ono books.

    Spear writes:

    "few manufacturers have managed to imitate Toyota successfully - even though the company has been extraordinarily open about its practices.... observers confuse the tools and practices they see on their plant visits with the system itself. That makes it impossible for them to resolve an apparent paradox of the system - namely, that activities, connections, and production flows in a Toyota factory are rigidly scripted, yet at the same time Toyota's operations are enormously flexible and adaptable."

    [/docs] permanent link

    2005.Mar.29 Tue

    Toyota, XP and Slack

    The concept of Slack I got from DeMarco's book is that fast responsiveness to unplanned work requires people who do not have their schedule filled to 100% capacity.

    In Theory Of Constraints, we learn that scheduling extra work for any part of the system that is not the constraint will not improve the flow through the system, and may even slow down the entire system. Thus only one part of the system - the constraint - should be scheduled at 100% capacity [if that can be safely done], and other parts of the system should be idle some of the time in order to synchronize flow with the constraint.

    In my tour of the Toyota-managed NUMMI auto plant. I noticed that there is very little buffering... parts arrive in shipments as often as 4 times a day and get used up the same day. Hundreds of small groups of people work on the line: each group has 83 seconds to do their part of the job on each car that moves down the line. The members of a team ring the bell/electronic-music-chimes if they need their team leader to help - and those chimes are going off almost continuously [not the same team every time]. But the line hardly ever needs to be stopped, meaning that the help from the team's leader is quick enough and effective enough to fix whatever problem that came up within that 83 seconds almost all the time.

    I did not see people running or otherwise acting in a hurry at NUMMI. It looks like none of the people I saw were scheduled to fill 100% of their 83 seconds with constant work. (Some of the welding robots maybe, but there were few robots). Eighty-three seconds is a short iteration with very small buffers, but after decades of eliminating waste and improving the process, Toyota can take advantage of such short iterations.

    See also James Shore on Slack and Scheduling and More on Slack.

    [/docs] permanent link

    2005.Mar.28 Mon

    Exploring an Extreme of Refactoring

    Kent Beck once wrote of the Three Bears [Pedagogical] Pattern (scroll down to pattern #17): to enable a student to learn about something by exploring its limits. Quoting Kent: I have taught requirements engineering with this technique. I ask the learners to write stories that will define the system—too large in scope to be useful, one too small, and one just right. I taught this technique in India and ended up telling the story of Goldilocks and the Three Bears after lunch.

    Brian Button decided to explore refactoring by taking the Video Store example from Martin Fowler's book and refactoring it into methods one line long, no private methods, and aggressively removing all duplication, particularly duplication of iteration over containers.

    His starting point (and Fowler's ending point) is the class named "Customer", containing a list of rentals. It has private methods for calculating rental cost and "frequent renter points", and a large method for printing the customer's statement. Brian's ending point is seven classes: Customer, RentalStatement, RentalCollection, Collector, LineItemPrinter, FrequentPointsTotaller, RentalCostTotaller.

    If he had been programming in Ruby or Smalltalk instead of C#, he probably could have met his goals with only first two classes. Blocks and iteration methods built into Smalltalk/Ruby collection classes would have eliminated the need to create the other five classes. Brian wrote:

    Now for the questions. Is this code more clear than the original Customer class? I’m not sure. In some senses it is. If I want to go see how the statement is generated, I can now go look at a RentalStatement class and see it. Looking ahead a bit, knowing that one of the changes Martin talks about in his book is that we need to support an HTML statement as well as a text statement, so by creating the RentalStatement class, we’re well prepared to make that change. I’m never sure if the ReplaceExternalIterationWithInternalIteration ever makes code more clear, but it does eliminate duplication.

    I’m not sure that I would ever go this far in real life, but it is nice to know that I could.

    [/docs] permanent link

    2005.Mar.22 Tue

    XP Out of Early Adopter Phase

    Bruce Eckel writes:

    I'm attending and speaking at the Software Development Conference in Santa Clara...

    That day I had seen, among other things, an agile talk Robert Martin and one by Mary Poppendieck. Although I've been following the printed literature, the last time I had seen any agile talks was at least a couple of years ago. What most impressed me by these two talks is the focus and the level of polish, in particular the shift to more evidence-based presentations...

    Eric [Evans] has been attending XP and Agile conferences and following everything more closely than I, and he said that someone at one of the recent conferences had made a presentation that pointed out that the early adopter phase had ended, and the current phase of adopters are more conservative and require clearer evidence in order to be convinced...

    [/docs] permanent link

    2005.Mar.21 Mon

    Agile Databases

    I caught part of Scott Ambler's SDExpo talk on database refactorings, and he had lots of comments about integrating DBA's into the developer team(s) for enabling agility, and described a few ways that apps can accessing databases in a decoupled, flexible manner.

    He mentioned that another "Y2K" hit the retail industry because UPC numbers are increasing in size. He says that business leaders should recognize that this is a repeat of the Y2K fixed-field-width problem and demand more agile software and database practices from programmers and DBAs. Apparently the fixed-field-width problem is easily avoidable if the apps are written properly. ( See http://www.findarticles.com/p/articles/mi_m0DIS/is_3_5/ai_114716526 )

    He asked audience members to raise their hands if they could make a simple change (like renaming a column of a table) and re-deploy their database and associated apps in the same day. Only one guy, in a large room filled with database people, raised his hand (I bet that guy worked at Yahoo, Amazon, or Google.) That guy's DB had terabytes of data and 37 apps depending on it, but he could deploy a change in less than one day.

    Ambler also asked audience members to raise their hands if their database and associated apps had extensive automated testing. The same guy raised his hand, and maybe one other.

    Check out Scott Ambler's http://www.agiledata.org/

    [/docs] permanent link

    2005.Mar.19 Sat

    Domain Driven Design Temperature

    One of the classes at SDExpo West showed an example of some programmer tests (of Test Driven Development). It was something like this:

    void testConvertToCelsius() throws exception
    {
       TemperatureConverter converter;
       assertDoublesEqual( 100.0, converter.convertFahrenheitToCelsius(212.0), 0.001 );
    }
    
    void testConvertToFahrenheit() throws exception
    {
       TemperatureConverter converter;
       assertDoublesEqual( 212.0, converter.convertCelsiusToFahrenheit(100.0), 0.001 );
    }
    
    

    That's kind of lame. Eric Evan's advice from Domain Driven Design is that classes that end of "-er" or "-or" should be avoided. Here's a test [in Java] that may better reflect the domain.

    void testConvertFahrenheitToCelsius() throws exception
    {
       Fahrenheit tempF( 212.0 );
       Celsius tempC( 100.0 );
       Celsius tempFconvertedToC = tempF.asCelsius();
       assertDoublesEqual( tempC.value(), tempFconvertedToC.value(), 0.001 );
    }
    void testConvertCelsiusToFahrenheit() throws exception
    {
       Celsius tempC( 100.0 );
       Fahrenheit tempF( 212.0 );
       Fahrenheit tempCconvertedToF = tempC.asFahrenheit();
       assertDoublesEqual( tempF.value(), tempCconvertedToF.value(), 0.001 );
    }
    

    The trouble with that approach is that Fahrenheit and Celsius are two different types for the same kind of measurement. Maybe these tests (and the design they would force) would be better:

    void testConvertToCelsius() throws exception
    {
       Temperature temp( 212.0, Temperature.FAHRENHEIT );
       assertDoublesEqual( 100.0, temp.celsius(), 0.001 );
    }
    
    void testConvertToFahrenheit() throws exception
    {
       Temperature temp( 100.0, Temperature.CELSIUS );
       assertDoublesEqual( 212.0, temp.fahrenheit(), 0.001 );
       
    }
    

    Perhaps if NASA and Lockheed Martin had used Domain Driven Design when writing the software for the Mars Climate Orbiter, the 125 Million Dollar probe would not have been lost because NASA used metric units for distance and speed while Lockheed Martin used traditional English units. They didn't have to write conversion code, just class names (or "typedefs" or equivalent if using C or other non-OO programming language) that indicate the units being used. Someone expecting different units would be clued-in by the class or type names.

    [/docs] permanent link

    Not Victims

    The "agile panel" on the first day of SDExpoWest was talking about useless CASE tools -- how managers buy them, engineers try them out and find they're not helpful, and the tools become shelfware -- and how the money spent on those tools COULD have been spent on something more useful. Jerry Weinberg, in the audience, replied to the panel that we don't have to be victims. Professionals choose their tools as appropriate to the situation at hand and make sure others understand that. He said that no surgeon in the operating room would whine about being given a rusty scalpel because "that was all the hospital would pay for."

    Robert C. Martin said in his class about "Stemming the Offshore Tide" that a study of 15 projects found that doing the programming and other project work in a "war-room" enabled teams to be twice as productive as those that don't. He said that programmers didn't have to give up offices or cubicles for private spaces, or alone-time for thinking things through, but when working on the project, they should be in same room as the testers, business analysts, and other programmers so that any question about the project could be answered without leaving one's chair -- either by looking at charts and diagrams on the walls of the war-room, or by asking someone close by.

    Of course, it's not just software developers that corporations try to put into cubicles. Hallmark, the greeting card company, did that with its artistic talent -- until Gordon MacKenzie, the author of Orbiting the Giant Hairball: A Corporate Fool's Guide to Surviving With Grace put them into a more productive environment -- old-fashioned roll-top desks next to drawing boards, good chairs, partitions made from antique doors with stained glass -- which was also CHEAPER than cubicles and standardized office equipment.

    MacKenzie could do that because he had been at Hallmark long enough to have a good reputation, and he had a corporate sponsor who encourage him to hold the job-title "Creative Paradox". He didn't have several studies showing that a particular environment would help artist be more productive.

    Quoting How does radical collocation help a team succeed?" by Teasleye et al.:

    Most of the focus in this investigation is on the communication patterns of the individuals on the team. Past studies have indicated that less than 30% of a programmer's time is spent on traditional programming tasks and less than 20% of the time is spent on coding [4]. The rest of the time is spent on meetings, problem resolution with the team, resolving issues with customers, and product testing, etc. And, we know that the further away people are who have to communicate, the less they talk with each other. A distance of 30 meters is equivalent to being truly remote [2].

    When collocated, team communication is a subtle dynamic. Team members coordinate their actions around various artifacts and arrangements of people in space [Hutchins, Suchman and Heath & Luff, in 9]. Hutchins calls this phenomenon distributed cognition, whereby teammates exploit features of the social and physical world as resources for accomplishing a task [15].

    [/docs] permanent link

    2005.Mar.13 Sun

    Mindful Effectiveness

    Dale Emery writes:

    Three questions lie at the heart of effectiveness. The better you can answer these three key questions and act on the answers, the more effective you will be:

    1. What results do I want?
    2. How can I create the results I want? [What to do...?]
    3. What results am I creating?

    In my coaching and consulting practice, I've notice that people often focus predominantly on question 2 [...]

    It's only when focusing on action doesn't work that people become stuck. And in those cases, focusing on what to do often leaves people even more stuck. [...]

    [...] if people are persisting in a course of action that isn't working, it's likely that either they are not staying mindful of what they want or they are not seeing clearly the results they're creating.

    Dale wrote a message similar to this essay on the XP mailing list. The answer of "question #2" (what action do I take?) for the person who started the message-thread was "use a bug-base" (or perhaps he was asking "should I use a bug-base?").

    In many XP projects, the number of bugs is so small that a bug-base is unnecessary. Any bugs that arise are normally fixed in the same iteration in which they are found, unless the bug can be considered a feature (or story) all by itself, in which case it can be tracked using the same method as tracking stories: index cards or simple software.

    There is some concern that having a bug-base available may encourage treating bugs as something not to fix during an iteration, with the result that more bugs accumulate and the code-base gets progressively less stable over time.

    By keeping in mind question 1 ("What results do I want?" Answer: Software that meets the requirements -- that is, doesn't have bugs [bugs are failures to meet requirements.]) and question 3 ("What results am I creating?"), a team can discern whether having a bug-base has "legitimize" leaving bugs unfixed, and if so, adjust their answers to question 2.

    As Dale wrote in the mailing list:

    Make explicit the intentions and assumptions behind our decisions. Then as we put the decisiosn into action, actively gather feedback about how well our assumptions match the world and how well we're achieving our intentions.

    [/docs] permanent link

    2005.Mar.10 Thu

    Unknown Requirements

    In many environments over the years, software projects become so heavily burdened by technical debt (overly crufty code) that continuing enhancements become so fraught with danger and difficult to do that progress slows down to a crawl. This is when many programmers try to talk their management into doing a complete re-write.

    One of the problems with a complete re-write is that while it goes on, there are few (or no) resources to maintain the original application, and the end-result is the "same" as before in terms of functionality -- a lot of money gets spent on rebuilding the existing feature-set, and not much has gone into new features.

    There have been disasters when companies have attempted grand re-writes, many of them stemming from lost requirements: the existing product does "X" and no one remembers why it does "X". Was "X" a requirement, or was it an accident of history -- maybe even a bug? Either the project reproduces "X", and maybe wastes their time reproducing a bug, or they don't reproduce "X", and then find out from end-users (perhaps disasterously) that it's a requirement.

    In a project driven by automated customer tests (and programmer tests), requirements are encoded by the tests. Unlike requirements documents, the automated tests tell you if the software under test is living up to its requirements by passing or failing when executed. These tests serve as examples of what the code can do and how to do it. See also Wayne Allen asserting that these "tests" are more about communication and design rather than testing.

    If one wanted to do a complete rewrite of software project, and one had complete suites of tests, a lot of the guess-work is removed. Keep the tests, rewrite the code under test. When all the tests pass (assuming the tests are complete enough), you're done. Refactoring is also best supported by automated tests.

    Having this support from tests is also helpful in porting to a new platform (or even a new language). Port the tests as well as the code under test, and having the tests pass gives more than a little reassurance that the code is doing the right thing.

    Of course, tests rarely cover ALL possible uses and failure-points for a piece of code (and still run in a reasonable time); there's no magic bullet. However, code that is unit-tested is usually code that is more well-designed than untested code, simply because getting a piece of code under test requires de-coupling and other good design practices. This helps prevent a project from ever getting so burdened by technical debt that a complete rewrite becomes necessary.

    [/docs] permanent link

    2005.Mar.07 Mon

    Advice

    "Many receive advice, only the wise profit by it." -- a fortune cookie

    [/docs] permanent link

    2005.Mar.05 Sat

    Pair Programming

    Pair programming is NOT two people taking turns programming and reviewing.

    Consider what activities are done in programming: reading code; writing code; thinking about code and design; refactoring; writing tests; reading tests; running tests; occasionally stepping and investigating in the debugger; talking to someone about code, design, and bugs; waiting for compile/link to finish; running the app; and checking in and checking out source code to/from a repository. All of those are done by BOTH people who are pair programming.

    Part of pair programming's speed increase (approximately twice as fast as one person solo programming) comes from preventing mistakes (rather than identifying mistakes after they've been coded), having more design and test ideas (coming from different viewpoints and experiences), and fast feedback on those ideas.

    [/docs] permanent link

    Sustainable Pace

    Quoting "Why Crunch Mode Doesn't Work" by Evan Robinson:

    When Henry Ford famously adopted a 40-hour workweek in 1926, he was bitterly criticized by members of the National Association of Manufacturers. But his experiments, which he'd been conducting for at least 12 years, showed him clearly that cutting the workday from ten hours to eight hours — and the workweek from six days to five days — increased total worker output and reduced production cost. Ford spoke glowingly of the social benefits of a shorter workweek, couched firmly in terms of how increased time for consumption was good for everyone. But the core of his argument was that reduced shift length meant more output.

    I have found many studies, conducted by businesses, universities, industry associations and the military, that support the basic notion that, for most people, eight hours a day, five days per week, is the best sustainable long-term balance point between output and exhaustion. Throughout the 30s, 40s, and 50s, these studies were apparently conducted by the hundreds; and by the 1960s, the benefits of the 40-hour week were accepted almost beyond question in corporate America. In 1962, the Chamber of Commerce even published a pamphlet extolling the productivity gains of reduced hours.

    But, somehow, Silicon Valley didn't get the memo.

    [/docs] permanent link

    2005.Mar.01 Tue

    XP Explained, Second Edition, again (and IXP)

    Check out Michele Marchesi's summary

    1st edition Values: Communication, Simplicity, Feedback, Courage.

    2nd edition Values: Communication, Simplicity, Feedback, Courage, Respect.

    IXP Values: Communication, Enjoyment, Learning, Simplicity, Quality.

    1st edition Principles: Rapid Feedback, Assume Simplicity, Incremental Change, Embracing Change, Quality Work, Teach Learning, Small Initial Investment, Play to Win, Concrete Experiments, Open/honest Communication, Work with people's instincts - not against them, Accepted Responsibility, Local Adaptation, Travel Light, Honest Measurement.

    2nd edition Principles: Humanity, Economics, Mutual Benefit, Self-Similarity, Improvement, Diversity, Reflection, Flow, Opportunity, Redundancy, Failure, Quality, Baby Steps, Accepted Responsibility.

    1st edition Practices: Planning Game, Short Releases, On Site Customer, Metaphor, Sustainable Pace, Pair Programming, Continuous Testing, Refactoring, Simple Design, Continuous Integration, Collective Code Ownership, Coding Standards.

    IXP Practices: Readiness Assessment, Continuous Risk Management, Project Chartering, Project Community, Test-Driven Management, Sustainable Pace, Storytelling, Planning Game, Storytesting, Frequent Releases, Small Teams, Continuous Learning, Sitting Together, Iterative Usability, Evolutionary Design, Story Test-Driven Development, Continuous Integration, Collective Ownership, Coding Standard, Refactoring, Domain-Driven Design, Pairing, Retrospectives.

    2nd edition Practices:

    Primary Practices: Stories, Weekly Cycle, Quarterly Cycle, Slack, Sit Together, Whole Team, Informative Workspace, Energized Work, Pair Programming, Incremental Design, Test-First Programming, Ten-Minute Build, Continuous Integration.

    Corollary Practices: Real Customer Involvement, Incremental Deployment, Negotiated Scope Contract, Pay-Per-Use, Team Continuity, Shrinking Teams, Root-Cause Analysis, Code and Tests, Shared Code, Single Code Base, Daily Deployment.

    [/docs] permanent link

    XP Explained, Second Edition

    Bill Wake summarizes the key points of this new book, which is a complete rewrite -- different from the first edition in both tone and content. Check it out.

    J. B. (Joe) Rainsberger on the XP Mailing list described the first edition as teaching on the martial arts level of Shu (learning the rules via practice) and the second edition as Ha (reflecting on the rules and their exceptions), referring to the wiki page Shu Ha Ri.

    [/docs] permanent link

    2005.Feb.27 Sun

    Teaching Testing

    Bret Pettichord wrote:

    Twenty years ago, Cem Kaner was managing testers and was completely dissatisfied with the texts and training on testing then available. He developed his own training material and eventually published it as Testing Computer Software, the best-selling testing book of all time. That book was last revised in 1993, but Cem has been continuing to update his teaching materials year after year, in collaboration with James Bach.

    Their curriculum is now available online, as open-source. It includes detailed slide decks, examples, review questions and other supporting material. Cem has also begun recording several of the lectures on video, which you can watch on your own computer.

    [/docs] permanent link

    2005.Feb.25 Fri

    Aggregated Blogs

    Smalltalk: Planet Smalltalk. Check it out.

    Agile and Systems Thinking: SystemsThinking.net. I'm reading Rachel Davies via that aggregator, among others.

    [/docs] permanent link

    2005.Feb.22 Tue

    Done

    "One never notices what has been done; one can only see what remains to be done." – Marie Curie, letter (1894). To avoid this problem, make sure to celebrate completed stories and projects.

    [/docs] permanent link

    2005.Feb.16 Wed

    Why Stories and Not Tasks

    Why does XP do Release Planning and Iteration Planning using Stories (user-centered mini-use-cases) rather than tasks (technically-centered things to do)? Because it's fairly easy to come up with a mostly-complete list of user-centered stories for a piece of software. You can track their completion, and when all the stories are done, you're done writing the software, even if the estimates for the stories varied wildly from the actuals.

    On the other hand, at the beginning of a project, it's much more difficult to break down a project into technical tasks correctly, and to come up with a mostly-complete list of tasks. We've all had the experience of discovering lots of tasks during the project that were not anticipated at the beginning. The problem of poor estimates is compounded by our lack of perfect foreknowledge of all the tasks to do.

    By waiting until a story is scheduled in an Iteration Planning meeting (or afterwards during the iteration itself), to come up with tasks for that story, we enable the Lean [pdf] practice of deferring decisions "until the last responsible moment". The decisions for those tasks will be better, in the light of previous development and the situation as it stands "now", than if all technical decisions were made at the beginning of the project -- when we're most ignorant of what technical choices will work or fail.

    See Alistair Cockburn's "moving" example of tracking the estimated number of boxes to be packed versus tracking rooms to be emptied.

    See also Ron Jeffries on Big Visible Charts and Running Tested Features Metric.

    [/docs] permanent link

    2005.Feb.15 Tue

    BayXP Wed. Feb. 16 - Tools and Techniques

    The next meeting of the BayXP user groups will be Wednesday, Feb 16th, 7:00-9:00 PM at the offices of Agitar Software (1350 Villa, Mountain View). The topic is "Tools and Techniques for Agile Software Development". We are very fortunate to have several dynamic presenters who are recognized leaders in the field of developer tools and software testing.

    • Alberto Savoia, the founder of Agitar, will demo Agitation-Driven Development using Agitator.
    • Elisabeth Hendrickson, a well-known consultant in the Agile testing field, will demo the WATIR tool for testing web applications.
    • Jeffrey Fredrick, a committer on the CruiseControl project, will demo CruiseControl and discuss best practices for continuos integration.
    • David Vydra, founder of testdriven.com, will demo the EMMA code coverage tool for java.

    For those arriving on time there will be a tour of Agitar's Agile development room featuring the original version of the now famous lava lamps and extreme feedback monitor written about in Mike Clark's Pragmatic Project Automation book.

    Doors open at 6:30 PM. The first presentation will begin at 7:00 PM sharp.

    Meeting Location:
    Agitar Software, Inc.
    1350 Villa Street
    Mountain View, CA 94041

    Please contact David Vydra with any questions at david@testdriven.com or 510-333-7579

    [/docs] permanent link

    2005.Feb.08 Tue

    Pair Programming with a Robot Dog

    http://www.object-arts.com/Conferences/Oopsla/2002/XP-BestFriendReport.htm

    In this particular case we use the Aibo as a real world interface to our new Code Mentor browser plug-in that will become available in the forthcoming Dolphin 6 release.

    Code Mentor

    The Code Mentor is based (as is the existing Dolphin Refactoring Browser) on the SmallLint package by John Brant and Don Roberts of Refactory Inc. As one browses code in the new Hierarchy or System browsers, the mentor continuously evaluates the quality of the code in the background. When it finds that certain Lint checks have been violated it gives a report advising the programmer of the problem(s)....

    ... We did have some problems with Timo's speech recognition, caused by the room being rather noisy as it opened onto the main OOPSLA exhibition hall. In a quiet room the Aibo had been quite reliable at interpreting Blair's comments and requests.

    If you follow the links to the OOPSLA description of the session, you'll see:

    While this "programmer's best friend" is not an altogether serious proposition with the limitations of the current technology, one can see how such robotic mentoring might become truly useful in the not too distant future. If nothing else, we've found it can offer a certain amount of light relief for the caffeine crazed programmer hell bent on bashing out just one more class before midnight.

    [/docs] permanent link

    2005.Feb.05 Sat

    PatternShare

    A web-site listing design patterns from many sources. See Full List of Patterns, and List of Authors for two good entry-points. It doesn't seem as open as a wiki, but multiple contributors are allowed. Note also that the license is Creative Commons, and the site hosted ("informally") and moderated by Microsoft.

    [/docs] permanent link

    2005.Feb.04 Fri

    Agile Project Management Manifesto

    Similar to the Agile Manifesto, a group of ten people have gotten together and worked out a small number of principles for "modern (agile/adaptive) (product/project) management". Check it out here: http://alistair.cockburn.us/crystal/articles/doi/declarationofinterdependence.htm.

    [/docs] permanent link

    2005.Feb.03 Thu

    Tomo quote

    ... because every human personality has its shortcomings, and so long as we are engaged in observing the imperfections of others we deprive ourselves of the opportunity of learning from them.... The greater our imperfections, the more we are inclined to see the faults of others, while those who have gained deeper insight can see through these faults into their essential nature. -- Tomo Géshé Rimpoché.

    [/docs] permanent link

    plans

    "In preparing for battle I have always found that plans are useless, but planning is indispensable." -- Dwight D. Eisenhower

    "Our real problem, then, is not our strength today; it is rather the vital necessity of action today to ensure our strength tomorrow." -- Dwight D. Eisenhower

    [/docs] permanent link

    2005.Jan.29 Sat

    Extreme Programming Adoption Stories

    Slides from a presentation by Bob Jarvis: http://www.nycagile.org/index_files/res/Bob_Jarvis.pdf [pdf]. Starts with an overview of XP and agile, results and metrics start at slide 29, then discusses Agile project management versus Traditional (plan-driven) project management, lessons learned and so on.

    Paper by Paul Hodgetts on incremental XP adoption versus wholesale adoption of all practices at once. http://www.agilelogic.com/files/RefactoringTheDevelopmentProcess.pdf [pdf]. (See also Agile Logic publications.) In one wholesale adoption, some developers who had training and understood how to do certain XP practices (test-driven development and refactoring), refused to do them when working independently. They didn't believe those practices were the best way to develop software, but didn't speak out about their objections.

    In the second wholesale adoption Hodgetts describes, then team did not allow time for training, and thus spent so much time trying to learn how to do the practices and trying to produce software at the same time, that they were unable to do either.

    In the incremental adoption stories, the teams try to identify the worst problems they are currently facing ("process smells"), and adopt specific practices to fix the root causes of those problems. They use metrics (like bug counts per iteration) and retrospectives or informal group reflection to understand and measure the success of the new practices. Success with some practices encourages the adoption of other practices.

    [/docs] permanent link

    2005.Jan.28 Fri

    Star Crossed Dreams

    In one of the commentaries by Joss Whedon on the Buffy The Vampire Slayer DVD's, or perhaps in an interview, Joss said that he and some of the cast of Buffy would hang out at his place, reading/performing Shakespeare plays. I dreamed a bit of Shakespeare with some of the Buffy cast in it last night, and decided to try my hand at casting this morning:

    "Twelfth Night" by William Shakespeare, direction, music and lyrics by Joss Whedon
    
    cast:
      Orsino, Duke of Illyria, played by Marc Blucas
      Viola, in love with the Duke, played by Sarah Michelle Gellar
      Sebastian, brother of Viola, played by James Marsters
      Olivia, a rich countess, played by Amber Benson
      Antonio, a sea captain, played by Anthony Stewart Head
      Maria, Olivia's maid, played by Charisma Carpenter
      Sir Toby Belch, uncle of Olivia, played by Alexis Denisof
      Sir Andrew Aguecheek, played by Nicholas Brendon
      Malvolio, steward to Olivia, played by David Boreanaz
      Feste, a clown; Olivia's servant, played by Seth Green
    
    
    "A Midsummer Night's Dream" by William Shakespeare, direction, music and lyrics by Joss Whedon
    
    cast:
      Theseus, Duke of Athens, played by DB Woodside
      Hippolyta, Queen of the Amazons; betrothed of Theseus, played by Amber Benson
      Hermia, in love with Lysander, played by Sarah Michelle Gellar
      Lysander, in love with Hermia, played by James Marsters
      Egeus, father of Hermia, played by David Boreanaz
      Demetrius, in love with Hermia, played by Danny Strong
      Helena, in love with Demetrius, played by Alyson Hannigan
      Oberon, King of Fairies, played by Anthony Stewart Head
      Titania, Queen of Fairies, played by Emma Caulfield
      Bottom, a weaver, played by Nicholas Brendon
      Puck, or Robin Goodfellow, played by Eliza Dushku
      Philosrate, Master of the Revels, played by Armin Shimerman
      Quince, a carpenter, played by Harry Groener
      Snug, a joiner, played by Alexis Denisof
      Flute, a bellows-mender, played by Michelle Trachtenberg
      Snout, a tinker, played by Adam Busch
      Starveling, a tailor, played by Marc Blucas 
      unnamed man, plays the Wall, played by Tom Lenk
      unnamed Fairy (first dialog with Puck), played by Julie Benz
      Peaseblossom, a fairy, played by Juliet Landau
      Cobway, a fairy, played by Kristine Sutherland
      Moth, a fairy, played by Charisma Carpenter
      Mustardseed, a fairy, played by Seth Green
    
    

    [/docs] permanent link

    2005.Jan.26 Wed

    Notes from reading Four Levers of Corporate Change

    The Four Levers of Corporate Change by Peter L. Brill and Richard Worth

    "First, we examine human nature and how to persuade employees to work for, not against, change. Second, we discuss power, a subject most executives are even more reluctant to talk about than their sex lives. Properly used, power can make change succeed; misapplied, it can destroy a company's entire effort. Third, we explain how to use social processes to initiate change and give it momentum... overcoming pockets of resistance. And fourth, we describe the role of the leader..."

    "Universal Solvent" exercise: equal numbers of two opposing groups sit around a table. Each takes a turn to ask ONE question to his opposite number, and then record (without reply) the answer. After an hour, "people had gotten a lot of pent-up feelings off their chests and also begun to see problems from the other group's perspective." (page 27)

    1. Crisis clearly demonstrated to all employees - short enough time-frame to require a response, long enough time-frame for a response to be possible.

    2. Expert clearly demonstrates how their company is deficient compared to others.

    3. Exercises got emotions out in the open to motivate change.

    4. Employees created their own concrete plans [in cooperation with each other] to solve the problems revealed by #2 and #1 -- note that management-imposed plans would not be sufficient, nor be likely to be adopted.

    Fundamental Change requires:

    1. strong emotions: fear, greed, pride, recognition, accomplishment

    2. (someone/something) must destabilize the existing system [Welch / GE]

    3. the changed system must be self-reinforcing

    4. vision / ideology of the change reinforces the credibility and legitimacy of the leadership

    First Principle of Power: people who have power usually do not give it up voluntarily.

    Second: Hierarchies are the natural order of things. Formal hierarchies can be replaced by informal ones.

    Third: in each organization, there are different types of power: moral (priests), expertise (gurus), coercive (hire and fire)

    new CEO, established old company, wanted to restructure the company to cross-functional teams focused on market segments.

    Resistance from "Field Consultants' and the VP in charge of them -- they did not want to become "sales people".

    CEO spent months trying to persuade that VP, and after failing to, fired him

    instead of taking charge of the Field Consultants group or putting a flunky in charge, he set up training to

    1. strengthen their commitment to the company

    2. change their identities from consultants to sales people

    3. change the structure of the organization

    using "Universal Solvent", employees asked and answered questions on

    1. how to improve market share

    2. what changes are taking place in the market?

    3. how should we respond to those changes?

    4. what are the strengths of this company?

    5. what is the current strategy?

    6. how effective is communication between this group and others in the co.? NOTE: the CEO is listening to these answers.

    Training included simulations of mis-communication and blaming.

    Training on analysis of the markets involved, what was needed to satisfy those customers.

    After all this, the CEO presents his vision for the new corporate strategy. The consultants are formed into small groups to discuss how the strategy might be applied to their department... and their identities and why they need to change to sales to function effectively in the new markets.

    Training session where participants play at using new identities Simulation to emphasize the need for team-work and cooperation and usefulness of cross-functional teams.

    Teams created to gather data needed for the re-org: lead by sales/consultant "stars", not by ex-VP's managers.

    This last bit, as well as all the training earlier, established a "caring" relationship between the CEO and the employees, by-passing the managers that might try to get into between to resist and redirect the CEO's desires.

    [/docs] permanent link

    2005.Jan.17 Mon

    BayXP Jan 19

    this week, Wednesday January 19.

    Vandana Shah, a Project Lead at Hewlett-Packard will be presenting experiences using Agile Processes in developing internal software projects of significant complexity.

    "I have been developing software for last 7+ years. I started practicing Extreme Programming since last 2-1/2 years. Projects that were not successful using standard waterfall methods, had a great success when practiced again using XP. In the process we have learned what works, and how to apply it with great efficiency.

    "We would like to share our experience in the practice of agile development and how it can improve any development efforts. We will demonstrate a template of the process that worked for us and present best practices and tools."

    The meeting socializing starts at 7 PM, presentation starts at 7:30 PM and will be held at the offices of:

    Electronics For Imaging, Inc.
    303 Velocity Way,
    Foster City CA 94404

    Wolfram Arnold and Keith Ray of EFI will be your hosts.

    [/docs] permanent link

    2005.Jan.16 Sun

    Test-Driven is Faster

    One point I forgot to make in my previous posting: TDD is faster than test-after and code-n-fix. In Test-Driven Development, testing is part of the design process, it doesn't take much time to write a small test that represents a part of your thinking about a problem. Test-after is slower because the traditional design/code process -- without tests -- takes about the same amount of time as the TDD design/code process, and then the traditional coding time is followed by writing tests that take even more time.

    Also, test-driven code is less buggy than the usual results the from code-n-fix approach. Since bug-fixing by itself is a lot longer than the TDD process, code-n-fix with no automated tests is actually slower when you take coding-time + bug-fixing-time into account.

    Unfortunately, there is an attitude in this industry that bugs are inevitable, so not much attention is paid to techniques that reduce the creation of bugs -- automated tests, code-reviews, or pair programming. Those of us interested in TDD are still the early-adopters.

    [/docs] permanent link

    TDD Explained

    This explanation of Test-Driven Development provided insight to some people when I was doing a presentation on the subject. Perhaps it will help someone else out there. Imagine that you're designing/implementing a class or function to solve a problem without TDD. Even though we tend to think of design/coding as one "lump" (or two), it's actually an incremental and iterative process for most problems. You pick an initial data-structure and/or an algorithm, and see how it handles various aspects of the problem - perhaps by thinking it through or running the code though the debugger. You adjust the data-structure(s) or algorithm(s) until all necessary aspects of the problem are solved. In a traditional disciplined coding process, you then write unit tests for the working code.

    In TDD, you do pretty much exactly the same thing, except that you write tests along the way. Each time you consider an aspect of the problem, you write a test to represent that aspect, and then write just enough code (or modify just enough code) to test that aspect, while keeping previous tests passing. When all necessary aspects of the problem have been solved, you end up with a suite of tests and the working code.

    In the traditional development style, there's a big psychological barrier against writing tests against code that you just spent an hour or two (or days) getting to work. You made an investment (in code), and now you don't really want your investment to be proven bad, so you don't write a really rigorous suite of tests. This is one reason for the rise of testing departments. From what I've seen over the years, most developers don't write unit tests at all, they rely on the "Quality Assurance" people to do black-box tests; if you're one of those that do write unit tests after coding, good for you! If you don't write automated tests at all, please consider adding TDD to your skill-set.

    In Test-Driven Development, each test that you write is for code that hasn't been written yet. There's no investment yet to be proven bad. You think "I'll need to handle this aspect of the problem, so let's represent this as a test" -- the tests are documenting the problem-space. Unlike traditional documentation of requirements, the tests are executable. In the TDD, you write a test, watch it fail (because the code for it to pass doesn't exist yet), then write the code to make the test pass, and watch the test pass, (sometimes) refactor to clean up the code, removing duplication and other code-smells, and then watch the test pass again, showing that your refactoring didn't break anything.

    Test-driving the code that solves the problem, independent of user-interface (graphical, web, or otherwise), encourages you to create objects and functions that reflect the problem-domain, particularly if you are trying to do domain-driven-design. Porting Test-driven code is relatively easy, because running the tests can let you know if the solution-part of the ported code is working right, before getting involved in porting the GUI. Contrast that with the code-n-fix approach of writing the GUI first and (often) mixing the GUI code and the solution-code... this mixture makes understanding the problem/solution domain difficult and the mixed-up code is much less portable.

    In a "legacy-code" situation, you quite often no longer have access to any design documentation or requirements documentation (other than a user-manual), so you have to reverse-engineer the problem-space and solution-space out of the code. With TDD, you have tests to describe the problem-space, and the solution-space is the code being tested... the rest of the code is the UI, cleanly separated.

    In TDD, you don't give up any of the learning you've done about design... you employ a new technique for iterating and testing the design that you're evolving. The hardest part is remembering to keep your (test-code-refactor) steps small: you don't need to solve the whole problem all in one shot.

    [/docs] permanent link

    2005.Jan.13 Thu

    Mind-Reading is Bad

    People aren't good at mind-reading (another term for mind-reading is "making stuff up" -- see any comedy of errors for examples). Software is even worse at mind-reading. The worst features in Microsoft Word are those that attempt to do mind-reading... auto-formatting, auto-capitalization, auto-correction, etc.

    A blogger has finally explained where some of the madness in Word's auto-formatting comes from: attempting to interpret the user hitting the TAB key in various situations as if the user has formed habits from type-writers, which don't have auto-indent. [However, typewriter users don't hit the TAB key in the middle of paragraph in order to indent the whole paragraph...]

    Two problems with this particular mind-reading is that (1) eventually users learn that a word-processor is not a typewriter [that is, if the word-processor behaves consistently and predictably, which Word, to all external appearances, does not], and (2) most people learning to type TODAY are learning on computers, not typewriters. Trying to sometimes emulate a typewriter in a word-processor is about as useless as sometimes emulating a slide-rule when the application is a spreadsheet: oh, the user just dragged the mouse horizontally to the left here -- instead of selecting text or cells, I'll reduce the value displayed instead.

    The same blogger also says: here: "People who tend to curse Word have had significant prior experience with some other word processing and/or document producing software. People who don’t have that kind of prior experience tend to find Word’s power and features very helpful." I used Word 1.0 and several succeeding versions, and I curse current versions of Word. Does using Word 1.0 count as "some other word processing... software"? Is someone with no experience of alternative programs really finding Word to be helpful? Perhaps they blame themselves whenever Word does something confusing -- self-blaming is very often the case with inexperienced computer users -- so their evaluation of Word has a built-in bias. Jerry Weinberg has a rule about always looking for three interpretations: what else could users of Word, who have no experience with alternatives, be thinking when they say Word is "powerful"?

    He also says "I don’t make software for Aunt Tillie." Well, yes, you do. Word's monopoly status in the word-processing market for Mac and Windows means that you're making software for everybody, not just power-users. And that mind-reading about TAB key usage certainly sounds like trying to cater to Aunt Tillie, who learned to type on a typewriter 30 years ago.

    [/docs] permanent link

    2005.Jan.11 Tue

    Agile Languages

    Christopher Diggins asks "What would a developer expect from a more agile C++"? My answer: the first steps towards agility from C++ would be to move away from the source-file-based compiler/linker setup. Consider that Extreme Programming, the first Refactoring browser, and many of the people involved in the Design Patterns movement all started with Smalltalk programmers. In Smalltalk, the compiler, byte-code-interpreter, the debugger, class browser and editors, and all classes and methods, are all objects that can be manipulated like any other by writing code or using tools provided in the GUI environment.

    While Java code starts as source files, a Java source file has to parsed only once to create a .class file: after that, when compiling other source files, any references to that class can work with the .class file instead of re-parsing the source. Contrast that to C++ compilers that have to reparse the header files for every source file that #includes them. Sure, there are some optimizations supported by various compilers and IDE. I use #pragma once and precompiled headers when my development system supports them, but the text-file based system, the preprocessor, and the syntax of C++ combine to make it very difficult for anyone to create refactoring tools for C++. Without refactoring tools, C++ will never be as agile as Java or Smalltalk.

    Consider using Objective-C as a dynamic C-based language instead of C++. It has some reflection capabilities, and its classes are represented as objects at run-time. Objective-C's objects are "completely" polymorphic (unlike non-virtual methods in C++) and the "optional-typing" features of the language allow header files to be almost entirely empty -- speeding compilation.

    Objective-C is still being enhanced by Apple... try/catch/finally has been added not too long ago. Key-Value Coding/Key-Value Observing are another useful feature in Objective-C/Cocoa.

    Two big things missing from Objective-C/Cocoa are refactoring tools and garbage-collection. In theory, a conservative garbage collector could be built into the Objective-C run-time, but in practice there's a lot of legacy code inside and outside of Cocoa that probably would need revision to properly work with GC. While Objective-C still has the problem that C++ has with the preprocessor and including header files, the syntax of the language is simple enough that refactoring tools could be implemented, if the people with the right skills are motivated to work on the problem.

    [/docs] permanent link

    2005.Jan.10 Mon

    First Rules

    The first rule for doctors is "First, do no harm". That also applies to agile methods. The first two rules for agile is "do what works" and "change what doesn't work". Since agile methods are people-centric, agilists understand that people are what makes change work; change should not be imposed on people.

    [/docs] permanent link

    Rajesh's AYE Conference 2004 Trip Report

    I've been to two AYE Conferences, almost went last year, and plan to go this year. This can be a life-changing conference. As a result of attending AYE, I had an article published in STQE magazine (now known as "Better Software" magazine), found out about and attended the last PSL, and I got to know many really wonderful people. Unlike many conferences, the sessions are interactive -- not lectures. The "guests" and "hosts" are all participants, and the hosts can learn from the guests as well as the other way around.

    Rajesh's trip report is in four parts. The first part covers the optional introduction to MBTI, Satir communication model, and Satir change model. Even if you know this stuff, if you haven't attended AYE before, I would recommend going to the optional intro session. When I attended the session, one of the presenters described using the concepts of the Aikido practice of "Center, Enter, Turn" to react to a Blaming attack: take a breath to center yourself, enter the dialog by agreeing with the Blamer that there is a problem to be solved, and verbally turn yourself to be along-side the Blamer as someone to help solve that problem.

    The second day of Rajesh's trip report covers a session he took on geographically disperse teams, a session on Virginia Satir and her work, and the Agile BOF. When I went to my first AYE conference, agile methods were new, several attendees thought Kent Beck and Ron Jeffries were offensive (and maybe nuts); there were a lot of people asking questions about them, asking XP in particular. Jerry Weinberg invited me and others to dinner to talk about XP. I was able to explain to him and to various people who do rigorous heavy-weight methods that XP isn't an invitation to hack... that the testing and other practices make for a disciplined process. Jerry said XP should be named "a set of practices that people have known to be good for the last 40 years". Jerry was doing iterative software development work on the Mercury space program in 1950's.

    The third day of Rajesh's trip report, he describes the seesion "Increasing Your Effectiveness as a Change Agent", which seems to either be a new session or one that has evolved a great deal (this is why I need to go back to AYE.) He also attended "Using your Yes/No Medallion", which is one of the Satir tools Jerry describes in More Secrets of Consulting: The Consultant's Tool Kit.

    The fourth day of Rajesh's trip report, he attended and participated in "Satir System Coaching" (Family Sculpting), and "No Best Practices" by James Bach.

    [/docs] permanent link

    2005.Jan.09 Sun

    Meaningful Workplaces

    Interesting page that I encountered while searching for something else: http://www.third-culture.com/OrgBehavior/MeaningAtWork.htm. It's something like a pattern language: there's a quality (like "Dialogue"), a description section of "when it's lacking" and "when it's thriving", two or three examples, and section of "Action Ideas". It would be interesting if someone turned the "lacking/thriving" parts of this page into an anonymous poll, where employees could rate their companies, and have published cumulative/averaged results published. Quotes from each quality:

    Acknowledgement

    The organization takes time to celebrate its major efforts (the journey) and successes (the destination).

    Balance

    People at all levels of the organization respect the fact that there's life beyond work. This is backed by real action -- as in the case of the manager who gives a half day off to a staff member following a 12-hour sprint to meet a key deadline.

    Challenge

    People are in work situations that require them to make full use of their talents.

    Dialogue

    As conversations unfold, people do their best to set aside their own opinions and assumptions in order to understand other perspectives.

    Direction

    If your organization (...) has a written vision statement, mission statement, set of goals/objectives, or anything similar, pull them from the oak frame and put them under the hot lights of critical, collective examination.

    Equality

    People throughout the organization genuinely feel that they're on the same level, regardless of how things look on the org chart.

    Fit

    Individual employees clearly see how they and their work fit into the bigger mission of the organization.

    Flexibility

    Apply the mission test: Do the rules contribute to the greater mission of the organization, or are they actually making it more difficult for people to carry out the mission?

    Informality

    When John talks about the ingredients of a meaningful workplace, he always comes back to...sugar. His office has an annual tradition called the "Festival of Treats,".... In some cases, people who've kept their conversations to an occasional hallway hello finally get the chance to chat.

    Invention

    Learn some of the creativity tools that facilitators routinely use, and make them a routine part of your organization's tool kit.

    Oneness

    Each person understands how his or her colleagues fit into the system -- what they do, where they excel, how they add value.

    Picture this: Creative information booths that tell the story of each division/unit/functional area, people engaged in conversation, discoveries being made at every turn ("So that's what you do!").

    Ownership

    As long as we think of managers as having a monopoly on the processes, nothing will come of our efforts to foster a wide sense of ownership.

    Routinely think in terms of co-creation -- involving large cross-sections of employees in the development of new systems, plans, direction, initiatives, improvements, and so forth.

    Personal Development

    Variety (trying new equipment, building new relationships, varying your work, etc.) is encouraged because it fosters learning and development.

    Who knows, the colleague who's next working to you each day may have something to teach you -- an idea, a skill, a piece of software, whatever.

    If an all-day experiment is impossible, try a half day -- or at least get together and share stories about the joys, demands, and frustrations of various roles in the organization.

    Purpose

    Open dialogue can help people see how their daily activities (relatively insignificant when thought of in isolation) contribute to the larger mission (very significant).

    Call one (at least) customer a day, ask how they're enjoying the product/service, then open your ears and mind as they comment.

    In a group of two to ten people who are closely linked by the work they do, pose this question: "What would make your/our job more purposeful?"

    Relationship Building

    This should not be thought of as another break room, but as the home for regular dialogues in which employees apply their collective brainpower to current and pending problems and opportunities. Done right, a community space does more than help people get to know one another -- though that's a big accomplishment in itself.

    Relevance

    The system allows employees to use their time efficiently; they can spend it on any activities that are relevant to the mission.

    one driving question: Does this policy help or hinder us in carrying out our organizational mission?

    Respect

    Pay special attention to how you interact with people whose roles in the organization tend to be less valued than your own.

    Self Identity

    The organization respects the fact that people sometimes need their own space (even in this era of teams!).

    For example, you may know that Joan is especially effective as a devil's advocate -- yet this part of her style has gone underground, in part because the organization favors people who are chronically agreeable.

    Service

    Each and every employee can quickly name the customers they serve.

    If there's no clear purpose to begin with, now's the time to craft one through dialogue, making sure that service figures prominently as the conversation unfolds.

    Support

    Employees are given the resources (information, time, funding, expertise, tools, etc.) they need to be successful in their work.

    Validation

    Contact with customers (internal and external) is a routine part of doing business, giving employees a first-hand view of how their products/services are used.

    Give special consideration to people whose roles in the organization put them far from the finished product/service stage.

    Worth

    Gratitude is the purest way to tell someone that you understand what they've done and how it contributes to the greater good.

    The next time you're working through a problem, seek input from a greater number of people.... Make a habit of showing -- and not simply telling -- that you value people's expertise and interests.

    [/docs] permanent link

    2005.Jan.02 Sun

    Reviews of C++ Unit Testing Frameworks

    Noel Llopis has a survey of CppUnit, Boost.Test, CppUnitLight, NanoCppUnit, Unit++, CxxTest. He has some examples and links to each of those frameworks.

    Chuck Allison has an article on StickyMinds on XP-style unit testing with his own frameworks (C++ and C versions).

    William Tanksley described how he and his coworker created CUT, which is on SourceForge/projects/cut/.

    I use an old version of Michael Feather's CppUnit, with a few changes to avoid warnings from VC++ 6.0 and some additional macros to simplify creating test classes. Creating a simple unit test framework, once you have experience with one, is pretty easy. I would recommend doing it once so that you have the experience; later, if you need a framework when one isn't handy, you can whip one up in an hour or less.

    This page is something of a clearing-house for unit test frameworks: http://www.xprogramming.com/software.htm. Check it out. Submit your own framework to this page if you want to share it.

    [/docs] permanent link