<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>dagolden</title>
	<atom:link href="http://www.dagolden.com/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dagolden.com</link>
	<description>Whatever comes to mind</description>
	<lastBuildDate>Tue, 21 May 2013 02:42:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>How I manage new perls with perlbrew</title>
		<link>http://www.dagolden.com/index.php/2134/how-i-manage-new-perls-with-perlbrew/</link>
		<comments>http://www.dagolden.com/index.php/2134/how-i-manage-new-perls-with-perlbrew/#comments</comments>
		<pubDate>Tue, 21 May 2013 02:42:16 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[perl programming]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[perlbrew]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2134</guid>
		<description><![CDATA[Perl v5.19.0 was released this morning and I already have it installed as my default perl. This post explains how I do it. First, I manage my perls with perlbrew. I install that, then use it to install some tools I need globally available: You must install cpanm with perlbrew -- if you don't, weird [...]]]></description>
				<content:encoded><![CDATA[<p>Perl v5.19.0 was released this morning and I already have it installed as my default perl.  This post explains how I do it.</p>
<p>First, I manage my perls with <a href="http://perlbrew.pl/" title="perlbrew" target="_blank">perlbrew</a>.  I install that, then use it to install some tools I need globally available:</p>
<pre class="brush: plain; title: ; notranslate">
$ install-patchperl
$ install-cpanm
</pre>
<p>You <b>must</b> install cpanm with perlbrew -- if you don't, weird things can happen when you switch perls and try to install stuff.</p>
<p>I keep my perls installed read-only and add a local::lib based library called "@std".  (I stole this technique from Ricardo Signes.)  That way, I can always get back to a clean, stock perl if I need to test something that way.</p>
<p>(There are still some <a href="https://github.com/gugod/App-perlbrew/issues/305" title="perlbrew warnings changing perls with local::lib" target="_blank">weird warnings</a> that get thrown doing things this way when I switch perls, but everything seems to work.)</p>
<p>I also install perls with an alias, so "19.0" is short for "5.19.0".</p>
<p>Then I have a little program that builds new perls, sets things up the way I want, and installs my usual modules. All I have to do is type this:</p>
<pre class="brush: plain; title: ; notranslate">
$ newperl 19.0
</pre>
<p>And then I've got a brand new perl I can make into my default perl.</p>
<p>Here's that program.  Feel free to adapt to your own neeeds:</p>
<pre class="brush: perl; title: ; notranslate">
#!/usr/bin/env perl
use v5.10;
use strict;
use warnings;
use autodie qw/:all/;

my $as = shift
  or die &quot;Usage: $0 &lt;perl-version&gt;&quot;;
my @args = @ARGV;

# trailing &quot;t&quot; means do threads
my @threads = ( $as =~ /t$/ ) ? (qw/-D usethreads/) : ();

$as =~ s/^5\.//;
my $perl = &quot;5.$as&quot;;
$perl =~ s/t$//; # strip trailing &quot;t&quot; if any
my $lib = $as . '@std';

my @problem_modules = qw(
  JSON::XS
);

my @to_install = qw(
  Task::BeLike::DAGOLDEN
);

my @no_man = qw/-D man1dir=none -D man3dir=none/;

# install perl and lock it down
system( qw/perlbrew install -j 9 --as/, $as, $perl, @threads, @no_man, @args );
system( qw/chmod -R a-w/, &quot;$ENV{HOME}/perl5/perlbrew/perls/$as&quot; );

# give us a local::lib for installing things
system( qw/perlbrew lib create/, $lib );

# let's avoid any pod tests when we try to install stuff
system( qw/perlbrew exec --with/, $lib, qw/cpanm TAP::Harness::Restricted/ );
local $ENV{HARNESS_SUBCLASS} = &quot;TAP::Harness::Restricted&quot;;

# some things need forcing
system( qw/perlbrew exec --with/, $lib, qw/cpanm -f/, @problem_modules );

# now install the rest
system( qw/perlbrew exec --with/, $lib, qw/cpanm/, @to_install );

# repeat to catch any circularity problems
system( qw/perlbrew exec --with/, $lib, qw/cpanm/, @to_install );
</pre>
<p>Yes, that takes a while.  I kicked it off right before going to get lunch.  When I got back, I was ready to switch:</p>
<pre class="brush: plain; title: ; notranslate">
$ perlbrew switch 19.0@std
</pre>
<p>I also have a couple bash aliases/functions that I use for easy, temporary toggling between perls:</p>
<pre class="brush: bash; title: ; notranslate">
alias wp=&quot;perlbrew list | grep \@&quot;
up () {
  local perl=$1
  if [ $perl ]; then
    perlbrew use $perl@std
  fi
  local current=$(perlbrew list | grep \* | sed -e 's/\* //' )
  echo &quot;Current perl is $current&quot;
}
</pre>
<p>I use them like this (notice that I don't need to type my @std library for this fast switching):</p>
<pre class="brush: plain; title: ; notranslate">
$ up
Current perl is 18.0@std

$ wp
  10.0@std
  10.0-32@std
  10.1@std
  12.5@std
  14.4@std
  16.3@std
  16.3@test
  16.3t@std
* 18.0@std
  19.0@std
  8.5@std
  8.9@std

$ up 19.0
Use of uninitialized value in split at /loader/0x7fa639030cd8/local/lib.pm line 8.
Use of uninitialized value in split at /loader/0x7fa639030cd8/local/lib.pm line 8.
Current perl is 19.0@std
</pre>
<p>(there's that warning I mentioned)</p>
<p>I hope this guide helps people keep multiple perls for development and testing.  In particular, I'd love to see more more people doing development work and testing using 5.19.X so it can get some real-world testing.</p>
<p>See you June 21 for v5.19.1...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2134/how-i-manage-new-perls-with-perlbrew/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Anyone want vanillaperl.com?</title>
		<link>http://www.dagolden.com/index.php/2130/anyone-want-vanillaperl-com/</link>
		<comments>http://www.dagolden.com/index.php/2130/anyone-want-vanillaperl-com/#comments</comments>
		<pubDate>Thu, 16 May 2013 13:54:38 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[perl programming]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2130</guid>
		<description><![CDATA[I'm tired of paying the domain bill for vanillaperl.com (which currently just redirects to strawberryperl.com). It will lapse at the beginning of July unless someone wants to take it. If you're interested, leave a comment below and explain what you want to do with it. I'll award it to the best proposal received by June [...]]]></description>
				<content:encoded><![CDATA[<p>I'm tired of paying the domain bill for vanillaperl.com (which currently just redirects to strawberryperl.com).</p>
<p>It will lapse at the beginning of July unless someone wants to take it.</p>
<p>If you're interested, leave a comment below and explain what you want to do with it.  I'll award it to the best proposal received by June 1.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2130/anyone-want-vanillaperl-com/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>OODA vs technical debt</title>
		<link>http://www.dagolden.com/index.php/2116/ooda-vs-technical-debt/</link>
		<comments>http://www.dagolden.com/index.php/2116/ooda-vs-technical-debt/#comments</comments>
		<pubDate>Wed, 24 Apr 2013 14:51:33 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[perl programming]]></category>
		<category><![CDATA[startups]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2116</guid>
		<description><![CDATA[This post is a response to Ovid's series about agility without testing: How to be agile without testing When must you test your code? Code evolution vs intelligent design I started to respond to the last and realized that my comment was long enough to be a blog post of my own. First, let me [...]]]></description>
				<content:encoded><![CDATA[<p>This post is a response to Ovid's series about agility without testing:</p>
<ul>
<li><a href="http://blogs.perl.org/users/ovid/2013/04/how-to-be-agile-without-testing.html" target="_blank">How to be agile without testing</a></li>
<li><a href="http://blogs.perl.org/users/ovid/2013/04/when-must-you-test-your-code.html" target="_blank">When must you test your code?</a></li>
<li><a href="http://blogs.perl.org/users/ovid/2013/04/code-evolution-versus-intelligent-design.html#_login_koFyXXM0jwugEBwJEQbMqh6v8t1ZcNP9R8R25Rw4" target="_blank">Code evolution vs intelligent design</a></li>
</ul>
<p>I started to respond to the last and realized that my comment was long enough to be a blog post of my own.</p>
<p>First, let me say that I'm enjoying this series.  Ovid and Abigail are both challenging conventional wisdom around technical debt and I think that's really healthy.</p>
<p>However, I note that Ovid's evidence in favor of emergent behavior is anecdotal, which is probably inevitable for this sort of thing, but dangerous.  "It worked these handful of times I remember it" has confirmation bias and no statistical significance.</p>
<p>We can't run a real experiment, but we can run a thought experiment: 100 teams of strict TDD vs 100 teams of the Ovid approach [which he really ought to brand somehow] from the same starting point (perhaps in parallel universes) for a few months of development.</p>
<p>What could we expect?  Certainly, the TDD teams will spend more of their time on testing than the Ovid teams.  So the Ovid teams will deliver more features and fix more bugs in the same period of time.</p>
<p>If one believes even a little of the Lean Startup hype, the Ovid teams will have more opportunities to see customer reactions — they will have a shorter <a href="http://venturehacks.com/articles/certain-to-win" target="_blank">OODA loop</a>.</p>
<p>On the flip side, the TDD team has less technical debt and lower risk profile.  I disagree with the idea that <a href="http://blogs.perl.org/users/ovid/2011/11/technical-debt-when-metaphors-go-wrong.html" title="Technical debt: when metaphors go wrong" target="_blank">technical debt is an option</a>.  I believe it does have an ongoing cost — that future development is less efficient and more time consuming to at least some degree.</p>
<p>I call this "servicing" technical debt, which is just like paying only the interest on your credit card.  You might never pay down any of the technical debt, but as you accumulate more, you'll pay more to service it.</p>
<p>It seems clear to me that which result you prefer depends quite a lot on the maturity of the product (possibly expressed in terms of expected growth rate) and the overall risk level.</p>
<p>For a brand-new startup, the risk of failure is already pretty high regardless of coding style.  A faster OODA loop probably reduces risk more than improved tests do, because the bigger risk is building something customers don't want.  And with such a high risk of failure, there's a chance that you'll simply be able to default on technical debt.</p>
<p>If I can riff on the financial crisis, <strong>a startup has subprime technical debt</strong>.  It's either successful — in which case there will be growth sufficient to pay off technical debt (if the risk/reward tradeoff justifies it) — or it fails, in which case the debt is irrelevant.  Rapid growth deflates technical debt.</p>
<p>For a mature business, however, it might well go the other way.  Risk to an existing profit stream is more meaningful and technical debt has to be paid off or serviced (rather than defaulted on) which reduces future profitability that might not be sufficiently offset by growth.</p>
<p>The quandary will be businesses — or products (if part of an established business) — that are in between infancy and maturity.  There the "right" approach will depend heavily on the risk tolerance and growth prospects.</p>
<p>Regardless, I tend to strongly favor TDD at the unit-test level, where I find TDD helps me better define what I want out of a particular piece of code and then be sure that subsequent changes don't break that.  At the unit test level, the effort put into testing can be pretty low and the benefits to my future code productivity fairly high.</p>
<p>But as the effort of testing some piece of behavior increases — due to external dependencies or other interaction effects — it's more tempting to me to let go of TDD and rely on human observation of the emergent behaviors because I'd rather spend my time coding features than tests.</p>
<p>I think that puts me a little closer to the Ovid camp than the strict TDD camp, but not all the way.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2116/ooda-vs-technical-debt/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Why the latest File::Temp might surprise you</title>
		<link>http://www.dagolden.com/index.php/2109/why-the-latest-filetemp-might-surprise-you/</link>
		<comments>http://www.dagolden.com/index.php/2109/why-the-latest-filetemp-might-surprise-you/#comments</comments>
		<pubDate>Wed, 24 Apr 2013 00:42:54 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[perl programming]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2109</guid>
		<description><![CDATA[There was a subtle API change in File::Temp 0.23 that improves consistency, but might break old, buggy code. Prior to 0.23, here was the calling signature for the functional and object oriented interfaces for File::Temp (with some creative spacing to show the problem): Notice how new() doesn't take a template argument. Instead, you're supposed to [...]]]></description>
				<content:encoded><![CDATA[<p>There was a subtle API change in File::Temp 0.23 that improves consistency, but might break old, buggy code.</p>
<p>Prior to 0.23, here was the calling signature for the functional and object oriented interfaces for File::Temp (with some creative spacing to show the problem):</p>
<pre class="brush: perl; title: ; notranslate">
# functional
my ( $fh, $filename ) = tempfile( $template, %options );
my $tempdir           = tempdir ( $template, %options );

# object oriented
my $tmp = File::Temp-&gt;new       (            %options );
my $dir = File::Temp-&gt;newdir    ( $template, %options );
</pre>
<p>Notice how <code>new()</code> doesn't take a template argument.  Instead, you're supposed to pass it as an option in the <code>%options</code> hash: <code>TEMPLATE => 'tempXXXXX'</code>.</p>
<p>Frankly, this interface sucks.  There are too many ways to get confused or do it wrong:</p>
<ul>
<li>What happens if you pass a leading template to <code>new()</code>?</li>
<li>What happens if you leave off the leading template for <code>newdir()</code>?</li>
<li>What happens if you pass a TEMPLATE option to <code>newdir()</code>, <code>tempfile()</code> or <code>tempdir()</code>?</li>
<li>What happens if you call <code>tempfile()</code> or <code>tempdir()</code> as methods?</li>
</ul>
<h2>A test program</h2>
<p>Here's a little test program to try out some variations.  Notice that a leading template argument is 'arg_XXXX' and a TEMPLATE option is 'opt_XXXX', so we can see which takes precedence if we try with both:</p>
<pre class="brush: perl; title: ; notranslate">
#!/usr/bin/env perl
use v5.10;
use strict;
use warnings;
use File::Temp qw/tempfile tempdir/;

my @cases = (
    # documented API
    q{tempfile            ('arg_XXXX'                        )},
    q{tempdir             ('arg_XXXX'                        )},
    q{File::Temp-&gt;new     (            TEMPLATE =&gt; 'opt_XXXX')},
    q{File::Temp-&gt;newdir  ('arg_XXXX'                        )},

    # variations with both arg and TEMPLATE
    q{tempfile            ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')},
    q{tempdir             ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')},
    q{File::Temp-&gt;new     ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')},
    q{File::Temp-&gt;newdir  ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')},

    # newdir called like new
    q{File::Temp-&gt;newdir  (            TEMPLATE =&gt; 'opt_XXXX')},

    # functions called as methods
    q{File::Temp-&gt;tempfile('arg_XXXX'                        )},
    q{File::Temp-&gt;tempdir ('arg_XXXX'                        )},
    q{File::Temp-&gt;tempfile('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')},
    q{File::Temp-&gt;tempdir ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')},
    q{File::Temp-&gt;tempfile(            TEMPLATE =&gt; 'opt_XXXX')},
    q{File::Temp-&gt;tempdir (            TEMPLATE =&gt; 'opt_XXXX')},
);

for my $c ( @cases ) {
    my @result = eval $c;
    my $err = $@;
    $err =~ s/\n.*//ms;
    say $c;
    say &quot;    &quot; . ( $result[-1] ? &quot;Got $result[-1]&quot; : $err ) . &quot;\n&quot;;
}
</pre>
<h2>Results with File::Temp 0.22</h2>
<p>Here are the result running under File::Temp 0.22 for the documented API:</p>
<pre class="brush: plain; title: ; notranslate">
tempfile            ('arg_XXXX'                        )
    Got arg_Y9B5

tempdir             ('arg_XXXX'                        )
    Got arg_Joq0

File::Temp-&gt;new     (            TEMPLATE =&gt; 'opt_XXXX')
    Got opt_p9I5

File::Temp-&gt;newdir  ('arg_XXXX'                        )
    Got arg_PmNf
</pre>
<p>That's just as we expect.</p>
<p>Now, let's try those odd cases.  First, calling everything with both a leading template and a TEMPLATE option:</p>
<pre class="brush: plain; title: ; notranslate">
tempfile            ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got arg_gIL3

tempdir             ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got arg_xPXg

File::Temp-&gt;new     ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got /var/folders/5t/sy1gxkwj2l1gfd20s2g470200000gn/T/AYeB74PT0K

File::Temp-&gt;newdir  ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got arg_GfwP
</pre>
<p>For everything except <code>new()</code>, the TEMPLATE argument is ignored and the leading argument works just like in the documented API.  But how about <code>new()</code>?  You see what's happening don't you?  Here's what it thinks you did:</p>
<pre class="brush: perl; title: ; notranslate">
File::Temp-&gt;new( arg_XXXX =&gt; 'TEMPLATE', opt_XXXX =&gt; undef );
</pre>
<p>Since none of those keys are known, it uses the default directory and template.</p>
<p>What about more wrong variations:</p>
<pre class="brush: plain; title: ; notranslate">
File::Temp-&gt;newdir  (            TEMPLATE =&gt; 'opt_XXXX')
    Got /var/folders/5t/sy1gxkwj2l1gfd20s2g470200000gn/T/AkI6pFjyq_

File::Temp-&gt;tempfile('arg_XXXX'                        )
    Got /var/folders/5t/sy1gxkwj2l1gfd20s2g470200000gn/T/3F2V8UPIbx

File::Temp-&gt;tempdir ('arg_XXXX'                        )
    Got /var/folders/5t/sy1gxkwj2l1gfd20s2g470200000gn/T/aSljGO6feU

File::Temp-&gt;tempfile('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got /var/folders/5t/sy1gxkwj2l1gfd20s2g470200000gn/T/MGCo_TSXX5

File::Temp-&gt;tempdir ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got /var/folders/5t/sy1gxkwj2l1gfd20s2g470200000gn/T/TEAXNoECbB
</pre>
<p>We get more weird behavior.  The <code>newdir</code> method doesn't know about TEMPLATE.  And calling functions as methods is like doing this:</p>
<pre class="brush: perl; title: ; notranslate">
tempfile( 'File::Temp' =&gt; 'arg_XXXX', TEMPLATE =&gt; 'opt_XXXX' );
</pre>
<p>Again, it can't find the template and the default is used.</p>
<p>And finally, there's this:</p>
<pre class="brush: plain; title: ; notranslate">
File::Temp-&gt;tempfile(            TEMPLATE =&gt; 'opt_XXXX')
    Error in tempfile() using File::Temp: The template must end with at least 4 'X' characters

File::Temp-&gt;tempdir (            TEMPLATE =&gt; 'opt_XXXX')
    Error in tempdir() using File::Temp: The template must end with at least 4 'X' characters
</pre>
<p>Why is that an error when the previous method calls weren't?  Because it looks like this:</p>
<pre class="brush: perl; title: ; notranslate">
tempfile( 'File::Temp', TEMPLATE =&gt; 'opt_XXXX' );
</pre>
<p>Since there are an odd number of arguments, it thinks it was given a (bad) leading template and some arguments.</p>
<p>If you're ready to <a href="https://www.google.com/search?tbm=isch&#038;q=facepalm" title="facepalm" target="_blank">facepalm</a>, go right ahead.</p>
<h2>What about File::Temp 0.23</h2>
<p>In 0.23, sanity (of a sort) returns.  <strong>All</strong> the functions and methods now respect <strong>both</strong> ways of specifying a template.</p>
<pre class="brush: perl; title: ; notranslate">
tempfile            ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX'); # fine
File::Temp-&gt;newdir  (            TEMPLATE =&gt; 'opt_XXXX'); # fine
</pre>
<p>If you specify both, the last one wins, just as if you gave multiple TEMPLATE arguments.</p>
<p><strong>But there is a catch.</strong></p>
<p>Calling the functions as methods is now an error.  In 0.22, you could call functions as methods and File::Temp would (usually) just quietly give you a tempfile where you didn't expect it.  That was a bug and now it's a fatal error.</p>
<p>Here's the same test program under 0.2301:</p>
<pre class="brush: plain; title: ; notranslate">
tempfile            ('arg_XXXX'                        )
    Got arg_l2TB

tempdir             ('arg_XXXX'                        )
    Got arg_5y15

File::Temp-&gt;new     (            TEMPLATE =&gt; 'opt_XXXX')
    Got opt_sziU

File::Temp-&gt;newdir  ('arg_XXXX'                        )
    Got arg_3imY

tempfile            ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got opt_NTAn

tempdir             ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got opt_TZzT

File::Temp-&gt;new     ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got opt_CFPu

File::Temp-&gt;newdir  ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    Got opt_ueeQ

File::Temp-&gt;newdir  (            TEMPLATE =&gt; 'opt_XXXX')
    Got opt_vkNh

File::Temp-&gt;tempfile('arg_XXXX'                        )
    'tempfile' can't be called as a method at (eval 19) line 1.

File::Temp-&gt;tempdir ('arg_XXXX'                        )
    'tempdir' can't be called as a method at (eval 20) line 1.

File::Temp-&gt;tempfile('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    'tempfile' can't be called as a method at (eval 21) line 1.

File::Temp-&gt;tempdir ('arg_XXXX', TEMPLATE =&gt; 'opt_XXXX')
    'tempdir' can't be called as a method at (eval 22) line 1.

File::Temp-&gt;tempfile(            TEMPLATE =&gt; 'opt_XXXX')
    'tempfile' can't be called as a method at (eval 23) line 1.

File::Temp-&gt;tempdir (            TEMPLATE =&gt; 'opt_XXXX')
    'tempdir' can't be called as a method at (eval 24) line 1.
</pre>
<p>If you are calling functions as methods, your code will break. This is sensible because <strong>functions and method have very different scope implications.</strong></p>
<ul>
<li>Functions are "global": files and directories get cleaned up at the end of the program</li>
<li>Methods are "lexical": they return objects that clean up when the object is destroyed</li>
</ul>
<p>If you are calling a function as a method, File::Temp has no way to know which way you want it and so it can't DWIM.  So BOOM!  It dies.</p>
<p>Now go fix your code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2109/why-the-latest-filetemp-might-surprise-you/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>The Annotated Lancaster Consensus</title>
		<link>http://www.dagolden.com/index.php/2098/the-annotated-lancaster-consensus/</link>
		<comments>http://www.dagolden.com/index.php/2098/the-annotated-lancaster-consensus/#comments</comments>
		<pubDate>Fri, 19 Apr 2013 17:54:21 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[cpan]]></category>
		<category><![CDATA[perl programming]]></category>
		<category><![CDATA[toolchain]]></category>
		<category><![CDATA[conferences]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2098</guid>
		<description><![CDATA[The official Lancaster Consensus document is on Github. This blog post is an annotated review of it. The Lancaster Consensus At the first Perl QA Hackathon in 2008 in Oslo, a number of QA and toolchain authors, maintainers and experts came together to agree on some common standards and practices. This became known as "The [...]]]></description>
				<content:encoded><![CDATA[<p class="aside">The official <a href="https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md" title="Perl Lancaster Consensus" target="_blank">Lancaster Consensus</a> document is on Github.  This blog post is an annotated review of it.</p>
<h1>The Lancaster Consensus</h1>
<p>At the first Perl QA Hackathon in 2008 in Oslo, a number of QA and<br />
toolchain authors, maintainers and experts came together to agree on some<br />
common standards and practices.  This became known as<br />
<a href="https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/oslo-consensus.md">"The Oslo Consensus"</a>.</p>
<p>Five years later, at the 2013 Perl QA Hackathon, a similar brain trust came<br />
together to address new issues requiring consensus.</p>
<p>These decisions provide direction, but, as always, the speed of<br />
implementation will depend on the interests and availability of volunteers<br />
to do the work.</p>
<h2>Toolchain and testing</h2>
<h3>Minimum-supported Perl</h3>
<p>Going forward, the Perl toolchain will target Perl 5.8.1, released<br />
September 2003.  This will allow toolchain modules to reliably use PerlIO<br />
and improved Unicode support.</p>
<p>Because of the many Unicode bug-fixes in early 5.8 releases,<br />
toolchain maintainers reserve the right to later bump the<br />
minimum to 5.8.4 (which ships with Solaris 10).</p>
<p class="aside">There was huge agreement about 5.8.1, and the 5.8.4 discussion hinged on the amount of work to avoid early 5.8 bugs compared to the number of people affected, particularly given that there is <a href="http://cpxxxan.barnyard.co.uk/" title="CPXXXAN" target="_blank">CPXXXAN</a> to support older Perls.</p>
<h3>Specifying pure-perl builds</h3>
<p>Some distributions offer an "XS" version or a "Pure Perl" version that can<br />
be selected during configuration.  Currently, each of these has their own<br />
way for users to indicate this, which makes it impossible for CPAN clients<br />
or other build tools to help users select automatically.</p>
<p class="aside">For example, the version.pm module checks the PERL_ONLY environment varialbe and the following command line flags: --perl-only, --perl_only and --xs.  Other modules do it differently.  It's chaos.</p>
<p>Going forward, the "spec" for Makefile.PL and Build.PL will include command<br />
line options to request a "pure Perl only" build.  These will be:</p>
<ul>
<li>PUREPERL_ONLY=1 (for Makefile.PL)</li>
<li>--pureperl-only (for Build.PL)</li>
</ul>
<p>These may be set in the <code>PERL_MM_OPT</code> or <code>PERL_MB_OPT</code> environment<br />
variables just like any other command line option.</p>
<p>If present, distribution authors must ensure that the installed modules do<br />
not require loading XS (whether directly or via Inline) or dynamically<br />
generate any platform-specific code.  The installed files must be able to<br />
run correctly if copied to another machine with the same Perl version but a<br />
different architecture (e.g. "fatpacking" an application).  If this<br />
condition can not be met, configuration must exit with an error.</p>
<p class="aside">Fatpacking is the most common use case for this, so module authors should think about that explicitly when deciding if they can be "pure perl only" or not.</p>
<h3>Environment variables for testing contexts</h3>
<p>The Oslo Consensus defined two testing contexts: <code>AUTOMATED_TESTING</code> and<br />
<code>RELEASE_TESTING</code>.  Of these, <code>AUTOMATED_TESTING</code> has been the most<br />
confusing, as it sometimes was used to mean "don't interact with a user"<br />
and sometimes "run lengthy tests".</p>
<p class="aside">I've also used it for tests which depended on some external website working correctly.  I wouldn't want to stop someone from installing the module if it failed, but I did want to see what CPAN smokers experienced.</p>
<p>We also (briefly) discussed how some tools like Dist::Zilla are using<br />
<code>AUTHOR_TESTING</code> distinct from <code>RELEASE_TESTING</code>.</p>
<p>Distribution authors should now follow these semantics:</p>
<ul>
<li>
<p><code>AUTOMATED_TESTING</code>: if true, tests are being run by an automated testing<br />
facility and not as part of the installation of a module; CPAN smokers<br />
must set this to true; CPAN clients must not set this</p>
</li>
<li>
<p><code>NONINTERACTIVE_TESTING</code>: if true, tests should not attempt to interact<br />
with a user; output may not be seen and prompts will not be answered</p>
</li>
<li>
<p><code>EXTENDED_TESTING</code>: if true, the user or process running tests is willing<br />
to run optional tests that may take extra time or resources to complete.<br />
Such tests must not include any development or QA tests.  Only tests of<br />
runtime functionality should be included.</p>
</li>
<li>
<p><code>RELEASE_TESTING</code>: if true, tests are being run as part of a release QA<br />
process; CPAN clients must not set this variable</p>
</li>
<li>
<p><code>AUTHOR_TESTING</code>: if true, tests are being run as part of an author's<br />
personal development process; such tests may or may not be run prior to<br />
release.  CPAN clients must not set this variable.  Distribution<br />
packagers (ppm, deb, rpm, etc.) should not set this variable.</p>
</li>
</ul>
<p class="aside">AUTHOR_TESTING was not really discussed, but I included it in the writeup for completeness.  It was discouraged in the Oslo Consensus, but some people seem to have tests they want run throughout development and others they want run only at release time, so it still gets used.  For example, Dist::Zilla sets it for "dzil test" since that command is only run by authors, not by end users.</p>
<p>There are already two libraries on CPAN to make it easier to set these<br />
variables correctly:</p>
<ul>
<li><a href="http://p3rl.org/Test::Is">Test::Is</a></li>
<li><a href="http://p3rl.org/Test::DescribeMe">Test::DescribeMe</a></li>
</ul>
<p>CPAN smokers and integration testers must indicate automated,<br />
non-interactive testing and may request extended testing, depending on<br />
their resources.</p>
<p class="aside">For example, a CPAN tester may decide not to run extended testing on old, slow hardware.</p>
<p>CPAN clients are free to request non-interactive or extended testing<br />
depending on their needs or configuration.</p>
<p>CPAN smokers and clients that "must not set" a variable also must not clear<br />
it if it is already set externally.</p>
<h3>Amendments to the Build.PL spec</h3>
<p>David Golden and Leon Timmermans have been working on a<br />
<a href="https://github.com/Perl-Toolchain-Gang/cpan-api-buildpl">Build.PL</a> spec<br />
to describe how any Perl build tool using Build.PL must behave.  It is<br />
necessarily based on Module::Build, but does not need to follow its<br />
behaviors exactly.</p>
<p>The group agreed that the use and semantics of <code>.modulebuildrc</code> should<br />
be excluded from the specification.</p>
<h3>Installed distributions database</h3>
<p>One of the QA hackathon projects was the creation of a replacement<br />
for packlists.  An installed-distribution database would facilitate<br />
easy inventory of installed distributions, uninstall tools and tracking of<br />
the dependency graph of installed modules.</p>
<p class="aside">The consensus discussions were explicitly not designing the system; the brief was to answer questions about the various ways/places modules can be installed so people doing the actual design work didn't paint themselves into a corner.</p>
<p>The group agreed that because modules can be installed into many different<br />
locations, any such database would need to be "per @INC" and that it would<br />
need to stack in the same way that @INC itself does.  That means that<br />
adding paths to @INC could change what the database sees as installed.</p>
<p>Such a database system must not require any non-core dependencies, but<br />
could offer enhanced capabilities if recommended CPAN modules are<br />
installed.</p>
<p>Other implementation details are left to anyone designing such a system.</p>
<h3>Post-installation testing</h3>
<p>Several people at the hackathon have been interested in a system for<br />
running module tests after installation, for example to ensure that<br />
upgraded dependencies don't break a module or to test overall integrity.</p>
<p>The group agreed that any such testing must make all distribution files<br />
available during testing -- tests must be run from within a distribution<br />
tarball directory.  Any such tests must be run using new <code>make</code> or<br />
<code>Build</code> targets: <code>make test-installed</code> or <code>Build test-installed</code>.  These<br />
should be equivalent to <code>make test</code> or <code>Build test</code> but without adding<br />
<code>blib</code> to @INC.  The <code>prove</code> application must not be used.</p>
<p class="aside">These targets don't exist and would have to be created in each tool.  But conceptually they should work just like "make test" would, except they should run against the installed modules, not the ones built into "blib".</p>
<p>The group also agreed that any such tests need to respect how modules can<br />
be shadowed in @INC.  Setting PERL5LIB could change which is the<br />
"installed" distribution and thus which tests should run.  Coordination<br />
with an installed distribution database was encouraged.</p>
<p>Other implementation details, including whether the distribution directory<br />
is saved from the initial installation or retrieved fresh from CPAN/BackPAN,<br />
are left to anyone designing such a system.</p>
<h2>META file specification</h2>
<h3>The 'provides' field</h3>
<p>The 'provides' field of the<br />
<a href="http://p3rl.org/CPAN::Meta::Spec">CPAN::Meta::Spec</a> requires a 'file'<br />
sub-key, but the meaning was unclear for dynamically-generated packages.<br />
We agreed that the 'file' key must refer to the actual file within the<br />
distribution directory that originates the package, whether that is a .pm<br />
file or a .PL or other dynamic generator.</p>
<p class="aside">The group also agreed that having a required 'file' sub-key didn't make sense, but I realized afterwards that changing the spec would break any existing validators and that chaos that could cause wouldn't be worth the benefit.  But it's absolutely worth making it optional for whenever we get to v3 of the spec.</p>
<h3>Improving on 'conflicts'</h3>
<p>We briefly discussed some of the known problems with the 'conflicts' key<br />
within prerequisite data.</p>
<p>What most developers seem to want is a way to indicate that installing a<br />
particular module is know to break other modules of particular versions.<br />
E.g. upgrading Foo to 2.0 breaks any Bar before 3.14.</p>
<p>We encouraged anyone interested in improvements to prototype it using an<br />
<code>x_breaks</code> or similar custom key and getting patches to support it into<br />
CPAN clients.  Once battle tested, it could be a candidate for a future v3<br />
of the spec.</p>
<p class="aside">This discussion had huge risk of turning into a design discussion, so we declared that people should prototype with a custom key rather than get into a spec discussion prematurely.</p>
<h2>PAUSE and CPAN</h2>
<h3>Long-term goal for distribution-level data on PAUSE</h3>
<p>Several of the PAUSE issues discussed highlighted the need for PAUSE to<br />
maintain not just package (namespace) level index and permission data, but<br />
also "distribution" level data.  This would allow, for example,<br />
transferring permissions for a distribution as a unit instead of needing<br />
to transfer permissions on all packages.</p>
<p>We agreed that this is the right long-term goal, but that other proposals<br />
would be implemented in the near-term to solve current issues.</p>
<p class="aside">This was a classic "good", "fast" and "cheap" tradeoff.  With volunteer labor, we are "cheap".  The long-term idea was "good", but we agreed that we wanted something "fast" more than we wanted something "good" so the rest of the proposals represent what could be done quickly.</p>
<h3>Case insensitive package permissions</h3>
<p>While not discussed directly, it should be noted that PAUSE package<br />
permissions will shortly become case-insensitive, but case-preserving<br />
to ensure that indexed modules would be unique even if installed on a<br />
case-insensitive file system.</p>
<p class="aside">For example, there was a File::Stat on CPAN.  Installing it into sitelib on a case-insensitive system (like Mac OS X), meant that <code>use File::stat</code> would actually load File::Stat.  The core module would be completely hidden.  Ouch!</p>
<h3>Rules for distribution naming</h3>
<p>Many CPAN ecosystem websites and tools treat a "distribution name" as<br />
a unique identifier, even though nothing has enforced uniqueness to date.<br />
Allowing non-uniqueness is confusing at best and a security risk at worst.</p>
<p class="aside">Gory details are in this email to modules@perl.org: <a href="http://www.nntp.perl.org/group/perl.cpan.workers/2013/03/msg1047.html" title="Distribution names are not unique" target="_blank">"Distribution names are not unique..."</a></p>
<p>Going forward, distributions uploaded to PAUSE must have a name that<br />
"matches" the name of an indexed package within the distribution and the<br />
uploader must have permissions for that package or else the entire<br />
distribution will not be indexed.</p>
<p>For example, if DAGOLDEN uploads Foo-Bar-1.23.tar.gz, the distribution name<br />
is "Foo-Bar" and there must be an indexable "Foo::Bar" package within the<br />
distribution.</p>
<p>There are about 1000 distributions on CPAN that do not follow this rule and<br />
they will be grandfathered, though they are encouraged to conform to the<br />
standard either by renaming the distribution, adding a new .pm file or by<br />
introducing a properly named package internally.</p>
<p>For example, LWP ships as libwww-perl-6.05.tar.gz.  If it included <code>package<br />
libwww::perl;</code> into one of its .pm files, that package would be indexed and<br />
would conform with the standard.</p>
<p>Technically, the correct package could also be declared only in the<br />
META.json file using a 'provides' field.  In such a case the 'file' sub-key<br />
must be 'META.json' to indicate that 'META.json' is the file responsible<br />
for declaring the package.</p>
<h3>Flagging abandoned modules and modules requesting help</h3>
<p>Currently, when a CPAN author passes away, his or her module permissions<br />
are transferred to a fake author called 'ADOPTME'.  Volunteers can step<br />
up to request a takeover if they wish to maintain them.</p>
<p>We agreed that in the short-term, a similar mechanism should be used to<br />
signal abandonment or that an author is looking for someone to share<br />
responsibility.  Unlike the case where an author is deceased, these will<br />
use <strong>co-maint</strong> privileges as a signaling mechanism so that the original<br />
author may remove them as needed.</p>
<p>(In the long-term, the group hopes that a distribution-level data model for<br />
PAUSE will be able to address these needs more directly.)</p>
<p>CPAN search engines and other community sites may use these permissions<br />
markers and associated meanings to communicate the status of distributions.</p>
<ul>
<li>
<p><strong>ADOPTME</strong> as <strong>primary</strong>: this generally indicates a deceased author.<br />
Volunteers can request a takeover via modules@perl.org.</p>
</li>
<li>
<p><strong>ADOPTME</strong> as comaint: this indicates a verified, non-responsive author.<br />
The community may propose that a package be so marked following the same<br />
rules as for a take-over (i.e. multiple attempts to contact the author<br />
and a request via modules@perl.org).  Volunteers can request a takeover<br />
of an ADOPTME module via modules@perl.org without an additional waiting<br />
period.</p>
</li>
<li>
<p><strong>HANDOFF</strong> as comaint: this indicates that an author wishes to<br />
permanently give up the primary maintainer role to someone else</p>
</li>
<li>
<p><strong>NEEDHELP</strong> as comaint: this indicates that an author seeks people to<br />
help maintain the module, but plans to continue as primary maintainer</p>
</li>
</ul>
<p class="aside">It's very important that CPAN search engines treat ADOPTME differently from HANDOFF or NEEDHELP.  Flagging one's module as "NEEDHELP" shouldn't result in a big red "Abandoned module!" warning.</p>
<p class="aside">Matt S. Trout has voluntered to administer requests for modules to be flagged as co-maint ADOPTME.  Proposals <b>must</b> follow the normal rules for takeover.  You must make several public, documented attempts to contact the author publicly before appealing to modules@perl.org for ADOPTME to get comaint.</p>
<p>With the exception of a 'takeover' from ADOPTME (which must go through<br />
modules@perl.org), CPAN authors must manage these comaint privileges using<br />
the regular PAUSE interface.</p>
<p class="aside">A "takeover" from ADOPTME can be immediate because PAUSE admins already know that the author is non-responsive for whatever reason.</p>
<p>An author may also voluntarily transfer primary or co-maint to ADOPTME to<br />
indicate that PAUSE admins may transfer permissions immediately to anyone<br />
who requests it.</p>
<h3>Automating PAUSE ID registration</h3>
<p>Historically, PAUSE ID's have been manually approved, often with a<br />
substantial delay.  We agreed that assuming appropriate protections against<br />
bots/spam are in place, PAUSE should move to an automated approval system.<br />
This would bring it in line with other programming language repositories<br />
and open source community sites.</p>
<p>Additionally, we agreed that unused, inactive PAUSE IDs should be deleted<br />
and made available for reuse after a period of time.  Specifically, any<br />
PAUSE ID that ever uploaded anything must not be deleted (because the files<br />
exists on BackPAN under that PAUSE ID).  A login to PAUSE (or via a proxy<br />
like rt.pcan.org) is sufficient to indicate activity.  Inactive IDs will<br />
not be deleted without a warning message about logging in to PAUSE.</p>
<h3>Automating CPAN directory cleanup</h3>
<p>Approximately half the files on CPAN are older than 5 years.  Many authors<br />
never clean up old distributions.  In order to keep the size of CPAN down,<br />
we agreed that under certain conditions, old distribution will be<br />
automatically scheduled for deletion (and will thereafter only exist on<br />
BackPAN).</p>
<p>For a distribution to be selected for deletion, there must be at least 3<br />
stable releases.  Anything older than the oldest of those 3 will be<br />
scheduled for deletion if it is older than 5 years and is not indexed in<br />
the 02packages file.</p>
<p class="aside">This is a bit confusing, but is intended to be really conservative.  For example, if I have Foo-Bar-1.24, Foo-Bar-1.23_03, Foo-Bar-1.23_02, Foo-Bar-1.23_01, Foo-Bar-1.22, Foo-Bar-1.21_01, Foo-Bar-1.20 and Foo-Bar-1.18, Foo-Bar-1.20 is the third oldest stable release, so only Foo-Bar-1.18 would be considered for deletion if more than 5 years old and not indexed in 02packages.  The 1.23_XX and 1.21_XX dev releases will be kept.</p>
<p>All perl tarballs will be excluded from deletion, of course.</p>
<p>Scheduled deletion will notify the author as usual and they will have the<br />
usual period of time to cancel the scheduled deletion.</p>
<p>Cleanup will be implemented on some sort of rolling basis by author ID to<br />
avoid bothering authors with frequent deletion notices.</p>
<h3>Module registration</h3>
<p>The group agreed that the PAUSE module registration has largely outlived its<br />
usefulness.  Because only a fraction of CPAN modules are registered,<br />
registration does not provide a comprehensive source of metadata (e.g.<br />
"DSLIP") and much of the information registration covers is more widely<br />
available via META files.</p>
<p class="aside">One benefit if module registration is that the data can be changed without requiring a new release the way META files do.  On reflection, about the only field that matters for is the "support level".</p>
<p>The group acknowledged the remaining benefit has been that new CPAN authors<br />
often attempt to register their first module and benefit from feedback, but<br />
felt that other venues, such as <a href="http://prepan.org/">PrePAN</a>, would offer a<br />
better new author experience.  In particular, PrePAN offers community<br />
participation beyond one or two PAUSE admins and a wealth of examples to<br />
learn from (without having to search through a mailing list archive).</p>
<p class="aside">brian d foy has been the module registration hero, tirelessly responding to requests for years.  PrePAN will help share the burden and new authors will benefit from different points of view.</p>
<p>Therefore, we agreed that existing PAUSE documentation will be changed to<br />
direct new (and experienced) authors to PrePAN for guidance.</p>
<p>Soon, PAUSE will stop publishing the module registration database to CPAN<br />
mirrors.  (The index file will exist but be empty to avoid breaking CPAN<br />
clients that expect it.)  After an assessment period, module registration<br />
will likely be closed and this feature will be retired from PAUSE.</p>
<h2>Participants in the Lancaster Consensus discussions</h2>
<p>Discussions lasted over 3 days, participants came and went, but each day<br />
had about 20 people.  Thank you to the following participants:</p>
<p>Andreas König, Barbie, Breno Oliveira, Chris Williams, Christian Walde,<br />
David Golden, Daniel Perrett, Gordon Banner, H. Merijn Brand, James<br />
Mastros, Jens Rehsack, Jess Robinson, Joakim Tormoen, Kenichi Ishigaki,<br />
Leon Timmermans, Liz Mattijsen, Matthew Horsfall, Michael Schwern, Olivier<br />
Mengué, Paul Johnson, Peter Rabbitson, Philippe Bruhat, Piers Cawley,<br />
Ricardo Signes, Salve J. Nilsen and Wendy van Dijk</p>
<p>(Apologies to anyone present who was left off the list.  Email dagolden at<br />
cpan dot org or send a pull request to be added.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2098/the-annotated-lancaster-consensus/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Perl QA hackathon 2013 wrapup</title>
		<link>http://www.dagolden.com/index.php/2092/perl-qa-hackathon-2013-wrapup/</link>
		<comments>http://www.dagolden.com/index.php/2092/perl-qa-hackathon-2013-wrapup/#comments</comments>
		<pubDate>Fri, 19 Apr 2013 10:38:14 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[cpan]]></category>
		<category><![CDATA[perl programming]]></category>
		<category><![CDATA[toolchain]]></category>
		<category><![CDATA[cpan testers]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2092</guid>
		<description><![CDATA[I've been back from the Perl QA 2013 hackathon for a few days and I'm probably overdue to write about the trip. I'm intimidated by last years writeup — I must have been feeling a lot peppier on the plane a year ago. I've also been busying writing up the notes from the "Lancaster Consensus" [...]]]></description>
				<content:encoded><![CDATA[<p>I've been back from the <a href="http://2013.qa-hackathon.org/qa2013/" title="2013 Perl QA hackathon" target="_blank">Perl QA 2013 hackathon</a> for a few days and I'm probably overdue to write about the trip.  I'm intimidated by <a href="http://www.dagolden.com/index.php/1660/perl-qa-hackathon-wrapup/" title="Perl QA hackathon 2012 writeup" target="_blank">last years writeup</a> — I must have been feeling a lot peppier on the plane a year ago.</p>
<p>I've also been busying writing up the notes from the "Lancaster Consensus" discussions, so I'll keep this update on the shorter side.</p>
<h2>Wednesday: Day -1</h2>
<p>This year I flew in a day early to try to get over the worst of the jet lag before the hackathon started.  In my stupor, I converted File::Temp from Module::Build to Dist::Zilla to avoid a circular dependency and make my life a bit easier.  That required a bit of yak shaving: a pull request for Dist::Zilla::Plugin::DualLife.</p>
<p>That evening, Ian and Claire took me out for awesome tapas and then put me up in their guest room.  Thank you, guys!</p>
<h2>Thursday: Day 0</h2>
<p>I started the day with a lovely English breakfast then meandered back to Chez Shadowcat for a day alternating between hacking and crushing exhaustion.  I shipped File::Temp, reviewed the PAUSE case-insensitivity fix that Ricardo Signes and I worked on at the NY.pm hackathon in March.  I also fixed a Path::Tiny bug and discovered a <a href="https://rt.perl.org/rt3/Ticket/Display.html?id=117595" title="Perl 5.16 regression: lost warning for -l on filehandle" target="_blank">Perl 5.16 regression</a>.</p>
<p>I met several arriving hackers for lunch, caught up with friends, got myself checked into the hotel and then we all met up for great Indian dinner.</p>
<h2>Friday: Day 1</h2>
<p>I sent a pull request on CPAN.pm to make www.cpan.org the default mirror, making CPAN.pm autoconfiguration practically instant.  I talked to Matthew Horsfall about his BackPAN indexing project.  I helped Ricardo nail down a loose-end in the case-sensitivity PAUSE fix.</p>
<p>Then it was time for Day 1 of the Lancaster Consensus discussions, covering toolchain issues.  We had a group of about 20 talking intensely for about 2 hours.  Great progress, but I was pretty wiped afterwards.</p>
<p>I finished up the day by rebasing my massive CPAN.pm refactoring work from Paris up to the current master.  Ouch.  After a year of atrophy, that meant a lot of painful merge conflict resolution.</p>
<h2>Saturday: Day 2</h2>
<p>With the CPAN.pm refactoring done, I also revived my Paris work on support for "recommends" and "suggests" prerequisites.  Then I wrapped it all up into one <a href="https://github.com/andk/cpanpm/pull/38" title="DAGOLDEN unified mega patch for CPAN" target="_blank">massive pull request</a> for Andreas.</p>
<p>Next, I led Day 2 of the Lancaster Consensus discussions covering PAUSE and META issues.  Again, we had a crowd of about 20 people and talked for a couple hours.</p>
<p>Afterwards, through my haze of exhaustion, I started reviewing some abandoned work I had for improving how CPAN.pm does index lookups.  I also caucused with Andreas and Ricardo to discuss ideas for better coordinating between the perl core, the CPAN.pm distribution, and the App::Cpan distribution.</p>
<p>I grabbed Schwern to discuss how Path::Tiny should implement move/copy features.  And I debugged a weird META validation/conversion issue that Tux had with Spreadsheet::Read.</p>
<h2>Sunday: Day 3</h2>
<p>In the morning, I wrote up the App::Cpan discussions in an email for brian d foy and dug into some PAUSE issues.  The latter resulted in a PAUSE pull request to close a security hole related to the perl distribution.</p>
<p>I then led Day 3 of the Lancaster discussion, covering testing and some toolchain issues held over from Day 1.  Again, we went about two hours before wrapping up.</p>
<p>I then started work designing a new common CPAN index lookup module.  That led me to send another PAUSE pull request to get 01mailrc sorted.  I patched CPAN::Meta::Spec to clarify the 'provides' key per Lancaster Consensus discussions.</p>
<p>I also spend a bunch of time on Sunday at the venue and at dinner getting sucked into conversations with Liz about how to use PAUSE/CPAN for Perl 6 and about the semantics of Perl 6 module loading (which is lexical and thus supposed to allow loading different author/versions of the same module to be loaded).</p>
<h2>Post-hackathon, but related</h2>
<p>I wrote a draft patch for the Perl regression bug I found and sent it to perlbug.  And I wrote a PAUSE patch to encourage new authors to use PrePAN, per the Lancaster Consensus discussions.</p>
<p>I've also been writing up the Lancaster Consensus results and hope to post that soon.</p>
<h2>Acknowledgments</h2>
<p>This was my fourth hackathon and I was thrilled to have another chance to attend.</p>
<p>I want to thank the organizers, Mark, Ian and Claire, for putting together a great conference -- we were taken care of very well and they provided everything we needed to allow for a hugely productive weekend.</p>
<p>I want to specially thank Wendy van Dijk for her tireless work scribing (and typing up) the notes from over 6 hours of Lancaster Consensus discussions.  Awesome!</p>
<p>I would also like thank the <a href="http://2013.qa-hackathon.org/qa2013/sponsors.html" title="Perl QA hackathon sponsors" target="_blank">hackathon sponsors</a> whose generosity made the hackathon possible and enabled me to attend. (If you'd like to <a href="https://members.enlightenedperl.org/drupal/donate-perlqa?id=6" title="Donate to Perl QA Hackathon" target="_blank">donate</a>, it's not too late and will help support next year's QA hackathon.)</p>
<p>These companies and organizations support Perl. Please support them: <a href="http://www.cpanel.net" target="_new">cPanel</a>, <a href="http://www.dijkmat.nl" target="_new">Dijkmat</a>, <a href="http://www.dyn.com" target="_new">Dyn</a>, <a href="http://www.eligo.co.uk/" target="_new">Eligo</a>, <a href="http://www.evozon.com/" target="_new">Evozon</a>, <a href="http://www.perl-magazin.de/" target="_new">$foo</a>, <a href="http://shadow.cat" target="_new">Shadowcat Systems Limited</a>, <a href="http://enlightenedperl.org/" target="_new">Enlightened Perl Organisation</a> and <a href="http://mongueurs.net/" target="_new">Mongueurs de Perl</a>    </p>
<p>Finally, thank you to all my fellow attendees!  I hope to see you again at the next one!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2092/perl-qa-hackathon-2013-wrapup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CPXXXAN is SexPAN</title>
		<link>http://www.dagolden.com/index.php/2088/cpxxxan-is-sexpan/</link>
		<comments>http://www.dagolden.com/index.php/2088/cpxxxan-is-sexpan/#comments</comments>
		<pubDate>Tue, 16 Apr 2013 18:11:14 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[cpan]]></category>
		<category><![CDATA[perl programming]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2088</guid>
		<description><![CDATA[At the Perl QA Hackathon, I and others were constantly tripping over how to pronounce CPXXXAN — David Cantrell's family of platform-specific or Perl version-specific subsets of CPAN. Some people suggested we pronounce it "spandex" for some reason, but that's already a better fit for Chris Williams' CPANIDX modules. Only on the final night did [...]]]></description>
				<content:encoded><![CDATA[<p>At the Perl QA Hackathon, I and others were constantly tripping over how to pronounce <a href="http://cpxxxan.barnyard.co.uk/" title="CPXXXAN" target="_blank">CPXXXAN</a> — David Cantrell's family of platform-specific or Perl version-specific subsets of CPAN.</p>
<p>Some people suggested we pronounce it "spandex" for some reason, but that's already a better fit for Chris Williams' <a href="https://metacpan.org/module/App::CPANIDX" title="CPANIDX" target="_blank">CPANIDX</a> modules.</p>
<p>Only on the final night did I realize the right thing to do is to play off the "XXX" in the name and just pronounce it "SexPAN".</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2088/cpxxxan-is-sexpan/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>UNIVERSAL::new for command line MU</title>
		<link>http://www.dagolden.com/index.php/2077/universal-new-command-line-mu/</link>
		<comments>http://www.dagolden.com/index.php/2077/universal-new-command-line-mu/#comments</comments>
		<pubDate>Sat, 06 Apr 2013 03:41:58 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[hacks]]></category>
		<category><![CDATA[perl programming]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2077</guid>
		<description><![CDATA[Years ago, chromatic released Acme::UNIVERSAL::new. It was a joke. This is not. Using object-oriented modules from the command line can be a PITA. I have to type the module name twice: once to load it and once to construct objects with it. In a program, that's not huge overhead, but in a one-liner, it annoys [...]]]></description>
				<content:encoded><![CDATA[<p>Years ago, chromatic released <a href="http://p3rl.org/Acme::UNIVERSAL::new" title="Acme::UNIVERSAL::new" target="_blank">Acme::UNIVERSAL::new</a>. It was a joke.  This is not.</p>
<p>Using object-oriented modules from the command line can be a PITA.  I have to type the module name twice: once to load it and once to construct objects with it.  In a program, that's not huge overhead, but in a one-liner, it annoys me every time.</p>
<p>So I wrote <a href="http://p3rl.org/UNIVERSAL::new" title="UNIVERSAL::new" target="_blank"><strong>UNIVERSAL::new</strong></a> and a handy alias <a href="http://p3rl.org/U" title="U" target="_blank"><strong>U</strong></a>.  It lets you call "new" on a module name and have it loaded on the fly.  Like this:</p>
<pre class="brush: plain; title: ; notranslate">
$ perl -MU -we 'HTTP::Tiny-&gt;new-&gt;mirror(&quot;http://www.perl.org/&quot;, &quot;perl.html&quot;)'
</pre>
<p>If the module can't be loaded, or if the module doesn't have a "new" method, things just die in the usual way.</p>
<p>Of course, messing with <a href="http://p3rl.org/UNIVERSAL" title="UNIVERSAL" target="_blank">UNIVERSAL</a> is naughty, so save this for the one-liners, OK?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2077/universal-new-command-line-mu/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>How I&#039;ve started managing GitHub pulls</title>
		<link>http://www.dagolden.com/index.php/2065/how-ive-started-managing-github-pulls/</link>
		<comments>http://www.dagolden.com/index.php/2065/how-ive-started-managing-github-pulls/#comments</comments>
		<pubDate>Wed, 27 Mar 2013 22:59:02 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[git]]></category>
		<category><![CDATA[perl programming]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2065</guid>
		<description><![CDATA[I don't like GitHub's pull interface. They make merge commits, which suck. And I want to work from the command line, not the web site. When I noticed that I was losing on the scoreboard, I wrote a quick and dirty script to list open pull requests for a repository from the command line: github-list-pulls. [...]]]></description>
				<content:encoded><![CDATA[<p>I don't like GitHub's pull interface.  They make merge commits, which suck.  And I want to work from the command line, not the web site.</p>
<p>When I noticed that I was <a href="http://www.dagolden.com/index.php/2054/the-github-pulls-scoreboard-says-im-losing/" title="The GitHub pulls scoreboard says I'm losing" target="_blank">losing on the scoreboard</a>, I wrote a quick and dirty script to list open pull requests for a repository from the command line:  <a href="https://gist.github.com/dagolden/5258683" title="github-list-pulls" target="_blank">github-list-pulls</a>.</p>
<p class="aside">You'll need a GitHub token, as I describe in <a href="http://www.dagolden.com/index.php/1938/how-to-move-cpan-rt-tickets-to-github/" title="How to move CPAN RT tickets to Github" target="_blank">"How to move CPAN RT tickets to Github"</a>.  And you'll need to put it and your user name in your <code>~/.gitconfig</code> file.  Or you need to edit my code to store those another way.</p>
<p>It works like this:</p>
<pre class="brush: plain; title: ; notranslate">
$ cd ~/git/path-iterator-rule
$ github-list-pulls
dagolden/path-iterator-rule:

  2013-02-28T21:48:19Z Implementation for line_match and contents_match rules

    Includes test cases and documentation.

    Link: https://github.com/dagolden/path-iterator-rule/pull/8

    git-fetch-branch git://github.com/tobyink/path-iterator-rule.git master
</pre>
<p>That last line lets me copy and paste the command for another script I have that creates a local review branch of a pull: <a href="https://gist.github.com/dagolden/5258726" title="git-fetch-branch" target="_blank">git-fetch-branch</a>.</p>
<p>Here's how that one works:</p>
<pre class="brush: plain; title: ; notranslate">
$ git-fetch-branch git://github.com/tobyink/path-iterator-rule.git master
Fetched git://github.com/tobyink/path-iterator-rule.git master -&gt; review/tobyink-master
</pre>
<p>Then I can work with the local <code>review/tobyink-master</code> branch to inspect it, rebase it, cherry-pick it, amend it, run tests or whatever.</p>
<p>I'm glad the pull requests and related discussions are on GitHub, but I like working with them locally.  Now I can.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2065/how-ive-started-managing-github-pulls/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The GitHub pulls scoreboard says I&#039;m losing</title>
		<link>http://www.dagolden.com/index.php/2054/the-github-pulls-scoreboard-says-im-losing/</link>
		<comments>http://www.dagolden.com/index.php/2054/the-github-pulls-scoreboard-says-im-losing/#comments</comments>
		<pubDate>Wed, 27 Mar 2013 15:12:26 +0000</pubDate>
		<dc:creator>dagolden</dc:creator>
				<category><![CDATA[git]]></category>
		<category><![CDATA[perl programming]]></category>
		<category><![CDATA[ironman]]></category>
		<category><![CDATA[p5p]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.dagolden.com/?p=2054</guid>
		<description><![CDATA[I'm embarrassed to admit that I just fixed a bug, shipped the module, and then discovered a 2-year old pull request that fixed it better. Oops. I hate things like that! Fortunately, I just discovered that GitHub offers a pull request scoreboard with two views: Pulls sent: https://github.com/dashboard/pulls Pulls pending: https://github.com/dashboard/pulls/public Unfortunately, the scoreboard says [...]]]></description>
				<content:encoded><![CDATA[<p>I'm embarrassed to admit that I just fixed a bug, shipped the module, and then discovered a 2-year old pull request that fixed it better.  Oops.</p>
<p>I hate things like that!</p>
<p>Fortunately, I just discovered that GitHub offers a pull request scoreboard with two views:</p>
<ul>
<li>Pulls sent: <a href="https://github.com/dashboard/pulls" title="GitHub pull requests sent" target="_blank">https://github.com/dashboard/pulls</a></li>
<li>Pulls pending: <a href="https://github.com/dashboard/pulls/public" title="GitHub pending pull requests" target="_blank">https://github.com/dashboard/pulls/public</a></li>
</ul>
<p>Unfortunately, the scoreboard says I'm losing:</p>
<div id="attachment_2055" class="wp-caption aligncenter" style="width: 277px"><a href="http://www.dagolden.com/wp-content/uploads/2013/03/2013-03-27-github-scoreboard.png"><img src="http://www.dagolden.com/wp-content/uploads/2013/03/2013-03-27-github-scoreboard.png" alt="Pll request scoreboard" width="267" height="214" class="size-full wp-image-2055" /></a><p class="wp-caption-text">My Pull request scoreboard</p></div>
<p>I'll have to do something about that.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagolden.com/index.php/2054/the-github-pulls-scoreboard-says-im-losing/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
