Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Monday September 04, 2006
09:53 AM

The beauty of runtime traits

[ #30879 ]

The problem: let's say we need "platform" specific information for "regular" and "premium" customers. These customers have servers with us and they get to pick their operating system. The "platform" information depends upon which of the two types of customers and which of three types of operating systems we are using (this isn't quite what the problem is but you get the point). What I need to be able to do is this:

my $platform = Company::Platform->new;
print $platform->base_dir;
print $platform->lib_path;
my $dbh = $platform->dbh;
# ... and so on

But how do I represent this? There are several strategies, all of which really aren't too much fun. One way is to use some broken multiple-inheritance implementation. Another way, assuming we use Company::Platform::Premium and Company::Platform::Regular classes is to set up delegation for the various OS dependent classes we need. However, as it turns out, the OS stuff also is potentially dependent on whether it's a regular or premium customer (and vice versa) and this makes delegation a bit harder.

Or I can use traits (that's a nice little review by chromatic).

package Customer::Platform;

use strict;
use warnings;
use Class::Trait;

sub new {
    my $class = shift;
    # Whee! I can specify behavior when the constructor is called!
    Class::Trait->apply( $class, $class->_get_os_trait );
    bless {}, $class;
}

{
    my %trait_for = (
        MSWin32 => 'Customer::Platform::Trait::OS::Win32',
        freebsd => 'Customer::Platform::Trait::OS::FreeBSD',
        linux   => 'Customer::Platform::Trait::OS::Linux',
    );

    sub _get_os_trait {
        my $class = shift;
        my $os    = $class->_get_operating_system;
        return $trait_for{$os} or $class->_croak("No OS trait found for $os");
    }
}

sub _get_operating_system {$^O}    # testing hook

Now all of my OS-dependent behaviors are flattened into the class and delegation isn't necessary. Later, I might need to refactor the "premium" and "regular" customer behaviors into their own traits and everything which needs this behavior/knowledge can use it with ease. Problem solved.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.