My current position at Thomson Reuters is a contract position scheduled to end on April 29. It looks like budget constraints dictate that this contract won’t be renewed, so it’s time for me to get my interviewing shoes on.

I’m looking for consulting work (part time up to about 30 hours a week). My skill set includes Perl (no kidding), Javascript, web applications, non-web applications (batch data processing, daemons, etc), database design, testing, development processes, and lots of other good stuff. My resume is up to date as of a few minutes ago.

Please contact me if you’re looking for a great developer.

Perl Best Practices (PBP) was released in 2004, about 7 years ago. Perl is a great language, but its culture of TIMTOWTDI can be a problem. These days, we often hear that “there’s more than one way to do it, but sometimes consistency is not a bad thing either” (TIMTOWTDIBSCINABTE). PBP deserves a lot of credit for encouraging discussion about the downsides of TIMTOWTDI.

PBP has a lot of recommendations. A lot of them are fairly trivial, like recommendations on code formatting. I’m a big fan of using a consistent style throughout a single code base, but I’m flexible about what that style should be. Some of his other recommendations are more meaningful, and deserve some review 7 years later.

I’ll take a look at each recommendation in Chapter 15, Objects, and see how it’s stood up in the era of Modern Perl. Maybe I’ll tackle some other chapters in the future.

“Make object orientation a choice, not a default” and “choose object orientation using appropriate criteria”

Damian presents a list of criteria on when to use OO. This is a great list. Read it, understand it, think about it.

“Don’t use pseudohashes”

Well, they’re gone from the Perl core, so I agree!

“Don’t use restricted hashes”

I never ran across any code using this feature, even back in the early 2000s. Has anyone else? I agree with Damian, but this seems like a non-issue.

“Always use fully encapsulated objects”

Right on.

“Give every constructor a standard name”

As more and more people use object systems like Moose, Class::Accessor, and so on, this becomes less of an issue.

However, offering alternate constructors can be useful. The DateTime module has a standard new() constructor, but it also has constructors named from_epoch() and today().

“Don’t let a constructor clone objects”

Again, this seems to have become less of an issue as fewer people hand roll their own OO code. I agree with Damian. Cloning should be a separate, explicit operation.

“Always provide a destructor for every inside-out class”

Damian really pushes inside-out objects in PBP. At one point, it seemed like inside-out objects were the next big thing in Perl, but I don’t think they really took off, especially compared to Moose and Class::Accessor.

This recommendation is basically irrelevant today.

“When creating methods, follow the general guidelines for subroutines”

Basically, Damian says “write methods like I told you to write subroutines in previous chapters.” That advice in previous chapters is all pretty good, but I won’t go through it here.

“Provide separate read and write accessors”

Damian wants you to write get_name() and set_name(). I don’t think this ever took off. My personal preference is name() and set_name(), though that’s just as unpopular.

I think the real recommendation should be to use read-only attributes as much as possible. Mutability adds complexity to your code. Avoid it whenever possible.

In that context, I’d avoid the get_name() style. Very little Perl code I’ve seen uses that naming scheme. The naming of writers matters less if they’re rare, but readers will be common, and you should just use the style that everyone else uses.

“Don’t use lvalue accessors”

Indeed. I think the lvalue feature was a waste of time. Really, is writing $object->foo = 42 so much better than $object->foo(42)? I don’t get it.

“Don’t use indirect object syntax”

Double indeed!

“Provide an optimal interface, rather than a minimal one”

Basically, Damian says that your classes should provide methods that will be as useful as possible for callers. Don’t write an API that makes people do lots of extra work.

For example, with Moose, instead of returning raw array and hash references from accessors, use the Native Traits feature to provide cleaner APIs.

This is a good recommendation, but it’s very difficult to teach this to people. Most people write terrible APIs, period.

“Overload only the isomorphic operators of algebraic classes”

Let me translate this. Damian is saying “don’t get cute with operator overloading, just use it for math-like things”.

I agree, and would go further. I’ve written about how Perl 5′s operator overloading is broken. With that in mind, I suggest avoiding it entirely in most cases.

“Always consider overloading the boolean, numeric, and string coercions of objects”

I disagree. Unfortunately, because of the broken nature of Perl 5 overloading, providing these coercions oftens ends up being useless.

Conclusion

This chapter of PBP holds up pretty well 7 years later. He was out of sync with the community on accessor naming in 2004, and that hasn’t changed. I disagree with him on overloading, but I don’t know that there’s any community agreement on that.

Other chapters talk more about inside-out objects, and I think he missed the mark in thinking those were the future of Perl OO. I’ll cover that in more detail if I review one of those chapters.

His remaining recommendations remain pretty solid in 2011.

I’ve been spending a fair bit of time working on Perl 5 core documentation. I started by editing and reorganizing some of the documents related to core hacking. This update will be in 5.14, due to be released in April. I’m also working on replacing the existing OO tutorials and updating the OO reference docs, though this won’t make it into the 5.14 release.

There’s been a lot of discussion on my OO doc changes, some of it useful, some of it useless, and some of it very rude (welcome to p5p!). Many of the people in the discussion don’t have a clear vision of who the docs are for. Without that vision, it’s really not possible to say whether a particular piece of documentation is good or not. A piece of documentation has to be good for a particular audience.

There’s a number of audiences for the Perl 5 core docs, and they fall along several axes. Here are the axes I’ve identified.

Newbies vs experienced users

Newbie-ness is about being new to a particular concept. You could be an experienced Perl user and still be new to OO programming in general, or new to OO in Perl.

For my OO docs, I’m writing for two audiences. First, I’m writing for people who are learning OO. That’s why the document starts with a general introduction to OO concepts. Second, I’m writing for people who want to learn more about how to do OO in Perl 5. For those people, the tutorial points them at several good OO systems on CPAN.

I’m not writing for people who already know Perl 5 OO and want to learn more, that’s what the perlobj document is for.

From the discussion on p5p, I can see that many people there have trouble understanding how newbies think. I like how chromatic addresses these issues in a couple of his blog posts.

How the reader uses Perl

Perl is used for lots of different tasks, including sysadmin scripts, glue code in a mostly non-Perl environment, full app development, etc.

Ideally, we’d have tutorial documents that are appropriate for each of these areas. I think the OO tutorial is most likely to be of interest to people writing full Perl applications. If you’re just whipping up some glue code, OO is probably overkill.

It would also be great to see some job-focused tutorials, like “Basic Perl Concepts for Sysadmins” or “Intro to Web Dev in Perl 5″. Yes, I know there are books on these topics, but having at least some pointers to modules/books/websites in the core docs is useful.

Constraints on the reader’s coding

If you’re doing green field development, you have the luxury of using the latest and greatest stuff on CPAN. If you’re maintaining a 10-year old Perl web app (I’m so sorry), then you probably don’t. Some readers may not be able to install CPAN modules. Some readers are stuck with in house web frameworks.

People stuck with old code need good reference docs that explain all the weird shit they come across. People writing new code should be guided to modern best practices. They don’t need to know that you can implement Perl 5 OO by hand using array references, ties, and lvalue methods

My OO tutorial is obviously aimed toward the green field developers. It’s all about pointing them at good options on CPAN. As I revise perlobj, I’m trying to make sure that I cover every nook and cranny so that the poor developer stuck with 2001 Perl OO code can understand what they’re maintaining.

(Sadly, that’s probably my code they’re stuck with.)

Conclusion

I’d like to see more explicit discussion of who the intended readers are when we discuss core documentation. Any major doc revision should start with a vision of who the docs are for.

There’s probably other axes we can think about when writing documentation as well. Comments on this are most welcome.

Recently I’ve been working on revising the Perl 5 core OO documentation, starting with a new OO tutorial.

My first draft used Person and Employee as my example classes, where Employee is a subclass of Person. After I posted the first draft, several people objected to these particular classes. I realized that I agreed with their objections, but I wasn’t able to come up with anything better.

I brought this up on the #moose IRC channel, and we had a really interesting discussion. Mostly it consisted of people coming up with various ideas and me shooting them down. The rejected suggestions included:

  • Person/Employee
  • Number/Integer
  • Real/Complex (numbers)
  • Window/ScrollableWindow
  • Animal/Moose
  • CD/Single
  • Assessment/Survey (in the context of teaching assessments)
  • Others I’m probably forgetting

Let’s go through my criteria and talk about why each of these examples was rejected.

No Abstract Base Classes

The base class must be meaningful on its own. It must be something you might instantiate. This ruled out Animal/Moose, we don’t want instantiate a generic Animal. Our understanding of animals is always more specific. At the very least, we recognize them as Birds, Mammals, Fish, and so on, if not as specific species.

Instead, Animal is really more of a role. In fact, thinking back to high school biology, deciding whether something is an animal is based entirely on its behavior (its interface).

If the parent class is better as a role, the suggestion doesn’t work.

The other suggestions all passed this test.

Must Not Be Too Domain Specific

The example classes should not require domain knowledge to understand. The Real/Complex and Assessment/Survey suggestions are clearly too domain specific. The Window/ScrollableWindow suggestion may also fail this. Yes, everyone knows that some windows scroll and some don’t, but very few people would know how that’s implemented.

The example needs to be something that any programmer can be expected to understand.

Must Lend Itself to Example Methods

I need an example that lends itself well to writing small example methods. The Window/ScrollableWindow suggestion fails this criterion. The actual implementation of a windowing toolkit is quite complex, and extremely domain-specific.

The Subclass’s Specialization Must Be Intrinsic to Its Nature

This one is best explained through an example that doesn’t pass the test, Person/Employee. Being a Person is intrinsic to the class. However, when a person is an Employee, that’s not really intrinsic to the Employee, it’s just something a Person does. A Person can also be a spouse, a parent, a child, etc.

In other words, these are all roles that a Person plays. Clearly, this example is better implemented through roles.

Must Not Be Useless

The classic shapes example used in so many books falls into this category. It’s really hard for me to imagine a program where I need to model Ellipse and Circle classes. I suppose I might do this if I were writing MS Paint.

The shapes example is useful for illustrating some technical ideas, but it’s too abstract for a good tutorial.

Must Not Raise the Idea of Specialization By Constraint

Specialization by constraint is an object orientation concept defined by Chris Date and Hugh Darwen in their book The Third Manifesto.

This is a complex idea perhaps best illustrated by an example:

my $number = Number->new(3.9);
$number->add(0.1);

Under the system proposed by Date and Darwen, the $number object would automatically become an Integer object when that is appropriate.

This is a fascinating idea, but something that’s best left out of a basic OO tutorial.

As an aside, if you’re interested in DBMS theory and design, you should really read The Third Manifesto, which I think has now been renamed as Databases, Types and the Relational Model (their website is horrible and confusing).

The Subclass Should Add Attributes and Behavior

The Number/Integer suggestion fails in this regard because the subclass takes away an attribute.

The Subclass Should Not Be Better As an Attribute

The CD/Single suggestion fails this criterion, since there’s really no behavior or attribute difference between a CD and a Single. Instead, “single-ness” is better modeled as a simple attribute on a CD class.

The Winner

So after a lot of discussion, Jesse Luehrs (doy) suggested File/File::MP3. This example satisfies (almost) every criteria.

The File/File::MP3 example works really well in a number of ways:

  • The base class is not abstract.
  • A generic File makes perfect sense.
  • We can expect every programmer to understand the nature of the classes.
  • It lends itself well to simple example methods.
  • The subclass’s nature is intrinsic. Files have one specific type, or we don’t know their type. Yes, I know it’s possible to have a file that satisfies multiple format requirements, but that’s a bizarre special case.
  • It is clearly not useless, and is in fact something you might find yourself writing in real world code.
  • The subclass adds behavior (track title attribute, play() method, etc.).
  • The subclass is clearly not better modeled as an attribute.

The only negative is that this example does bring up the idea of specialization by constraint. In a real world implementation, you might have a File factory that looked at the file’s contents and returned an appropriate File subclass.

There’s no perfect example, but this one is significantly better than Person/Employee, and it’s what I’ll be using in my work on the core docs.

Thanks, Jesse!