<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Buddy Burden</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/" />
    <link rel="self" type="application/atom+xml" href="http://blogs.perl.org/users/buddy_burden/atom.xml" />
    <id>tag:blogs.perl.org,2009-11-03:/users/buddy_burden//1118</id>
    <updated>2013-02-23T08:51:37Z</updated>
    <subtitle>A blog about the Perl programming language</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.38</generator>

<entry>
    <title>Method::Signatures: here a tweak, there a bugfix</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2013/02/methodsignatures-here-a-tweak-there-a-bugfix.html" />
    <id>tag:blogs.perl.org,2013:/users/buddy_burden//1118.4370</id>

    <published>2013-02-23T08:38:52Z</published>
    <updated>2013-02-23T08:51:37Z</updated>

    <summary><![CDATA[ Just a quick note to say that I&rsquo;ve released a new version of Method::Signatures today.&nbsp; There&rsquo;s nothing major, just a few housekeeping duties.&nbsp; Here&rsquo;s the highlights: Previously, you weren&rsquo;t able to mix alias parameters and named parameters.&nbsp; Now, thanks...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    <category term="methodsignatures" label="Method::Signatures" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p><br />
Just a quick note to say that I&rsquo;ve released a new version of <a href="https://metacpan.org/module/Method::Signatures">Method::Signatures</a> today.&nbsp; There&rsquo;s nothing major, just a few housekeeping duties.&nbsp; Here&rsquo;s the highlights:</p>

<ul><li>Previously, you weren&rsquo;t able to mix alias parameters and named parameters.&nbsp; Now, thanks to a patch from the Damian and schwern fixing a buglet on 5.8 and 5.10 that had confounded me for the past month or so, you can.</li><li>Previously, run-time errors were pretty nice looking, with fairly precise line number reporting.&nbsp; The compile-time errors, such as the ones you get when your signatures don&rsquo;t parse correctly, were not as nice.&nbsp; This is fixed now (this is the only one I actually did myself).</li><li>If you&rsquo;d like the run-time errors to do something other than <code>die</code>, you can now override the new <code>signature_error_handler</code> method in a subclass.&nbsp; Thanks to <a href="https://github.com/larryl">larryl</a> for the patch.</li><li>Our use of <a href="https://metacpan.org/module/Data::Alias">Data::Alias</a> was causing a bug when used in conjunction with threads.&nbsp; Happily, schwern has put in code which will only load Data::Alias on demand, avoiding the bug at least in the cases where you use threads but not alias parameters, and also speeding up our compile-time performance a bit.</li></ul>

<p>Hopefully you find these tidbits helpful.&nbsp; Let us know&mdash;here, on <a href="https://github.com/schwern/method-signatures/issues?direction=desc&sort=created&state=open">GitHub</a>, or in an RT ticket&mdash;if you see any problems, or want to make any suggestions.&nbsp; Enjoy!</p>]]>
        
    </content>
</entry>

<entry>
    <title>Debuggit: now with Data::Printer-y goodness</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2013/02/debuggit-now-with-dataprinter-y-goodness.html" />
    <id>tag:blogs.perl.org,2013:/users/buddy_burden//1118.4339</id>

    <published>2013-02-16T22:04:56Z</published>
    <updated>2013-02-16T22:26:31Z</updated>

    <summary><![CDATA[Short Version: I&rsquo;ve released version 2.04 of Debuggit.&nbsp; It allows you to substitute Data::Printer for Data::Dumper when dumping variables. Long Version: If I&rsquo;m known for anything on CPAN (and I&rsquo;m not saying I am), it&rsquo;s probably for my work on...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    <category term="debuggit" label="Debuggit" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p><strong>Short Version:</strong> I&rsquo;ve released version 2.04 of <a href="https://metacpan.org/module/Debuggit">Debuggit</a>.&nbsp; It allows you to substitute <a href="https://metacpan.org/module/Data::Printer">Data::Printer</a> for <a href="https://metacpan.org/module/Data::Dumper">Data::Dumper</a> when dumping variables.</p>

<p><strong>Long Version:</strong></p>

<p>If I&rsquo;m known for anything on CPAN (and I&rsquo;m not saying I am), it&rsquo;s probably for my work on other people&rsquo;s modules: my co-maintenance of <a href="https://metacpan.org/module/Method::Signatures">Method::Signatures</a> in particular, or perhaps my co-maintenance of <a href="https://metacpan.org/module/Test::File">Test::File</a> (both of which <a href="http://blogs.perl.org/users/buddy_burden/2012/01/stepping-up.html">I&rsquo;ve talked about before</a>).&nbsp; But the first CPAN module I ever released was Debuggit.</p>

<p>I wrote a post upon the occasion, on my <a href="http://barefootcoder.blogspot.com/2011/04/perl-procrastination-and-cpan.html">other blog</a>.&nbsp; I didn&rsquo;t put it here, mostly because I hadn&rsquo;t <em>started</em> this blog yet.&nbsp; But also because it was more of a philosophical musing on procrastination than a useful commentary about CPAN or my particular module.</p>

<p>In fact, I haven&rsquo;t talked much about Debuggit on this blog.&nbsp; That&rsquo;s partly because it&rsquo;s one of those modules I wrote for me, and I don&rsquo;t much care if anyone else uses it or not.&nbsp; I&rsquo;m not in the business of evangelizing in general, but, if I <em>were</em>, I&rsquo;d spend my time telling you how cool Method::Signatures is, not Debuggit.&nbsp; Debuggit is just a little thing, a bit nifty, but nothing you couldn&rsquo;t write yourself, most likely.&nbsp; Nothing you <em>haven&rsquo;t</em> already written yourself, most likely, or at least some version of it.&nbsp; But perhaps my version, which I&rsquo;ve mucking about with for over 10 years now,<sup><a href="#note1">*</a></sup> has something which your version(s) didn&rsquo;t, or don&rsquo;t, so perhaps it&rsquo;s worth chatting about for a bit.&nbsp; Or you can just completely ignore me; I&rsquo;m fine with that too.</p>

<p>So the idea behind Debuggit is, sometimes you need to put output in your Perl scripts to tell you the values of variables, or just to let you know how far your program is getting before it bombs out.&nbsp; You could use the debugger for this, but some people don&rsquo;t like debuggers&mdash;I personally developed a distaste for them ever since I once spent 3 days tracking down a bug in a C++ program that it turned out didn&rsquo;t even <em>exist</em> outside the debugger&mdash;or sometimes it&rsquo;s hard to get to the code you need to debug (perhaps it&rsquo;s in a BEGIN block, and you forgot how to make the debugger run through that, or perhaps it&rsquo;s being run in mod_perl), or sometimes you just forget what all the single-letter debugger commands are and you just want an alternative.&nbsp; So you start putting in <code class="prettyprint">print</code> statements, until you realize that STDOUT is buffered and you might not be seeing all the statements that are executed, so you change to <code class="prettyprint">print STDERR</code> statements until you realize that <code class="prettyprint">warn</code> would be much easier to type, so you do that until you realize that in some mod_perl setups <code class="prettyprint">warn</code> and <code class="prettyprint">print STDERR</code> can go to two different places, or what if you have a <code class="prettyprint">SIGWARN</code> handler or you have <code class="prettyprint">Carp</code> always doing stack traces?&nbsp; Anyways, you pepper your code full of output statements, of whatever stripe, until you find the problem, and then you take them all back out.</p>

<p>Until the next problem, when you have to put them all back in again.</p>

<p>So your next attempt is to create some global variable called <code class="prettyprint">$DEBUG</code> which allows you turn all those output statements off at once, so now you just leave them in all the time.&nbsp; Of course, now they&rsquo;re in all the time: they take up memory, and they take up execution time (even though the output never gets run, the <code class="prettyprint">if $DEBUG</code> is always evaluated, over and over again).&nbsp; It&rsquo;s not <em>much</em> memory or time, of course, and in most instances you&rsquo;ll never even notice, but then again what if it&rsquo;s in some tight loop, which is called by another loop?&nbsp; You can&rsquo;t <em>guarantee</em> that it&rsquo;ll never matter if you just leave them in&nbsp;... right?</p>

<p>But then you discover <code class="prettyprint">use constant</code> and the magic of compile-time folding, and <code class="prettyprint">warn("foo") if DEBUG</code> turns out not to take any memory or execution time <em>at all</em>, if the <code class="prettyprint">DEBUG</code> constant is set to 0.&nbsp; So that&rsquo;s nifty.&nbsp; Of course, you may other have annoyances, like constantly having to remember to put spaces between your arguments so your output is readable, or what if your variable has leading or trailing spaces? that can be hard to see sometimes, and then if your variable is undefined, you get a nasty &ldquo;uninitialized&rdquo; warning, and, if you have warnings set to <code class="prettyprint">fatal</code>, that will actually blow up your program itself, and what if your variable is an arrayref or hashref? then what you <em>really</em> want is to use Data::Dumper to print it out legibly, except you really don&rsquo;t want to leave a <code class="prettyprint">use Data::Dumper</code> lying around in your code for eternity because Data::Dumper can eat a healthy chunk of memory, depending on Perl version and DD version and various and sundry other things (phases of the moon? I have no idea, actually), so&nbsp;...</p>

<p>So you really don&rsquo;t want to have to think about all that crap, right?&nbsp; You just want to slap some debugging in your code, be able to leave it there forever, not have it take up any extra memory or CPU time, and not to have to remember too many special rules to make the output look nice.</p>

<p>You want Debuggit.&nbsp; You just never knew it.</p>

<p>Anyway, Debuggit handles all that, and more, like letting you trick out where your output goes, what it looks like when it gets there, and add little &ldquo;debugging functions&rdquo; like the default one that calls Data::Dumper for you:</p>

<pre><code class="prettyprint">use Debuggit;

<p>my $hash = { some =&gt; 'very', complex =&gt; 'hashref' };<br />
debuggit("hash is currently", DUMP =&gt; $hash) if DEBUG &gt;= 3;<br />
</code></pre><br />
Of course now Data::Dumper is old and busted, and Data::Printer is the new hotness.&nbsp; So I fixed that:</p>

<pre><code class="prettyprint">use Debuggit DataPrinter =&gt; 1;

<p>my $hash = { some =&gt; 'very', complex =&gt; 'hashref' };<br />
debuggit("hash is currently", DUMP =&gt; $hash) if DEBUG &gt;= 3;<br />
</code></pre><br />
Perhaps one day I&rsquo;ll change it so that Data::Printer is the default and you have to specify <code class="prettyprint">DataPrinter =&gt; 0</code> to get Data::Dumper.&nbsp; But this is good for now.</p>

<p><br />
Anyways, I mostly put this on CPAN because I got tired of trying to send people a tarfile of it, not so I could convince the world to use my super-cool debugging module.&nbsp; But, then again, if you want to check it out, that&rsquo;s cool too.&nbsp; Maybe it&rsquo;ll be as useful for you as it has been for me.</p>

<p><br />
<small><a name="note1">*</a> The original version of Debuggit was called Barefoot::debug, and my first commit to it was on August 28, 2000.</small></p>]]>
        
    </content>
</entry>

<entry>
    <title>Method::Signatures: where and when</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/12/methodsignatures-where-and-when.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.4091</id>

    <published>2012-12-02T11:31:46Z</published>
    <updated>2012-12-02T11:48:50Z</updated>

    <summary><![CDATA[I&rsquo;ve just released a new version of Method::Signatures: 20121201, a.k.a. yesterday.&nbsp; This one has been a long time coming&mdash;I thought for a while there that $work was going to either bury me or sap my will to live&mdash;but it&rsquo;s finally...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>I&rsquo;ve just released a new version of <a href="https://metacpan.org/module/Method::Signatures">Method::Signatures</a>: 20121201, a.k.a. yesterday.&nbsp; This one has been a long time coming&mdash;I thought for a while there that $work was going to either bury me or sap my will to live&mdash;but it&rsquo;s finally here, and I hope you MS fans out there will be rejoicing.&nbsp; Let&rsquo;s take a look at some of the goodies.</p>

<p>(By the way, most of these awesome new features came from <a href="https://metacpan.org/author/DCONWAY">the Damian</a>, as I described in my post about <a href="http://blogs.perl.org/users/buddy_burden/2012/09/please-dont-throw-me-into-that-briar-patch.html">Git and patches</a>.&nbsp; The remainder come from <a href="https://metacpan.org/author/MSCHWERN">schwern</a>, who is of course the original author of MS.&nbsp; This time around, I really am just the guy who put it all together and uploaded it for all y&rsquo;all.)</p>

<h2><code class="prettyprint">where</code> Constraints</h2>

<p>One thing that MooseX::Method::Signatures has always been able to do that MS (and consequently <a href="https://metacpan.org/module/Method::Signatures::Modifiers">Method::Signatures::Modifiers</a>) couldn&rsquo;t was what are called <code class="prettyprint">where</code> constraints.&nbsp; This is a Moose concept that&rsquo;s a bit like on-the-fly typing.&nbsp; For instance, if you declare that your parameter is an <code class="prettyprint">Int</code>, what you&rsquo;re actually saying is, &ldquo;please check the incoming value of this parameter and, if it&rsquo;s not an integer, please throw a fit about it, thankyouverymuch.&rdquo;  If you wanted to make sure that you were getting an integer less than 10, say, what you <em>could</em> do is define a new type, say <code class="prettyprint">IntUnderTen</code>.&nbsp; But that might be a huge pain in the butt, particularly if you had a lot of different maximum values, or if said maximum was parameterized.&nbsp; So an easier way to do it would be:</p>

<pre><code class="prettyprint">method foo (Int $bar where { $_ &lt; 10 }) { do_stuff_with($bar) }
</code></pre>
And this is exactly the syntax that MXMS uses (and is similar to, if not the same as, the Perl 6 syntax).&nbsp; We&rsquo;ve long wanted to add this syntax to MS as well; we just never had the tuits.&nbsp; Happily, the Damian has done it for us, and now it&rsquo;s available for all your constrainting needs.

<h2>Conditional Defaults</h2>

<p>A while back, <a href="https://metacpan.org/author/RUZ">Ruz</a> sent us a patch concerning default values.&nbsp; Your standard default value goes like so:</p>

<pre><code class="prettyprint">method foo ($bar = 'fred') { say $bar }
</code></pre>
So if you call it like so:

<pre><code class="prettyprint">$obj->foo('sue');  # you get "sue"
</code></pre>
but if you call it like so:

<pre><code class="prettyprint">$obj->foo();  # you get "fred"
</code></pre>
But what happens if  you call it like so?

<pre><code class="prettyprint">$obj-&gt;foo(undef);
</code></pre>
You get a warning about uninitialized values, that&rsquo;s what.&nbsp; See, defaults only apply if you explicitly omit the parameter.&nbsp; If it&rsquo;s present, but undefined, the default isn&rsquo;t even consulted.&nbsp; But suppose you <em>want</em> the default when it&rsquo;s undefined?&nbsp; Well, you could always:

<pre><code class="prettyprint">method foo ($bar = 'fred') { $bar //= 'fred'; say $bar }
</code></pre>
But that&rsquo;s a bit redundant, right?&nbsp; Well, what Ruz suggested was something more like this:

<pre><code class="prettyprint">method foo ($bar //= 'fred') { say $bar }
</code></pre>
Now, the default is still applied if the parameter is omitted altogether, but it&rsquo;s also applied if the value is undefined.&nbsp; Ruz also pointed out that you might want to apply the default if the value is false in any way:

<pre><code class="prettyprint">method foo ($bar ||= 'fred') { say $bar }
</code></pre>
Or, say: what if you&rsquo;re reading off a web form?&nbsp; You might get &lsquo;0&rsquo; back, in which case you <em>don&rsquo;t</em> want the default, but if you get &rsquo;&rsquo; back, it probably just means the user left it blank, so proably you <em>do</em> want the default.&nbsp; Maybe something like:

<pre><code class="prettyprint">method foo ($bar ''= 'fred') { say $bar }
</code></pre>
The concensus on this patch (from everyone except Ruz) was that <code class="prettyprint">//=</code> was a great idea, <code class="prettyprint">||=</code> was okay, but <code class="prettyprint">''=</code> was just too weird.&nbsp; But schwern and Damian came up with a way to satisfy everyone:

<pre><code class="prettyprint">method foo ($bar = 'fred' when undef) { say $bar }  # if it's not defined
method foo ($bar = 'fred' when 0) { say $bar }  # if it's explicitly zero
method foo ($bar = 'fred' when '') { say $bar }  # if it's the empty string
method foo ($bar = 'fred' when { !$_ }) { say $bar }  # if it's false
method foo ($bar = 'fred' when { !/\S/ }) { say $bar }  # if it's all spaces
</code></pre>
Of course the defaults are still applied if the argument is omitted&mdash;it&rsquo;s <em>always</em> applied if it&rsquo;s omitted&mdash;but they can also be applied in just about any other situation too.&nbsp; The actual test is done using the smart match operator, so you can do any wacky thing you like, like testing against an array or regexen or whatnot.&nbsp; This is another great feature from Damian, and he also supplied a shortcut for the most common one:

<pre><code class="prettyprint">method foo ($bar //= 'fred') { say $bar }  # same as: = 'fred' when undef
</code></pre>
Which is where we started.

<h2>No More Devel::BeginLift</h2>

<p>We had long used <a href="https://metacpan.org/module/Devel::BeginLift">Devel::BeginLift</a> to make a MS method or function parse at compile-time, just like a real Perl <code class="prettyprint">sub</code>.&nbsp; But it turns out this is a problem for our Windows brethren and sistren, because Devel::BeginLift doesn&rsquo;t want to compile on Windows.&nbsp; Happily, schwern found another way to achieve the compile-time goodness and we&rsquo;ve dropped DBL as a prerequisite.&nbsp; You should be able to MS to your heart&rsquo;s content on Windows now.</p>

<h2>Disabling Parameter Checking</h2>

<p>Normally, if someone passes more arguments to you than you were expecting, that&rsquo;s an error.&nbsp; But occasionally you find yourself in the position of needing to create a function or method that&rsquo;s being called from someone else&rsquo;s code, and perhaps they don&rsquo;t play nice, or they are sending arguments that other people need but you don&rsquo;t.&nbsp; In these sorts of cases, you could always just slap a slurpy parameter in there:</p>

<pre><code class="prettyprint">method foo ($bar, $baz, @stuff_I_dont_care_about) { do_stuff($bar, $baz) }
</code></pre>
But one always hates to pay for an array copy you&rsquo;re never going to use.&nbsp; Or create a variable you&rsquo;re never going to access.&nbsp; Would just be nicer if you could just say to MS &ldquo;you know what? at this point, just stop caring about the parameters, okay?&rdquo;  Well, now you can:

<pre><code class="prettyprint">method foo ($bar, $baz, ...) { do_stuff($bar, $baz) }
</code></pre>
Or maybe you don&rsquo;t need any arguments at all:

<pre><code class="prettyprint">method foo (...) { say ':-P'; }
</code></pre>
Another useful feature from Damian.

<h2>Signature Parsing Improvements</h2>

<p>Three final miscellaneous improvements: the first two from Damian, the final one from schwern.</p>

<p>This has always worked:</p>

<pre><code class="prettyprint">method foo (Str|ArrayRef $bar) { handle_multi_types($bar); }
</code></pre>
But this didn&rsquo;t used to:

<pre><code class="prettyprint">method foo (Str|ArrayRef|HashRef $bar) { handle_multi_types($bar); }
</code></pre>
Now it does.

<p><br />
Likewise, this always worked:</p>

<pre><code class="prettyprint">method foo (ArrayRef[Str] $bar) { process($bar); }
</code></pre>
But this didn&rsquo;t used to:

<pre><code class="prettyprint">method foo (ArrayRef[ArrayRef[Str]] $bar) { process($bar); }
</code></pre>
Now it does.

<p><br />
Finally, this didn&rsquo;t used to work:</p>

<pre><code class="prettyprint">method foo ($bar, $baz, ) { do_stuff($bar, $baz); }
</code></pre>
Now it does.&nbsp; (The trailing comma is just ignored, exactly as it would be in a list definition.)

<h2>Results from CPAN Testers</h2>

<p>I haven&rsquo;t seen any reports for this new version yet, but the last dev version that I saw reports for had a failure rate under 10%.&nbsp; Most of those failures I was able to identify and fix (just little buglets in the tests themselves).&nbsp; But there&rsquo;s still a few reports of failures on Windows (about a third of the total Windows reports, last time I checked) that I can&rsquo;t quite pin down.&nbsp; They don&rsquo;t seem consistent based on Perl version, Windows version, or anything else I could find.&nbsp; If anyone tries out MS on Windows and sees a failure that looks like <a href="http://www.cpantesters.org/cpan/report/6ac0ccca-29d5-11e2-9138-dbfbadeabf73">this</a>, please open up a <a href="https://github.com/schwern/method-signatures/issues">GitHub issue</a> and let me know.</p>

<h2>Competition</h2>

<p>Thanks to <a href="http://perlweekly.com/">Perl Weekly</a> (which is absolutely great for discovering such things; you really should toddle off and sign up if you haven&rsquo;t already), I see that MS has some new competition: <a href="https://metacpan.org/module/Function::Parameters">Function::Parameters</a>, by <a href="https://metacpan.org/author/MAUKE">Mauke</a>.&nbsp; It looks like FP has roughly the same syntax as MS; in fact, it looks like Mauke has used some of MS&rsquo;s test suite in FP, which will help him guarantee that he maintains compatibility (a pretty good thought on his part).&nbsp; Of course, MS does a few things that FP doesn&rsquo;t do (the biggest one being types, but also the new features above and a few other bits and bobs, such as explicit optional/required, alias parameters, readonly parameters, etc).&nbsp; But, then, FP does a few things that MS doesn&rsquo;t do:</p>

<ul><li>You can add a prototype to an FP function.</li><li>You can change the keyword used to introduce a function or method with signatures.</li><li>You can turn checking for required parameters and unexpected parameters off.</li></ul>
(You might think that handling function attributes is something else FP does that MS doesn&rsquo;t, but MS actually does handle those.&nbsp; We just don&rsquo;t advertise it much.)  I wonder if anybody thinks of any of these as big holes in MS&rsquo;s feature set.&nbsp; Please let me know in the comments if you do.

<p><br />
Of course, the big difference is that MS uses <a href="https://metacpan.org/module/Devel::Declare">Devel::Declare</a>, whereas FP uses the <a href="http://perldoc.perl.org/perl5120delta.html#Pluggable-keywords">pluggable keywords</a> API introduced in 5.12.&nbsp; I think that&rsquo;s pretty much an invisible, under-the-hood difference, but perhaps it will matter to some.&nbsp; In any event, competition is always good, so I welcome the new face on the function signatures block.</p>

<h2>Future Plans</h2>

<p>What I&rsquo;ll be working on next is a small-ish patch from Damian which will allow you to have named alias parameters (right now, you can have named parameters, and you can have alias parameters, but you can&rsquo;t have named alias parameters).&nbsp; There are also a few minor GitHub issues I want to take a look at.&nbsp; Nothing major.</p>

<p>I&rsquo;m also very interested in hearing from folks that are using MS.&nbsp; Have a problem? or a suggestion?&nbsp; Don&rsquo;t hesitate to open a GitHub issue, even if it&rsquo;s just to chat about something.&nbsp; I love hearing from people who are actually using this in the real world.</p>

<p>So install the latest version, give it a whirl, and let us know how it goes for you.&nbsp; Happy signature parsing!</p>]]>
        
    </content>
</entry>

<entry>
    <title>Please Don&apos;t Throw Me into that Briar Patch ...</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/09/please-dont-throw-me-into-that-briar-patch.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.3898</id>

    <published>2012-09-29T20:47:58Z</published>
    <updated>2012-09-30T21:58:32Z</updated>

    <summary><![CDATA[[Quick note: This is mostly a Git story, although there&rsquo;s plenty of links to Perl code and Perl discussions.&nbsp; It also turned out to be quite a bit longer story than I originally intended.&nbsp; But, even though it gets pretty...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
        <category term="CPAN" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Git" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p><em>[Quick note: This is mostly a Git story, although there&rsquo;s plenty of links to Perl code and Perl discussions.&nbsp; It also turned out to be quite a bit longer story than I originally intended.&nbsp; But, even though it gets pretty deep into Git features, I think it should be interesting enough for anyone who has a CPAN module and uses Git.&nbsp; I hope.]</em></p>

<p><strong>The Backstory:</strong>  So, a couple months back, I look in my email and spy a message from Damian Conway.&nbsp; Now, some of you fine readers probably know Damian personally, and I&rsquo;m sure I&rsquo;ll get several comments pointing out how he&rsquo;s just an ordinary bloke and all, but to you I say: hush!&nbsp; <em>You</em> may be all jaded and world-weary, but I&rsquo;m still just a regular Perl schmoe, and when <em>I</em> see an email from The Damian addressed personally to me, I get all goosebumpy.&nbsp; So hush up and allow me my fanboy gushes.</p>

<p>Especially since the purpose of his email was to send me a patch for <a href="https://metacpan.org/module/Method::Signatures">Method::Signatures</a> (for which I&rsquo;m a co-maintainer) and to tell me:</p>

<blockquote>I adore Method::Signatures and am now using it in nearly all my own development...and in absolutely all my teaching.</blockquote>
Ooohh&nbsp;... high praise indeed, from a Perl luminary.&nbsp; Coolio, man!

<p><br />
Anyways, this missive just happened to have the ill fortune to land at the same time that $work began to (uncharacteristically) demand a larger chunk of my life than normal.&nbsp; So I didn&rsquo;t have time to review the patch too closely, but I certainly didn&rsquo;t want to lose the opportunity to discuss a few larger design issues with Mr. Conway.&nbsp; Thus began a long, winding discussion among me, Damian, and Schwern (who must be given full credit as the original author of MS), both in email and in <a href="https://github.com/schwern/method-signatures/issues/45">GitHub</a> <a href="https://github.com/schwern/method-signatures/issues/48">issues</a>, and even spilling over into <a href="http://blogs.perl.org/users/buddy_burden/2012/08/a-methodsignatures-retrospective.html">my blog</a>.&nbsp; And I learned something about Damian: he thinks in code.&nbsp; So, every time he comes up with a new idea, he sends me a new patch.&nbsp; By the time it&rsquo;s all over, and $work is settled enough that I can really start devoting some time to this issue, I&rsquo;ve got six, fairly hefty patchfiles from Damian&mdash;some of them overwriting or cancelling out the direction of others, the first four of them patched against current HEAD (of master) on GitHub, and the last two as <em>both</em> patches against current HEAD and against the previous patch.</p>

<p>What to do, what to do?</p>

<p><strong>A Brief Tangent on Contributions:</strong> At some point, Schwern noted that we&rsquo;d finally come to a general agreement on basic design, and that he&rsquo;d made Damian a contributor, so Damian should just go ahead and make a branch, and put his code on it.&nbsp; To which Damian <a href="https://github.com/schwern/method-signatures/issues/48#issuecomment-7780752">replied</a>:</p>

<blockquote>Re branching repo: Probably won&rsquo;t. Expect annoyingly complete patches.&nbsp; (I know. Not properly social. Not a team player. Not git-ish.&nbsp; But also not a new phenomenon. Every single report card I ever received included some variation of: &ldquo;Does not play well with others&rdquo;.)</blockquote>
Now, at the risk of putting words in The Damian&rsquo;s mouth, I read this as &ldquo;hey, I&rsquo;ve been delivering patches to CPAN authors for years, and I&rsquo;m not going to change now just because of the latest newfangled method.&rdquo;  Which leads me to ponder a bit on the relationship between author and contributor.

<p><br />
Like so many things in life, this involves a balance.&nbsp; The contributor has a feature they want added.&nbsp; The author wants people to fix their code for them (for free, even).&nbsp; This is a mutually beneficial arrangement, but there&rsquo;s still all sorts of things to work out.&nbsp; Perhaps the author uses <a href="https://metacpan.org/module/Dist::Zilla">Dist::Zilla</a> and the contributor doesn&rsquo;t, or perhaps the author adheres to strict <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> and the contributor has sent no tests for the new feature.&nbsp; Or, maybe, the contributor has sent a patch when the author would really prefer a GitHub pull request.</p>

<p>Now the two can have some negotiation.&nbsp; In the TDD example, perhaps the author wants the new feature badly enough that they&rsquo;re willing to write the tests themselves.&nbsp; Or perhaps the contributor wants the new feature badly enough that they&rsquo;re willing to go back and add the tests upon request.&nbsp; But, the point is, everybody has to evaluate how bad they want it.</p>

<p>So&nbsp;... how bad do <em>I</em> want a pack of new features and refactorings from The Damian?&nbsp; Yeah, you bet your ass.</p>

<p><strong>The Meat of the Matter:</strong>  So here&rsquo;s what I suggested: I&rsquo;ll make a branch, apply the patches to it, one at a time, review the code (not that I feel Damian&rsquo;s code needs a lot of review, but, as he said: &ldquo;Long and bitter experience indicates I&rsquo;m every bit as fallible as a real human. Better check that code. ;-)&rdquo;), make sure it all fits together, and then offer up the results for review.</p>

<p>This sounded simple enough at the time.</p>

<p>Of course, the tricky part is that, for the first four patches at least, they&rsquo;re all patches against HEAD.&nbsp; That means that, while the first patch is no problem, the next three are going to be annoying, because the source I&rsquo;m patching against isn&rsquo;t the source originally used to generate the patchfile.&nbsp; Happily, I foresee this, and start to formulate a plan to work around it.&nbsp; Here&rsquo;s how it went, and hopefully this is helpful to someone else out there.</p>

<p>First, I make a new branch off head, which I creatively name &ldquo;damian_features&rdquo;.&nbsp; Next, I apply patch #1 to my new branch.&nbsp; Since it was an exact copy of master&rsquo;s HEAD, it applied cleanly&nbsp;... once I remembered how to work <code class="prettyprint">patch</code>.&nbsp; Been a while since I had any cause to apply a patchfile.&nbsp; Looking at the structure of the file helped me jog my memory: each file consists of a set of context diffs from several files.&nbsp; Each file is identified with a relative path.&nbsp; Within each file&rsquo;s section are one or more &ldquo;hunks&rdquo;; that is, the individual context diffs themselves.&nbsp; The <code class="prettyprint">patch</code> command (which, you may recall, was Larry Wall&rsquo;s original <a href="http://en.wikipedia.org/wiki/Patch_%28Unix%29">claim to fame</a>, before he invented Perl) simply finds the files indicated in the patchfile, then applies each &ldquo;hunk&rdquo; of context diffs, one at a time, to said files.&nbsp; If the source of the file being patched matches the source of the file the patchfile was generated from, the hunk &ldquo;applies cleanly&rdquo; and all is well.&nbsp; If not&nbsp;... then you&rsquo;ve got a problem to solve.</p>

<p>Since patchfiles are nearly always generated a directory <em>above</em> the source directory, but nearly always applied <em>in</em> the source directory, the filenames in the patchfile generally have an extra directory component in them that you need to strip off.&nbsp; Happily, <code class="prettyprint">patch</code> can do that for you.&nbsp; In fact, it can strip off an arbitrary number of directories for you, but we&rsquo;ll just tell it to strip one.&nbsp; The only other mildly tricky bit is that patchfiles are read from stdin, not as args:</p>

<pre><code class="prettyprint">    patch -p1 &lt;/tmp/Method-Signatures-Conway.patch
</code></pre>
And it all works just fine.&nbsp; Next a simple <code class="prettyprint">git diff</code> to review the changes&mdash;making notes of anything I want to change or ask about, but not actually changing anything yet&mdash;then I stage and commit.&nbsp; For the commit message, I make up a brief summary line, but I pull the guts of the message from Damian&rsquo;s description of the patch in his email.&nbsp; <em>Then</em> I make any little tweaks I want to, as separate commits (that way Damian&rsquo;s changes and my changes aren&rsquo;t comingled).&nbsp; I could hold off on this until the end, but doing it in between each commit preserves the history better, and plus the next patch isn&rsquo;t going to work straight up anyway, so there&rsquo;s no advantage in waiting.

<p><br />
Okay, the next few patches aren&rsquo;t going to apply cleanly, so let&rsquo;s see how bad I want them.&nbsp; Looks like patch #3 pretty much wipes out everything patch #2 did (hey, when you&rsquo;re thinking out loud in code, you&rsquo;re going to go down a few blind alleys here and there), but, other than that, all the patches are pretty useful, at least in terms of showing a gradual progression to how we got to the end product.&nbsp; So I decide to toss patch #2 but keep the rest.</p>

<p>So, how do I proceed?&nbsp; Simple:</p>

<ol><li>I switch back to the <code class="prettyprint">master</code> branch.</li><li>I apply patch #3 there, which is the same HEAD the patchfile was generated from, so it <em>will</em> apply cleanly.</li><li>I then stash the changes.</li><li>Then I switch back to the <code class="prettyprint">damian_features</code> branch.</li><li>Then I unstash.</li></ol>

<p>Voil&agrave;.&nbsp; Now, this <em>sounds</em> simple(ish) in theory, but of course in practice it isn&rsquo;t perfect.&nbsp; First, I want to stash any files which the patchfile <em>adds</em> as well as the ones it modifies.&nbsp; To do this, I need <code class="prettyprint">git stash -u</code>, but that&rsquo;s only available in <code class="prettyprint">git</code> 1.7.7 or later, which I don&rsquo;t actually have, so I have to upgrade <code class="prettyprint">git</code>.&nbsp; That&rsquo;s okay; I probably needed to do that anyway.</p>

<p>Next problem I run into is what happens when patch #1 adds a file, and then patch #3 adds the <em>same</em> file.&nbsp; This blows the unstash up (because it&rsquo;s trying to add a file that already exists), and I have to move the existing file out of the way, then re-unstash, then do a manual <code class="prettyprint">diff</code> to see if the two &ldquo;new&rdquo; files are identical or not.&nbsp; And, of course, if the first unstash added any <em>really</em> new files before it blew up, I have to remove those before the re-unstash or it&rsquo;ll blow up again (this takes me a few tries to get right).&nbsp; Overall, this is an annoyance, but luckily none of the changes between patches to any such files are any big deal.</p>

<p>Final problem I run across is, what happens if patch #1 adds some code in a place, and patch #3 doesn&rsquo;t touch the code in that same place?&nbsp; Well, the code really should be removed, because patch #3 doesn&rsquo;t contain it, and it&rsquo;s a full replacement for patch #1.&nbsp; But my method is going to leave it, because an unstash is essentially a merge, so it has no idea that code shouldn&rsquo;t just stay right where it is.&nbsp; Luckily this only happens once throughout the process (if you think about it, it makes sense that this would be rare, since the patches are all messing with the same features), and I catch it easily.</p>

<p>So basically it&rsquo;s just rinse and repeat this whole shebang for patch #4, and then patches #5 and #6 have versions against the previous patches, so I just apply those directly.</p>

<p>Now, you may be asking yourself: why go through all this rigamarole with the stashing and unstashing?&nbsp; If the patch doesn&rsquo;t apply cleanly, you have a mess to clean up.&nbsp; On the other hand, if the <em>unstash</em> doesn&rsquo;t merge cleanly, you have a mess to clean up there too.&nbsp; What&rsquo;s the difference?</p>

<p>Well, when the patch doesn&rsquo;t apply cleanly, it often keels over right there and doesn&rsquo;t move on to the next file.&nbsp; Plus, what it generates is a file where as many of the hunks as it <em>could</em> apply cleanly are applied, the hunks it <em>couldn&rsquo;t</em> apply cleanly are stuffed into a <code class="prettyprint">.rej</code> file, and the original source is saved as a <code class="prettyprint">.orig</code> file.&nbsp; Which is fine, as far as it goes.&nbsp; But it means that you have to pick the rejected hunks out of the <code class="prettyprint">.rej</code>, find where they were supposed to go in the file based on the context (because the line numbers likely aren&rsquo;t right if there are earlier hunks which <em>were</em> applied), insert the rejected hunk, which is actually a diff, which means it&rsquo;s got little +&lsquo;s and -&lsquo;s in front of all the lines&nbsp;... it&rsquo;s just a little messy, is all.&nbsp; But if the <em>unstash</em> doesn&rsquo;t apply cleanly, it&rsquo;s just a merge conflict, and those are simple to fix.</p>

<p>At the end of this whole process, I&rsquo;ve got 11 commits (5 substantial ones from Damian, and 6 little ones from me), and I review them all before I push:</p>

<pre><code class="prettyprint">    git log origin/damian_features..HEAD
</code></pre>
That shows me all the commits that I haven&rsquo;t pushed yet (that command is so handy and yet so hard to remember that I have it scripted).&nbsp; In my review, the first thing I notice is that I can&rsquo;t really tell Damian&rsquo;s commits from mine, at least not at a glance.&nbsp; I&rsquo;ve done all the committing, so they all show up under my name.&nbsp; But that&rsquo;s wrong: I really want them to show up under Damian&rsquo;s name.&nbsp; And I know that <code class="prettyprint">git</code> has the concept of the author and committer being separate, which is perfect for this application.&nbsp; If only I&rsquo;d remembered to use the <code class="prettyprint">--author</code> switch when I committed!

<p><br />
But, wait: this is <code class="prettyprint">git</code> we&rsquo;re talking about.&nbsp; I can fix this&nbsp;... right?</p>

<p>Of course I can:</p>

<pre><code class="prettyprint">    git rebase -i HEAD^^^^^^^^^^^
</code></pre>
Yes, that&rsquo;s 11 carets, and, yes, there&rsquo;s a way to abbreviate that, but I don&rsquo;t recall it off the top of my head (I&rsquo;m sure someone will supply it in the comments).&nbsp; You might think it should be 10 carets, because HEAD counts as one&mdash;at least <em>I</em> always think that&mdash;but it&rsquo;s actually not.&nbsp; This puts me in an editor with all 11 commits listed, with &ldquo;pick&rdquo; in front of each.&nbsp; Now all I need to do is change &ldquo;pick&rdquo; to &ldquo;edit&rdquo; for each of the Damian commits.&nbsp; When I save that file, <code class="prettyprint">git</code> reapplies each commit, stopping at each one that I changed to <code class="prettyprint">edit</code> (actually, stopping just <em>after</em> committing each of those), then I just have to:

<pre><code class="prettyprint">    git commit --amend --author "Damian's info here"
    git rebase --continue
</code></pre>
with just a quick <code class="prettyprint">ZZ</code> in between to resave the commit messages (which are fine), rinse and repeat 4 more times for the other Damian commits, and, Bob&rsquo;s yer uncle, it&rsquo;s all fixed.&nbsp; One last review to make sure it all looks good, then <code class="prettyprint">git push</code> to GitHub and send Damian an email with a <a href="https://github.com/schwern/method-signatures/commits/damian_features/">link</a> to review (look at the commits on Sep 26, 2012, in case there happen to be more by the time you read this), and I&rsquo;m all done.

<p><br />
<strong>Wrap-up:</strong> I hope you found <em>something</em> in this long post useful, or interesting, or at least entertaining.&nbsp; I found it to be an interesting and challenging exercise in making two different forms of contributing work together, and I bet it&rsquo;s not the last time I&rsquo;ll need to do that.</p>

<p>Certainly, as long as Damian is willing to keep sending me patches, I&rsquo;ll keep integrating them.&nbsp; Look at the awesomeness we&rsquo;ve gotten so far!</p>

<p><br />
<em>[Notes: 1) Excerpts from Damian&rsquo;s emails used by permission.&nbsp; 2) If you&rsquo;re interested in getting to use the actual code that Damian wrote for Method::Signatures, don&rsquo;t worry: I&rsquo;m going to be doing a bit more testing on different Perl versions, but you should see it hit CPAN soon.&nbsp; 3) If you didn&rsquo;t catch the reference in the post title, you could <a href="http://americanfolklore.net/folklore/2010/07/brer_rabbit_meets_a_tar_baby.html">read the classic American folktale online</a>.]</em></p>]]>
        
    </content>
</entry>

<entry>
    <title>A Method::Signatures Retrospective</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/08/a-methodsignatures-retrospective.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.3685</id>

    <published>2012-08-12T09:35:13Z</published>
    <updated>2012-08-12T09:45:13Z</updated>

    <summary>As some of you may know, I worked on a partial rewrite of Method::Signatures last year, mainly to add Moose types to the sigs, but also to do some tweaks here and there, and to use it as a base...</summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>As some of you may know, I worked on a partial rewrite of <a href="https://metacpan.org/module/Method::Signatures">Method::Signatures</a> last year, mainly to add Moose types to the sigs, but also to do some tweaks here and there, and to use it as a base for Method::Signatures::Modifiers (included with MS), which can replace MooseX::Method::Signatures inside <a href="https://metacpan.org/module/MooseX::Declare">MooseX::Declare</a>.&nbsp; This latter reason was the primary goal for me, and I&rsquo;ve gleefully been using MS, and MSM, in practically all the code I&rsquo;ve written since.&nbsp; I&rsquo;ve also <a href="http://blogs.perl.org/users/buddy_burden/2012/05/a-porters-tale.html">ported over</a> a rather large codebase (although admittedly not much of it was using MXD).&nbsp; We&rsquo;re almost at the eleven month mark since our first release of the new MS, so I thought it might be interesting to check in with how things are doing.</p>

<p>First of all, we haven&rsquo;t seen too many bugs.&nbsp; A couple of obscure things here and there, but nothing earth-shattering.&nbsp; So that&rsquo;s positive.&nbsp; I noticed a <a href="http://blogs.perl.org/users/joel_berger/2011/11/methodsignatures-some-relief-for-moosexdeclare-users.html">fairly early adoption</a> by <a href="https://metacpan.org/author/JBERGER">Joel Berger</a>, and he seems to be using it in many of his code snippets that he posts.&nbsp; So there&rsquo;s a plus as well.&nbsp; And I just received a feature request from <a href="https://metacpan.org/author/DCONWAY">the Damian</a>, who said in his opening remarks, &ldquo;I adore Method::Signatures and am now using it in nearly all my own development...and in absolutely all my teaching.&rdquo;  So <em>that&rsquo;s</em> pretty nice.</p>

<p>If you have found MS and/or MSM to be helpful in your development, I encourage you to leave a short note in the comments, and I&rsquo;d also like to ask your opinion on a small design issue.&nbsp; This has been bugging me for a few months now, and I brought it up with Damian, and then schwern opened a <a href="https://github.com/schwern/method-signatures/issues/26">GitHub issue</a> for it.&nbsp; Well, technically he <em>re</em>opened an issue that I had opened way back when I was first digging into MS.&nbsp; Back then, I didn&rsquo;t really have an opinion on it.&nbsp; But now I do.</p>

<p>Here it is.&nbsp; Let&rsquo;s start with some basic stuff.&nbsp; This:</p>

<pre><code class="prettyprint">method foo ()
{
}
</code></pre>
means that you&rsquo;re declaring a method which allows no parameters.&nbsp; If you <em>did</em> try to pass it a parameter, you&rsquo;d get an error like so:

<pre><code class="prettyprint">In call to Test::foo(), was given too many arguments, it expects 0 at ./test.pl line 16.
</code></pre>
So far so good.&nbsp; Now, this:

<pre><code class="prettyprint">method foo (@_)
{
}
</code></pre>
is the MS way of saying, &ldquo;I don&rsquo;t actually <em>care</em> what my parameters are.&rdquo;  It&rsquo;s the no-signature signature, so to speak, and the only real advantage it has over just falling back to <code class="prettyprint">sub</code> is that it still shifts off <code class="prettyprint">$self</code> for you.&nbsp; (And also it maintains some consistency, in that it might look weird if every method is a <code class="prettyprint">method</code> except for that one, which is a <code class="prettyprint">sub</code>.&nbsp; But that&rsquo;s just sugar.)  You can call that with whatever parameters you like; MS doesn&rsquo;t bother to check them.

<p>With me so far?&nbsp; Good.&nbsp; Now here&rsquo;s the sticky part.</p>

<p>What does this one mean?</p>

<pre><code class="prettyprint">method foo
{
}
</code></pre>
Well, as far as MS is concerned, it means the same as <code class="prettyprint">method foo ()</code>: that is, it expects no arguments, and blows up if you try to pass any.&nbsp; But that&rsquo;s not consistent with other systems that have signatures.&nbsp; For instance, in Perl 6, no signature just means&nbsp;... well, no signature.&nbsp; That&rsquo;s also true of MooseX::Method::Signatures, which means that this creates yet another difference between MXMS and MSM, which is always slightly irksome.&nbsp; That is, P6 and MXMS treat <code class="prettyprint">method foo</code> as equivalent to <code class="prettyprint">method foo (@_)</code>, except that they don&rsquo;t actually recognize that particular syntax.&nbsp; P6 will (I believe) just shift off <code class="prettyprint">$self</code> for you, and MXMS won&rsquo;t even do that (that is, it <em>sets</em> <code class="prettyprint">$self</code>, but it doesn&rsquo;t shift it off, so <code class="prettyprint">@_</code> will still contain <code class="prettyprint">$self</code>).

<p><br />
This seemingly trivial change can trip you up in surprising places.&nbsp; For instance, this (which you may recognize from <a href="https://metacpan.org/module/Moose::Manual::Construction">Moose::Manual::Construction</a>):</p>

<pre><code class="prettyprint">around BUILDARGS
{
    if ( @_ == 1 && !ref $_[0] )
    {
        return $self->$orig( ssn =&gt; $_[0] );
    }
    else
    {
        return $self->$orig(@_);
    }
}
</code></pre>
won&rsquo;t do what you expect with MSM, because the extra arguments to <code class="prettyprint">BUILDARGS</code> results in the &ldquo;too many arguments&rdquo; error.&nbsp; Likewise, this, which is pretty much straight from the <a href="https://metacpan.org/module/MooseX::App::Cmd">MooseX::App::Cmd</a> POD:

<pre><code class="prettyprint">method execute
{
    my $result = $self->blortex ? blortex() : blort();
     
    recheck($result) if $self->recheck;
          
    print $result;
}
</code></pre>
will blow up, because the <code class="prettyprint">App::Cmd</code> underneath is passing parameters to <code class="prettyprint">execute</code> which you don&rsquo;t actually need.&nbsp; At least in the <code class="prettyprint">BUILDARGS</code> example, you were actually referencing <code class="prettyprint">@_</code>; in this one, adding a signature of <code class="prettyprint">(@_)</code> doesn&rsquo;t seem to make much sense, but it&rsquo;s what you need to do to make it work with MS or MSM.

<p><br />
So why <em>wouldn&rsquo;t</em> we change it?&nbsp; Well, one thing to consider is backwards compatibility.&nbsp; We&rsquo;ve had it working this way for the nearly-a-year that I&rsquo;ve been involved, and I&rsquo;m pretty sure it was working that way before I got here as well.&nbsp; So changing it might surprise some people that have gotten used to it working the way it does.&nbsp; Now, one good thing about it is that it&rsquo;s not going to <em>add</em> a fatal error into your existing code.&nbsp; Rather, it would be <em>removing</em> a fatal error&nbsp;... and, since it was, in fact, a fatal error, you probably <em>already</em> removed it, so most likely this change would impact any old code at all.&nbsp; Still, there could be something, somewhere, that perhaps does a method call in an eval block, then checks <code class="prettyprint">$@</code> and expects to find the &ldquo;too many arguments&rdquo; error&nbsp;... okay, it&rsquo;s a long shot, but, as <a href="http://www.judytenuta.com/">Judy Tenuta</a> used to say: it could happen!</p>

<p>So, if you have an opinion on whether we should make this change or not, we&rsquo;d love to hear it.&nbsp; Comment below, or join the discussion on <a href="https://github.com/schwern/method-signatures/issues/26">GitHub</a>.&nbsp; And thanks for using Method::Signatures!</p>]]>
        
    </content>
</entry>

<entry>
    <title>The Mind-killer</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/07/the-mind-killer.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.3506</id>

    <published>2012-07-09T02:10:01Z</published>
    <updated>2012-07-09T02:30:47Z</updated>

    <summary><![CDATA[I happen to be a TDD proponent.&nbsp; Now, right there I&rsquo;ve probably lost about half of you, and the rest are probably going, &ldquo;okay, yeah, get on with it.&rdquo; TDD is one of those things that people either love or...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
        <category term="TDD" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>I happen to be a TDD proponent.&nbsp; Now, right there I&rsquo;ve probably lost about half of you, and the rest are probably going, &ldquo;okay, yeah, get on with it.&rdquo;  TDD is one of those things that people either love or hate.&nbsp; For a full meditation on the ins and outs of technical hype, I&rsquo;ll refer you to <a href="http://barefootcoder.blogspot.com/2011/11/if-you-meet-hype-on-road-kill-it.html">my other blog</a>.&nbsp; In the meantime, if you&rsquo;re one of those people whose sneer at the thought of TDD is still stuck to your face, I&rsquo;ll ask you to indulge me for a few more paragraphs (two of which are only one sentence long).&nbsp; After that, if you still feel like TDD is the stinkiest thing to come along since Pep&eacute; Le Pew, you can either jump over to the link above, or just continue on, mentally subsituting &ldquo;TDD&rdquo; with some technical process you actually like.&nbsp; Or, you know, find something else to do entirely.</p>

<p>My first experience with TDD was via XP (that is, Extreme Programming, not the horrid Windows version), specifically the <a href="http://www.amazon.com/Extreme-Programming-Explained-Embrace-Edition/dp/0321278658">original book</a> by Kent Beck, where it&rsquo;s referred to as &ldquo;test-first programming.&rdquo;  Like many of the ideas therein, test-first programming was completely insane.&nbsp; I knew instinctively that it could never work.&nbsp; So I immediately decided to try it.&nbsp; Why?&nbsp; Probably because I often find myself in the position of telling other people about insane ideas that they&rsquo;re positive can&rsquo;t possibly work, and hypocrisy is one of my pet peeves.&nbsp; So I decided to pick a project (not a paid one; one that I was working on on the side) and use test-first programming at least until I reached my first milestone.&nbsp; And, let me tell you: I hated it.&nbsp; Utterly despised it.</p>

<p>For about two or three weeks.</p>

<p>Then, all of a sudden, the lightbulb went on.&nbsp; Just like it had when I suffered through learning vi for the first time.&nbsp; Just like it did about halfway through my first project using version control (RCS, it was, back in those days).&nbsp; Just like it did when I finally grokked spreadsheets using Lotus 1-2-3, or (as I mention in the other blog post) OOP while learning C++.&nbsp; And now I use TDD a lot, and I evangelize it to my co-workers.&nbsp; It really has changed the way I program.</p>

<p>Still, I&rsquo;m fond of saying I&rsquo;m not a TDD zealot.&nbsp; TDD is good sometimes, but it&rsquo;s not for every project, I say.&nbsp; Heck, last time I mentioned (ever so briefly) TDD in <em>this</em> blog, I even referred you over to <a href="http://www.modernperlbooks.com/mt/2011/09/always-tdd-except-when-you-shouldnt.html">chromatic&rsquo;s blog</a>, where he gives a great, balanced view on using TDD (and not using TDD).&nbsp; And definitely go read that, if you didn&rsquo;t last time I pointed you at it: it really does say everything I might want to.&nbsp; You use TDD when you should, and not when you shouldn&rsquo;t.&nbsp; And I&rsquo;m still going to stand by that.</p>

<p>But I&rsquo;m starting to rethink how how often the &ldquo;shouldn&rsquo;t&rdquo; comes up.</p>

<p>See, I had an experience recently (a couple months ago, but it&rsquo;s taken a while for the idea to percolate into a blog post) where I had to do a &ldquo;quick&rdquo; thing for work.&nbsp; This thing was to enable our QA department to test some stuff that, right now, is a huge PITA to test.&nbsp; So my code would not actually be part of our codebase; it would not &ldquo;go to production&rdquo; and be run by our customers.&nbsp; It was strictly for use by QA, and it was all fiddling with data in the database (and not even the production database), and it was just a really quick thing I was going to hack together.</p>

<p>And, one of the downsides of using TDD is, it takes longer.&nbsp; Now, why would you <em>ever</em> use a developement technique (and, don&rsquo;t forget: TDD is <strong>not</strong> a QA technique, but rather a development technique: that&rsquo;s why it&rsquo;s &ldquo;TDD&rdquo; and not &ldquo;TDQ&rdquo;) that slows you down?&nbsp; Well, there are two big reasons why the speed hit is not as awful as it sounds.</p>

<p>The first is that TDD often slows you down in a <em>good</em> way.&nbsp; Like, you know how sometimes you&rsquo;re just ripping along, coding like a bat out of hell, and you realize you&rsquo;ve been coding in completely the wrong direction? for several hours?&nbsp; Yeah, TDD eliminates a lot (but not all!) of that.&nbsp; When you have to write the tests first, it essentially forces you to design the interface first, and not just from a theoretical perspective: you have to write working (well, non-working, at first) code that actually <em>uses</em> your stuff.&nbsp; That helps settle your thinking and avoids a lot of (but not all!) blind alleys.</p>

<p>Secondly, you <strong>will</strong> produce software with fewer bugs when using TDD.&nbsp; This is not something that can be <em>definitively</em> proven, but <a href="http://www.wakaleo.com/blog/230-for-a-fistful-of-dollars-quantifying-the-benefits-of-tdd">case studies</a> so far bear it out, and, if you&rsquo;ve tried it both ways, you&rsquo;ll know it&rsquo;s true.&nbsp; Does the time saved fixing bugs exceed the time lost due to slower development?&nbsp; Probably&nbsp;... almost certainly.&nbsp; Does it make up for any lost opportunity costs in being slower to market?&nbsp; Ah, that&rsquo;s much trickier&nbsp;... I&rsquo;m not aware of any studies that even attempt to address that thorny issue.&nbsp; But it&rsquo;s often the yardstick I use when deciding to TDD or not to TDD: do I want it fast, or do I want it right?&nbsp; Neither one is the &ldquo;wrong&rdquo; answer&mdash;just depends on the situation.</p>

<p>So, this particular time, I wanted it quick, so I chose not to TDD.&nbsp; But I forgot something crucial.&nbsp; Something that I often bring up when evangelizing TDD, as it happens.&nbsp; See, the primary advantage of TDD is not that it reduces bugs, that it forces you to design your interface first, that it magically creates a test suite as you develop, or that it can short-circuit some of your more insane ideas before they cost you time.&nbsp; No, the primary advantage of TDD is actually much simpler than that.</p>

<p>It reduces fear.</p>

<p>To explain what I mean, allow me a brief tangent.&nbsp; As I mentioned <a href="http://blogs.perl.org/users/buddy_burden/2012/05/a-porters-tale.html">last time</a>, at $work we&rsquo;re working on refactoring a 10-year-old codebase with nearly 2 million lines of code.&nbsp; In order to be able to do this, our first step was to convince the business that we needed to slow down development of new features in order to put time into the refactor.&nbsp; So we had to make a business case for this.&nbsp; After all, just because code is <em>old</em> doesn&rsquo;t make it <em>bad</em>, right?&nbsp; After all, as Joel Spolsky <a href="http://www.joelonsoftware.com/articles/fog0000000069.html">once wrote</a>:</p>

<blockquote>The idea that new code is better than old is patently absurd.&nbsp; Old code has been <em>used</em>.&nbsp; It has been <em>tested</em>.&nbsp; <em>Lots</em> of bugs have been found, and they&rsquo;ve been <em>fixed</em>.&nbsp; There&rsquo;s nothing wrong with it.&nbsp; It doesn&rsquo;t acquire bugs just by sitting around on your hard drive.&nbsp; Au contraire, baby!&nbsp; Is software supposed to be like an old Dodge Dart, that rusts just sitting in the garage?&nbsp; Is software like a teddy bear that&rsquo;s kind of gross if it&rsquo;s not made out of <em>all new material?</em></blockquote>
Like so much of what Spolsky writes, this makes a lot of sense&nbsp;... and yet is totally wrong.&nbsp; There <em>is</em> a problem with older code: it&rsquo;s cobbled together with duct tape and bubble gum, a creaky Frankenstein&rsquo;s amalgam of &ldquo;there&rsquo;s no time to fix this&rdquo; and &ldquo;here&rsquo;s a better way to do that.&rdquo;  It has 3 or 4 different ways to implement objects, 2 or 3 different ways to read and write to the database, dozens of codepaths that are never reached at all, and dozens more that <em>seem</em> like they&rsquo;re never reached but really are, in certain unlikely corner cases.&nbsp; And the end result?&nbsp; Fear.&nbsp; How many times have you started to fix something in that 10-year-old ball of spaghetti, only to pull yourself up short and say, &ldquo;whoa&nbsp;... if I mess this up, that&rsquo;s really going to cost us some money&rdquo;?&nbsp; How many times have you (or the business) put the kibosh on a plan to clean up this or that code, because it&rsquo;s just too risky?&nbsp; How many times have you been yelled at because you tried to improve something and ended up inadvertently causing an obscure bug that went undetected for months?&nbsp; And what did you take away from those experiences?

<p><br />
Better to just leave it.&nbsp; Better to not risk improving.&nbsp; If it ain&rsquo;t broke, don&rsquo;t fix it, and, even if it is broke, that may be less costly than breaking it even worse.</p>

<p>Your estimates (and your actual implementation time) starts to creep up.&nbsp; &ldquo;Oh, <em>that</em> part of the code is really scary; that&rsquo;ll take much longer to fix.&rdquo;  Or, &ldquo;well, there&rsquo;s no one left who understands that code any more; it&rsquo;ll take extra time to study it.&rdquo;  And this turns out to be a vicious cycle that just feeds on itself: we don&rsquo;t have <em>time</em> to clean things up, or write good documentation, because just implementing new things takes so much longer now.</p>

<p>And TDD fixes that.&nbsp; It takes the fear out of refactoring, because you know that all your code is going to work the same way after the refactor, because all the tests will pass.&nbsp; If you wrote the tests <em>after</em> the code, passing tests wouldn&rsquo;t mean that.&nbsp; As I constantly tell people: if I write some code, then write a test, and then run the test, and the test passes, I don&rsquo;t know that my code works.&nbsp; Rather, I know that <em>either</em> my code works, or my test is broken.&nbsp; Sort of a 50-50 shot at correctness.&nbsp; But, with TDD, I know the test works (&rsquo;cause it failed when I ran it before writing the code), and I know the code works (&rsquo;cause the test passed after writing the code).&nbsp; And I can refactor with impunity, &rsquo;cause the tests guarantee the code still works.&nbsp; And, if I followed my TDD fairly strictly, and never wrote any code without writing a failing test first, I know <em>all</em> the code still works.&nbsp; The fear just&nbsp;... melts away.</p>

<p>Now, realistically, does TDD guarantee that your code doesn&rsquo;t have any bugs 100% of the time?&nbsp; No, of course not.&nbsp; There can be interactions between your code and other code that nobody foresaw or thought to test.&nbsp; There can be accidental side-effects introduced by passing code.&nbsp; There can be misunderstanding of the specs, so that the tests merely prove that you implemented the wrong thing correctly.&nbsp; There&rsquo;s still plenty of places to go wrong.&nbsp; But, the point is, your bug rate drops <em>dramatically</em>.&nbsp; And your confidence in your code&rsquo;s correctness goes to like 90%.&nbsp; Of course, 90% ain&rsquo;t perfect.&nbsp; But it&rsquo;s still a <strong>massive</strong> improvement over the 0% you&rsquo;ve got now.</p>

<p>And I forgot all this, or more likely I thought it just didn&rsquo;t matter.&nbsp; But my little task turned into 3 little tasks, and those 3 little tasks were all interrelated, and then I realized that I could build a common substructure for all 3, and that common substructure was a <em>little</em> complicated (not a lot, but not simple either), and all of a sudden I was making 4 or 5 Moose classes with dependency graphs in them and MAN I wished I could refactor all that crap.&nbsp; But I was too scared to.&nbsp; It was already taking longer than I meant for it to, and I didn&rsquo;t want to be the hold-up on the testing, and if I tried to refactor and broke something, how would I ever know?&nbsp; Hell, even adding new features was starting to terrify me, because I had no way of guaranteeing that I wasn&rsquo;t breaking all the stuff that I&rsquo;d tested and proclaimed done.</p>

<p>In the end, I finished it up, and delivered it, and so far no one&rsquo;s found any problems with it.&nbsp; But I&rsquo;m not looking forward to any of my coworkers going into the code for any reason.&nbsp; (None of you guys read this blog, right?&nbsp; Ummm&nbsp;...)  I mean, there are parts that fairly elegant, and I think it&rsquo;s moderately well commented, but still&nbsp;... there are plenty of parts where someone could go &ldquo;WTF did you do <em>this</em> for?&rdquo; and I&rsquo;ll just have to shake my head helplessly.&nbsp; &lsquo;Cause it was too scary to try to change it, is the real answer, although I probably won&rsquo;t say that.&nbsp; Makes you sound kinda sissy when you put it like that.</p>

<p>I think, next time, I&rsquo;ll consider even <em>more</em> carefully whether to dispense with TDD or not.&nbsp; &lsquo;Cause it turns out that even those &ldquo;quick&rdquo; projects can benefit from a lack of fear.</p>]]>
        
    </content>
</entry>

<entry>
    <title>A Porter&apos;s Tale</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/05/a-porters-tale.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.3305</id>

    <published>2012-05-28T08:05:45Z</published>
    <updated>2012-05-28T08:17:33Z</updated>

    <summary><![CDATA[Well, I&rsquo;m just about done with my porting project.&nbsp; For $work, we&rsquo;ve been working on porting a fairly large codebase (the official count is nearly 2 million LOCs, although I think that probably includes whitespace and comments) from Perl 5.8.9...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
        <category term="Perl versions" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>Well, I&rsquo;m just about done with my porting project.&nbsp; For $work, we&rsquo;ve been working on porting a fairly large codebase (the official count is nearly 2 million LOCs, although I think that probably includes whitespace and comments) from Perl 5.8.9 to 5.14.2.&nbsp; Actually, our goal is threefold:</p>

<ul><li>Get our code using the newest Perl.&nbsp; (Although, of course, that&rsquo;s always a moving target: by this point 5.16 is out, so it&rsquo;s not the newest any more.)</li><li>Get our code using the newest Moose.&nbsp; (We&rsquo;re currently on 1.21, and want to go to 2.x.)</li><li>Switch from using <a href="https://metacpan.org/module/MooseX::Method::Signatures">MooseX::Method::Signatures</a> to using <a href="https://metacpan.org/module/Method::Signatures::Modifiers">Method::Signatures::Modifiers</a>.&nbsp; In fact, this port was the primary impetus for me writing MSM in the first place (although, back then it was Perl 5.12 we were aiming at).&nbsp; Now, in a bizarre sort of paradoxerie, the desire to get away from MXMS is the driving force behind completing the port.</li></ul>
I&rsquo;ve been working on this port for several months now, although of course other projects have intruded here and there, and part of the time is me just waiting for our excellent QA department to find another problem.&nbsp; And they&rsquo;re still working on it, so technically we still might find something else, but the last few rounds of &ldquo;problems&rdquo; have just been merge conflicts and that sort of thing, so I&rsquo;m feeling pretty confident that we&rsquo;ve flushed out the majority of the issues now.&nbsp; I thought it might be instructive to share the issues that I&rsquo;ve seen during this process, in the hopes that it helps someone out who might be traveling this same road.

<p><br />
Let&rsquo;s go in reverse order: first, the switch from MXMS to MSM.&nbsp; This is fairly standard stuff, and for the most part is detailed in MSM&rsquo;s POD.&nbsp; </p>

<ul><li>Change anything like so: <code class="prettyprint">method foo (Str $class: )</code> to <code class="prettyprint">method foo ($class: )</code>.&nbsp; <a href="https://metacpan.org/module/Method::Signatures">Method::Signatures</a> doesn&rsquo;t believe in type checking invocants, and thus neither does MSM.</li><li>I had several unit tests that were verifying that methods didn&rsquo;t accept bad parameters by checking the contents of the exception that was thrown.&nbsp; Since MS / MSM fixes MXMS&rsquo;s hideous error messages, I had to change those tests.&nbsp; I still haven&rsquo;t decided if it was bad of me to rely on the exact exception text in the first place or not.&nbsp; The reason I did so, though, was so that a completely unrelated error wouldn&rsquo;t pass the test, which would be bad.&nbsp; So I left it that way for now.</li><li>I had to mark some slurpy parameters as optional (although I think I went back and fixed this in MS / MSM later).</li><li>I changed parameter lists like <code class="prettyprint">@args</code> to <code class="prettyprint">@_</code>.&nbsp; MS / MSM allows that latter signature to mean &ldquo;leave my arguments alone, just shift off <code class="prettyprint">$self</code> for me.&rdquo;  I could have left them as <code class="prettyprint">@args</code> and they would have worked fine, but I figured, why have the unnecessary array copy?</li></ul>
Nothing significant, really.

<p><br />
Next, the Moose upgrade.&nbsp; I can&rsquo;t find anything in the logs that indicate that I did a single thing for this.&nbsp; All our existing Moose code Just Worked.&nbsp; Of course, Moose is a relatively recent thing for us, and it still doesn&rsquo;t constitute a major percentage of the total codebase.&nbsp; So perhaps we just aren&rsquo;t doing anything Moosively interesting enough.&nbsp; I seem to (vaguely) recall having to upgrade some MooseX modules to match the new Moose versions, and maybe having to wait on a few of those to catch up, but that&rsquo;s to be expected.</p>

<p>Finally, the actual Perl version upgrade.&nbsp; I didn&rsquo;t really expect to have anything to do for this, but it turns out there were a few things here and there.&nbsp; Remember, our codebase goes back to 2001&nbsp;... at least, that&rsquo;s the earliest commit I see in the VC logs (currently Git, converted from Subversion, converted from CVS).&nbsp; So there were a few long-standing bugs that the good Perl folks have decided to expunge, and I can&rsquo;t really blame them for that.&nbsp; But I&rsquo;ll call them out here, in case they should prove to be pitfalls to you too, if you&rsquo;re ever porting anything from the general vicinity of 5.8 to the neighborhood of 5.14.</p>

<p><strong>Switch structures.</strong>  We had some code using <code class="prettyprint">use Switch 'Perl6';</code>  I had to change all those lines to <code class="prettyprint">use feature 'switch';</code>  I thought that would be all it took, but apparently the <a href="https://metacpan.org/module/Switch">Switch</a> module allows you to omit parends for <code class="prettyprint">when</code> clauses (most likely &rsquo;cause Perl 6 allows you to omit &rsquo;em), whereas the new core switch says you need them.&nbsp; Still, not a huge quantity of changes, and easy to search for.</p>

<p><strong>qw in foreach loops.</strong>  Here&rsquo;s an interesting one.&nbsp; Apparently you used to be able to do this:</p>

<pre><code class="prettyprint">foreach my $id qw(timestamp person_id property_id unit_id) {
</code></pre>
which I never even realized.&nbsp; I can&rsquo;t imagine that I ever would have tried it, personally.&nbsp; It just looks wrong to me.&nbsp; To me, that&rsquo;s an unparenthesized <code class="prettyprint">foreach</code> list, and that&rsquo;s not allowed.&nbsp; Apparently someone over in Perl development land agreed with me, because you&rsquo;re not allowed to do it any more.&nbsp; So I just changed all those instances to something like:

<pre><code class="prettyprint">foreach my $id (qw&lt; timestamp person_id property_id unit_id &gt;) {
</code></pre>
Changing the <code class="prettyprint">qw</code> delimiter to something other than parends wasn&rsquo;t strictly necessary, but a) I think it makes it a bit clearer as to what&rsquo;s going on here, and b) I just don&rsquo;t like using parends for <code class="prettyprint">qw</code>.&nbsp; We use parends all the time, for loads and loads of things already.&nbsp; I want my <code class="prettyprint">qw</code> constructs to stand out a little more.&nbsp; My choice of angle brackets is mainly because that&rsquo;s what Perl 6 will use (without the actual &ldquo;qw,&rdquo; even), so I feel like I&rsquo;m somehow getting ready for that change.&nbsp; Probably I&rsquo;m fooling myself.&nbsp; But, hey, I had to pick something, and that was as good a choice as any.

<p><br />
This was a big pain in the ass to search for, as it turns out.&nbsp; It was okay as long as the <code class="prettyprint">foreach</code> and the <code class="prettyprint">qw</code> were all on the same line, but not so much when they weren&rsquo;t.&nbsp; I missed a few the first time around (and the second time around, to be honest), but luckily we have a very diligent QA team, and they had my back.</p>

<p><strong>Named subs in Mason templates.</strong>  Okay, first of all, let me categorically state that I don&rsquo;t care for Mason.&nbsp; I&rsquo;m sorry if it&rsquo;s your favorite templating system or whatnot, but after working for 5 years in 2 million lines of code that use it, I just find that it not only <em>allows</em> tainting your presentation layer with back-end-specific code, it practically <em>encourages</em> it.&nbsp; Yes, yes, blah-di-blah, you-can-write-bad-code-in-any-language/toolset, but I&rsquo;d rather my language/toolset made it <em>hard</em> for me to write bad code, not reward me with candy and kittens every time I do.</p>

<p>So, this problem, which we only had one instance of, involved having a named sub in the Mason template.&nbsp; Apparently, this produces one of those weird closure warnings: &ldquo;variable will not stay shared,&rdquo; I think it was.&nbsp; This has to do with how Mason eval&rsquo;s the template and all that happy horsepucky.&nbsp; Anyway, solution was just to change the named sub to an anonymous sub and assign it to a variable, and then call the sub via said variable.&nbsp; Simple enough, once I understood the problem.</p>

<p>I&rsquo;m not sure if this is a new warning (or, rather, a new instance of an old warning), or if perhaps the newer version of Mason just wasn&rsquo;t willing to overlook the warning where the old one was.&nbsp; My brain hurt so much by the time I got this far that I just wanted to fix it and move on with life.&nbsp; (And, by the way: the mere <em>existence</em> of an entire subroutine in the middle of a Mason template just goes to prove my original point about Mason, as far as I&rsquo;m concerned.)</p>

<p><strong>UNIVERSAL isa.</strong>  So, apparently, code like <code class="prettyprint">use UNIVERSAL qw( isa can );</code> is deprecated now.&nbsp; Whereas it used to be the recommended way to do things.&nbsp; See how times change?&nbsp; I&rsquo;m not entirely sure what&rsquo;s going on here, but I&rsquo;m sure has to do with esoteric Perl OO guts and I probably don&rsquo;t really need to know.&nbsp; Mainly this involved changing a lot of code like this:</p>

<pre><code class="prettyprint">unless isa($validator, 'CODE');
</code></pre>
to look like this instead:

<pre><code class="prettyprint">unless reftype($validator) eq 'CODE';
</code></pre>
and of course adding <code class="prettyprint">reftype</code> to the import list for <code class="prettyprint">Scalar::Util</code>.&nbsp; There was also a bit of changing this:

<pre><code class="prettyprint">if isa($obj, $class);
</code></pre>
to look like this:

<pre><code class="prettyprint">if $obj->isa($class);
</code></pre>
and one instance of:

<pre><code class="prettyprint">unless can($handler, 'new');
</code></pre>
which had to change to:

<pre><code class="prettyprint">unless $handler->can('new');
</code></pre>
<strong>Wrap-up.</strong> And that was pretty much it.&nbsp; Overall, not a bad set of changes to have to make.&nbsp; My (professional) programming life started out in C and C++, so let me tell you this is nothing when it comes to porting.&nbsp; Still, a bit more than some Perl porting projects I&rsquo;ve worked on, so I thought I&rsquo;d share.&nbsp; Hopefully someone will find the info useful.]]>
        
    </content>
</entry>

<entry>
    <title>Lazy == Cache ?</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/04/lazy-cache.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.3172</id>

    <published>2012-04-29T23:51:24Z</published>
    <updated>2012-04-30T00:01:17Z</updated>

    <summary><![CDATA[While I was working on some Moose code this past week, I was struck (again) by how the lazy property of attributes functions almost like a cache.&nbsp; In fact, often when working in Moose I find that when I want...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>While I was working on some Moose code this past week, I was struck (again) by how the <code class="prettyprint">lazy</code> property of attributes functions almost like a cache.&nbsp; In fact, often when working in Moose I find that when I want something to be cached, I just make it lazy and call it a day.</p>

<p>Let me illustrate what I&rsquo;m talking about with some code.&nbsp; Now, the real process of putting this code together involved a lot of blind alleys and false starts, but I&rsquo;m going to present it like I came up with the final product smoothly and without interruption.&nbsp; I do this for two reasons: one, it makes for less frustrating reading, and, two, it makes me look smarter. <code class="prettyprint">;-></code></p>

<p>So I&rsquo;m creating a little command line utility to do some moderately complex data loading.&nbsp; I decide to use <a href="https://metacpan.org/module/MooseX::App::Cmd">MooseX::App::Cmd</a> for the basic structure&mdash;this is an excellent module that I&rsquo;m using more and more these days.&nbsp; Definitely check it out.</p>

<p>So, I&rsquo;m going to need to some support classes.&nbsp; Since this utility is going to need to know things about data structures, indices, foreign keys, etc, I&rsquo;ll need a class to manage the database stuff.</p>

<pre><code class="prettyprint">use Company::Moose;

<p>class Rent::Data::DB<br />
{<br />
    use MooseX::Types::Moose qw&lt; :all &gt;;</p>

<p>    has name        =&gt;  (isa =&gt; Str, is =&gt; 'ro', required =&gt; 1);<br />
    has user        =&gt;  (isa =&gt; Str, is =&gt; 'ro');<br />
    has Dbh         =&gt;  (isa =&gt; 'DBI::db', is =&gt; 'ro', lazy =&gt; 1, builder =&gt; '_connect_dbh');<br />
}<br />
</code></pre><br />
Pretty basic:</p>

<ul><li>The <code class="prettyprint">Company::Moose</code> module is a &ldquo;policy module&rdquo; that gathers up all the common Moose stuff we want for our company.&nbsp; See the second example in the synopsis of <a href="https://metacpan.org/module/Method::Signatures::Modifiers">Method::Signatures::Modifiers</a> for what it basically looks like.</li><li>The class name starts with <code class="prettyprint">Rent</code> because that&rsquo;s what <a href="http://www.rent.com">$work</a> is.&nbsp; Then <code class="prettyprint">Data::DB</code> because is it&rsquo;s a class that deals with our database, but specifically our particular data structures within that DB.&nbsp; (In retrospect, I probably should have tried to work &ldquo;schema&rdquo; in there somewhere.&nbsp; Ah, well.)</li><li>It has 3 basic attributes: database name, user to log in as (not required because there is a default user), and the actual <a href="https://metacpan.org/module/DBI">DBI</a> database handle.</li><li>Not shown would be the constructor, <code class="prettyprint">connect</code>, and the builder for the <code class="prettyprint">Dbh</code> attribute, <code class="prettyprint">_connect_dbh</code>, which utilize a bunch of company-specific connection stuff.</li></ul>
Okay, that&rsquo;s simple enough, as it goes.&nbsp; So now I can start writing a bunch of code to enable me to query my <code class="prettyprint">Rent::Data::DB</code> for the primary key columns of a table, dependencies and reverse depdencies, and so forth.

<p><br />
Except&nbsp;... maybe my &ldquo;DB&rdquo; class should really be a container.&nbsp; Just like a real database, it should contain a bunch of tables.&nbsp; Okay, fine, now I need a table class:</p>

<pre><code class="prettyprint">use Company::Moose;

<p>class Rent::Data::DB::Table<br />
{<br />
    use MooseX::Types::Moose qw&lt; :all &gt;;</p>

<p>    has name        =&gt;  (isa =&gt; Str, is =&gt; 'ro', required =&gt; 1);<br />
    has db          =&gt;  (isa =&gt; 'Rent::Data::DB', is =&gt; 'ro', required =&gt; 1, weak_ref =&gt; 1, handles =&gt; ['run_query']);</p>

<p>}</p>

<p>class Rent::Data::DB<br />
{<br />
    use MooseX::Types::Moose qw&lt; :all &gt;;</p>

<p>    has name        =&gt;  (isa =&gt; Str, is =&gt; 'ro', required =&gt; 1);<br />
    has user        =&gt;  (isa =&gt; Str, is =&gt; 'ro');<br />
    has Dbh         =&gt;  (isa =&gt; 'DBI::db', is =&gt; 'ro', lazy =&gt; 1, builder =&gt; '_connect_dbh');<br />
    has _tables     =&gt;  (isa =&gt; HashRef, is =&gt; 'ro', lazy =&gt; 1, default =&gt; sub { {} });</p>

<p>    # sort of a pseudo-attribute<br />
    method table (Str $tablename)<br />
    {<br />
        unless (exists $self->_tables->{$tablename})<br />
        {<br />
            $self->_tables->{$tablename} = Rent::Data::DB::Table->new(name =&gt; $tablename, db =&gt; $self);<br />
        }<br />
        return $self->_tables->{$tablename};<br />
    }<br />
}<br />
</code></pre><br />
Wow, that was pretty simple.&nbsp; My &ldquo;table&rdquo; class has a name, and a reference to its parent DB.&nbsp; Since the parent will <em>also</em> have a reference to the table, I make the <code class="prettyprint">db</code> attribute a weak reference.&nbsp; Then I make a <code class="prettyprint">HashRef</code> attribute of <code class="prettyprint">Rent::Data::DB</code> which will hold all the table objects.&nbsp; It&rsquo;s lazy, of course, starts off as an empty hashref (tablename =&gt; table_obj), and then I create a <code class="prettyprint">table</code> method which will create table objects on demand, and return the cached results.</p>

<p><br />
This is pretty cool, right?&nbsp; But it gets even cooler.&nbsp; How about a way to get primary key columns?</p>

<pre><code class="prettyprint">use Company::Moose;

<p>class Rent::Data::DB::Table<br />
{<br />
    use MooseX::Types::Moose qw&lt; :all &gt;;</p>

<p>    has name        =&gt;  (isa =&gt; Str, is =&gt; 'ro', required =&gt; 1);<br />
    has db          =&gt;  (isa =&gt; 'Rent::Data::DB', is =&gt; 'ro', required =&gt; 1, weak_ref =&gt; 1, handles =&gt; ['run_query']);<br />
    has pk_cols     =&gt;  (isa =&gt; ArrayRef, is =&gt; 'ro', lazy =&gt; 1, builder =&gt; '_get_pk_cols');</p>

<p>    method _get_pk_cols<br />
    {<br />
        my $query = q{<br />
            select cc.column_name<br />
            from all_constraints c, all_cons_columns cc<br />
            where c.table_name = ?<br />
            and c.constraint_type = 'P'<br />
            and c.owner = cc.owner<br />
            and c.constraint_name = cc.constraint_name<br />
        };</p>

<p>        return [ map { lc } $self->run_query($query, uc $self->name) ];<br />
    }<br />
}</p>

<p>class Rent::Data::DB<br />
{<br />
    use MooseX::Types::Moose qw&lt; :all &gt;;</p>

<p>    has name        =&gt;  (isa =&gt; Str, is =&gt; 'ro', required =&gt; 1);<br />
    has user        =&gt;  (isa =&gt; Str, is =&gt; 'ro');<br />
    has Dbh         =&gt;  (isa =&gt; 'DBI::db', is =&gt; 'ro', lazy =&gt; 1, builder =&gt; '_connect_dbh');<br />
    has _tables     =&gt;  (isa =&gt; HashRef, is =&gt; 'ro', lazy =&gt; 1, default =&gt; sub { {} });</p>

<p>    # sort of a pseudo-attribute<br />
    method table (Str $tablename)<br />
    {<br />
        unless (exists $self->_tables->{$tablename})<br />
        {<br />
            $self->_tables->{$tablename} = Rent::Data::DB::Table->new(name =&gt; $tablename, db =&gt; $self);<br />
        }<br />
        return $self->_tables->{$tablename};<br />
    }</p>

<p>    # we can handle all methods that a Rent::Data::DB::Table can handle<br />
    # args will be the same except the table name is the first arg<br />
    foreach my $method (Rent::Data::DB::Table->meta->get_method_list)<br />
    {<br />
        next if $method eq uc $method;                                  # special methods like BUILD and DESTROY<br />
        next if $method =~ /^_/;                                        # private methods<br />
        next if $method eq 'new' or $method eq 'meta';                  # the two special methods that are lc<br />
        next if grep { $_ eq $method } qw&lt; name db run_query &gt;;         # not special, but not required here either</p>

<p>        __PACKAGE__->meta->add_method($method, sub<br />
        {<br />
            my $self = shift;<br />
            my $tablename = shift;</p>

<p>            my $table = $self->table($tablename);<br />
            return $table->$method(@_);<br />
        });<br />
    }<br />
}<br />
</code></pre><br />
Easy peasy.&nbsp; I just add a lazy attribute called <code class="prettyprint">pk_cols</code> and give it an appropriate builder (revealing my secret shame: yes, I&rsquo;m using Oracle (no, it&rsquo;s not by choice)).&nbsp; Now, every time I call <code class="prettyprint">pk_cols</code> on a table object, I get the appropriate columns, and because it&rsquo;s an attribute (instead of a method) it&rsquo;s stored (essentially cached).&nbsp; The bit of trickery in the <code class="prettyprint">DB</code> class just allows me a little shortcut:</p>

<pre><code class="prettyprint"># instead of this:
my $cols = $db->table($table)->pk_cols;
# I can just do this:
my $cols = $db->pk_cols($table);
</code></pre>
and, furthermore, when I add this:

<pre><code class="prettyprint">use Company::Moose;

<p>class Rent::Data::DB::Table<br />
{<br />
    use MooseX::Types::Moose qw&lt; :all &gt;;</p>

<p>    has name        =&gt;  (isa =&gt; Str, is =&gt; 'ro', required =&gt; 1);<br />
    has db          =&gt;  (isa =&gt; 'Rent::Data::DB', is =&gt; 'ro', required =&gt; 1, weak_ref =&gt; 1, handles =&gt; ['run_query']);<br />
    has pk_cols     =&gt;  (isa =&gt; ArrayRef, is =&gt; 'ro', lazy =&gt; 1, builder =&gt; '_get_pk_cols');<br />
    has indexes     =&gt;  (isa =&gt; HashRef, is =&gt; 'ro', lazy =&gt; 1, builder =&gt; '_get_indexes', traits =&gt; ['Hash'],<br />
                            handles =&gt;<br />
                            {   <br />
                                is_indexed  =&gt;  'exists',<br />
                            },<br />
                        );</p>

<p>    method _get_pk_cols<br />
    {<br />
        my $query = q{<br />
            select cc.column_name<br />
            from all_constraints c, all_cons_columns cc<br />
            where c.table_name = ?<br />
            and c.constraint_type = 'P'<br />
            and c.owner = cc.owner<br />
            and c.constraint_name = cc.constraint_name<br />
        };</p>

<p>        return [ map { lc } $self->run_query($query, uc $self->name) ];<br />
    }<br />
    <br />
    method _get_indexes<br />
    {   <br />
        my $query = q{<br />
            select distinct aic.column_name<br />
            from all_indexes ai, all_ind_columns aic<br />
            where ai.table_name = ?<br />
            and ai.index_name = aic.index_name<br />
            and aic.column_name not like '%$'<br />
            and aic.column_position = 1<br />
        };</p>

<p>        return { map { lc $_ =&gt; 1 } $self->run_query($query, uc $self->name) };<br />
    }<br />
}</p>

<p>class Rent::Data::DB<br />
{<br />
    use MooseX::Types::Moose qw&lt; :all &gt;;</p>

<p>    has name        =&gt;  (isa =&gt; Str, is =&gt; 'ro', required =&gt; 1);<br />
    has user        =&gt;  (isa =&gt; Str, is =&gt; 'ro');<br />
    has Dbh         =&gt;  (isa =&gt; 'DBI::db', is =&gt; 'ro', lazy =&gt; 1, builder =&gt; '_connect_dbh');<br />
    has _tables     =&gt;  (isa =&gt; HashRef, is =&gt; 'ro', lazy =&gt; 1, default =&gt; sub { {} });</p>

<p>    # sort of a pseudo-attribute<br />
    method table (Str $tablename)<br />
    {<br />
        unless (exists $self->_tables->{$tablename})<br />
        {<br />
            $self->_tables->{$tablename} = Rent::Data::DB::Table->new(name =&gt; $tablename, db =&gt; $self);<br />
        }<br />
        return $self->_tables->{$tablename};<br />
    }</p>

<p>    # we can handle all methods that a Rent::Data::DB::Table can handle<br />
    # args will be the same except the table name is the first arg<br />
    foreach my $method (Rent::Data::DB::Table->meta->get_method_list)<br />
    {<br />
        next if $method eq uc $method;                                  # special methods like BUILD and DESTROY<br />
        next if $method =~ /^_/;                                        # private methods<br />
        next if $method eq 'new' or $method eq 'meta';                  # the two special methods that are lc<br />
        next if grep { $_ eq $method } qw&lt; name db run_query &gt;;         # not special, but not required here either</p>

<p>        __PACKAGE__->meta->add_method($method, sub<br />
        {<br />
            my $self = shift;<br />
            my $tablename = shift;</p>

<p>            my $table = $self->table($tablename);<br />
            return $table->$method(@_);<br />
        });<br />
    }<br />
}<br />
</code></pre><br />
now this just works too:</p>

<pre><code class="prettyprint">my $indices = $db->indexes($table);
</code></pre>
(Yes, I named the method &ldquo;indexes&rdquo; even though I <em>say</em> &ldquo;indices.&rdquo;  What can I say?&nbsp; Being an English major programmer has its ups and downs.)

<p><br />
See?&nbsp; Instant caching.&nbsp; Now, <em>every</em> attribute I add to the table object from here on out gives me an on-demand, insta-cached property of tables for my <code class="prettyprint">Data::DB</code>.&nbsp; It&rsquo;s pretty damn cool, if I do say so myself.</p>

<p>Note that the real code includes a bit more stuff: more comments, more infrastructure, and my possibly-too-clever <code class="prettyprint">run_query</code> method, which includes error checking and debugging, and makes snap decisions about whether you want a scalar, an array, or an array (or arrayref) of hashrefs, based on caller context and number of columns being requested.&nbsp; But this should give you the flavor of what I&rsquo;m talking about for this post.</p>

<p>Hopefully this will inspire you to utilize Moose&rsquo;s <code class="prettyprint">lazy</code> property for some caching of your own.&nbsp; All we need now are Moose properties for <code class="prettyprint">impatient</code> and <code class="prettyprint">hubristic</code> and we&rsquo;ll be all set.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Perl vs Shell Scripts</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/04/perl-vs-shell-scripts.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.3109</id>

    <published>2012-04-15T23:31:41Z</published>
    <updated>2013-04-07T18:07:53Z</updated>

    <summary><![CDATA[Last week, I posted on my Other Blog about how I still prefer to use tcsh for my interactive shell.&nbsp; Of course, I maintained that bash was the only real choice for shell scripts. But then this brings us to...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>Last week, I <a href="http://barefootcoder.blogspot.com/2012/04/shell-game.html">posted on my Other Blog</a> about how I still prefer to use <code class="prettyprint">tcsh</code> for my interactive shell.&nbsp; Of course, I maintained that <code class="prettyprint">bash</code> was the only real choice for shell scripts.</p>

<p>But then this brings us to another interesting point.&nbsp; I, of course, am a Perl programmer.&nbsp; A choice between Perl and shell scripts is not like a choice between C++ programs and shell scripts.&nbsp; Back when I was a C++ programmer, there was no question but that some tasks should be done in <code class="prettyprint">bash</code> (or, actually, I was using <code class="prettyprint">ksh</code> back in those days).&nbsp; But Perl is quite different: it&rsquo;s not only the case that Perl <em>can</em> do anything that <code class="prettyprint">bash</code> can do (that&rsquo;s true of C++ as well), but Perl can also do it just as easily.&nbsp; Perl is often considered a scripting language, and, while we could argue about whether that&rsquo;s true or not due to the fact that Perl is compiled while <code class="prettyprint">bash</code> is not, we can&rsquo;t (and shouldn&rsquo;t) argue that <em>deploying</em> a Perl program is as easy as deploying a shell script, and that&rsquo;s part of what being a &ldquo;scripting language&rdquo; entails.</p>

<p>But, in the end, I still, <em>sometimes</em>, choose to use <code class="prettyprint">bash</code> over Perl, for certain tasks.&nbsp; I suppose you could argue there&rsquo;s a certain amount of inertia involved: I got used to doing certain types of things with shell scripts back when my only other (viable) option was C++, or maybe <code class="prettyprint">awk</code>.&nbsp; But the comparison to <code class="prettyprint">awk</code> is quite appropriate.&nbsp; Before I learned Perl, I used <code class="prettyprint">awk</code> a lot.&nbsp; Nowadays&nbsp;... hardly ever.&nbsp; I certainly would never use <code class="prettyprint">awk</code> inside a shell script: it would always be Perl there.&nbsp; At the command line, I still occasionally type <code class="prettyprint">awk</code> when I mean <code class="prettyprint">perl</code>, but it happens less and less often, and more and more I find myself just giving up on <code class="prettyprint">awk</code> before I even get to the end of the line.&nbsp; Perl just really completely replaces <code class="prettyprint">awk</code>.</p>

<p>But not <code class="prettyprint">bash</code>.</p>

<p>Recently I was doing a personal scripting task (it involved fiddling around with MP3s, if you&rsquo;re curious).&nbsp; I started out doing it in <code class="prettyprint">bash</code>, and then ended up ripping it apart about halfway through and starting over in Perl.&nbsp; I had just made a bad decision on that particular task.&nbsp; But, while I was cursing myself out for not just using Perl in the first place, it occurred to me that maybe I ought to try to articulate the places where <code class="prettyprint">bash</code> really is (or might be) better.&nbsp; If I had a checklist, maybe I could more easily identify where to put my efforts in from the get-go.&nbsp; If I had a checklist, and I posted it here on this blog, <em>maybe</em> even you other Perlites would come along and tell me why I&rsquo;m wrong, and maybe I&rsquo;ll learn something. ;-&gt;</p>

<p>For the impatient, the executive precis is this: I generally write <code class="prettyprint">bash</code> scripts for tasks which are essentially job control scripts.&nbsp; Yes, Perl can call external programs just as well as any shell script can, but there are a few things <code class="prettyprint">bash</code> gives us which Perl doesn&rsquo;t.&nbsp; This is not surprising, really: <code class="prettyprint">bash</code> (as <code class="prettyprint">ksh</code> before it, and the venerable <code class="prettyprint">sh</code> before that) was basically <em>invented</em> for doing job control.&nbsp; What <code class="prettyprint">sh</code> lacked in that department, <code class="prettyprint">csh</code> filled in, and then <code class="prettyprint">ksh</code> and <code class="prettyprint">bash</code> backported.&nbsp; Perl has other foci.&nbsp; Personally, I&rsquo;m okay with Perl not being the answer for every job.</p>

<p>So, let&rsquo;s take a look at the (few) places where <code class="prettyprint">bash</code> beats Perl:</p>

<p><strong>Job Failure</strong></p>

<p>If I want to run a command in <code class="prettyprint">bash</code>, I simply do it, like so:</p>

<pre><code class="prettyprint">run some command
</code></pre>
In Perl, I&rsquo;d have to do it more like so:

<pre><code class="prettyprint">system("run some command");
</code></pre>
It&rsquo;s a bit more typing, sure, but that&rsquo;s not the real problem.&nbsp; The real problem is that, if the <code class="prettyprint">bash</code> version has a problem&mdash;command not found, not enough memory, process table full&mdash;it stops and throws an error.&nbsp; The Perl version just blithely keeps going.&nbsp; Now, these days the situation is better than it used to be, because I can do this:

<pre><code class="prettyprint">use autodie qw&lt; :all &gt;;
system("run some command");
</code></pre>
And that works as well as the <code class="prettyprint">bash</code> version.&nbsp; Except, what if I care whether the command succeeded or not?&nbsp; Here&rsquo;s the <code class="prettyprint">bash</code> version:

<pre><code class="prettyprint">if ! run some command
then
    some recovery command
fi
</code></pre>
In Perl, perhaps the best we can do is this:

<pre><code class="prettyprint">use autodie qw&lt; :all &gt;;
use Try::Tiny;                  # TryCatch is nicer, but more overhead

<p>try<br />
{<br />
    system("run some command");<br />
}<br />
catch<br />
{<br />
    system("some recovery command");<br />
};                              # do NOT forget this semi-colon!<br />
</code></pre><br />
That&rsquo;s a <strong>lot</strong> more typing, and probably not as clear either.&nbsp; And clarity is maintainability, as we know.</p>

<p><br />
<strong>Commands on Exit</strong></p>

<p>In Perl, if you want to run something when your program exits, no matter where it&rsquo;s exiting from, you can do this:</p>

<pre><code class="prettyprint">END
{
    system("run some command");
}
</code></pre>
The equivalent in <code class="prettyprint">bash</code> looks like this:

<pre><code class="prettyprint">trap "run some command" EXIT
</code></pre>
Except the <code class="prettyprint">bash</code> command actually does what you want.&nbsp; That command in the <code class="prettyprint">bash</code> script gets run <em>no matter what</em>.&nbsp; Normal exit, error exit, explosion, Ctrl-C, core dump&nbsp;... unless someone does a <code class="prettyprint">kill -9</code> on you, you&rsquo;re pretty much guaranteed to get your command run.&nbsp; Not so in Perl.&nbsp; In fact, the <code class="prettyprint">perlmod</code> man page has this to say on the topic:

<blockquote>(But not if it&rsquo;s morphing into another program via &ldquo;exec&rdquo;, or being blown out of the water by a signal&mdash;you have to trap that yourself (if you can).)</blockquote>
Lame.

<p><br />
Now, admittedly, the vast majority of times I use <code class="prettyprint">trap</code> in this fashion, it looks like this:</p>

<pre><code class="prettyprint">trap "/bin/rm -f $tmpfile" EXIT
</code></pre>
and, if that were Perl, I&rsquo;d be using <code class="prettyprint">File::Temp</code>, and then I wouldn&rsquo;t have to <em>worry</em> about removing my tempfile.&nbsp; But, then, I don&rsquo;t think <code class="prettyprint">File::Temp</code> handles signals either.&nbsp; Overall, <code class="prettyprint">trap</code> is a much easier way to deal with signals than Perl&rsquo;s <code class="prettyprint">%SIG</code> hash, although I have to admit that I&rsquo;ve never written a <code class="prettyprint">trap</code> statement that didn&rsquo;t end with <code class="prettyprint">EXIT</code>.

<p><br />
<strong>Processing Job Output Lines</strong></p>

<p>If I know my output lines won&rsquo;t have any spaces in them, I&rsquo;m golden:</p>

<pre><code class="prettyprint">for line in $(run some command)
do
    process each "$line"
done
</code></pre>
That&rsquo;s a good bit simpler than the equivalent Perl:

<pre><code class="prettyprint">use autodie qw&lt; :all &gt;;

<p>open(PIPE, "run some command|");<br />
while ( &lt;PIPE&gt; )<br />
{<br />
    chomp;<br />
    system(qw&lt; process each &gt;, $_);<br />
}<br />
close(PIPE);<br />
</code></pre><br />
The only problem I have in <code class="prettyprint">bash</code> is if my lines might have spaces.&nbsp; That complicates the shell script version to where it&rsquo;s not particularly better than the Perl:</p>

<pre><code class="prettyprint">OIFS="$IFS"
IFS="
"
for line in $(run some command)
do
    process each "$line"
done
IFS="$OIFS"
</code></pre>
Still, the simple case is often sufficient.

<p><br />
<strong>Here Documents</strong></p>

<p>Sure, Perl has &ldquo;here documents.&rdquo;  But they&rsquo;re different.&nbsp; In Perl, a here doc defines a string.&nbsp; In shell scripts, it defines <code class="prettyprint">STDIN</code>.&nbsp; So, in <code class="prettyprint">bash</code>, I could say:</p>

<pre><code class="prettyprint">mysql &lt;&lt;END                       # assume ~/.my.cnf is set up
    select count(*) from some_table;
END
</code></pre>
whereas in Perl, it would be:

<pre><code class="prettyprint">use autodie qw&lt; :all &gt;;

<p>open(PIPE, "| mysql");<br />
print PIPE &lt;&lt;END;<br />
    select count(*) from some_table;<br />
END<br />
close(PIPE);<br />
</code></pre><br />
Of course, for this particular example, I could just use DBI instead, but I generally find that to be more of a PITA than I want to deal with for a quick script.</p>

<p><br />
<strong>File Equivalencies</strong></p>

<p>I have no idea why Perl doesn&rsquo;t have something like this.&nbsp; Here&rsquo;s some <code class="prettyprint">bash</code> I&rsquo;ve needed on several occasions:</p>

<pre><code class="prettyprint">if [[ ! $(dirname $0) -ef $(pwd) ]]
then
    echo "must run this from its home dir" &gt;&2
    exit 1
fi
</code></pre>
Until recently, this was stupidly difficult to replicate.&nbsp; The <code class="prettyprint">Cwd</code> module includes a <code class="prettyprint">realpath</code> function, but its original implementation only worked on directories (leading to a number of subs in my Perl code named <code class="prettyprint">really_realpath</code>).&nbsp; Finally that was fixed, making it easier.&nbsp; Nowadays, I&rsquo;d probably use <code class="prettyprint">Path::Class</code> to do this in Perl:

<pre><code class="prettyprint">use Path::Class;

<p>if (file($0)->dir->absolute->resolve ne dir()->absolute->resolve)<br />
{<br />
    die("must run this from its home dir");<br />
}<br />
</code></pre><br />
which&nbsp;... well, actually, now that I look at it, isn&rsquo;t <em>so</em> bad, although awfully verbose.&nbsp; But the <code class="prettyprint">bash</code> version reads a lot more cleanly.</p>

<p><br />
<strong>File Timestamp Comparisons</strong></p>

<p>This one doesn&rsquo;t come up <em>that</em> often, but, still.&nbsp; In <code class="prettyprint">bash</code> I can do:</p>

<pre><code class="prettyprint">if [[ $last_run -ot $touchfile ]]
then
    do it again
    touch $last_run
fi
</code></pre>
In Perl, I&rsquo;d have to do the stat calls myself, and pluck out the mtime from the array, which I always have to look up which element it is&nbsp;... moderately irksome.&nbsp; The <code class="prettyprint">bash</code> version is just cleaner.

<p><br />
<strong>Tilde Expansion</strong></p>

<p>I know, I know&nbsp;... it&rsquo;s just a convenience.&nbsp; But it&rsquo;s so very&nbsp;... well, convenient.&nbsp; In <code class="prettyprint">bash</code>:</p>

<pre><code class="prettyprint">rcfile=~/.me.rc
</code></pre>
In Perl, there&rsquo;s <code class="prettyprint">File::HomeDir</code>, which once-upon-a-time had the vaguely nifty <code class="prettyprint">$~</code>, but they went and deprecated it.&nbsp; Yeah, I&rsquo;m sure it was a perfectly awful idea for multiple reasons.&nbsp; But it was a lot more convenient than:

<pre><code class="prettyprint">use File::HomeDir;

<p>my $rcfile = File::HomeDir->my_home . "/.me.rc";<br />
</code></pre><br />
And that&rsquo;s without even going all <code class="prettyprint">Path::Class</code> on it, for portability (not that I&rsquo;m likely to care much about having most of my personal job control scripts run on Windows or whatnot).&nbsp; Yet another minor place where Perl just gives me more to type without significantly increasing any functionality I might actually use.</p>

<p><br />
<strong>Now don&rsquo;t get me wrong:</strong> Perl still beats the crap out of <code class="prettyprint">bash</code> for most applications.&nbsp; Reasons I might prefer Perl include (but are not limited to):</p>

<ul><li>It&rsquo;s going to be faster.&nbsp; Mainly because I don&rsquo;t actually have to start new processes for many of the things I want to do (<code class="prettyprint">basename</code> and <code class="prettyprint">dirname</code> being the most obvious examples, but generally <code class="prettyprint">cut</code>, <code class="prettyprint">grep</code>, <code class="prettyprint">sort</code>, and <code class="prettyprint">wc</code> can all be eliminated as well).</li><li>String handling in <code class="prettyprint">bash</code> is rudimentary at best, and the whole <code class="prettyprint">$IFS</code> thing is super-clunky.</li><li>Conditionals in shell scripts can be wonky.</li><li>Quoting in shell scripts can be a nightmare.</li><li><code class="prettyprint">bash</code>&rsquo;s <code class="prettyprint">case</code> statement leaves a lot to be desired beyond simple cases (NPI).</li><li>Arrays in <code class="prettyprint">bash</code> suck.&nbsp; Hashes in <code class="prettyprint">bash</code> (assuming your <code class="prettyprint">bash</code> is new enough to have them at all) suck even harder.</li><li>Once processing files or command output goes beyond the simple case I listed above, Perl starts really smoking <code class="prettyprint">bash</code>.</li><li>CPAN.</li></ul>

<p>So it&rsquo;s not like <code class="prettyprint">bash</code> is going to take over for Perl any time soon.&nbsp; But I still find, after all these years, that many times a simple shell script can <em>sometimes</em> be simpler than a simple Perl script.&nbsp; As I say, I welcome all attempts to convince me otherwise.&nbsp; But, then again, there&rsquo;s nothing wrong with having a few different tools in your toolbox.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Some new releases</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/02/some-new-releases.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.2847</id>

    <published>2012-02-20T20:25:33Z</published>
    <updated>2012-02-20T20:32:02Z</updated>

    <summary><![CDATA[I released Test::File 1.33 yesterday, which fixed a minor MANIFEST glitch with 1.32, which I released three days ago.&nbsp; (I know it&rsquo;s been discussed before, but I guess I never really appreciated it: it sure would be nice if CPAN...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>I released <a href="https://metacpan.org/release/Test-File">Test::File</a> 1.33 yesterday, which fixed a minor <code class="prettyprint">MANIFEST</code> glitch with 1.32, which I released three days ago.&nbsp; (I know it&rsquo;s been discussed before, but I guess I never really appreciated it: it sure would be nice if CPAN Testers could report stuff like that).&nbsp; Version 1.32 fixes a number of CPAN RT tickets (in fact, it pretty much closes out all the open bugs), most of which you won&rsquo;t care about.&nbsp; If you happen to be using Windows, this may fix a number of test failures, although there are still a few left that I&rsquo;m working with schwern to fix.&nbsp; (If you <em>are</em> running Windows and you happen to see some mysterious errors which boil down to the fact that &ldquo;skip&rdquo; isn&rsquo;t the same as &ldquo;SKIP&rdquo;, it&rsquo;s definitely safe to ignore those.)</p>

<p>What may be less exciting to you, but is definitely more exciting to me, is that I finally, after weeks of trying, got <a href="https://metacpan.org/module/Debuggit">Debuggit</a> 2.02 released.&nbsp; CPAN Testers kept me on my toes on this one, and I would guess that about half of my dev releases since 2.01 were simply fixes for stupid mistakes that CPAN Testers exposed.&nbsp; Thanks again to Barbie for all his efforts; if you didn&rsquo;t see his recent <a href="http://blogs.perl.org/users/cpan_testers/2012/02/cpan-testers-summary&mdash;-january-2012&mdash;-bringing-it-all-back-home.html">blog post</a>, you should check it out.&nbsp; (He gave a shout out to one of my blog posts, so I figure I can at least return the favor.)</p>

<p>Anyway, the substantive changes in Debuggit 2.02 are, first off, a major reorganization of the POD.&nbsp; I am, in many respects, a compulsive documenter, and Debuggit is my first CPAN module, so it was overflowing with doco&nbsp;... to the point where 80% of <code class="prettyprint">Debuggit.pm</code> was POD.&nbsp; Which is awesome if you need to know every single detail about Debuggit, but perhaps a bit overwhelming if you&rsquo;re trying to check it out for the first time.&nbsp; Taking a cue from Moose, I&rsquo;ve split the POD up into <code class="prettyprint">Debuggit</code>, <code class="prettyprint">Debuggit::Manual</code>, and <code class="prettyprint">Debuggit::Cookbook</code>.&nbsp; Of course, Moose is a multi-module behemoth that constitutes a complete object system for Perl 5, whereas Debuggit is a kinda cool way to put debugging statements in your code, so it could well be argued that it&rsquo;s a bit presumptuous of me to be taking cues from Moose.&nbsp; But at least this way you can just ignore the extra documentation if you so desire.</p>

<p>Secondly, although I&rsquo;ve been using various versions of Debuggit for over ten years now, I had never tried to use it in a CPAN-style module before, weirdly, so I never realized that, if you did that, and if you had a POD coverage test (such as many people recommend, and <a href="https://metacpan.org/module/Dist::Zilla">Dist::Zilla</a> can provide automatically), it reports <code class="prettyprint">DEBUG</code> and <code class="prettyprint">debuggit</code> as &ldquo;naked&rdquo; subroutines.&nbsp; Well, it did.&nbsp; Now it doesn&rsquo;t.</p>

<p>Finally, I fixed some &ldquo;redefined&rdquo; warnings in some corner cases, fixed a problem with overriding <code class="prettyprint">DEBUG</code> in a single module, and then fixed the resulting problem of <code class="prettyprint">namespace::autoclean</code> breaking stuff when it autocleaned <code class="prettyprint">DEBUG</code>.&nbsp; And I added a second way to verify that <code class="prettyprint">use</code>ing Debuggit adds no extra memory to your program (when debugging is off).</p>

<p>Hopefully something in all that is useful for someone somewhere.</p>]]>
        
    </content>
</entry>

<entry>
    <title>A Tale of CPAN Testers</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/01/a-tale-of-cpan-testers.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.2745</id>

    <published>2012-01-29T20:55:55Z</published>
    <updated>2012-01-29T21:28:34Z</updated>

    <summary><![CDATA[So the most important takeaway from this blog post is that Test::File version 1.31 is now available on CPAN, with some new functions for your testing pleasure: dir_exists_ok, dir_contains_ok, file_contains_like, and file_contains_unlike.&nbsp; Check it out. But I thought it might...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
        <category term="CPAN Testers" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>So the most important takeaway from this blog post is that <a href="https://metacpan.org/module/Test::File">Test::File</a> version 1.31 is now available on CPAN, with some new functions for your testing pleasure: <code class="prettyprint">dir_exists_ok</code>, <code class="prettyprint">dir_contains_ok</code>, <code class="prettyprint">file_contains_like</code>, and <code class="prettyprint">file_contains_unlike</code>.&nbsp; Check it out.</p>

<p>But I thought it might also be enlightening if I went into a little more detail about the story behind this release.&nbsp; Now, I <a href="http://blogs.perl.org/users/buddy_burden/2012/01/stepping-up.html">already talked about</a> how I became co-maintainer for this module.&nbsp; At the time, I asked brian d foy if there was anything special he wanted me to do for releasing, any particular procedures he wanted followed.&nbsp; As I said, it&rsquo;s his car&mdash;I&rsquo;m just driving it for a bit&mdash;so I want to do things the way he expects them done.&nbsp; The only thing he really mentioned was that he typically puts out a developer release and makes sure it passes CPAN Testers before doing an official release.&nbsp; Of course, I replied, I do that too.</p>

<p>Actually, I thought <em>everyone</em> did that.&nbsp; But his statement got me thinking&nbsp;... it reminds me of our vists to <a href="http://www.chuckecheese.com/">Chuck E. Cheese&rsquo;s</a>.&nbsp; I know that seems like a stretch, but hear me out.&nbsp; Every time we go to our local CEC, my elder son points out the <a href="http://www.flickr.com/photos/kukorakin/5909767497/">prominent sign</a> by the front door.&nbsp; Yes, that&rsquo;s right: firearms are not allowed in the kiddie arcade/pizza parlor.&nbsp; What is the world coming to?&nbsp; But my son&rsquo;s point in drawing attention to this sign is that, <em>some</em>where, at <em>some</em> point, <em>some</em>one must have tried to bring a gun into Chuck E. Cheese&rsquo;s.&nbsp; Otherwise, they&rsquo;d have no need for the sign, right?</p>

<p>And, likewise, the fact that brian d foy felt the need to tell me I should be running my releases through CPAN Testers before making them official means that there are still folks out there who don&rsquo;t.&nbsp; So, if you&rsquo;re one of those folks, let me tell you how to make a CPAN release:</p>

<ol><li>Write/fix your code.</li><li>Mark it as a <a href="http://www.cpan.org/modules/04pause.html#conventions">developer release</a>.</li><li>Upload it to PAUSE.</li><li>Wait a few days.</li><li>Go look at <a href="http://www.cpantesters.org/">CPAN Testers</a> and find out how bad you fucked up.</li><li>Repeat until you didn&rsquo;t fuck up.</li><li>Change nothing but the version number, making it a production (i.e. non-developer) release, and reupload to PAUSE.</li></ol>
There you go.&nbsp; Words to live by.

<p>Now, typically when you screw something up, it&rsquo;s blatant.&nbsp; Narly every CPAN Tester will fail you, and it&rsquo;s usually obvious what you did wrong.&nbsp; Forgot to include a prerequisite.&nbsp; Forgot to specify a particular version of a prerequisite.&nbsp; Forgot to regenerate your MANIFEST file, or your META.yaml/META.json.&nbsp; Et cetera.</p>

<p>But, every once in a while, you get a just a few weird errors that you can&rsquo;t figure out.&nbsp; If you&rsquo;re lucky, they&rsquo;re all from the same (typically older) Perl version, or maybe the same operating system, and you can either try to figure out how to fix that, or at the very least just update your POD to say you don&rsquo;t support that version/OS.&nbsp; If you&rsquo;re <em>not</em> lucky&nbsp;...</p>

<p>So, I wasn&rsquo;t lucky.&nbsp; I put out 1.28_02 of <code class="prettyprint">Test::File</code> (after discovering the hard way there was already a 1.28_01) and I ended up with like 15 failures.&nbsp; Out of like 200 or so&nbsp;... I can&rsquo;t figure out how to make CPAN Testers count the total reports for me (except on my author page, where it only lists totals for the most recent distros).&nbsp; So we&rsquo;re talking somewhere in the ballpark of 7% failures here.&nbsp; That&rsquo;s not much&nbsp;... right?</p>

<p>Now, I wonder how other people would deal with this situation.&nbsp; I bet we&rsquo;re all different.&nbsp; I bet it&rsquo;s just like balancing your checkbook (assuming my readers are old enough to remember the days when you had to do that by hand) and coming up 3 cents short.&nbsp; Some of us will just shrug and say &ldquo;fuck it&rdquo; and move on with our lives.&nbsp; It&rsquo;s 3 cents, man!&nbsp; Who cares?&nbsp; But others of us will go back and hunt down that lousy stinkin&rsquo; 3 cents like our lives depended on it.&nbsp; Otherwise it will just mock us mercilessly, and we won&rsquo;t be able to sleep at night knowing it&rsquo;s out there.</p>

<p>I have a little of both in me.&nbsp; If we really <em>were</em> talking about balancing checkbooks, I couldn&rsquo;t let the 3 cents slide.&nbsp; It&rsquo;s a touch of OCD I inherited from my mother.&nbsp; But a 7% failure rate on my software doesn&rsquo;t really seem that bad&nbsp;... I mean, I&rsquo;m not talking about medical software, or airline autopilot programs.&nbsp; And I actually <em>looked</em> at the failures, and they all look fine&nbsp;... I can&rsquo;t see any reason why they would be failing, actually.&nbsp; Still, I looked up the email addy for one of the testers (one who provided 3 or 4 of the failures) and sent him off an email.&nbsp; I&rsquo;m sure he&rsquo;s very busy with other stuff (like putting out a <a href="http://www.nntp.perl.org/group/perl.perl5.porters/2012/01/msg182230.html">new version of Perl</a>), so I wasn&rsquo;t offended when he didn&rsquo;t get back to me.</p>

<p>In the end, I decided I would check previous releases of <code class="prettyprint">Test::File</code> and see what sort of error rate brian d foy was willing to live with&nbsp;... after all, it&rsquo;s <em>his</em> car, right?&nbsp; So, by my rough estimate (still not being able to find the exact count anywhere&mdash;if there&rsquo;s not something I&rsquo;m blatantly missing, I wonder if the CPAN Testers folks would be willing to add this) the last production release had an error rate of around 5%.&nbsp; I&rsquo;m close enough to that, I figure.&nbsp; So I went ahead and released version 1.30 (having discovered, <em>not</em> too late this time, that there was a 1.29 I didn&rsquo;t know about).</p>

<p>And 1.30 had an error rate closer to 3%, which is pretty awesome.&nbsp; I figured all was well.&nbsp; Until I actually went to install my newly released version on my own box.</p>

<p>And it failed.</p>

<p>Now, this completely floored me.&nbsp; I had run the exact same tests on <em>this exact same box</em> so many times it wasn&rsquo;t funny.&nbsp; I&rsquo;m primarily a TDD developer, especially when it comes to code I release into the wild, so I was running those tests several times a minute at some points.&nbsp; Certainly I&rsquo;ve run the entire test suite over and over again&nbsp;... hell, my script which I use to toss the tarfile up to PAUSE won&rsquo;t <em>run</em> if the tests fail (which is as it should be).&nbsp; There&rsquo;s no way (I says to myself) that these tests can be failing now.</p>

<p>Yet they were.</p>

<p>I tried again.&nbsp; I exited out of my <code class="prettyprint">CPAN</code> shell and got back in.&nbsp; I made sure my <code class="prettyprint">CPAN</code> was the most recent version and reloaded it.&nbsp; Still failing.&nbsp; With errors that made no sense: the file called <code class="prettyprint">not_readable</code> (and I&rsquo;ll give you 1 guess as to why it&rsquo;s named that) was apparently <em>not</em> failing the readable test.&nbsp; How could this be?&nbsp; Was the code that set the permissions to make it unreadble not working?&nbsp; But, if that were the case, how had the code suddenly stopped working when I hadn&rsquo;t changed anything?</p>

<p>I bet some of you have cottoned on to what&rsquo;s going on here.&nbsp; Please, feel free to be very smug about it.&nbsp; I deserve it.</p>

<p>The problem, as it turned out, was that I was running all my tests, every time, as me.&nbsp; But I was <em>installing</em>, via the <code class="prettyprint">CPAN</code> shell, as root.&nbsp; And, as you may know, root doesn&rsquo;t have any problems reading files, even if they&rsquo;re unreadable.&nbsp; D&rsquo;oh!&nbsp; I had cribbed the <code class="prettyprint">non_readable</code> file itself from brian d foy&rsquo;s existing code, but I had failed to properly copy over his tests, all of which specifically had SKIP blocks and checked the UID (and EUID) to see if it was root running the tests.&nbsp; I added those and put out a version 1.31 and that&rsquo;s where we are today.&nbsp; Thus far, my error rate is under 1%.&nbsp; Woohoo!</p>

<p>Anyway, I&rsquo;m not entirely sure what the ultimate moral of the story should be&nbsp;... don&rsquo;t discount CPAN Testers too quickly? always check to see what versions are out there before you release a module for the first time? always try to install your module as root before releasing? know your CPAN Testers error rate? something completely different that I missed myself?&nbsp; Probably better if the reader decides that for themselves, I think.&nbsp; But I figured it was illuminating enough to share with the group, at least.&nbsp; Hopefully you agree.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Miscellany</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/01/miscellany.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.2684</id>

    <published>2012-01-16T05:49:27Z</published>
    <updated>2012-01-16T05:54:57Z</updated>

    <summary><![CDATA[ I was thinking about writing a blog post on TDD, but then I discovered that chromatic had beaten me to it.&nbsp; Damn that chromatic for saying everything I wanted to say before I had a chance to say it!&nbsp;...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p><br />
I was thinking about writing a blog post on TDD, but then I discovered that chromatic had <a href="http://www.modernperlbooks.com/mt/2011/09/always-tdd-except-when-you-shouldnt.html">beaten me to it</a>.&nbsp; Damn that chromatic for saying everything I wanted to say before I had a chance to say it!&nbsp; But, seriously: go read that if you haven&rsquo;t already.&nbsp; Anything I might add to it would be mostly redundant.&nbsp; Although I do have a post on <a href="http://barefootcoder.blogspot.com/2011/11/if-you-meet-hype-on-road-kill-it.html">the other blog</a> where I discuss TDD in the context of techno-dogma and our fear of it.&nbsp; You might find it interesting.</p>

<p>Also, big thanks to Gabor for including <a href="http://blogs.perl.org/users/buddy_burden/2012/01/stepping-up.html">last week&rsquo;s blog post</a> in the <a href="http://perlweekly.com/">Perl Weekly</a> this past week.&nbsp; If you haven&rsquo;t yet signed up for PW, you should do so now!&nbsp; It&rsquo;s invaluable.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Stepping Up</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2012/01/stepping-up.html" />
    <id>tag:blogs.perl.org,2012:/users/buddy_burden//1118.2657</id>

    <published>2012-01-08T22:03:47Z</published>
    <updated>2012-01-08T22:41:44Z</updated>

    <summary><![CDATA[ This week I became co-maintainer of a second module: Test::File.&nbsp; I now have the privelege of being co-maintainer on modules by two of our most prolific Perl authors (i.e. schwern and brian d foy).&nbsp; And, as you may have...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p><br />
This week I became co-maintainer of a second module: <a href="https://metacpan.org/module/Test::File">Test::File</a>.&nbsp; I now have the privelege of being co-maintainer on modules by two of our most prolific Perl authors (i.e. <a href="https://metacpan.org/author/MSCHWERN">schwern</a> and <a href="https://metacpan.org/author/BDFOY">brian d foy</a>).&nbsp; And, as you may have gathered from my blogs thus far, I&rsquo;m certainly no one special.&nbsp; What did I do to receive such honors?</p>

<p>Nothing, really.</p>

<p>I just contributed.&nbsp; I found two modules that I actually cared about, where the existing art was <em>almost</em> what I wanted, but not quite, and then instead of hacking on them in private, or creating my own extension, I reached out to their authors, and I said, &ldquo;hey, how would you feel if I sent you a patch for thus and so?&rdquo; and they said &ldquo;sure, sounds good&rdquo; and I did, and then I sent more stuff&mdash;stuff that I actually needed, not just stuff to be doing stuff &rsquo;cause it sounded cool&mdash;and eventually they both ended up saying, &ldquo;say, you seem like you have a strong interest, and you&rsquo;ve demonstrated some meager ability, and I&rsquo;m a busy guy&nbsp;... why don&rsquo;t you handle the releases for a bit?&rdquo; and I said &ldquo;sure, why not?&rdquo;  In this latter case, the entire conversation happened to be held <a href="https://github.com/briandfoy/test-file/issues/3">in public</a>, if you seriously cared that much to go read it.</p>

<p>But the point I&rsquo;m trying to make is, this wasn&rsquo;t brain science.&nbsp; Anyone can do it.&nbsp; You could end up becoming a co-maintainer, or end up taking over an orphaned module like <a href="http://blogs.perl.org/users/buddy_burden/2011/12/a-random-story.html">I also recently did</a>.&nbsp; And I think you should.&nbsp; Why do I think that?</p>

<p>You know, just the other day <a href="https://metacpan.org/author/BMILLARES">a friend of mine</a> (also co-worker, also currently boss) was remarking to me that he couldn&rsquo;t find a decent CPAN module for XML validation.&nbsp; (Feel free to point me at one he may have missed in the comments.)  He wasn&rsquo;t necessarily upset by this in the specific case&mdash;we&rsquo;ve all been in the position of not finding something you need on CPAN.&nbsp; He was commenting more on the big picture presented by this.&nbsp; Once upon a time, he opined (not necessarily as flowerily as I am waxing here, but you catch my drift), once upon a time, you could find anything you needed on CPAN.&nbsp; You&rsquo;d have to be looking for some pretty obscure shit to come up blanks on a reasonably intelligent CPAN search.&nbsp; It&rsquo;s not so much the case any more.&nbsp; Now there are gaps&nbsp;... perhaps there aren&rsquo;t any <em>serious</em> gaps yet, but the cracks are showing.&nbsp; We have to face the fact that we need to break out some putty and start filling in those cracks.</p>

<p>And, don&rsquo;t forget: CPAN is Perl&rsquo;s killer app.&nbsp; It&rsquo;s been said dozens of times, but I still say it bears repeating.&nbsp; Python may be cool and all (personally, I swore off whitespace-dependent languages after Fortran, but whatever floats your boat), but there ain&rsquo;t no CPAN for Python.&nbsp; Ruby may be elegant and whatnot (with or without the rails), but there ain&rsquo;t no CPAN for Ruby.&nbsp; Javascript may be&nbsp;... okay, look, Javascript is just insane.&nbsp; Who the hell thought <em>that</em> was a good idea?&nbsp; Is there anyone out there using Javascript for any reason other than because every browser on the planet implements it?&nbsp; Objects but no classes?&nbsp; It&rsquo;s just weird.&nbsp; Oh, and there ain&rsquo;t no CPAN for Javascript.</p>

<p>Now, there are <a href="http://acmeism.org/">movements</a> looking to start changing that, of course.&nbsp; But those other languages have a bit of catch-up to play.&nbsp; We&rsquo;re out in front, but you know what they say in the marketing biz: you don&rsquo;t keep a number one spot by restin&rsquo; on your laurels.&nbsp; We all have to put some effort into it.&nbsp; What can we do?&nbsp; Simple: contribute.&nbsp; Step up, help out, take over, keep up.&nbsp; There is a small number of prolific CPAN authors.&nbsp; There is a <em>large</em> number of regular-Joe Perl programmers like you and me.&nbsp; Let&rsquo;s rebalance that tree.</p>

<p>What is holding us back?&nbsp; Well, I talked about this a bit on my other blog, upon the occasion of <a href="http://barefootcoder.blogspot.com/2011/04/perl-procrastination-and-cpan.html">releasing my first CPAN module</a>.&nbsp; Inertia, procrastination, apprehension, perfectionism.&nbsp; Blah blah blah.&nbsp; Screw all that.&nbsp; Just release something.&nbsp; It doesn&rsquo;t matter if it&rsquo;s any good or not.&nbsp; There are these constant rants by people about how CPAN is full of crap (there was one recently on module-authors, which I refuse to link to because of its inanity), but screw those people: a lot of that crap is composed of first attempts by people who later went on to do great things.&nbsp; You know the coolest thing about crap?&nbsp; It makes awesome fertilizer.</p>

<p>So put something out there.&nbsp; Uploading a new module is good, and I encourage people to try it, but I&rsquo;ve got to tell you: it&rsquo;s a huge pain in the ass figuring out how to get started on that.&nbsp; Not because of a <em>lack</em> of tutorials on it: rather because of a <em>plethora</em> of tutorials, all of which say something different.&nbsp; I may relate my experiences on that, because I think I may have tried them all at this point, but I want to make sure I have something useful to say on the topic instead of becoming just one more tutorial with a different take on things.&nbsp; As Voltaire (supposedly) said, &ldquo;It is far better to be silent than merely to increase the quantity of bad books.&rdquo;</p>

<p>But you have another option besides creating and uploading your own module: you can submit a patch, you can add a feature, you can fix a bug.&nbsp; You live in the era of git, and GitHub, and that makes it easier to do than ever.&nbsp; (There are <a href="https://www.google.com/search?q=github+contribute+easy">lots of articles</a> on why that is, so I won&rsquo;t repeat that here.)  MetaCPAN has come along, and now you can often just hover over the &ldquo;Clone repository&rdquo; link on the left side and get a direct link to the repository where the code lives, be it on GitHub or elsewhere.&nbsp; Assuming it <em>is</em> on GitHub, you can (usually) just hop over there and open an issue.&nbsp; (A plea to GitHub authors: <em>please</em> make sure your &ldquo;Issues&rdquo; tab is turned on&mdash;just click that &ldquo;Admin&rdquo; button if it&rsquo;s not.&nbsp; Finding the code on GitHub and not being able to submit an issue on it really derails the whole process.)  Use that issue to talk about what you want to fix or change&mdash;note that I did <strong>not</strong> say to talk about what needs fixing or changing!&nbsp; Always approach it from the angle that this is work that <em>you</em> are willing to do.&nbsp; (And, if you&rsquo;re not willing to do it, go back to the top and read this blog again, because it obviously didn&rsquo;t take the first time.)  Tell the author that you&rsquo;ve put in the effort to see where the problem is, or where your new feature could be added.&nbsp; Show them that you&rsquo;ve taken the time to read their documentation (yes, all of it, now matter how long-winded they are) and you&rsquo;ve grasped what they want to achieve with this module, and you know that what you want to do isn&rsquo;t contrary to that.&nbsp; Demonstrate that you&rsquo;ve put in the time and effort to search elsewhere for solutions and you&rsquo;ve still come to the conclusion that this is the right place for it.</p>

<p>Then wait for a response.&nbsp; You want to make sure the person agrees with the fix or feature and is willing to include it in their module.&nbsp; If they <em>aren&rsquo;t</em>, then maybe you want to look at working on a subclass or plugin or extension to their module instead.&nbsp; But, you know what? that&rsquo;s the exception, not the rule.&nbsp; Generally, they&rsquo;re happy to have someone else taking an interest in their baby.</p>

<p>That&rsquo;s what your module is, you know.&nbsp; It&rsquo;s your baby.&nbsp; You&rsquo;ll always be proud of it, even when you know it could have turned out better.&nbsp; You&rsquo;ll always be a little touchy about other people messing with it.&nbsp; brian d foy compared giving me co-maintenance to giving me the keys to his car.&nbsp; And, you know, when you drive another person&rsquo;s car, you better show some respect for it.&nbsp; You better make sure you understand what it needs, and what its quirks are, and where all the controls are (&rsquo;cause sometimes the windshield wipers are in a weird place or something), and whether you need to goose the accelerator when you&rsquo;re stopped at a red light, and whether that yellow light on the dashboard comes on all the time and it&rsquo;s no big deal, or whether it means pull over RIGHT NOW!&nbsp; In other words, when I start working on someone else&rsquo;s module, I adhere to their coding standards (even if I think they&rsquo;re insane), and I make my POD style match theirs (even if I think it&rsquo;s bizarre), and I organize it and comment it the way they would (even if I don&rsquo;t understand it).&nbsp; To break out another analogy, you want to leave the campsite as clean as you found it, at the minimum.&nbsp; Preferably cleaner.</p>

<p>And you put in that effort, and you become a contributor.&nbsp; Maybe the author will ask you to be a co-maintainer.&nbsp; Or maybe not, but that doesn&rsquo;t matter.&nbsp; The point isn&rsquo;t to become co-maintainer so you can get on your blog and go &ldquo;ooh! ooh! I&rsquo;m a co-maintainer now!&rdquo;  That&rsquo;s not what this blog is about.&nbsp; Really.&nbsp; The point is that you&rsquo;re doing something to make CPAN a better place, and to make someone else&rsquo;s life easier.&nbsp; They&rsquo;ll tell you how you can best do that.&nbsp; Typically, they ain&rsquo;t shy, so don&rsquo;t worry about that.&nbsp; As long as they&rsquo;re happy with your contributions, you&rsquo;re doing something positive for CPAN, for us other regular-Joe Perl hackers, for everyone.&nbsp; And that&rsquo;s what it&rsquo;s all about.</p>]]>
        
    </content>
</entry>

<entry>
    <title>If you look on every exit as being an entrance somewhere else ...</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2011/12/if-you-look-on-every-exit-as-being-an-entrance-somewhere-else.html" />
    <id>tag:blogs.perl.org,2011:/users/buddy_burden//1118.2564</id>

    <published>2011-12-11T10:18:03Z</published>
    <updated>2011-12-11T10:22:47Z</updated>

    <summary><![CDATA[I didn&rsquo;t write anything specifically about Perl this week, but I did broach a topic in my other blog that you may find interesting if you&rsquo;re a professional programmer.&nbsp; Check it out, if you like, or not.&nbsp; If nothing else,...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>I didn&rsquo;t write anything specifically about Perl this week, but I did broach a topic in my <a href="http://barefootcoder.blogspot.com/2011/12/drag-reduction.html">other blog</a> that you may find interesting if you&rsquo;re a professional programmer.&nbsp; Check it out, if you like, or not.&nbsp; If nothing else, it has a reference to a great blog post which is much better than mine. <code class="prettyprint">;-></code><br />
</p>]]>
        
    </content>
</entry>

<entry>
    <title>A Random Story</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/buddy_burden/2011/12/a-random-story.html" />
    <id>tag:blogs.perl.org,2011:/users/buddy_burden//1118.2539</id>

    <published>2011-12-05T08:16:17Z</published>
    <updated>2011-12-05T08:32:08Z</updated>

    <summary><![CDATA[For my first (real) tale, I thought I&rsquo;d tell the story of how I came to be the maintainer for Data::Random. I first came across this module when I was trying to find some way to test some date routines...]]></summary>
    <author>
        <name>Buddy Burden</name>
        
    </author>
    
        <category term="CPAN" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/buddy_burden/">
        <![CDATA[<p>For my first (real) tale, I thought I&rsquo;d tell the story of how I came to be the maintainer for <a href="https://metacpan.org/module/Data::Random"><code class="prettyprint">Data::Random</code></a>.</p>

<p>I first came across this module when I was trying to find some way to test some date routines I was doing for $work.&nbsp; Funnily enough (or not, depending on your perspective), the date routines were themselves for testing&mdash;I&rsquo;m working on introducing <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> to my department, and so I try to maintain a decent library to make testing easier.&nbsp; To that end, I decided to make it easier to set up records with certain dates:</p>

<pre><code class="prettyprint">    # go far back in time to avoid conflicting with real rates
    my $initial_date = '1/1/1990';
    $prop->create_billing_period(
        start_date => days_from($initial_date, 30),
        end_date => days_from($initial_date, 60)
    );
</code></pre>
That sort of thing.&nbsp; And of course you must use TDD on your test function helpers&mdash;if you can&rsquo;t trust your testing code, you&rsquo;re in pretty big trouble.&nbsp; So I wanted to test my <code class="prettyprint">days_from</code> method very thoroughly.

<p><br />
So I thought, why not come up with a function to create random dates?&nbsp; And then I thought, I&rsquo;m sure someone&rsquo;s already done that.&nbsp; So I looked on CPAN.&nbsp; And I found <code class="prettyprint">Data::Random</code>.&nbsp; So I used it, and everyone lived happily ever after.</p>

<p>No, wait, that&rsquo;s not right&nbsp;...</p>

<p>Well, we all <em>were</em> living happily ever after for a while.&nbsp; Then, one day, I&rsquo;m running some tests and I start getting these weird Moose errors in a new module one of my colleagues has written.&nbsp; I grabbed said colleague and we started debugging.&nbsp; My code called something which had a <code class="prettyprint">use Test::Rent::Config</code> in it.&nbsp; <code class="prettyprint">Test::Rent::Config</code> is a test object designed to replace a <code class="prettyprint">Rent::Config</code>, naturally enough, so it subclasses that class and overrides a few methods here and there.&nbsp; But the code kept complaining about a method being missing.&nbsp; There it was, right there in <code class="prettyprint">Rent::Config</code>, but the code couldn&rsquo;t find it.&nbsp; What the heck??&nbsp; Well, after nearly two hours of staring at the code, and digging into internal Moose code (&rsquo;cause it had to be something tricky going on, and we all know there&rsquo;s few things trickier than Moose guts), and putting debugging statements all over, and fiddling with the debugger (always dicey when trying to catch compile-time errors), we finally figured it out: <code class="prettyprint">Data::Random</code> contained this line:</p>

<pre><code class="prettyprint">    use lib qw(..);
</code></pre>
And I just happened to be running my tests in the directory <code class="prettyprint">lib/Test/t</code>.&nbsp; Which means that when <code class="prettyprint">Test::Rent::Config</code> tried to load <code class="prettyprint">Rent::Config</code>, it actually loaded&nbsp;... itself.

<p><br />
Crap.</p>

<p>Obviously the fix was simple: remove that line.&nbsp; What was it doing in there anyway?&nbsp; Probably something that had been put in during testing, and just never taken out.&nbsp; No one had noticed it in the past 8 years, apparently, because it takes a very special set of circumstances to trigger this bug.&nbsp; Lucky me.</p>

<p>So I put in a hack fix (something along the lines of <code class="prettyprint">shift @INC if $INC[0] eq '..'</code>) and decided to open an RT bug.&nbsp; Didn&rsquo;t expect it to do me a lot of good, of course, since a) there had been no CPAN release in 8 years, b) the author only had one other module and <em>it</em> hadn&rsquo;t seen a new release in <em>10</em> years, c) and there were 5 open RT bugs, ranging from 4 to 8 years old, none of which had any responses from the author.</p>

<p>Not that I&rsquo;m casting any aspersions on the author, of course.&nbsp; People move on; their lives get complicated.&nbsp; Sometimes shit (and real life) happens.&nbsp; In fact, I thought I&rsquo;d poke around Google and see if I could see what this particular author was up to these days, just for fun.&nbsp; (And also because I figured an 8-year-old email address didn&rsquo;t have much chance of working.)  And I found him: he&rsquo;s currently the CEO of a successful company in San Francisco.&nbsp; Well, heck: no wonder he didn&rsquo;t have time to fiddle with CPAN distributions any more.&nbsp; He&rsquo;s busy building a business empire and whatnot.</p>

<p>So I sent him an email.&nbsp; I used 3 addresses: first, the one in the module&rsquo;s POD, even though I felt pretty sure it was outdated; and secondly, two wild guesses based on the fact that I knew the author&rsquo;s full name, and I now knew the domain name for his new company.&nbsp; My email said, hey, I see you haven&rsquo;t been around CPAN for a while; perhaps you&rsquo;re interested in passing on maintainership of this module?&nbsp; Lo and behold, he responded.&nbsp; Sure, he said, take it over; I don&rsquo;t have much time for Perl any more.&nbsp; By the way&nbsp;... how do I even <em>do</em> that?</p>

<p>Well, heck, I dunno&nbsp;... but I figured I ought to figure it out for him.&nbsp; He was a busy CEO, after all; <em>I</em> was the one who wanted my bug fixed.&nbsp; So I got to poking around <a href="http://pause.perl.org/pause/query">PAUSE</a>.&nbsp; Didn&rsquo;t take long to find it: &ldquo;Change Permissions,&rdquo; it&rsquo;s called.&nbsp; So I explained to him how to do it (and prayed he could remember his PAUSE password), and, next thing you know, I was the primary maintainer.</p>

<p>Great, now to fix the bug.&nbsp; First thing I need, of course, is source code.&nbsp; I could ask the author if he had a repository I could start from, but it certainly wouldn&rsquo;t be in Git (on account of, you know, Git didn&rsquo;t <em>exist</em> 8 years ago), so best case scenario is I&rsquo;d have to import it from another VCS.&nbsp; Alternatively, I could take advantage of the awesomeness that is <a href="https://github.com/schwern/gitpan/blob/master/README">gitPAN</a>.&nbsp; So I started a <a href="http://www.mail-archive.com/module-authors@perl.org/msg09100.html">discussion about it</a>, and eventually just <a href="https://github.com/barefootcoder/Data-Random">forked the gitPAN repo</a> and called it a day.</p>

<p>Now I was ready to fix the bug.&nbsp; First, I created a <a href="https://github.com/barefootcoder/Data-Random/commit/6901a5606f34323cd71146fddc820c8068e77bff#diff-1">failing test</a>, then I simply <a href="https://github.com/barefootcoder/Data-Random/commit/6901a5606f34323cd71146fddc820c8068e77bff#diff-0">removed the offending line</a>.&nbsp; Simple enough.&nbsp; I made a few packaging changes for easier releasing and was ready to start.</p>

<p>First, a developer release.&nbsp; I don&rsquo;t know much about how to release stuff on CPAN, but one thing I do know: first thing you do is make a developer release (i.e. a release number with an underscore in it), then you see how many FAIL reports you get back from <a href="http://static.cpantesters.org/">CPAN Testers</a>.&nbsp; This also helps make sure you&rsquo;ve got all your packaging stuff just right and don&rsquo;t end up with a half-broken official CPAN release&nbsp;... which is exactly what I did on my first try.&nbsp; My <code class="prettyprint">MANIFEST</code> file was wrong and the install failed for everyone.&nbsp; Okay, second try.</p>

<p>This time I got a more subtle problem.&nbsp; A few of the CPAN Testers reports showed a test failing, but that same test passed on all the others.&nbsp; I looked for patterns in versions of Perl, operating systems, etc, but found none.&nbsp; What could it be?&nbsp; I looked more closely at the test in question.&nbsp; It was a test of <code class="prettyprint">rand_time</code>, which was a method I personally had not been using, but, looking at the test, I could easily see what was going on.&nbsp; The test generated a random time between <code class="prettyprint">now</code> and <code class="prettyprint">now</code>, which was essentially guaranteed to return the current time.&nbsp; It then compared the results against the current time.&nbsp; But the problem with that is that there were two different places where &ldquo;the current time&rdquo; was being captured, and, every once in a great while, it was possible for the clock to roll over to a new second in between the two places.&nbsp; Thus, intermittent failures.&nbsp; I&rsquo;d seen this sort of error before when messing around with datetimes, luckily, so I recognized it fairly easily.</p>

<p>Okay, fine: rewrite that test.&nbsp; But there was another test having intermittent failures too: it turned out that the test was making sure the that the random time was defined by testing its truth or falsehood.&nbsp; But what if the random time returned 0 seconds after midnight?&nbsp; That is, 00:00:00, also known as: 0 seconds.&nbsp; A.k.a., &ldquo;false.&rdquo;  The test was only generating a very small number of random samples to test, so it was very rare that it just so happened to get 0 back as an answer.</p>

<p>Obviously the whole test file needed to be rewritten.&nbsp; I decided to generate 5 times as many random numbers as there were possible values, figuring that that would practically guarantee me generating all possible values.&nbsp; I left the undefined/false bug to make sure I tripped it, then ran my new test several times.&nbsp; The current time bug was fixed, but I wasn&rsquo;t getting that 0 seconds failure reliably enough.&nbsp; I kept on upping it, until I got the failure every time; I ended up at generating 10 random times for every possible value.&nbsp; Of course, now the problem was that the test took forever to complete.&nbsp; Don&rsquo;t want people to have to sit and stare at the CPAN shell for 2 minutes while my tests are running, right?&nbsp; But isn&rsquo;t there a way to have long-running tests only run sometimes?&nbsp; Well, <a href="http://wiki.cpantesters.org/wiki/CPANAuthorNotes">sure there is</a>!&nbsp; Just check <code class="prettyprint">$AUTOMATED_TESTING</code>.&nbsp; Rock on.&nbsp; So now my test does 10x as many tests as possible values when <code class="prettyprint">$AUTOMATED_TESTING</code> is on, but only half as many as possible when it&rsquo;s off.&nbsp; Cool.</p>

<p>My third try had another packaging failure.&nbsp; When I rewrote the test file, I naturally updated it to use the <code class="prettyprint">done_testing</code> feature of modern <code class="prettyprint">Test::More</code> versions, but I forgot to change the <code class="prettyprint">Test::More</code> version number (to 0.88) under <code class="prettyprint">test_requires</code> in the <code class="prettyprint">Makefile.PL</code>.&nbsp; D&rsquo;oh!</p>

<p>My fourth try had a number of insane failures from CPAN Testers.&nbsp; You can read <a href="http://www.mail-archive.com/perl-qa@perl.org/msg12632.html">the full discussion</a> if you really care about the details, but let me summarize it for you:  There are 86,400 seconds in a day.&nbsp; If you run a test file that generates 10x as many random time values as there possible values, that&rsquo;s 864,000 tests (and that&rsquo;s only the first range I was testing).&nbsp; If you have a test file, using <code class="prettyprint">Test::More</code>, that actually generates around a million tests, you <em>will</em> run out of memory.&nbsp; Bummer.</p>

<p>So I rewrote the test file such that every range of tests was one big test.&nbsp; And, finally, on dev release number 5, it worked.&nbsp; Thank &lt;insert deity of choice&gt;.</p>

<p>Then I changed nothing but the version number, to something without an underscore, and I was done.&nbsp; Except I still need to go back and remove all those extranneous dev versions from PAUSE so they&rsquo;re not eating up disk space for no reason.</p>

<p>Anyhow, that&rsquo;s the story of how I took over <code class="prettyprint">Data::Random</code>, and I hope there&rsquo;s something instructive in there for folks.&nbsp; Taking over a module can be a bit of a chore, but I think it&rsquo;s worthwhile in the end.&nbsp; Perhaps if we all did that, we could clean up some of the cruft that&rsquo;s out there and make our CPAN a better place to visit.<br />
</p>]]>
        
    </content>
</entry>

</feed>
