Perl101: Simplified Abstract Methods

In my previous post (you should read it if you haven't), I eventually arrived at this:

package Employee;

use strict;
use warnings;
use Carp 'croak';
use Scalar::Util 'looks_like_number';

sub new { bless {} => shift }

sub salary {
    my ( $self, $month ) = @_;

    # validate arguments
    unless ( $month->isa('Fiscal::Month') ) {
        croak("... with an appropriate error message ...");
    }

    my $salary = $self->_salary($month);

    # validate returned values
    unless ( looks_like_number($salary) && $salary > 0 ) {
        croak("... with an appropriate error message ...");
    }
    return $salary;
}

sub _salary { croak 'You must override _salary() in a subclass' }

1;

That's going to look intimidating to a new programmer, but I wanted to point out how you can use this technique now without all of that extra code:

package Employee;

use strict;
use warnings;
use Carp 'croak';

sub new { bless {} => shift }

sub salary {
    my ( $self, $month ) = @_;
    return scalar $self->_salary($month);
}

sub _salary { croak 'You must override _salary() in a subclass' }

1;

I should have used this example up front, but failed to do so. Note that there's no extra validation because you really don't need it yet. Your class provides public methods and you tell subclass authors to override the protected ones. Also, note the use of scalar in the public method. This guarantees that subclasses overriding the protected method won't be relying on side-effects of context. As your system grows, you can go back and add validation as needed. You don't have to pile on tons of it up front until you really know what your validation should look like.

Leave a comment

About Ovid

user-pic Have Perl; Will Travel. Freelance Perl/Testing/Agile consultant. Photo by http://www.circle23.com/. Warning: that site is not safe for work. The photographer is a good friend of mine, though, and it's appropriate to credit his work.