Tuesday, June 30, 2009

Refactoring with roles for testing

The programming I've been doing lately is very straightforward Perl. It's hard to think what might be interesting about it... and I don't want to look like an idiot and blather on about something that everybody else was doing in kindergarten.

So maybe this is nothing exciting, but it's what I was doing yesterday.

I'm working on replacing an ancient grew-up-over-seventeen-years Perl backend system with more modern Perl. Instead of using a database for most of it, information on state and status is encoded in Linux file permissions and empty files, and in strings in files. Etc. Etc. I'm updating a large portion of it to use a semi-real database (MySQL - but in this case it really is a step upward), but I'm a one person programming team and it just wasn't feasible to rewrite the whole system in one project. As it is, the project was really too big for one person, but it just wasn't possible to do a decent job without completely re-doing a fairly large chunk.

So I get to an interface to a part of the old system, where instead of just storing some flags in the database I have to write an empty file in one directory for one state, copy a file to a different directory for another state, append a line with an identifier in it to a file for a third state... You get the idea.

At this point it's not clear whether the section I'm interfacing to will ever be rewritten. The higher-ups have gotten pretty twitchy at how much this is costing, and I'll probably have to work on some PHP project part time in the fall. So I don't know if this interface code will ever be used in any other module. But it's irritating stuff to test and debug because it's used in the middle of a fairly long and complex process.

So I plopped it all into a Moose role and created a test case with a dummy package:

   use Test::More tests => 3;
      package Test::SomeInterface;
      use Moose;
      with 'Some::Kludgy::Interface';
   my $test = Test::SomeInterface->new;
   ok( $test, 'it compiled!' );
   ok( $test->process, 'it didn't blow up!' );
   ok( $test->some_status, 'it worked!' );

So now the funky interface code is packaged off by itself and easily replaced, it was much easier to test than buried in some larger module, and if I'm lucky I'll never have to look at it again.One nice side effect of doing this was that I was forced to clean up what I was passing in to the methods instead of relying on the fairly global object attributes.

Pretty obvious, I guess. But it's yet another way in which Moose makes programming more bearable - when fun is too much to hope for. I <3 Moose.

No comments: