Book Report - December 2014

As you may be aware, I'm writing a book which will eventually become a free e-book. This is my third report on how I'm getting along.

If you've been paying attention, you might have noticed a distinct lack of CPAN activity from me lately. Well I had a cold for a while, and a few other things that put me behind on a bunch of other projects which had to take priority over open source stuff. I hope to be back with a bang in January 2015!

In the mean time I have started work on the book chapters which introduce objects and classes which I'm sure you'll agree are two fairly vital topics for object-oriented programming.

One slightly novel approach I'm trying to take is to emphasise the object-oriented part of object-oriented programming. Objects are the main topic, not classes. Conceptually you can create and use objects without bothering much with classes - for example, by composing a bunch of roles and then instantiating an object from that. OK, so internally what Moose/Moo is doing underneath is creating a class which does all those roles, but from the programmer's perspective Moose/Moo enables quite classless object-oriented programming.

Which is not to say that classes are unimportant, and will not be covered. Of course they'll be covered. But I'm trying to introduce objects first. How they are passed by reference; how methods are called; and so forth. All that before I cover writing classes, and before I cover writing roles.

Right now I am writing examples like:

my $A   = get_some_object();
my $B   = $A;
 
$A->set_value(20);
 
say $B->get_value();

... which yes, covers the concepts I want to cover, but feels quite contrived. It's hard to cover these ideas without having to also mention, say, constructors, which I don't want to introduce until the next chapter. I'm thinking of using Time::Piece in some examples because it can produce objects without visible calls to a constructor, plus it's a core module.

What do people think? Any problems with this approach? Any other good object-oriented modules I can use to illustrate concepts like method calls, without discussing classes?

4 Comments

I am surprised that I was not aware Time::Piece before. thanks.

Time::Piece has some XS in it, which will add some overhead for people who are new to OOP or Perl.

Real world module is usually not that friendly to learn a concept. Contrived example is ok for me as long as it runs.

I'd say it's contrived to discuss objects before constructors. It sounds like you feel constructors need to be discussed in detail before object are mentioned, but perhaps you can introduce them (ctors) briefly, i. e. just enough to provide context for the discussion of objects, before returning to them.

Sid Burn:

You didn't really need any module at all to explain classes. I would say, someone only has really understand object-orientation if he knew how to code OO in an imperative or functional style. And that is the most important thing. OO is not about shiny syntax and having "class, method, new" keywords and so on, it is about the idea of encapsulating data/state.

For example an imperative way of describing a "Person-Class". At first you think about a datastructure which data/state it should hold. Well something simple, a person just have a name and an age field. And you use a simple hash to describe it.


my $person = {
    name => 'Foo',
    age  => 10,
};

But what you want is not directly messing with the hash, because it can be error-prone. The fields always need to be the same. You probably want validation and so on. So instead of directly using a hash, you just use a function to create that structure for you. Function that creates such structures are named "constructors".


sub person_new($name, $age) {
    // Some other validation for $name and $age
    return {
        name => $name,
        age  => 10,
    };
}

Now you want to do some things with it, adding age, printing the name of a person. But instead of directly accessing the hash you write functions. Only the functions should access the internals. Why? Well it is your part to explain the whole concept of methods and why someone should do that.


sub person_hello($person) {
    // Validate if a correct $person was provided
    printf "Hello my name is %s and i am %i years old", 
        $person->{name}, 
        $person->{age};
}

sub person_add_age($person, $years) {
    // Validate that $years is a positive integer number 
    // (persons don't get younger) etc.
    $person->{age} = $person->{age} + $years
}

How to use it:


my $person = person_new("Foo", 10);
person_hello($person)
person_add_age($person, 5);

Actually you can explain everything about OO in this style. If you use good old "bless" or "Moose" nothing of any of the concepts really change. Only the syntax how to use it changes slightly.


my $person = Person->new("Foo", 10);
$person->hello();
$person->add_age(5);

But the difference in syntax should be a no-brainer. Because the whole concepts about OO and why encapsulation is good/bad, why you never should directly access the internals of the hash and instead only over methods is also valid with just pure functions.

(If you can't explain)/(If someone doesn't understand) why someone should only use person_add_age() then he will also not understand why he only should use methods and never do a "$person->{age}" directly on an blessed object.

And actually that whole concept is also how Perl's OO works. In fact you could say that Perls "bless" and "->" is just syntactic sugar.

If it is "$person->foobar" it is "$foobar" that is automagically passed as the first parameter, if you have "Person->foobar" than the string "Person" is passed as the first Parameter. So someone will directly understand why "$person->add_age(5)" gets two parameters instead of just one, the "5".

So, you don't really need any modules at all. You also can explain immutability with functions and why it is better to return something new, instead of mutate data in an hash. Or other stuff about OO.

Leave a comment

About Toby Inkster

user-pic I'm tobyink on CPAN, IRC and PerlMonks.