in reply to Perl and Objects, how do you resolve the two?

Actually, I don't see anything wrong with creating accessor or mutator methods with Autoload. Class::MethodMaker does that, and it's very useful for simple classes. I've used Autoload to come up with accessor methods. The trick is to document the methods as though they were normal. After all, implementation shouldn't be part of the interface anyway.

Worrying needlessly about syntax, and which is better, seems counterproductive to me. Any vaguely workable syntax becomes transparent after about a month of use. :)

If you like Perl, but enjoy your object orientation more pure than Perl offers, you might want to look at Ruby. It's not a Perl-killer yet-- it lacks DBI classes AFAICT, among other things-- but it has some of the purest object-orientation I've ever seen. (Example: what do you do when you want something looped five times? You tell the number five, "Do this!")

It's true that doing object-oriented Perl requires more self-discipline than some other languages. I actually see this as a good thing. Writing OO Perl forces you to think about your design and stick with it. In more enforced object-oriented contexts, it's easier to forget that OO is a design quality, not a language quality.

Oh, and to metoo merlyn, you should definitely, definitely read Object-Oriented Perl.

Update: In the interest of accuracy I'll correct myself-- Class::MethodMaker doesn't generate accessors on autoload; it autogenerates them on class load. In terms of the argument, though, I personally don't see a difference, as such matters would be hidden from other classes.

stephen

  • Comment on Re: Perl and Objects, how do you resolve the two?

Replies are listed 'Best First'.
(Zigster) Re: Re: Perl and Objects, how do you resolve the two?
by zigster (Hermit) on Apr 10, 2001 at 22:13 UTC
    Actually, I don't see anything wrong with creating accessor or mutator methods with Autoload. Class::MethodMaker does that, and it's very useful for simple classes. I've used Autoload to come up with accessor methods. The trick is to document the methods as though they were normal. After all, implementation shouldn't be part of the interface anyway.

    Because it defeats the whole idea of having them. The point is you hide the information behind a method interface so if you change the structure of the object then you do not break the interface, there are other reasons but that is sufficient for now. If you have automatically generated methods (which if I understand correctly that is in effect what autoload does) changing the structure of the object will change the interface. Information hiding is a fundamental part of OO and it is not just about having methods to call, you need to understand what is under the hood. This is what I was refering to when I talked about questioning OO ask why why why. A cursory glance at OO is not sufficient.
    --

    Zigster

      This completely does not match my experience.

      For a random instance, if I initially write the class so that a set of properties are exported based on the structure of the object, and I restructure the object, I can just add a few new methods to calculate the things that AUTOLOADER is not doing for you. As long as you remember that your interface needs to be stable, there is no problem with autogenerating large chunks of that interface. After all - thanks to the same principle that you are trying to invoke - there is no need to know or care about the implementation as long as it does the right thing.

      And from a maintainability point of view, autogenerated interfaces can be very, very useful. They can be used to avoid a lot of manual synchronization between pieces of code. (Just try to write a class that proxies off of another transparently without them!) Which is why many OO languages offer equivalents to AUTOLOAD. Perhaps it is called something like method_missing. BFD. It is the same thing and can be used in the same way for about the same things.

      Ah, I think I see where the misunderstanding lies.

      You ("you" meaning zigster) are assuming that I'm autogenerating methods based on the underlying object implementation. That's not what I'm talking about. I'm talking about generating methods based on some other standard, like so:

      Note: code based on working code and Camel, but untested

      package Foo; use strict; use vars qw($AUTOLOAD %ACCESSOR_TABLE); use Carp; %ACCESSOR_TABLE = ( 'name' => '_name', 'id' => '_id_code', 'phone' => '_phonenum' ); sub DESTROY { } sub new { my $type = shift; my ($name, $id, $phone) = @_; my $self = { _data_table => { _name => $name, _id_code => $id, _phonenum => $phone, }, }; bless $self, $type; return $self; } sub AUTOLOAD { my ($sub_name) = $AUTOLOAD =~ m{.*::(.*)$}; $sub_name =~ /^get_(.*)/ or croak "Can't autoload method $AUTOLOAD +"; my $data_name = $1; defined $ACCESSOR_TABLE{$data_name} or croak "Can't autoload method $AUTOLOAD"; my $field_name = $ACCESSOR_TABLE{$data_name}; *$AUTOLOAD = sub { (ref($_[0]) && $_[0]->isa('Foo')) or croak "Accessor method '$ +sub_name' called improperly"; return $_[0]->{'_data_table'}{$field_name}; }; goto &$AUTOLOAD; }
      And in other code...
      use Foo; my $foo = Foo->new('jenny', '24601', '408-867-5309'); my $phone = $foo->get_phone(); my $name = $foo->get_name();
      Then, I can add accessors by merely messing with the %ACCESSOR_TABLE, and not defining more subroutines. This is particularily useful for objects which are loaded from databases-- I can add new fields to the database without doing as much recoding. If there are accessors that don't store their data in '_data_table', I can define them separately, or just add some functionality to AUTOLOAD.

      These are implementation details; I just want to show that there are legitimate uses for AUTOLOAD in an object-oriented context. And once again, this illustrates the power of OO. From the perspective of the class user, it doesn't matter whether I've defined individual subroutines or if I've got them autoloaded instead. The class user doesn't need to understand "what is under the hood."

      stephen

      Update: Added an 'accessor exists' check.

        There is a FarSide cartoon of a court scene with a lawyer interogating a cow in the witness box: "We want to know why, Brown Cow. We know how now, brown cow.".

        It seems odd to me that zigster said "I think AUTOLOAD is bad for munging accessor methods and mutators" and you reply in, so many words...."no you don't understand, this is how it's done". I bet you could write a similar function in Java with clever use of exceptions. you wouldn't want to do it in a Java though, it'd be a hack (If it's a hack in Java then....)

        The addition of the exists function kinda highlights zigster's argument (although I fear the repecussions of Scott's opinion being affirmed, it's not something we like to encourage ;). It's like using AUTOLOAD to do overload functions on strict datatypes by using a regex to check the content of parameters. The difference is one is necessary and the other is unnecessary (but admirably lazy ;0)

        --
        
        Brother Frankus.
Re: Re: Perl and Objects, how do you resolve the two?
by frankus (Priest) on Apr 11, 2001 at 13:53 UTC

    The temptation is to let Perl do everything it can, which can include disregard OO best practices, so you have a choice what OO practices to apply. For me accessor and mutator processes clarify the relationship of data in a method, so to have an Autoload function is almost self-defeating, it says I want the advantages of accessors and mutators, but.. I'm not going to write them. (I like Autoload for this reason, and this dichotomy is why I posted this, I need help %^)

    There is a really cool implementation of an OO Autoload with a list of valid attributes etc which I like.

    OK, I know I didn't mention Mr Conway's exceedingly good book in this node, but I was guessing, people might start getting bored of me singing it's praises.

    As for Ruby, I've got it on my machine, but I am still toying with Perl. I think if I really wanted to do OO for OO's sake I'd go with Eiffel or Smalltalk before Ruby.