Results tagged “newbies”

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.

Perl101: Encapsulation via Protected Abstract Methods

Imagine you have an employee base class, but you know that the salary calculation will be different per employee type. You might decide to do this:

package Employee;

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

sub new { bless {} => shift }

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

1;

The idea is that you're providing this class to a bunch of other programmers and they're going to subclass Employee for their specific needs. There are a variety of things you would probably want to do differently for this class but for this post we'll just talk about the risks of making a public abstract method and how to minimize them. But first, some terms need to be defined.

Perl 101: What Do You Want?

I may be out of touch for a bit as I'm moving to Amsterdam tomorrow night, but in the meantime, tell me what you would like to see for "Perl 101" blog posts. Every time I post something with the newbies tag (which I'm going to change to the friendlier "perl101"), I get a fair number of comments and the post shows up a few times on Twitter. Since I'm getting a good response, I'm assuming that people actually like these posts and want to see more of them.

So tell me what you want and I'll see what I can do.

Perl 101: avoid "elsif"

We had some code which looked (sort of) like this:

if ( $ondemand->service eq 'iplayer_broadband_streaming' ) {
  $self->is_available_vp6_stream(1);
}
elsif ( $ondemand->service eq 'iplayer_streaming_h264_flv' ) {
  $self->is_available_h264_stream(1);
}
elsif ( $ondemand->service eq 'iplayer_streaming_h264_flv_high' ) {
  $self->is_available_h264_high_stream(1);
}
elsif ( $ondemand->service eq 'iplayer_streaming_h264_flv_hd' ) {
  $self->is_available_h264_low_stream(1);
}
elsif ( $ondemand->service eq 'iplayer_streaming_h264_flv_lo' ) {
  $self->is_available_h264_hd_stream(1);
}
elsif ( $ondemand->service eq 'iplayer_mobile_wmv' ) {
  $self->is_available_iplayer_mobile_wmv(1);
}
elsif ( $ondemand->service eq 'iplayer_broadband_download' ) {
  $self->is_available_http_wmv(1);
}
else ( $ondemand->service eq 'iplayer_download_http_h264_air' ) {
  $self->is_available_elektra_sd(1);
}

As a general rule of thumb, I recommend that when you use an "if" statement, you keep it as simple as possible:

if true 
    do something
end if

Or:

if true 
    do something
else
    do something else
end if

Long if/elsif/end chains like you see above have a few issues:

  • Duplicate code
  • Harder to maintain
  • Confusing to read (there's a probable bug in that code)

Let's look at these.

Objects are experts

Note: this is part of an occasional series of posts aimed at newer programmers, or newer Perl programmers. I'm going to talk about what objects are, but even programmers who think they know the answer might benefit from some of this. That includes myself. You might take exception to some of what I write, so feel free to chime in with counter-arguments.

For many older programmers such as myself (I'm 42 as of this writing), their first computer program is often a variant of the following BASIC program:

10 INPUT "What's your name? ", N$
20 PRINT "Hello, "; N$
30 GOTO 10

That's already pretty interesting. In just three lines of code we have some idea about:

  • I/O (input/output)
  • Variables (N$)
  • Data types (the '$' indicates a string variable)
  • Flow control (the GOTO)

That's a pretty heady mix and you can cover a lot of fascinating topics with that. Where you go from there is pretty wide open, but it also tends to express what limitations you'll experience. For example, after BASIC, I went on to 6809 Assembler and then C. What's interesting about the progression from BASIC to Assembler to C is that all of these are procedural languages. If you accept a variant of the Sapir-Whorf Hypothesis, the languages you learn determine (strong variant) or influence (weak variant) how you perceive the world. At least with computer languages, I believe this is true. Heavy exposure to procedural languages can make it difficult to understand object-oriented ones (let's not even go to functional or logic languages, lovely though they are). Thus, we find ourselves having to explain to new programmers what an "object" is.

Is cpanminus the future?

Yes.

How Not To Write A Subroutine

It's been pointed out to me that many programmers have issues with my blog because I'm writing about allomorphism, exceptions as flow control and other topics that are, frankly, not something a beginner programmer is going to warm to. I think that's a fair point and I'm going to try to start including information aimed at those new to Perl and those new to programming.

I'll start with subroutines. Specifically, an old, horrible example.

1

About Ovid

user-pic Freelance Perl/Testing/Agile consultant and trainer. See http://www.allaroundtheworld.fr/ for our services. If you have a problem with Perl, we will solve it for you. And don't forget to buy my book! http://www.amazon.com/Beginning-Perl-Curtis-Poe/dp/1118013840/