Bubble, Bubble, Toil And Trouble

chaoticset on 2002-03-18T00:39:59

Every time I get asked to do something for my yuppie brother, it usually results in rather severe irritation on my part. This time, however, he actually wanted to learn something, so he paid attention and learned. I suspect I'm underestimating him sometimes, because he does have the capacity to learn; he just seems to ignore it most of the time.

Here, I digress.

The irritation I've had for a few days now with the Perl version of a Markov (see previous entries, the one about _Practice Of Programming_) has come to a head and I finally sat down, typed the code in, and tried to understand it. (The irritation was a little cycle in my mind: "What, you think you can't even deal with a simple little Markov algorithm? You'll crumple like a house of cards if you ever get knee-deep in real code, you little pansy" over and over again, daring me to try.) Doesn't help that it's the first time I looked at it.

After several minutes of this, I decided I needed to play with the code, and their code was nearly indecipherable to me, so I just sat down and wrote as much of a Markov as I could.

A little voice said to me, "Write the tests first, that way you'll keep the steps straight."

Remarkably, it did. If I wrote the tests first and then wrote the code to fit the tests, the code worked, usually with just a few typo corrections. If I wrote the code, it was instantly a mess.

I don't know that I'll be able to actually improve the code in the book or not -- my Perl-fu is still kinda limited -- but I can sure give it a shot. Once I have a working version on my own, I'll look at their version and see if my idioms are better, and if not, why. If the code is an actual improvement I'll toss it in here; if it's not, I'm sure it will provide invaluable learning experience nonetheless.

And that's really the point anyway. Not like writing the best Markov implementation is going to win me a prize or something.


Write the tests first...

bart on 2002-03-20T00:01:16

You write:

A little voice said to me, "Write the tests first, that way you'll keep the steps straight."

Remarkably, it did. If I wrote the tests first and then wrote the code to fit the tests, the code worked, usually with just a few typo corrections. If I wrote the code, it was instantly a mess.


I'm curious. How exactly does that work? I can't imagine writing a test for code that doesn't even exist.

Re:Write the tests first...

koschei on 2002-03-20T03:23:50

If you know what the output is meant to be...

Y'see, in an ideal world, functions have pre conditions and post conditions. They have set inputs and set outputs. For example, if writing a modified julian day calculator, you should know that day number 51604 is 1 March 2000.

So one could happily write a test such as:
# caldate_mjd and caldate_frommjd
{
    ok(exists $main::{caldate_mjd}, "caldate_mjd imported");
    ok(exists $main::{caldate_frommjd}, "caldate_frommjd imported");
    use Time::Piece;
    my %dates = (
        0 => [ 1858, 11, 17 ],
        51604 => [ 2000, 3, 1 ],
        52345 => [ 2002, 3, 12 ],
    );
    foreach my $result (sort keys %dates)
    {
        my $mjd = caldate_mjd($dates{$result});
        is $mjd => $result, "mjd: Test for $result";
        my @back = caldate_frommjd($result);
        ok(eq_array(\@back, $dates{$result}), "frommjd $result");
        next if $dates{$result}[0] < 1970;
        my $tp = Time::Piece->strptime(
            join(' ', @{$dates{$result}},0,0,0),
            '%Y %m %d %H %M %S');
        is $mjd => $tp->mjd, "mjd vs TP for $result";
    }
}
This way, you'll know your code is doing the Right Thing(TM) when it passes the tests. (See also the TODO section in Test::More's doco.)

Re:Write the tests first...

chaoticset on 2002-03-20T04:32:08

I'm new to the whole test-writing thing, but usually I'd make a test for true on the variable/hash/array, then run it. Test passes, okay, something's in there, move on to validating the stuff in there...if it doesn't pass, I know I screwed something up.

It also makes you think ahead a little more, feels like. "It should do this...how do I test that?" is the question you were supposed to be asking yourself anyway; writing the test makes you do it.