A Foolish Manifesto

fREWdiculous!

Archive for April, 2010

“state”

Yesterday I was reading this post by chromatic and I finally understood what state does. If you look at the perldoc for state you will see why. There is quite a dearth of examples there.

Anyway, here’s a real world example from our code base which uses state in a slightly different way from what is probably typical.

Before:

1
2
3
4
5
6
7
8
9
10
11
12
{
   # predeclare a day's duration as well
   # as the set of weekdays to save time
   my $day = DateTime::Duration->new(days => 1);
   my $weekdays = none(1..5);

   method date_due($start_date, $max_days) {
      my $ret = $start_date + DateTime::Duration->new(days => $max_days);
      while($ret->dow eq $weekdays) { $ret -= $day }
      return $ret;
   }
}

After:

1
2
3
4
5
6
7
8
9
method date_due($start_date, $min_days) {
   # state declares the variables the first time that date_due is run
   state $day = DateTime::Duration->new(days => 1);
   state $weekdays = none(1..5);

   my $ret = $start_date + DateTime::Duration->new(days => $min_days);
   while($ret->dow eq $weekdays) { $ret -= $day }
   return $ret;
}

I agree with chromatic on this one; it’s not lifechangingly better, but given enough usage I think it could make things much more clear.

  • 0 Comments
  • Filed under: Uncategorized
  • ODBC in Ubuntu/Debian

    Ok, so I just had to refer to this unposted post since I upgraded to perl 5.12 and I figured I’d finally post it.

    Here’s everything I did to get ODBC working and connected to our MSSQL server at work:

    1
    2
    3
    4
    aptitude install tdsodbc
    dpkg-reconfigure tdsodbc
    aptitude install unixodbc-dev
    cpan DBD::ODBC  # (or aptitude install libdbd-odbcperl)

    Note:
    driver=FreeTDS refers to /etc/odbcinst.ini
    this is how it finds the .so

    And this is our DSN:

    “dsn”:”dbi:ODBC:server=10.6.0.9;database=ACDRI;port=1433;driver=FreeTDS;tds_version=8.0″,

    Hope this helps someone!

    update: For some reason I had to replace unixodbc-dev with libiodbc2-dev, so you may need to do that as well.

  • 1 Comment
  • Filed under: Uncategorized
  • commands!

    Yesterday Ovid posted this little snippet to get his top 10 used commands.

    I had to modify it a little for my zsh settings:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    valium [4030] ~acd % history -n 1 | awk {'print $1'} | sort | uniq -c | sort -k1 -rn | head
       1336 svn
        419 perl
        301 git
        245 rm
        233 cd
        179 vi
        151 ack
         67 sudo
         62 cpan
         61 mv

    I’m sure that my home computer would have the git and svn switched. I’ll update this post with that computer’s history if I remember.

    update Here’s my home computer:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    FrewSchmidt2 [10021] ~ % history -n 1 | awk {'print $1'} | sort | uniq -c | sort -k1 -rn | head                                                                              
       1917 git
        981 rm
        831 perl
        801 vi
        795 cd
        344 ls
        327 svn
        289 sudo
        233 mv
        201 cp
  • 1 Comment
  • Filed under: Uncategorized
  • Delegation via Roles

    DBIx::Class::DeploymentHandler is nearly ready for prime time, so I’m going to discuss a pattern mst described to me that I’ve found very helpful in developing this project.

    Roles

    If you don’t already know what roles are you probably don’t read very many perl blogs etc. chromatic has written a series of blog posts where he discusses the various merits of roles vs whatever your poison is. Maybe read that. This isn’t really about that. What this is about though is that roles aren’t always the answer.

    Delegation

    One of the assumptions of roles is that all of the methods in a role share their namespace. So if you compose Role1 and Role2 and they both implement a sleep method you will get an error at compile time saying that the method collides. This is a Good Thing and helps us not shoot ourselves in the foot. When it’s a problem is with private methods that the end user typically shouldn’t be calling, but happen to collide. As far as I know there is no way to have a role that partially composes with a class. I’m pretty sure that’s against the whole spirit of a role.

    So instead of using a role to compose in the interface for whatever it is you are doing you can instead use delegation, where object A has-a different object B and uses the public interface of object B. That way private methods of B stay that way and don’t collide. The problem is that this can make code a lot more verbose. So instead of

    1
    $dh->deploy

    one must do:

    1
    $dh->deploy_method->deploy

    That make things a lot more verbose, it gives away the inner workings of $dh, and most importantly it makes overriding parts of $dh harder.

    Roles with Delegation

    So basically the pattern goes like this:

    The Public Interface:

    1
    2
    3
    4
    5
    6
    package HandlesFooing;

    requires 'foo';
    requires 'bar';

    1;

    The Delegate:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package Im::A::Delegate;
    use Moose;
    with 'HandlesFooing';

    has foo => (
       is => 'ro',
       isa => 'Str',
       required => 1,
    );

    has bar => (
       is => 'ro',
       isa => 'Str',
       lazy_build => 1,
    );

    sub _build_bar { 'silly }

    1;

    The Role:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    package WithDelegate;
    use Moose::Role;
    use Im::A::Delegate;

    has foo => (
       is => 'ro',
       isa => 'Str',
       required => 1,
    );

    has bar => (
       is => 'ro',
       isa => 'Str',
       lazy_build => 1,
    );

    has delegate => (
       is => 'ro',
       isa => 'Im::A::Delegate',
       handles => 'HandlesFooing',
       lazy_build => 1,
    );

    sub _build_delegate {
       my $self = shift;
       my $args = {
          foo => $self->foo
       };

       $args->{bar} = $self->bar if $self->has_bar;
       Im::A::Delegate->new($args);
    }

    1;

    Usage:

    1
    2
    3
    4
    5
    package GetStuffDone;
    use Moose;
    with 'WithDelegate';

    1;

    And to use that you’d do:

    1
    2
    3
    4
    use GetStuffDone;
    my $gsd = GetStuffDone->new(
       foo => 'frewfrew',
    );

    Of course that’s totally contrived, but it gets the general pattern across. If you want to see examples in action check out some of the roles from DBIx::Class::DeploymentHandler!

    So basically you define your public interface, which isn’t a bad idea anyway, and the “handles” key for the delegate’s attribute takes the role that defines the public interface. This automatically delegates all the methods required by the role (and probably any defined by the role too.)

    If you have private methods you want to reuse make another role and compose that into the delegate’s class, but don’t put it in the handles section.

    I feel like this pattern, even though it yields a lot of boilerplate, helps to make very clean interfaces. Because of this pattern I’ve made well decomposed classes and testing them is dead easy. I imagine that to test roles normally you make stub classes using the roles. Here I just test the actual delegates alone and then I have an integration test that ensures the class that uses all the roles does the right thing.

    Hopefully you’ll find this as useful as I have.

  • 0 Comments
  • Filed under: Uncategorized