October 2009 Archives

Shlomi Fish made a good point in a comment on Embracing (Perl) Idioms. Sometimes a novice question can trigger a huge discussion of personal style among people ostensibly intending to answer the question.

I see this often on PerlMonks. I haven't see it as often on the Perl Beginners Mailing List. I think some community differences explain this behavior.

I don't intend to answer the question of why (though that could be amusing; I find bleak amusement in certain PerlMonks threads that descend into several respondents flailing about to offer suggestions which they have obviously not tried because Perl does not work that way). I prefer to give advice for novices who want to ask questions and get useful answers.

I could recommend How to Ask Questions the Smart Way and leave it at that. You should skim that document. I know most novices won't read it in part or in full, but they should. Even so, that document doesn't answer an important question: how can I tell if the advice I've received is useful or a meaningless debate over brace placement that isn't worth my time?

There's one general rule: if you've asked a good question (per the linked document) and you've received at least one meaningful response which seems to answer your question, you can safely ignore the contents of responses which don't answer your question directly.

In other words, if anyone on PerlMonks says "I don't know, but you should always use strict and warnings," you can ignore the rest of the post.

If someone gives you an answer that seems reasonable and, after you test it locally, seems to do what you need and then offers some style advice, consider it.

If someone tells you that your entire approach is wrong and gives you an alternative which seems credible, you should consider the alternative enough to get a sense of its benefits and drawbacks. If this means posting a followup, that's fine too.

If more than one response suggests that your code is too difficult to debug without changing your style, consider it.

If every response suggests that you're doing something wrong, take that advice.

That's all well and good, but how do you tell whether approaches are matters of style or the difference between correct and incorrect behavior or maintainable or unmaintainable problems? You cheat. Run your program through Perl::Critic and see which, if any, severity level discusses the style issue. If the default, least strict severity suggests you have a style problem, address it now. If the most strict severity level is silent about your style problem, you can ignore it for now.

If the style issue is over brace placement or indentation or something P::C doesn't care about, compare your code with Perl::Tidy's reformatting and see which you find easier to read. Then ignore style discussions.

As for the rest, take advice where you can get it. A lot of experienced developers have a lot of practical experiences using and maintaining Perl programs for many years. They have written and maintained programs that solve a lot of problems. They've seen community idioms and common solutions wax and wane as community members discovered problems and new solutions and better abstractions. Don't walk away from that wealth of knowledge and advice in favor of a short-term solution. Yet also don't get confused that people care about long-term sustainability of programs and programmers; the kind of people who care about answering novice questions -- the kind of people you want to answer novice questions -- have some interest in seeing you avoid the rough spots they had to encounter the hard way.

Safety and correctness are concerns -- but P::C goes a long way to identify the most important antipatterns there. Ultimately the question of whether one construct is more readable than another depends on your preferences, the coding standards of your organization, your problem domain, and your experience and familiarity with the language and its idioms. The best thing you can do is train yourself to consider short- and long-term ideas. That's not easy, but fortunately many people answering novice questions will do so. Learn from them.

I'm a programmer. I understand Perl. I'm comfortable configuring, building, installing, patching, reporting bugs in, distributing, and depending on Perl. If there's a problem, I can report it. Sometimes I can fix it. I want to be able to depend on the fix for my problem and I want it soon and I want it available for everyone who depends on the code I wrote. There's my perspective.

Suppose instead that I were a mere distributor of Perl -- and not because my product depended on Perl in any way, but that I hope that users might be able to make products which depend on that Perl. My business isn't supporting Perl. I might occasionally report bugs and feature requests upstream. I might feed upstream patches once in a while, if I have a unique platform, but Perl and Perl support is less important to my business than many, many other things.

I'm not making this up; Nokia's Maemo deliberately ships Perl 5.8.4 and has no plans to upgrade.

I can understand their position, in some ways. They have every legal right to do this. Perl's Artistic License asserts no conditions on use (and few conditions on redistribution) for good reason.

Even so, I find the argument that it's risky to switch to a new version on its own unconvincing. The word risk alone is insufficient justification for an action or inaction. The important questions are "What are the risks?", "How likely are they?", "What consequences do they suggest?", and "How can we identify and ameliorate the risk conditions?"

Certifying and validating and demonstrating that an upgrade to a dependency works as expected and doesn't introduce new, serious problems for users. Sure, the existing version has hundreds of bugs that p5p have fixed in the past five years, but new versions of Perl may have other bugs.

The difference between does and may in that line of reasoning irritates me.

I don't have specific numbers for Nokia and Maemo. I'm not privy to private communication between company, project, and specific Perl 5 developers. I don't want to single anyone out for good or bad behavior here. I chastise in general terms. I could be wrong about specifics; as such, I welcome specific corrections.

Users will find bugs. Users will find problems. Users will report some. Users won't report others. These are truisms.

A distributed version of Perl, especially a version of Perl distributed to users via a conduit such as Maemo, reaches more and different people than a source release of Perl 5.11 intended for developers. The more people who use Perl in different ways on different platforms, the more likely they are to find different bugs.

We know that Perl 5.8.9 has many bug fixes over Perl 5.8.4. Anyone who cares to delve into the RT queue and commit log for Perl 5 can give a count of exactly how many. (Start by reading the Perl 5.8.x delta documentation for hints about the most interesting bug fixes.)

We don't know if and how many new or re-opened bugs Perl 5.8.9 has over Perl 5.8.4. We believe that number is zero. We hope that number is small. Without feedback, we don't know.

I can understand that upgrading dependencies in a distribution -- dependencies not necessarily intrinsic to the core product -- requires testing. It requires deliberate thought about risk and benefit. It also ought to require attention to upstream's release cycle and support policy and backwards compatibility.

Picking an arbitrary release on a branch created explicitly for bug fixes, maintaining backwards compatibility with all prior branch releases, and containing an extensive test suite devoted to identify and diagnose any failures -- especially when there have been five subsequent releases on that branch (and two other stable releases since then) and that branch itself has explicitly disclaimed future support for almost a year -- well, that's one way to avoid risk. (It's also a good way to avoid performance improvements, memory use improvements, Unicode bug fixes, huge regular expression performance improvements, and more in 5.10.x. You might also wonder how many CPAN distributions want to support anything older than Perl 5.8.8. Note that if Perl 5 had had yearly major releases starting in 2004, we'd be discussing the difference between Perl 5.8.4 and Perl 5.18.x.)

Pegging a five year old Perl 5 release is well within the letter of the license as well, but I think it stretches the boundaries of the spirit of working with a free software community.

The second hack in the book Perl Hacks (no link; if you download it and send me $2 and Ovid $0.50 via PayPal or wherever, we get a lot more money than we would if you bought a printed copy from the publisher, grumble grumble) talks about perldoc for a good reason. If you don't take advantage of Perl 5's copious documentation, you'll struggle learning Perl 5, far more than necessary.

(The first hack in the book is to look up distributions and documentation on the CPAN. As mst says, CPAN is my language.) Note that well-behaved CPAN distributions also include copious documentation which integrates with perldoc. I miss this in other languages.

The examples here assume you use perldoc from the command line. If that's not the case -- if you have them installed on your system in HTML form or if you prefer to browse them on perldoc.perl.org, the suggestions will still work with modifications.

Start by running perldoc perltoc. You don't have to know or understand all of this, but it gives you an overview of all of the documentation included as part of a complete Perl 5 installation. If you've never read any of the documentation before -- if you're a novice to Perl 5 in general, perhaps -- then perldoc perlintro is a quick survey of what you can do with Perl. It does presume some familiarity with programming, but if you're reading this I presume the same.

Other documentation worth skimming includes perldoc perlstyle and perldoc perlglossary. The former will help you as a neophyte understand what makes decent Perl and the latter explains several of the terms of art in the Perl community. You should also read perldoc perldoc, as it includes gems many Perl gurus don't know.

Operator and Builtin Documentation

The most useful perldoc flag is -f. After eleven years with the language, syntax rarely fools me, but I still can't remember all of the return values of caller or localtime in the right order, and I can't always remember all of the arguments to splice and substr.

perldoc -f name looks through perldoc perlfunc and displays the documentation of the builtin named name. I use this regularly:

$ perldoc -f splice
       splice ARRAY,OFFSET,LENGTH,LIST
       splice ARRAY,OFFSET,LENGTH
       splice ARRAY,OFFSET
       splice ARRAY
               Removes the elements designated by OFFSET and LENGTH from an
               array, and replaces them with the elements of LIST, if any.  In
               list context, returns the elements removed from the array.  In
               scalar context, returns the last element removed, or "undef" if
               no elements are removed.  The array grows or shrinks as
               necessary.  If OFFSET is negative then it starts that far from
               the end of the array.  If LENGTH is omitted, removes everything
               from OFFSET onward.  If LENGTH is negative, removes the
               elements from OFFSET onward except for -LENGTH elements at the
               end of the array.  If both OFFSET and LENGTH are omitted,
               removes everything. If OFFSET is past the end of the array,
               perl issues a warning, and splices at the end of the array.

This is handy if you remember the name of the builtin, but not its exact syntax or semantics. When I can't remember what I want, I read a couple of pages into perldoc perlfunc, which categorizes builtins by their uses.

Occasionally the difference between a Perl 5 operator and builtin is significant, so you have to trawl through perldoc perlop for more details. That's rarely an issue for me, but that may be how I program. Be aware of the distinction and be willing to check the other document, if necessary.

Perl FAQs

Perl 5 also includes a copious FAQ which contains a wealth of information for novices. perldoc perlfaq is a great place to start, but when I need to look something up in the FAQ, I use the -q option to perldoc:

$ perldoc -q number
Found in /usr/share/perl/5.10/pod/perlfaq4.pod
    Why am I getting long decimals (eg, 19.9499999999999) instead of
       the numbers I should be getting (eg, 19.95)?
       Internally, your computer represents floating-point numbers in binary.
       Digital (as in powers of two) computers cannot store all numbers
       exactly.  Some real numbers lose precision in the process.  This is a
       problem with how computers store numbers and affects all computer
       languages, not just Perl.

       perlnumber shows the gory details of number representations and
       conversions.

       To limit the number of decimal places in your numbers, you can use the
       printf or sprintf function.  See the "Floating Point Arithmetic" for
       more details.

               printf "%.2f", 10/3;

               my $number = sprintf "%.2f", 10/3;

This relies on a keyword search, so you have to get a keyword in the title of a question right, but if you browse the titles of the FAQ, you'll get some idea of the questions in the FAQ and the answers you can expect.

I tend to use the -f and -q switches when I know I need something in the Perl 5 documentation but I can't remember its details.

From Novice to Adept: Embracing Idioms

| 2 Comments

If you ever want to annoy a native speaker of a language you're learning, translate idioms from your primary language literally into the other language. For example, if you're learning Spanish and you come across something surprising or perplexing, yell out "¡Santa vaca!" as loudly as you can within earshot of native Spanish speakers.

The best response I usually get is "That... doesn't mean what you think it means."

I smile knowingly.

It's easy to see similar behavior from novice programmers who haven't learned the idioms of their new language, as well. Baby Perl can be clunky due to lack of understanding of language features, but it can also be clunky due to lack of understanding of language idioms.

You can see this in iterating over arrays:

# Baby Perl

for (my $i = 0; $i < scalar @items; ++$i)
{
    my $item = $items[$i];
    ...
}

... which uses the C-style for loop, introducing a temporary variable unrelated to the problem, and often succumbs to fencepost errors. The Perl 5 idiom is simple iteration with a foreach loop (spelled for because it's shorter and equivalent, keyword-wise):

for my $item (@items)
{
    ...
}

(Amusingly, when I wrote the C-style loop, I left the sigil off of $i. Although you occasionally need this type of loop in Perl 5, it's rare. I write it often enough in C that my fingers write C and never Perl here.)

Another Perl 5 idiom causes a semi-frequent misunderstanding. Here's the idiom for reading from a file through iteration, assuming you have a lexical filehandle stored in $fh:

while (<$fh>)
{
    chomp;
    ...
}

It's common to see Baby Perl which reads all of the lines of a file into an array and then iterates through that array with a C-style loop:

# Baby Perl
my @lines = <$fh>;

for (my $i = 0; $i < scalar @lines; ++i)
{
    ...
}

One problem here is the missing chomp to strip off the input record separator from each line; that bites a lot of people. Another problem is that Perl 5 isn't lazy enough to read lines only as you access them in @lines; it populates the entire array in memory. The while version is much more parsimonious. That's subtle, but it surprises people.

The biggest surprise comes from people who consider <$fh> to refer to the filehandle, when it's mere syntax for an operator named readline(). This leads to code that appears to skip every other line in a file:

# probably buggy code

while (<$fh>)
{
    my $line = <$fh>;
    ...
}

There are plenty of other interesting idioms, such as list and hash slices, true-or and defined-or assignment, the temporary empty list operator, and more. The best way to learn these idioms is to read good code. I spent a lot of time browsing PerlMonks and trying to answer questions (even if I didn't post answers). Another good approach is to browse perldoc perlfaq.

Mostly, I believe there's no substitute for experience and code review from experienced developers. It may be painful to expose your hard work to a harsh and unforgiving world, but if you can get past your ego and take the hard-won advice of others to heart, you'll always learn something interesting.

That doesn't excuse harsh, demeaning, and abusive behavior, of course -- but that's a different problem. Your local Perl Mongers group or mailing list can be a friendlier place to start than many Perl IRC channels or newsgroups. The Perl Beginners mailing list is a great resource as well. Start there.

I clean my office every couple of months. Despite a decent filing system for paperwork, a day-of-the-month accordion folder for bills and appointments, and every good intent to organize papers and books out of piles, stuff piles up on my desk until I start to lose things. Right now, if I want to take notes on a manuscript (or outline a book in pen), I have to clear off a section my desk.

Tidiness is important to working effectively. It's easier to do good things if you're not working around random debris.

As this is with my desk, so it is with code.

I can't give you a magic incantation to turning thousands of lines of spaghetti code into a well-formatted program that's easy to read, easy to understand, easy to maintain, and easy to extend, but I can explain a couple of Perl 5 tools which will help.

Perl::Tidy

The Perl::Tidy module improves the formatting of messy Perl code. There are myriad options available, but by default it's pretty good -- so good, in fact, that my ~/.perltidyrc file contains only two lines:

-ci=4
-bl

You can run the included perltidy program from the command-line:

$ perltidy my_messy_code.pl

... or you can add a macro or plugin to your editor to tidy code for you. Padre has a plugin called Padre::Plugin::PerlTidy. I have two Vim macros:

map ,pt <ESC>:%! perltidy<CR>
map ,ptv <ESC>:'<,'>! perltidy<CR>

If I type ,pt, Vim will run perltidy on the entire file. If I select a region and type ,ptv, Vim will run perltidy on the selection.

This is my first line of defense against poorly-formatted code. Better formatting often helps clarify logic and logic errors.

B::Deparse

Sometimes it's more important to see how Perl interprets code than to suss it out for yourself, especially given complex expressions. The core module B::Deparse takes a program that Perl 5 has already parsed and turns it back into source code.

You can run it from the command line:

$ perl -MO=Deparse some_bad_program.pl

... or on a specific subroutine within a file:

$ perl -MO=Deparse,a_real_mess some_bad_program.pl

... or within a Perl 5 program itself:

use B::Deparse;

my $bdp  = B::Deparse->new();
my $code = $bdp->coderef2text( \&some_awful_function );

Email::Send->new({
    mailer      => 'SMTP',
    mailer_args => [ Host => 'my.example.com' ]
})->send(<<'END_MESSAGE');
From: a_kind_person@my.example.com
To: mortified_perl_programmer@your.example.com
Subject: Here's What Your Code Really Does

$code
END_MESSAGE

Of course, you might not want to mail deparsed code to people instead of talking to them first -- but you can if you must.

Perl::Critic

After you can read the code in a proper format and understand complex expressions well enough to consider rewriting them, the Perl::Critic toolset can help you identify and avoid well-understood problems in code -- both stylistic and substantial.

The perlcritic utility runs from the command line and can identify the most egregious potential errors in a program or module:

$ perlcritic MyAwfulModule.pm my_nifty_program.pl

There are many command-line options. I like --top which finds the 20 worst violations. Severity levels range from 5 (the default) to 1 (the pickiest); select your preferred range with -n. You can customize P::C policies for your project or organization and you can add other policies as you wish.

P::C policies tend to explain themselves. That is, Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalCan has a brief discussion of why the policy exists and what to do instead. If you take the time to explore various policy violations for a codebase and consider the arguments, you'll learn a lot about writing effective Perl 5 code.

If you want to enforce site policies, the Test::Perl::Critic module is useful. The criticism pragma is another approach worth considering. Gabor Szabo also pointed out the Padre Perl::Critic plugin.

All three of these utilities have options and suggestions and nuances ripe for discovery, but all three of them can provide you an immediate benefit without requiring arduous or tedious customization.

If you want to write better Perl 5 code, start here.

I've read a lot of novice Perl code over the past decade, often in response to requests for help.

One common feature of novice code is file-scoped variables:

#! perl

use strict;
use warnings;

my @customers;   # array of customers
my $sth;         # database statement handle
my $i;           # index variable

# ...

my %records;     # hash of records

You're lucky if the code is this good; often it's face-palmingly worse, as in the case of Microsoft's awful Perl code for the 2008 Winter Scripting Games:

%dictionary = ();  # create a hash table

The problem with the big block of variable declarations is that it fails to take advantage of the notion of scope -- that you can draw a little box around a unit of code and keep certain pieces of information inside that block private to the block.

If I went to my fridge and took out the leftover pizza you were saving in your fridge for lunch, you'd be confused and upset by our haunted magic refrigerators. Similarly (if less gastronomically pleasing to me), modifying a global variable somewhere where you didn't expect it to have an effect elsewhere is confusing and frustrating.

While advocates of certain dynamic languages decry the use of variable declarations as a relic of stupid static typing systems like you might find in the C, C++, and Java languages, Perl variable declarations have an enormous benefit in clarity: they help you see the scope of variables.

Yes, this means that sometimes adding syntax to a language can improve clarity.

There's a huge difference between:

my @customers;   # array of customers
my $dbh;         # database handle
my $sth;         # statement handle

...

find_customers();

sub find_customers
{
    $sth = $dbh->prepare( 'SELECT ...' );

    while (my $row = $sth->fetchrow_arrayref())
    {
        push @customers, $row;
    }
}

... and:

my $dbh;         # database handle

...

my @customers = find_customers($dbh);

sub find_customers
{
    my $dbh = shift;
    my $sth = $dbh->prepare( 'SELECT ...' );

    my @customers;

    while (my $row = $sth->fetchrow_arrayref())
    {
        push @customers, $row;
    }

    return @customers;
}

The second code may look more complex, but it has several advantages:

  • find_customers() can modify the contents of the $dbh and @customers variables internally without affecting code elsewhere.
  • The $sth variable does not conflict with other statement handles elsewhere. As well, Perl will clean it up when the function returns.
  • find_customers() can work with several different database handles, if necessary: the code is more reusable.
  • The inputs and outputs to the function are clear: every variable used within the function has a clearly scoped lifetime.

This issue may seem like a minor quibble over style -- after all, in small programs, scope really doesn't matter -- but for programs over a few dozen lines, the decrease in the risk of error and improvement in maintainability and readability is substantial.

The Perl community has a notion of "baby Perl". It's the subset of Perl in which you can write useful, one-off programs without learning how to program Perl. It's okay to write baby Perl, but if you come back to a baby Perl program you wrote six months ago and you can't maintain it, that's because you didn't learn how to write grownup Perl.

Now that's a divisive, polemic statement -- but assume it's true for the sake of a more interesting argument.

How can you tell if you've written baby Perl? One tell-tale characteristic is that baby Perl is almost entirely ignorant of the notion of context. Context is a linguistic component (important in tagmemics, for future language archaeologists) which means that the meaning of specific units of speech depends on the interpretation of surrounding units of speech.

There are deep parallels to draw between other computer programmy notions of genericity and polymorphism, but the important point right now in Perl is that the language will do its best to treat expressions as you've treated them.

If you can parse that sentence, you can understand context in Perl. (If you can find the single errors in this sentence, you'll do just fine.)

There are many aspects to context, but one reliable indicator of baby Perl is trying to find the number of elements in an array:

sub count_elements
{
    my $count = scalar @_;
    return "You passed $count elements!";
}

I've emboldened the applicable line.

One axis of context in Perl 5 is the distinction between one and many. You see something similar related to subject-verb number agreement in English: something seem wrong about this sentence, because the number of the verb (to seem) does not agree with the number of the noun (something).

The markers for scalar/list context in Perl 5 are different. In an assignment context, a list (or aggregate variable) on the left-hand side of the assignment induces a list context for the assignment. A scalar on the left-hand side induces a scalar context for the assignment.

The context of the assignment governs the type of evaluation of the right-hand side of the assignment.

That is, if you assign an array to a list, the list will contain elements of that array. If you assign an array to a scalar, the scalar will contain the count of the number of elements in the array.

There are other rules which govern how various Perl 5 constructs behave when evaluated in list versus scalar context, but I'm focusing on the specific case of counting the number of elements in an array.

The scalar operator in the example code can serve to disambiguate context, but it's unnecessary in this case -- clear evidence that someone copied and pasted code without necessarily understanding its purpose.

This code is more likely, however:

sub count_elements
{
    my ($count) = scalar @_;
    return "You passed $count elements!";
}

Note the additional parentheses around $count. In Perl 5, this turns the left-hand side of the assignment from a scalar into a one-element list, resulting in a list context for the assignment and evaluating the argument list in list context. The scalar is there to disambiguate the context -- but that uses two unnecessary constructs.

My guess is that, in this case, the original author thought that my is a function that requires parentheses around its arguments.

Occasionally this construct appears:

my $count = $#array + 1;

I'm not sure why there's never a scalar there. The $# sigil of an array produces the index of the final element of the array. As Perl 5 arrays start at 0 by default (don't correct this in the comments -- this isn't PerlMonks; there's a karmic penalty here for showing off how clevre you are), adding one to that gives the number of elements in the array.

Sometimes it is necessary to find the index of the last element (though it's rare), but I've seen books that recommend this idiom. This is not a joke; one of them recommended this approach over the documented, clearer, and Perlish "evaluate the array in scalar context" approach claiming that scalar context was "an apparent bug which will hopefully be fixed in a future version of Perl."

If that's not an argument for learning Perl before writing about Perl, I don't know what is.

Remove the Little Pessimizations

| 1 Comment

The single most useful tip I've ever received as a programmer is a bash alias from Damian Conway.

I already had a handful of bash aliases squirreled away in my .bashrc, but he showed off an alias called realias:

alias realias='$EDITOR ~/.aliases; source ~/.aliases'

By moving my aliases into a file called .aliases and adding source ~/.aliases to my .bashrc, I could use the new realias alias to write an alias in the same shell process. Instead of logging in and out of the shell (manually suspending and resuming any work in progress) or remembering to source the same file I was editing, I could add and use an alias immediately.

I now use plenty of shell aliases.

Only after the tiny pain of setting and using a new alias went away did I realize that the change was an optimization. Put another way, Damian's trick removed a tiny pessimization. Now I use these aliases all the time. I don't have to remember all of the command-line flags to invoke Callgrind or Valgrind in the proper way to profile Parrot or Rakudo. I use the cg and vg aliases. I don't have to remember how to build or publish a book in progress; I use a book-specific alias to build and upload the new version.

When I find myself repeating a complex command line and it's suitable for an alias instead of a script, I make an alias then and there.

Imagine what would happen if we could identify and remove other tiny pessimizations.

Modern::Perl is one attempt to do so. Whenever I use that module, I know what to expect. Whenever I see code which uses that module, I know what to expect as well. I can use say wherever I want without having to remember to use feature 'say';. I don't have to remember that the feature description of given/when is switch.

Yes, these are tiny little pieces of community knowledge that are easy to learn and reasonably easy to remember and they only trip me up for a second or two when I forget them, but sometimes removing a fraction-of-a-second pessimism is enough to keep my brain focused on what I really want to accomplish, not forehead-slapping minutiae related only to the expression of my desires.

Mark Fowler called it the simplest change that'll make the most difference. Adam Kennedy says productivity sometimes means saving ten seconds here and ten seconds there.

Does this apply elsewhere? Of course.

I have more to write about operator-oriented programming languages, but consider that even C has polymorphic behavior when adding integers and floats and Java's println method supports implicit stringification, if you look at it from one direction. Imagine if you had to be explicit about only being able to print (or concatenate) strings or if you needed a special operator to add numeric values with and without decimal components.

Now ask yourself this. What if, in Perl 5, hashes didn't have a single, global iterator? What if, in the Python shell, typing exit actually exited (at least if there were no symbol called exit bound in the current scope)? What if, in JavaScript, you didn't have to create a new function to get a new lexical scope? What if... I'm sure you have your own list.

I'm not saying that these changes are easy, nor that they're simple to implement, nor that there aren't valid compatibility reasons to proceed with caution. The world's not that simple.

Even still, if we're to replace badvocacy with real, working solutions, we should also consider sanding off the tiny, rough corners of our software that individually are small, ignorable distractions. It's surprising how much easier software is to use when even one tiny pessimization suddenly disappears.

Putting a Date on Modern::Perl

| 6 Comments

I need to update Modern::Perl. I waited until the release of Perl 5.10.1. I'm going to add autodie as a dependency (but not enable it; that's for you to decide to use). I'm also going to load IO::Handle, per Yuval's suggestion in Are Filehandles Objects?.

Note that perl5i does this.

These are all simple and obvious changes. I've blocked on a larger change, related to a simple philosophical user interface question for the module:

What happens when what's "modern" changes?

Adding an installation requirement and loading two new modules won't hurt anything. It won't change any existing code. There are no compatibility concerns.

Future changes might have compatibility concerns. If you use Modern::Perl; by itself, you're taking a slight risk that you may have to revisit existing code after an upgrade. What's modern in August 2009 might not be as modern in August 2010 and certainly won't be modern in August 2019.

Elliot Shank wrote in A reasonable approach for Modern::Perl the example code:

use Modern::Perl as_of => '2009-06-23';

What do you think?

I'd like to avoid complex date parsing where possible. I've also considered changing M::P version numbers to dates like 2009.10.06. The unification is tempting and the implementation is, at worst, of only modest difficulty.

What do you think?

(One other requested change is to enable no Modern::Perl;. I'm considering the best way to do so.)

Why Perl 5.11.0 Matters

Jesse Vincent announced the Perl 5.11.0 release.

Perl 5.11.0 is the first release in the development track of Perl 5. Perl 5.11.x will become Perl 5.12.0 at some point in the future. 5.11.0 represents years of development -- patches, branches, backports, changes, bugfixes, cleanups, rephrasings, and lots of work behind the scenes to improve the Perl 5 language.

The most important part of the release announcement is the schedule for subsequent releases in the Perl 5.11.x family: a new development release every month on the 20th. Jesse's announcement explains that the intent of the new development model is to avoid burning out the brilliant, dedicated, and valuable people who've been pumpkings before. That's important.

There are other valuable results of this change, though. The most important is that Perl 5.11.x reduces risks associated with developing and releasing Perl 5.12.0:

  • The release process itself has changed (and will continue to change) to make monthly releases possible. The release process won't scale if it takes a week's worth of effort on the part of any individual. Yet monthly development releases are much less risky than supported releases; a bit of confusion or a delay is less dramatic.
  • The development process will (likely) fall into a cadence around the monthly releases. Even though development releases can have less polish than a supported release, no one wants to release an uninstallable tarball which fails important tests. This provides a pressure to keep the trunk stable and to merge destabilizing changes just after a release.
  • Multiple potential release managers remove the bottleneck on one individual, require a well-understood, documented, and automated release process, and allow anyone trustworthy to step in at the last moment.
  • Writing release notes which represent a month's worth of work is easier than writing release notes (and changelogs and...) that represent a year's worth of work. The release notes and deltas for Perl 5.12 should be a concatenation of the release notes and deltas for all releases in the Perl 5.11.x family.
  • Regular releases improve the testability of software by providing a convenient point for mutual debugging. Bisecting a month's worth of changes to find a bug is easier than bisecting a year's worth of changes to find a bug.
  • Experimental features can reach a wider audience of testers and developers without p5p committing to supporting those features as-is (or at all) in stable releases. Faster feedback is always useful.

I suspect -- but cannot prove yet -- that regular releases will improve the velocity of Perl 5 development as well as improving the long-term planning of Perl 5. That'll be easier to measure by early 2010.

Congratulations to Jesse and all of the other Perl 5 committers.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide

Categories

Pages

About this Archive

This page is an archive of entries from October 2009 listed from newest to oldest.

September 2009 is the previous archive.

November 2009 is the next archive.

Find recent content on the main index or look in the archives to find all content.


Powered by the Perl programming language

what is programming?