Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Unit Tests and Creative Tension

by dws (Chancellor)
on Sep 07, 2003 at 08:19 UTC ( [id://289554]=perlmeditation: print w/replies, xml ) Need Help??

Lately I've been doing a lot of Test-Driven Development (TDD), writing tests cases first as a way to explore APIs and document expectations, and then fleshing out the code behind the test case. Working this way, I avoid writing unused code. The tempation is still there ("hm... as long as I'm here, I should also write the mummble method, because I know I'll need that at some point..."), but taking things story by story, test by test keeps me honest. By staying honest, and working parsimoniously, I'm tending to notice more quickly when team members start to add unused code, but that's a different meditation.

The TDD cycle is to first write a test that expresses how you want a given thing (typically, a class or a module) to function. Since you haven't written anything behind the test, it will fail. Next, you write enough of a simple dummy implementation to get the test to pass. Finally, you replace the dummy implementation with real code. You're done when the tests pass. (I typically skip the second step, and go right to working code. TDD purists might shoot me, but it works for me.)

My habit in years past has been to only walk away from a development session once everything works. That's not always possible, but it's been the ideal. It's the "I'll sleep better knowing that I solved it" approach. With TDD, I'm trying something different. Instead of stopping once tests pass, I'll end a session once I have a test in place with no code to back it up. That is, I'll walk away with a failing test. And it's working.

The reason it works goes back to the idea of "dramatic tension". Writers have known for some time that it's a bad idea to walk away from a writing session right after you've resolved all of the dramatic tension. You might feel good, but chances are you'll stall out when facing a blank page the next morning, because your subconcious has had a chance to relax. If instead you stop in the middle of a crisis, say, when the protagonist is facing down a bear but has just realized that his revolver isn't loaded (or that he's not wearing any pants), your subconcious is going to thrash the problem over all night, looking for a way to resolve the tension. When you pick up the story the next day, your mind will have throw out fresh ideas, and you're quickly into it without stalling.

I've found that coding is like that, too. Unless there's unresolved tension, facing a blank screen in the morning--trying to decide what do do and how to get started--is really hard. I'm easily distracted. While trying to figure out what do to, I'll check email. Then, two hours later, I'll wonder what the heck happened. But if I leave myself one new failing test case, my mind will have kept cranking overnight, and I'll start the morning with focus. I'll write the code to get the test case running, which gives me momentum that carries on into the next problem. Leaving the tension unresolved overnight so that my mind keeps generating ideas and options helps provide instant focus, quickly overcome morning starting friction. And I'm not sleeping any worse than normal.

Kent Beck recommends something like this in the back of one of the XP books. He warns that this trick works well when you're working on a solo project, but doesn't as well when you're pairing or on a team project. My experience supports the former claim, but the book is still open on the latter.

Do you do anything like this? How does it work for you?

Replies are listed 'Best First'.
Re: Unit Tests and Creative Tension
by demerphq (Chancellor) on Sep 07, 2003 at 10:24 UTC

    The tempation is still there ("hm... as long as I'm here, I should also write the mummble method, because I know I'll need that at some point..."),

    I know this goes against standard XP guidance, but I find that writing that extra method for completeness sake is often in of itself a form of advanced test. A supposedly general solution that has in fact been tailored for a specific problem set/domain often passes all tests for that domain, but as soon as you push it out of its "comfort zone" you find it breaks. And this breakage sometimes could have happened inside the desired domain, but wasn't being tested for properly because the percieved scope was narrowed so tightly to "get the job done".

    Leaving the tension unresolved overnight so that my mind keeps generating ideas and options helps provide instant focus, quickly overcome morning starting friction. And I'm not sleeping any worse than normal.

    In some respect I consider you a lucky man. When I have unresolved tension left at the end of the session I cant get my mind off of the subject. I become nervous and irritable and poor company. I far prefer to end sessions with the completion of a module or its core functions or whatever. That way I _can_ fall asleep.


    ---
    demerphq

    <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
      When I have unresolved tension left at the end of the session I cant get my mind off of the subject. I become nervous and irritable and poor company. I far prefer to end sessions with the completion of a module or its core functions or whatever.

      I find a big difference between walking away from an unsolved bug--particularly when I've done a lot of rip and tear to isolate it--and walking away after I've written a unit test that doesn't pass yet. Leaving a bug unsolved is frustrating, and frustration isn't great for sleep (or for inflicting on other people). To me, an unsatisfied unit test is more of a statement of intent. A unsatisfied statement intent doesn't eat away at me in the same way that an unresolved problem does. And starting the day with that statement gets me moving a lot sooner than having to make up a new statement, particularly before that magic first cup of coffee.

        Yesterday I reread your post and realized I had kinda missed the point. *blush* I have some pretty hairy design and code work coming up and I think before I write another line of code on that project (I am currently by lack of choice dealing with other matters) I will be putting together a full set of tests to experiement with TDD. It doesnt make sense to knock something you havent given a proper try of. And if the peace of mind you describe is a possible payoff then its definately worth the experiment.

        Many thanks for yet another thought provoking node. (Even if it did take a while to sink in, im kind thick sometimes. :-)


        ---
        demerphq

        <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...

      I know this goes against standard XP guidance, but I find that writing that extra method for completeness sake is often in of itself a form of advanced test.

      I think you are missing the point of You Aren't Gonna Need It. YAGNI is demand-loading applied to the writing of code. If you write code that you think you will need later, but you never use it later, you have wasted your time writing it. Worse than that, you might waste time trying to update the unneeded code to keep up with changes to the rest of the system. Unneeded code obviously should be left out, the only tricky part is knowing which code is not needed. All the code in a system was probably needed at one point in time, but if you go around writing stuff that you aren't even using yet, you create more cruft.

      If you have a "supposedly general solution" that isn't, that is just a bug. In TDD, there ought to be a test written that shows the bug. And then the solution can be refactored to fix the bug. If it actually fixed the bug, all the new tests pass and all the old tests still pass. Without those tests, you have less confidence that your refactored solution is actually better than the old solution.

        This should be filed under "what to do when YAGNI, but your boss thinks Y are GNI?"

        I'm in a new job, been here about a month, pretty much have a handle on my responsibilities, which entail maintaining a bunch of perl (yes!) and some coldfusion (bah!). Whether my boss overestimated the amount of work or I'm brilliant, I don't seem to have enough to keep busy, so today he told me to go write a subroutine to replace some logging code that happens in about 10 of our perl scripts.

        The catch is that the requirements for these logs are different depending on which script is doing the logging (despite the fact that they are all being written to the same place), so essentially what I'm doing is writing 10 different logging subroutines and making them all one with some if/else style logic to decide which flavor to use. And it turns out that there is no business reason that he's decided to do this--no client request, etc, driving this. I think rather what is driving it is a) I'm not very busy and b) rewriting code is taken for granted to be good.

        How do I have the conversation with him where I say "YAGNI" without sounding like I'm being subordinate/lazy? In my experience, grokking that this kind of anticipatory refactoring can be a waste of time is tricky for many people.

        AH

        p.s. Writing this post helped me figure out what I really want to do: I want to better define/standardize the logging requirements so that I can write a subroutine that can be plugged in to all 9 scripts. Thank you PM! Your thoughts are still appreciated, however.

Re: Unit Tests and Creative Tension
by pdcawley (Hermit) on Sep 07, 2003 at 09:28 UTC
    Beck suggests this in Test Driven Development as being the right thing to do when you're the only person working on a project. He points out that it doesn't work with a team for some fairly obvious reasons. However, in an XP environment (at least) the odds are that you'll start the next day paired with someone else, so you get your creative tension that way; even if you do pair with the same person, you at least have someone to bounce things off.
Re: Unit Tests and Creative Tension
by tachyon (Chancellor) on Sep 07, 2003 at 15:28 UTC

    TDD is just one component of Extreme Programming and in two words it works. 'Extreme Programming' is in my view a very sound approach. Once you get past the radical sounding name ;-). For a start it does not take itself too seriously and encourages you (in fact tells you) to use those bits that work for you and fix those bits that don't.

    There is plenty of gold to be mined in them there hills, have a gander.....

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Unit Tests and Creative Tension
by Cody Pendant (Prior) on Sep 08, 2003 at 03:44 UTC
    I don't have much to contribute, but I have come up with code in my sleep, in fact, dreamed code which would solve a particular problem. You wake up with the code and have no idea if it's actually good or not, you just know in your dream it worked. In this case it worked.

    ($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss') =~y~b-v~a-z~s; print
      This is funny. My wife had to kick me awake this morning because I was convinced the alarm was just the default in my $x = shift || $default;

      ------
      We are the carpenters and bricklayers of the Information Age.

      The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Unit Tests and Creative Tension
by castaway (Parson) on Sep 08, 2003 at 11:46 UTC
    I'll agree with this for general coding.. I've never used any defined/formal approach to coding things (not even bottom-up/top-down, more like from all sides :) - But as you say, going to bed (or just leaving the computer for a while), with a current task in mind keeps the brain churning over, and producing solutions.. And gives you something to get going on the next day. And I dont lose sleep over it (or other coding problems, for that matter, the best solution is usually to leave it for a while..)

    (Will admit to starting off my day with an hour or so of catching up on websites, groups etc, but thats all in the way of keeping up with the technical world etc, honest! ;)

    C.

Re: Unit Tests and Creative Tension
by jplindstrom (Monsignor) on Sep 08, 2003 at 22:06 UTC
    I tried it a couple of times but ended up not doing it very often. Don't know why, maybe because I don't do large enough things so when I discover I'm done with a task it's already too late to start an unfinished failing test :)

    As for not being suitable if you're more than one (I rarely am :), I don't see why it wouldn't work if you just keep the failing test for yourself, i.e. don't break anything by checking it in.

      just keep the failing test for yourself, i.e. don't break anything by checking it in.

      If you are using the Test::More module, you can declare that a test is supposed to fail because it is testing something that is not ready yet. This is called a TODO test.

Re: Unit Tests and Creative Tension
by thens (Scribe) on Sep 10, 2003 at 09:35 UTC
    Iam just thinking if creation of these failing tests can be associated with the Test Plan. If there is a way by which given the test suite we can generate a Test plan on the fly with some templates, it will be a great time saver. Also it reduces the frustration every developer has to go through from the 'Quality' department. Any thoughts.
      I am just thinking if creation of these failing tests can be associated with the Test Plan..

      Test Plans are usually about either acceptance tests or high-level functional tests. Unit tests are usually about implementation details. At the time the Test Plan is written, it's rare that the team knows enough about implementation details to specify in any detail what the unit tests will look like.

      Having good unit tests does make it less likely that QA will find bugs.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://289554]
Approved by abell
Front-paged by Enlil
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-03-29 07:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found