The Perl Book We Need

Ovid on 2007-09-13T13:51:51

How often do you see this in code?

sub new {
    my $class = shift;
    return bless [] => $class;
}

Not very often. However, I'll bet you often see errors like this:

my $cust = Customer->new($id);

# violates encapsulation
print $cust->{name};

# violates encapsulation again! (unless internal):
if ( $cust->_preferred ) { ... }

# bad interface if the following fails:
$cust->set_name($cust->name);

# Hello Demeter!  (Yeah, this is contrived)
my $office = $cust->salesman->manager->office;

What I would like to see is a book which focuses on OO programming for Perl, but with two primary considerations. The first is to focus primarily on what people are likely to encounter in the wild: blessed hashrefs. The second consideration is teaching them how to think about OO programming.

Intermediate Perl and Object Oriented Perl both have great things to say on these topics, but neither is quite what I would like to see out there. Unfortunately, many Perl programmers learn the syntax of OO in Perl but they don't learn OO. Blessing a hashref isn't enough. Instead, I'd love to see more Perl programmers who can reasonably discuss:

  • Responsibility-driven design.
  • The difference between class and instance data/methods.
  • How inheritance breaks encapsulation.
  • When to throw exceptions.
  • Composition via delegation.
  • Class consumers versus class cooperators.
  • Why the Liskov Substitution Principle is important.
  • Polymorphism and allomorphism.

This wouldn't be a design pattern book. This would not be a syntax book. It would be something which would open up the eyes of Perl programmers regarding OO, but it would be straight-forward. Want class data? Use Class::Data::Inheritable and explain the concept. Need delegation? Use Class::Delegator and explain the concept. It's not to claim the the tools the book uses are best practices. It's to claim that the ideas the book uses are best practices. That's why it would mention blessed array references, but all examples would be blessed hash references. That's what you're likely to see and it's more important to focus on the concepts than the implementations.

So, um, somebody go out and write the damned thing.


Read more than just Perl books!

brian_d_foy on 2007-09-13T18:22:59

It's already been written. It just doesn't use Perl. Good design transcends language.

But, this book wouldn't sell. It would be a great book, but no one would buy it (where no one means fewer people than it takes to keep the economic incentive above working at Starbucks instead).

I don't see the word "Perl" in the title magically making this a sellable or interesting book. People interested in good design are the same people that read about design despite the language.

I here rumor that the Perl book topics will divide differently for Perl 6 though. :)

You don't want a book...

Alias on 2007-09-14T02:23:40

... you want to educate the masses.

And unfortunately, for the most part (rare exceptions like Perl Best Practices excluded) books don't educate the masses.

Things like perlcritic rules are far more likely to have the impact that you want.

I think there's a number of interesting perlcritic rules that could be implemented based on your examples (most of which I agree with)

Damian covers these concepts...

cbrandtbuffalo on 2007-09-14T16:22:58

I recently had the good fortune to attend Damian's Intermediate OO class and he does an excellent job of covering the concepts and context for many of the issues you raise. We just need to send every perl coder to Damian's course! :)

Liskov can bite me

djberg96 on 2007-09-20T02:39:57

"Why the Liskov Substitution Principle is important."

It's important for academics who are more concerned with being correct than useful.

Override nothing! Delegate everything!

Ok, maybe I'm a wee bit bitter after losing a debate about Pathnames, Strings and subclassing.

Re:Liskov can bite me

Ovid on 2007-09-20T05:51:32

I think you must be thinking about something else. Liskov doesn't say anything about not being able to override anything. It merely states that a subclass must be substitutable for the parent class without affecting the correctness of a program. You can override all you want, just make sure that the interface doesn't change.

I don't get it

hex on 2007-09-27T10:27:16

# Hello Demeter!  (Yeah, this is contrived)
my $office = $cust->salesman->manager->office;
What's wrong with this?

Re:I don't get it

Ovid on 2007-09-27T10:37:09

my $office = $cust->salesman->manager->office;

It's a question of encapsulation. Imagine that the Salesman class no longer has need of a manager accessor, but you still need to know which office the salesman is with. You might get a office method pushed into the Salesman class. Then, every place where you have the above code needs to be changed to:

my $office = $cust->salesman->office;

If that's called a lot, it can be a maintenance nightmare.

However, what if you have this?

sub Customer::office { shift->salesman->manager->office }

Then, your calling code (again, remember this example is contrived), becomes this:

my $office = $cust->office;

At this point, if you need to change the hierarchy, you only have to alter &Customer::office instead of all of the calling code. You've properly encapsulated the hierarchical structure and greatly improved maintainability.

Re:I don't get it

hex on 2007-09-27T14:52:48

You've properly encapsulated the hierarchical structure and greatly improved maintainability.

Oh, I see what you mean now. Right, thanks.

Re:I don't get it

Ovid on 2007-09-27T14:59:34

You're welcome. It's not exactly intuitive. Took me a couple of tries to get it :)

Re:I don't get it

perigrin on 2007-10-01T05:22:13

Thank you. I hadn’t realized Moose’s powerful delegation mechanisms we’re more than handy shortcuts. This provides an excellent use case for them.

For those who don’t know Moose every attribute object can have a handles er … attribute … so the example here can be defined like:

package Salesman;
use Moose;

has manager  => (
    ...
    handles => [qw( office )],
);

package Cusotomer;
use Moose;

has salesman => (
    isa => 'Salesman',
    ...
    handles => [qw( office )],
)

Moose will setup Salesman::office which delegates to $self->manager->office and Customer::office which will delegate to $self->salesman->office providing exactly the kind of encapsulation wanted here.

Re:I don't get it

avik on 2008-03-05T22:24:14

Thanks for very thoughtful approach to teaching OO. Unfortunately, in my college days we learned OO in a worsed possible way (questionable faculty, clueless students, books never used).