Just A Summary

Piers Cawley Practices Punditry

Ruby

Falling out of love with a language

So, Giles Bowkett asked me on facebook “Why Perl?”. This is the long answer.

I’m a Perl hacker. I have been for around 16 years now. Around 5 years ago, prompted by the Pragmatic Programmer and Adam Turoff, I started looking at Ruby, and Ruby on Rails and sort of fell into maintaining Typo.

Why? I was getting hacked off with Perl.

I was coming to the end of my tenure/tether as Perl 6 Summarizer: watching a language that I still want to use before I die taking forever to get done gets wearing after a while, especially when you’re spending 8 hours a week summarizing the activities of a development community that, in parts, was verging on the toxic (it’s way better now).

I was also getting annoyed by small niggles in the way Perl 5 works. This was in the days before Moose. Stevan Little was just starting work on what became Class::MOP (as a prototype of Perl 6’s metaobject protocol) and way before the days of Devel::Declare.

Ruby seemed to be, as Matz has described it, “Perl, done right”. All the things that were pissing me off about Perl were so much easier in Ruby. I’ve joked, in a Ha Ha, only serious kind of way, that I left Perl for Ruby because I got fed up of unrolling @_, but there’s more to it than that. “Objects everywhere” fits my head. The language is dynamic. Ruby code had less boilerplate in it. Oh, and Ruby on Rails was looking very cool, even if David Heinemeier Hansson didn’t seem to have a clue about RESTful/Resourceful principles (he has rather more of a clue now). The community looked vibrant. What’s not to like?

I was a very happy Ruby programmer. It’s a great language. If you haven’t taken it out for a spin round the block, you should give it a try.

A Perl 5 rennaissance

While I was away on my failed attempt to become a maths teacher and then my Ruby sojourn, Perl 5 was waking up. If Perl 6 were declared a failure tomorrow by the people who are actually working on it (as opposed to the people who aren’t working on it, but bitch about it anyway – see some of chromatic’s more intemperate posts about those people), then it will still have had value for the way it’s inspired members of the Perl 5 community to nick the good bits and make them happen in Perl 5.

Stevan finished Class::MOP and it got used as the basis for Moose, which is essentially a layer of sensible defaults which sits on top of the insanely configurable and slightly more agnostic Class::MOP, which in turn sits on Perl’s weird reduced instruction set object orientation. Moose even got fast enough that it’s usable in polite company (it was always faster than Ruby), so people did. It grew an ecosystem.

Another, more recent development, is Devel::Declare. Devel::Declare is, in accordance with the long history of Perl, completely batshit insane. What it does is lets you trip the perl parser up and, while it’s standing there looking at the pretty birds flying around its head, you can run ahead and rewrite the code that it’s about to parse. Well, I say run, but what I mean is hobble ahead wearing narrow blinkers and mittens. You can accomplish amazing things in such circumstances, but it’s not fun. Devel::Declare enabled my current favourite module on CPAN: MooseX::Declare, which I’ve talked about here:

An introduction to MooseX::Declare from Piers Cawley on Vimeo.

MooseX::Declare lets me kill boilerplate. Instead of writing:

package Something;
use Moose;

has an_attribute => (is => ‘rw’);

sub a_method {
my($self, $with, $parameters)
= @_;

}

I can write:

use MooseX::Declare;
class Something {
has an_attribute => (is => ‘rw’);

method a_method($with, $parameters) { … }

}

which makes me happy. This is being done by a module which is written in Perl. It relies on a couple of modules that are implemented in C, but the bulk of the work is done in Perl itself.

So, that’s addressed one of the annoyances that led me to Ruby. What about ‘objects everwhere’. I got used writing things like:

5.times { |each| … }

Surely I’m not going to able to write:

5→times(sub {…})

in perl?

Well…

use Moose::Autobox;
sub Moose::Autobox::SCALAR::times {
my($count, $block) = @_;
1→to($count)→each_key($block);
}

5→times(sub {$_→say});

Bingo! I’d like to be able to write 5->times { $_->say } but can’t quite manage it. Give PerlX::MethodCallWithBlock a little more time though…

So, while I was away, most of the issues I had with Perl, issues that had driven me into the arms of Ruby, had been addressed.

It’s not about the bike

The new Perl tech is great, but all it does is removes barriers. I wasn’t attached to the Perl language by some huge bungee cord which was crushing me against these barriers while I sojourned in Ruby land, all the while pining for Perl. I was loving Ruby. It’s a great language.

What I am attached to is the group of friends I’ve made in the Perl community over the years. Many of whom I’ve never actually met face to face.

I felt like such a curmudgeonly old fart in the Ruby community (more specifically, the Rails community). Everything’s shiny and new and awesome. And, I suppose when you’re coming to the language from something like PHP, it is shiny and new and awesome. But it gets wearing after a while. And the arrogance? My dear! The arrogance! Admittedly, some people have a lot to be arrogant about – I still cheer DHH’s “Fuck you!” slide, but others… not so much. The kind of “Look! Ruby is uniquely suited to writing DSLs!” bullshit1 that sends chromatic off in fits of apoplexy annoyed me too, especially when I was looking at the kind of examples they were presenting as exemplary and remembering Perl from 5 years before that did the same thing but with cleaner language-like interfaces.

Coming back to Perl may well be a straightforward retreat to competence. I may be rationalizing like mad. But right now, it feels like I left Ruby because the ruby community, in the West at least, isn’t a fun place for me to be. The sexism is just the icing on that particular cake.

1 Here’s my response to Rspec:

testclass exercises Something {
test that we can create an object {
isa_ok $test→subject→new, ‘Something’;
}
}

Note the lack of perlish furniture in the test that we can create an object part. No need to quote the strings, no meaningless dos scattered about the place, no :symbols appearing at random. Okay, so I have to quote 'Something' in the implementation block, but the implementation block is unadulterated Perl. I don’t claim that only Perl can do this. I do claim that, right now at least, Ruby can’t.

Published on Wed, 10 Mar 2010 02:03:00 GMT by Piers Cawley under , , . Tags , ,

Twice now

In Ruby, when you’re doing division on integers, things can get a little counter intuitive. For instance, 6/4 is obviously 1. At least, it is until you decide that you’d rather have numbers that behave a little more like ‘real’ numbers and you do require 'mathn', a module in the Ruby standard library (ie, it comes as part of ruby). Then you enter a whole new world of rational maths, where 6 / 4 returns 3/2.

Several very fine and useful Ruby gems rely on the workings of mathn, including ruby-units, which is a spiffy tool for avoiding problems when one team is working in kilometres and the other in miles and it’s no fun at all when your space probe is suddenly incommunicado.

Other fine and dandy Ruby gems include ultrasphinx and webrat. Both of these two (and no doubt others) rely on the the fact that 302/100 == 3.

Hmm… can you see my problem?

Please, if you’re working on a gem that you intend to publish widely, then adopt the practice of never trusting that dividing an integer by another integer will return a third integer. You’re not even making yourself a hostage to some other gem, you’re making yourself a hostage to the standard library. Always do (an_integer / another).to_i and your code will be so much more robust.

I’ve got a pull request and lighthouse ticket in for webrat and, once I’ve hit ‘publish’ on this post, I shall be doing the same thing for ultrasphinx, but I’m sure there are other gems out there with the same problems. Please people, check your assumptions.

Published on Wed, 25 Nov 2009 16:49:00 GMT by Piers Cawley under , . Tags , ,

London.pm Presentation Video

Back in (crikey) February, I gave a talk at the London Perl Mongers’ technical meeting about Moose for Ruby Programmers and wrote it up here. Mike Whittaker was in the front row of the audience with his iPhone and, a couple of minutes in, started a voice recording and gave me a copy.

So… finally… I’ve taken the time I should have been using to write another article for The H and wrestled the slides and the audio into something like sync and uploaded the results to Vimeo for your viewing pleasure.

An introduction to MooseX::Declare from Piers Cawley on Vimeo.

Published on Wed, 13 May 2009 08:28:00 GMT by Piers Cawley under , , . Tags , , , , , ,

Writing parsers for fun and convenience

One aspect of coming back to Perl for ‘recreational’ programming is that if, like me, you’ve declared war on @_ and boilerplate code, then testing can be somewhat trying. The Perl testing framework that best fits my head is Test::Class, which is an excellent Perlish implementation of xUnit style testing. If you’re unfamiliar with the, library, Ovid is writing what’s shaping up to be an excellent series of introductory articles about it at http://www.modernperlbooks.com/.

The problem I’m having with Test::Class at the moment is that I can’t write:

use MooseX::Declare
class Test::Person
extends Test::Class
{
use Test::Most;

method class_under_test {’Person’} method startup : Test(startup => 1) { use_ok $test→class_under_test } …

}

Test::Class is doing too much in its initialization phase, and relies too heavily on code attributes, for it to play well with MooseX::Declare. Drat.

On reflection though, this might be a good thing, because maybe MooseX::Declare isn’t really what’s needed. What I’d like to write is something like:

use …;

testclass Test::Person
exercises Person
{
startup class under test should be usable (1 test) {
use_ok $test→class_under_test
}
}

And have the library ‘…’ expand the testclass declaration into something that looks like the first code snippet. After all, if MooseX::Declare can work without source filters, it should be possible to come up with something nicely declarative for specifying test classes.

Obviously, there’s nothing on CPAN that does this yet though. So I went fossicking through MooseX::Declare to see how it works1 and discovered thing of Lovecraftian beauty that is…

Devel::Declare

Devel::Declare is possibly the most hostilely documented library I’ve ever come across. Its documentation only begins to make sense when you already understand enough about how it works that you don’t really need the docs. What it does is to let you declare your own Perl keywords. You could, for instance use it to introduce given/when into versions of Perl that don’t have it yet. You declare your keywords and associate them with parsers. When, during its compilation phase, perl hits one of your keywords in the right context, it hands off to your parser which can then do what the hell it likes in the way of code transformation, before handing control back to Perl, which then parses the transformed code as if that was what was there all along.

So, to want to transform that testclass syntax I just pulled out of my ass into a real Test::Class package, I just need to write an appropriate parser and code generator, perform the appropriate Devel::Declare incantations, and I’m laughing.

Making progress

So far, I’ve got to the point where I have a working testclass keyword, but nothing yet for the ‘inner’ bits (setup, test, teardown, etc). I can write:

testclass Test::Person
exercises Person
{

}

testclass Test::Person::Employee
extends Test::Person
exercises Person
{

}

and, as I write this, I’m realising that the syntax I’d cooked up for using extra test helper modules:

testclass AnotherTest
helpers -More, -Exception, Carp
{

  1. use Test::More;
  2. use Test::Exception;
  3. use Carp;

}

would probably read better as:

testclass AnotherTest
+uses Carp
{

  1. use Test::Most;
  2. use Carp;

}

and also that I want this:

testclass exercises Person {

}

to build me a Test::Person class.

What’s still blowing my mind about Devel::Declare’s possibilities is that I’m no longer constrained to writing a Domain Specific Pidgin which works by building a tower of proxy objects and weird evaluation contexts to produce something that’s legal code in the host language, but which has the feel of another language. With Devel::Declare, I control the horizontal and the vertical until I choose to hand control back to Perl. Right now that means my error reporting is disgracefully bad, but it also means that I can roll a syntax that makes sense without worrying about how I’m going to get perl to parse it.

One of the things I find frustrating about writing RSpec specifications is that describe and it both want to be first class keywords – it feels like you should be able to write:

describe SomeClass, “in some context”
before each

  1. set things up
    end
it “should do something or another” … end

end

But, because RSpec works by taking advantage of Ruby’s block magic, you have to write:

describe SomeClass, “in some context” do
before :each do

  1. set things up
    end
it “should do something or another” do … end

end

I definitely prefer the version without the extraneous dos and the gratuitious : before each in the before declaration. Does anyone feel like writing devel/declare.rb?

Show us the code!

If you want to see the current state of my Test::Class::Sugar art, the place to look is http://www.github.com/pdcawley/test-class-sugar. At the time of writing it relies on http://www.github.com/rafl/devel-declare and doesn’t have anything so useful as documentation, a Makefile.PL or even any tests beyond the collection of code samples that is t/initial.t. Expect all those when and if I push it to CPAN.

Caveats

Yes, I know that this sort of metasyntactic abstraction is trivial in a Lisp. I just happen to like syntax, okay?

Update 20090312

use Test::Class::Sugar

testclass exercises Foo
+uses -Warn
{

}

Now generates

{
package Test::Foo;
use base qw/Test::Class/;
use Test::Most;
use Test::Warn

}

So that’s one hurdle jumped. And I now know how to write the various method helpers and, when I get the appropriately shaped tuits, I shall actually write the damned things.

Then all I have to do is document it.

And write up a proposal about it for YAPC::Europe.

Update 20090314

I now know what a plan looks like:

test with multiple assertions << 3 {…}

And, more importantly, I’ve implemented, and documented everything and am almost good to cut a 0.001 distribution. I need a few ducks up on CPAN, but once that’s done, we’re good and I can get on with parameterizing some of the assumptions that are hard coded at the moment.

1 Something I swore blind I wasn’t going to do in my London.pm presentation. Seems my word isn’t to be trusted…

Published on Wed, 11 Mar 2009 22:29:00 GMT by Piers Cawley under , , . Tags , , , , , , , ,

Perl: Test Infected since 1987

Here’s something interesting. This is the test directory from the very first version of Perl, released in 1987 and described by Larry as ‘a “replacement” for awk and sed’. Day one of Perl, and we already have the bare bones of the Test Anything Protocol and a prototype for Test::Harness in the TEST file.

If we truffle about in the various other branches we find other useful milestones for module developers:

  • 5.000, in 1994 came with the first iteration of h2xs which could be used to generate the basic boilerplate for a perl module. Even today, with more sophisticated module starters available, you won’t find a CPAN module of repute that doesn’t follow the basic directory structure laid down in this utility. ExtUtils::MakeMaker generates a Makefile with a test target which runs all the tests in the t subdirectory
  • 5.002, in 1996, h2xs starts stubbing test.pl
  • 5.003_12, late 1996, first version of CPAN in the Perl distribution. From day one, CPAN would not install a module if any tests failed, unless you forced it.

Meanwhile, Ruby:

  • Has only recently embraced a language test suite
  • Appears to have no standard layout for gem distributions
  • Doesn’t run tests as part of the installation process for a new gem

Is it any wonder that chromatic gets a little cranky when sweeping claims are made about how spiffy Ruby’s testing culture is?

There are those who claim that CPAN is Perl’s shining glory, but it’s not really the collection of servers, it’s the toolchain that enables it, and that toolchain can exist because so many libraries follow a pretty minimal set of conventions.

I’d love to see the Ruby community settle on a similar, single, set of conventions for the way things should work. Start with a guarantee of a either a top level Rakefile or setup.rb with build, test and install tasks. Make rubygems run the tests before installation, if the target is available, and halt the installation if they fail. Make it easy to send reports of test failures to module authors (look at the Perl CPAN and CPAN Testers sites, and their associated tooling for ideas).

I know… I should STFU And Write Some Code.

Update

Further investigation shows that gem install -t whatever does run the tests as part of the installation process. The capability is there, but it’s turned off by default. How depressing.

Published on Wed, 04 Mar 2009 16:33:00 GMT by Piers Cawley under , , . Tags , , ,

Things that may inspire me to hunt and kill you

Let’s say you’re writing a ruby library. Something you want and expect others to use. Here’s how to reduce those others to incandescent rage:

require ‘rexml’

include REXML

module MyShinyModule

end

No. Not no how. Not never. You just crapped in my namespace and stomped on who knows how many of my own classes. Now, include is a fine and dandy thing, and it certainly has its uses, but using it at the top level of your library files is not one of them.

Ahem.

Can anyone guess which library has been wasting my morning?

Published on Thu, 26 Feb 2009 09:24:00 GMT by Piers Cawley under , .

Moose for Ruby programmers

‘Moose for Ruby Programmers’ was the programmed title for the talk I gave at the London.pm technical meet on Thursday, but that was something of a stalking horse for the real title, but I’ll save that for the end of this writeup.

Why Ruby?

I’ve said this before, and I’ll no doubt say it again, but the main reason I started programming in Ruby was that I got fed up of unrolling @_. From a Perl programmer’s perspective, Ruby is like Perl 5, but with a way better object system out of the box.

What’s so awful about unrolling @_?

Think about the way we program has changed over time. There’s been a trend of replacing conventions with code or, to look at it another way, of replacing imperative code with declarative code.

An example

Here’s some pseudo code explaining how we used to do code reuse back when everything got written in assembly language:

save stuff we need later
put the RETURN label on the stack
put arguments on the stack
goto FUNC_FOO
RETURN:
# return in accumulator
# saved values on the stack

Every time we called another bit of code, we had to jump through all these hoops in order to manage the resources of the machine. The particular sequence of hoops used within a program or library is called a calling convention. Nowadays we don’t have to do all that explicit control stuff, we just make a function call. Instead of a chunk of imperative code, we simply declare that we’re making a function call and let the computer do the bookkeeping.

On the other side of the function call, our function fulfils its side of the conventional bargain:

FUNC_FOO:
pop arguments
# maybe check types
# do the real work of the function,
put the result in the accumulator register
pop continuation
goto continuation

Of course, it’s much easier in a high level language like Perl:

sub somefunc {
my($argument) = @_;
$argument→isa(Whatever) or die;
# do stuff
return $result;
}

Hmm… actually… okay, so we’re not having to manage the call stack in Perl, but we’re still writing imperative code just to give names to our parameters. Meanwhile, in Ruby, we have:

def somefunc(argument)
argument.is_a?(Whatever) or raise
# do stuff
return result
end

One line shorter, and we get to name our parameters in a declarative style. We’re still stuck with imperative code to do the type checking, but we’ll live.

It seems such a silly reason to switch programming languages doesn’t it?

Wading in treacle

The trouble is, unrolling @_ is like wading through treacle. It exerts a great deal of drag. When every function you write carries with it the need to write a little bit of custom code just to do the simplest of tasks every time, it’s awfully tempting to just stick another level of indentation into your function and leave your worries about the Single Responsibility Principle to one side. I mean, what’s a 127 line method or two between friends?

And those little bits of custom code are great places for silly little bugs to hide. Most measures of defect rates seem to suggest that defects per line is pretty much constant across languages. There’s a very real benefit in writing concise, expressive code and that benefit isn’t simply the programmer’s idea of elegance. Concise languages “make the easy things easy, and the hard things possible”. If your programming style is heavily object oriented, Perl 5 doesn’t make the easy things as easy as they could be (and are in other languages). Ruby, for me, hit that sweet spot — it feels sufficiently perlish to make the transition easy, and its syntax for making classes and methods kicks Perl’s arse.

Of course, after a while, you’ll start hitting other limits and annoyances in Ruby (just as you will in any other language), it’s software after all and rule 1 of software is “Software sucks”.

The Moose effect

Although, in recent years, I’ve been pretty much exclusively a Ruby programmer, I’ve kept my eye on Perl and it’s been almost impossible not to notice the rise of Moose. To a Ruby programmer, I’m sure that the very idea of Moose would seem silly. Having to install an entirely new package and its dependency chain just to get something that looks a bit like Ruby’s class objects and accessor method auto generation? Are you kidding? Ruby’s stuff is good enough.

I used to think Perl’s OO was good enough.

It turns out that it is. Because if there’s one glorious thing about Perl it’s malleability. There’s very little you can’t change if you’re prepared to delve into the weirder bits of the way the runtime is put together. And, for all Perl has a reputation for oodles of syntax and weird special cases, once you get down to the bones, it’s consistent. The syntax to get there can be horrible, but the structure makes sense. So Perl has just enough object support for sufficiently clever programmers to build something really decent.

Here’s a bit of noddy code to show you what I mean. First, a ruby version and then I’ll show you the Moose equivalent.

class Article
attr_reader :title
def title=(a_string)
raise unless a_string.is_a?(String)
@title = a_string
end

attr_reader :body def body=(a_string) raise unless a_string.is_a?(String) @body = a_string end def initialize(initial_values = {}) self.title = initial_values[:title] end def print_on(html) html.h1(title) html.div(class => ‘body’) { body } end

end

And here’s the Perl equivalent.

package Article;
use Moose;

has title => (is => ‘rw’, isa => ‘Str’);
has body => (is => ‘rw’, isa => ‘Str’);

sub print_on {
my($self, $html) = @_;
$html→h1($self→title);
$html→div(
$self→body,
class => ‘body’
);
}

Note that the Ruby version omits the detailed error reporting of the Moose version, and if I were writing a real Ruby class, I wouldn’t bother with type checking something as simple as a string. It’s not really a fair comparison (I could tilt things far more steeply in Moose’s favour by using some of the more sophisticated attribute declaration possibilities that Moose offers).

The important thing to remember is that accessor methods are the most boring bits of writing a class. The interesting bits are the methods that do stuff. There’s a school of thought that says that accessor methods should be private (or at least protected) – otherwise you’re just using data structures with benefits. In any class worthy of the name, there will be more methods that do stuff than accessors after all, and I definitely prefer the Ruby version of print_on to the Moose one.

However, if we sprinkle a bit of magic dust on the Perl version, we have:

use MooseX::Declare;

class Article {
has title => (is => ‘rw’, isa => ‘Str’);
has body => (is => ‘rw’, isa => ‘Str’);

method print_on (Document $html) {
$html→h1($self→title);
$html→div(
$self→body,
class => ‘body’
);
}
}

I still find myself pinching myself when I see that. I can’t quite believe it’s still Perl 5 and I haven’t fallen through a wardrobe to a magical land where everything is flowers and ponies, and Perl 6 Christmas has arrived at last after too long a winter1.

But it is Perl 5 and it’s here now. Sort of (see Caveats below).

How does it work?

I neither know nor care2. As far as I’m concerned it’s sufficiently advanced rocket science and I’ll leave it at that. I’m just glad to be able to use it. About the only thing I can say with confidence about it is that Florian Ragwitz, Ash Berlin, Stevan Little and all the other who’ve made this possible are geniuses.

There’s more to it, of course, but the documentation covers things in
more detail than I’m happy to write here, so I’d suggest you read that if you want to know more. Generally, things just work the way you’d expect them to.

Caveats

This is seriously bleading edge code. There are bugs (though substantially fewer of them today than there were when I delivered the talk on Thursday), and you will trip over them. And when you do, the error reporting currently leaves something to be desired3, but it’s improving in leaps and bounds. The more people who are using it, the more people there are to submit patches (and a patch to the test suite with a bug and no fix is just as welcome as a patch that includes a fix).

So, if you’re starting a new project, you should consider going one step further than Moose, and using MooseX::Declare. Heck, if you’re feeling courageous, you should consider using it in existing projects as well. You can introduce it piecemeal after all – you can simply use class Foo {...} and only gradually introduce the extra method goodness as you refactor existing methods.

The real title

I knew I’d forgotten something. The real title of my talk was MooseX::Declare — Why I came back to Perl

1 I can’t quite believe I just used that metaphor.

2 Not quite true. It’s important that MooseX::Declare doesn’t use source filters, and it doesn’t, so that’s all right.

3 That’s the error reporting that happens when you trip a bug, not when you, for example, call a method that that expects an argument of one type with an argument of the wrong type, which is pretty exemplary.

Published on Sun, 22 Feb 2009 15:04:00 GMT by Piers Cawley under , , .

Marking time...

So, it turns out that there’s a recording of my MooseX::Declare talk at the London.pm techmeet last night. And, on listening to it, I sound rather less incoherent than I thought I did while I was delivering it (still plenty of places where I could improve. Must remember to always repeat the questions in full…), but I’m happy enough with it that I’m looking into synching it up with the slides and making a slidecast, which will probable take longer than is sensible.

So, while I do that (and write it up properly as well), I thought I’d cover something I mentioned as a throwaway about using MooseX::Declare to easily set up what I called nonce classes for testing. A nonce class, in this context, is a one shot class that you can use to test inheritance, or to provide just enough behaviour to test the class you’re actually testing or whatever.

In ruby, it’s pretty simple really:

class Child1 < Announcements::Announcement
  attr_accessor :message
end

class Child2 < Announcements::Announcement; end

class GrandKid < Child1; end

Because ruby was designed as ‘Perl with better OO’, it has a convenient, compact notation for making classes, which means it’s easy and quick to define new classes, as you need them, near to where you’re going to use them. Which is very helpful in tests.

Meanwhile, in Perl, its a wee bit more… clunky. Assuming we’re using Moose, we have:

package Child1;
use Moose;
extends 'Announcements::Announcement';

has message => (is => 'rw', isa => 'str');
no Moose;

package Child2;
use Moose;
extends 'Announcements::Announcement';
no Moose;

package GrandKid
use Moose;
extends 'Child1';
no Moose;

Yikes.

So, let’s sprinkle some MooseX::Declare magic dust over things:

use MooseX::Declare
class Child1 extends Announcements::Announcement {
    has message => (is => 'rw', isa => 'str');
}

class Child2 extends Announcements::Announcement {
}

class GrandKid extends Child1 {
}

So, even if you completely eschew the really sexy bits of MooseX::Declare and simply use its new syntax for declaring classes, you’ve still improved your golf score and reduced your hoop count.

Published on Fri, 20 Feb 2009 18:41:00 GMT by Piers Cawley under , , . Tags , , ,

Warnings are the new test failures

Have you ever tried to run Rails, Rspec, Rake or, for that matter almost any Ruby library or application that you’ve ever heard of with the -w flag? How about running Rails with taint checking on?

They aren’t exactly pleasant experiences.

Meanwhile, over in Perl land, it’s a very rare module indeed that isn’t at least clean under -w and, where appropriate, taint friendly. It would be a very irresponsible Perl Monger indeed who wrote a web framework that didn’t assume it was going to be running under the -T flag. Warnings and taint checking are annoyances, and sometimes they’re flat out wrong, but more of the time they’re useful. Which is why, in Perl, you’ll sometimes see blocks of code like:

{
no warnings;
# Code that does stuff which would trigger a warning
}

If the author is being particularly careful, she will specify which warnings to suppress – after all, there’s no need to turn off all the warnings if all you’re intending to do is redefine a method. So the prudent Perl programmer would write:

{
no warnings ‘redefine’;
# Code that redefines an existing method
}

However, there are often ways of achieving your aim even with all the warnings on.

If modules that don’t have use warnings are rare on CPAN, modules that don’t have use strict will get the unwary programmer laughed at in the street. There are modules that simply won’t work under use strict, but they tend to have no strict, either wrapped around the narrowest scope that won’t work under strict, or proudly displayed up front. The presence of a no strict implies to the interested reader that the programmer knows (or thinks he knows) what he’s doing. Writing code that does even the most implausible metaprogramming things without raising errors from strict or spamming STDERR with warnings is a matter of professional pride. Writing straightforward code that stays silent is the absolute baseline for Perl programming professionalism in my book.

Meanwhile, here in Rubyworld, there’s no equivalent of strict and it’s actively hard to start coding with warnings turned on because important frameworks like rspec and rails aren’t -w clean. In Perl, this isn’t a problem, use warnings turns warnings on lexically. Your code might well call all sorts of noisy code elsewhere but, unless you’re running with -w as well, you’ll only see the warnings for your code. If you set $VERBOSE, you’ll get all the warnings. Warnings in the log file should be like red Fs in your test output – a sign that all is not as good as it could be in your code. Sure you could just ignore the ones you know are harmless, then you’re in danger of losing the real problems in the noise.

As a gesture of goodwill, here’s alias_method_chain written so it should raise no warnings except when the ‘without’ method already exists.

def alias_method_chain(target, feature)
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ’’), $1
yield(aliased_target, punctuation) if block_given?

with_method, without_method = “#{aliased_target}_with_#{feature}#{punctuation”, “#{aliased_target}_without_#{feature}#{punctuation}”

alias_method without_method, target
remove_method target # Warning begone!
alias_method target, with_method

case
when public_method_defined?(without_method)
public target
when protected_method_defined?(without_method)
protected target
when private_method_defined?(without_method)
private_target
end
end

Published on Thu, 18 Dec 2008 10:10:00 GMT by Piers Cawley under , , . Tags , , ,

If you're going to add a hook, make it a big one

Jay Fields responds to on Ola Bini’s Evil Hook Methods? about the common ruby idiom that lets us write:

class Fruit
  include DataMapper::Resource
  property :id, Integer, :serial => true
  property :name, String
  property :notes, Text, :lazy => false
end

What Ola and Jay don’t like about that is the way that a single include DataMapper::Resource actually adds class methods to Fruit because the implementation of DataMapper::Resource.included looks like:

module DataMapper::Resource
  def included(module)
    module.send :include, InstanceMethods
    module.send :extend, ClassMethods
  end
end

Which is a perfectly common idiom nowadays, but which breaks include‘s contract in annoying ways. Jay proposes fixing this by adding a become method to Object which would wrap the include and extend in such away that they’d be called by the including class. Huzzah. And it makes sense… sort of. But it really doesn’t go far enough.

Let’s take another look at the original code snippet shall we? The thing that I notice is the wide scope of that ‘property’ method. It really isn’t needed anywhere except for defining how a Fruit is mapped onto the database. What happens if we take a leaf out of Perl’s book:

class Fruit
  use DataMapper::Resource {
    property :id, Integer, :serial => true
    property :name, String
    property :notes, Text, :lazy => false
  }
  property :foo # => raises an exception
end

The block gives our extending module somewhere to play, it can introduce a full on domain specific pidgin for the duration of the block with no fear of polluting the including class with anything but the methods its contracted to provide. So, how do we implement use. Something like the following should serve the purpose:

class Module
  def self.use(mod, *args, &block)
    mod.used_by(self, *args, &block)
  end

  def self.used_by(mod, *args, &block)
    if instance_behaviours || class_behaviours
      mod.become(self)
    else
      mod.send(:include, self)
    end
  end

  def self.become(mod)
    include mod.instance_behaviours) if mod.instance_behaviours
    extend mod.class_behaviours if mod.class_behaviours
  end

  def self.instance_behaviours
    nil
  end

  def self.class_behaviours
    nil
  end
end

The key idea here is that, in the default case, use will ignore all its arguments beyond the first and just include that module (a more robust implementation would probably ensure that an exception was raised if any extra arguments got passed). If the module author had written her module to comply with Jay’s proposed become, then we simply call become.

The interesting stuff happens when a module wants to do something a little more trick. So a version of DataMapper might do something like:

class DataMapper::Resource
  def self.used_by(mod, &block)
    mod.become build_behaviours(mod, &block)
  end
end

And build_behaviours would instance_eval the block with an object that would capture the properties and use them to build a set of class and instance methods appropriate to the description.

Another module might simply take a hash to describe how things should be parameterized. It all depends on the needs of the module being used. The aim being to avoid polluting the caller’s namespace any more than necessary. If I use a DataMapper type package, then all I want to end up with in my client classes are appropriate instance accessor methods, I don’t need spare class methods like property or storage_names that are only of any use when I’m describing my class.

Updates

I edited one of the code snippets to remove a particularly heinous piece of brace matching. Thanks to Giles Bowkett for the catch. Also edited another snippet to make it into real ruby rather than some bastard combination of Ruby and Perl. Thanks to Yossef for that catch.

Published on Mon, 08 Sep 2008 01:11:00 GMT by Piers Cawley under .

Powered by Publify – Thème Frédéric de Villamil | Photo Glenn