Mystery Buglet #2

Hey! I know, I know: long time, no blog.  I would love to blame the pandemic, but the truth is, I just haven’t been inspired with any sufficiently Perl-y topics lately.  Until recently, when I ran into this.

Now, once upon a time, I wrote a post about a small buglet I had encountered.  The post presented the problem, then asked you if you saw the problem, then explained what was going on.  So let’s do that again.  First, the code:
sub generate_temp_file
state $TMPFILES = [];
END { unlink @$TMPFILES }
my $tmpfile = `script-which-generates-tempfile`;
chomp $tmpfile;
push @$TMPFILES, $tmpfile;
return $tmpfile;

As before, the actual code does a bit more, but I promise I’ve omitted nothing that’s relevant to the bug.  Do you see it?  If not, click to find out more.

TIL about Literate Programming

As a programmer whose first job was in the mortgage software industry, “TIL” has always meant “Truth In Lending” to me: you know, that document that the bank is required to give you when you get a mortgage, that’s supposed to explain how much you’re really paying after all the bank’s hidden finance charges, except the numbers don’t seem to make any sense so you just sign it anyway and don’t know anything more than you did before?  Yeah, that one.

Of course, nowadays it means something else, and I’ve had to redirect my ossified mental patterns into new channels, so that, now when I see “TIL,” I can have my brain recognize it as “Today I Learned.” Which is a handy phrase: it encapsulates feelings of discovery, serendipity, and epiphany all into one.  And TIL1 that the way I’ve always tried to write code has a name, a history, and a venerable progenitor—most of my life, without even realizing it, I’ve been trying to use literate programming (only without the tangling).

To Hardcode, or Not to Hardcode: That Is the (Unit) Test-ion

In my last blog post, there was a bit of a discussion in the comments about whether data in unit tests should be hardcoded or not.  Tom Metro scored the last point with this comment:

We always coach developers to use hard coded test data to the extent practical. When writing tests you have to unlearn a lot of DRY principles. We tolerate a lot more repetition, and factor it out sparingly.

and then I said that this really required a longer discussion than blog post comments would allow.  This, then, is that longer discussion.

So, first of all, let me agree whole-heartedly with Tom’s final statement there: “We tolerate a lot more repetition, and factor it out sparingly.” Absolutely good advice.  The only problem is that, as I noted previously on my Other Blog, we humans have a tendency to want to simplify things in general, and rules and “best practices” in particular.  I don’t think that Tom was saying “always hardcode everything in your unit tests!” ... but I think some people will read it that way nonetheless.  I would like to make the argument that this is a more nuanced topic, and hopefully present some reasons why you want to consider this question very carefully.1

A Date with CPAN, Update #3: Golden Jubilee

[This is an addendum post to a series.  You may want to begin at the beginning.  The last update was update #2.

IMPORTANT NOTE! When I provide you links to code on GitHub, I’m giving you links to particular commits.  This allows me to show you the code as it was at the time the blog post was written and insures that the code references will make sense in the context of this post.  Just be aware that the latest version of the code may be very different.]

In case you missed my talk on Date::Easy from a couple years back, I’ll sum it up for you: dates are hard, y’all.

On January 1st of 2019, a bunch of unit tests for Date::Easy started failing.  It was immediately reported, of course—and can I pause here just a moment to thank Slaven Rezić (SREZIC on CPAN and eserte on GitHub), who is surely the most awesome bug reporter ever?  Date::Easy is definitely a better module for his reports, and I’ve seen him reporting bugs for many others as well.  Anyhow, as I dug into the suddenly failing tests—tests which begin failing even though you didn’t change any code are just a side-effect of writing a date-handling module—I figured out what was wrong.  Happily, it wasn’t a problem with the module, which was still returning correct values, but rather with the unit tests themselves.

Think globally, act local-ly

Here’s a pattern which took me a while to figure out this past week, and therefore seemed worthy of sharing with you guys.

First, let’s set the situation.  (These are certainly not the only conditions under which you could use this pattern, but it’ll probably be easier to grasp it with a concrete example.)  Let’s say you have a script which you’re going to use to launch your other Perl scripts.  This script (in my example, it’s a bash script, but it could also be a super-minimal Perl script) has exactly one job: set up the Perl environment for all your personal or company modules.  That may even include pointing your $PATH at a different Perl (e.g. one installed via perlbrew or plenv) so you’re not reliant on the system Perl.  Here’s a typical example of what such a (bash) script might look like: