Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Overhead vs. ease of use in OOP

by fletcher_the_dog (Friar)
on Oct 17, 2003 at 15:52 UTC ( [id://300051]=perlmeditation: print w/replies, xml ) Need Help??

Hi All, Like many people, I think, I have been frustrated by perl's oo system. I have always liked in C++ and java you could declare your object's instance variables and then inside your methods you could just refer to those variables without having to use $self->variable or this->variable. So I figured out a way to use 'tie' to be able to do this in perl, so you can right code like this:
use strict; package person; use Class::InstanceVariables qw( $first $last $middle ); sub new{ my $class = shift; local $self = instance(); $first = shift; $middle = shift; $last = shift; return $self; } sub full_name{ local $self = shift; return "$last, $first $middle"; } sub marry{ local $self = shift; my $spouse = shift; return "$first married ".$spouse->first(); } package main; my $john = new person(qw(John F Jones)); my $sue = new person(qw(Suzy P Edwards)); print $john->full_name()."\n"; print $sue->full_name()."\n"; print $john->marry($sue)."\n";
How this works is for each instance variable desired in the parameters passed to the "InstanceVariables" module, a tied variable with the appropriate name is created for the package. These variables are tied to sub routines that access the package variable "$self". So for each method the first argument is shifted in a 'local $self'. Then when the tied variables are accessed the appropriate object is altered or accessed.
I know that having tied variables creates a certain amount of overhead and that using 'local' is generally frowned upon. But what I was wondering is it so bad to use these, if for me it makes it some much easier to use OOP? Right now I only use this module for personal stuff, but after I have refined it some more, I plan on using for work purposes, but before I did I would like to hear your comments about whether you would like to able to access your instance variables like this and what the plusses and minuses of this approach would be.
Here is the current source code for the module:
use strict; package Class::InstanceVariables; sub import{ my $class = shift; my $caller = caller(); my $ties = "package $caller;\n".'no strict; $self=""; sub TIESCALAR{ my $class = shift; my $var = shift; bless \$var,$class; } sub FETCH{ my $thing = shift; $self->{$$thing}; } sub STORE{ my $thing = shift; $self->{$$thing} = shift; } '; no strict 'refs'; *{$caller."::self"} = \${$caller."::self"}; foreach my $ivar (@_) { if($ivar!~/^\$([A-Za-z_]\w*)$/) { die "$ivar is not a valid variable name!\n"; } my $varname = $1; *{$caller."\:\:$varname"} = \${$caller."\:\:$varname"}; $ties .= "sub $varname : lvalue { \$_[0]->{$varname} }\n"; $ties .= "tie \${$varname},'$caller','$varname';\n"; } *{$caller."::instance"}=sub{ bless {},$caller; }; eval $ties; if ($@) { die $@; } } 1;

Replies are listed 'Best First'.
Re: Overhead vs. ease of use in OOP
by jeffa (Bishop) on Oct 17, 2003 at 19:12 UTC
    Nice, but it sounds like a familiar gripe ...
    • A Perl Adapt ... Curses the flexibility of the Perl object system.
    • A Perl Hacker ... Delights in the flexibility of the Perl object system.
    I prefer to use $self - it just isn't a big deal to me to type 6 or so more characters if it makes my code more apparent in intent. Even in C++ and Java i prefer to use this - you look at a method and immediately know what the attributes are.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Overhead vs. ease of use in OOP
by demerphq (Chancellor) on Oct 17, 2003 at 19:07 UTC

    I think that this is a bad plan. You're adding another layer of potentially buggy code on top of what is already an inefficient mechanism (OO is slow).

    I dont know how this could possibly make things easier. I would say that if you prefer Java style OO then program Java. Don't bother trying to force Perls OO into a Java style framework. Its not a good idea. You lose the flexibility of Perls OO model for what gain? The freedom to type $attribute instead of $self->{attribute}? Id say thats not freedom thats handcuffs. I use all kinds of underlying reference types for my OO. I have blessed scalars, blessed regexes, blessed code refs, blessed arrays, blessed globs, and of course the ubiqutous blessed hashes, not to mention a little bit of Inside Out Objects. If you choose to write Java in perl then you lose out on all this froody grooveyness.

    I will add one thing however ++ to you for effort and originality. You probably learned heaps from doing this, but I would say that this is nothing more than a cool learning project that highlights Perls underlying flexibility and power. But having such flexibility doesnt mean you should exploit it just to remain comfortable. Better to learn Perls OO inside out and then decide if you really have gained anything with this approach. I bet youll come to the same conclusion I have.

    As an added point, let me give you an analgy: You want to swim but you dont have much experience with it. But you have lots of experience walking. Does it make sense to wear lead shoes just so you can walk under water? No not at all. When you are in the water then swim when you are on land walk. Don't try to make swimming just like walking, the whole point of swimming is that its different from walking.


    ---
    demerphq

      First they ignore you, then they laugh at you, then they fight you, then you win.
      -- Gandhi


      Don't bother trying to force Perls OO into a Java style framework. Its not a good idea. You lose the flexibility of Perls OO model for what gain?
      Don't you see the contradiction in this? The complaint that Perl's OO is so bare bones that you have to do everything yourself is often parried with "but that makes it so flexible". After that, everyone turns around and implements objects using hashrefs, throwing decades of programming sense (scopes, namespaces) out of the window. And if someone tries to program OO in a different way, he/she is frowned upon Restricting yourself isn't always a bad idea - if it was, noone would use strict.

      What's the benefit of flexibility if you're not supposed to be flexible?

      Abigail

        Just because something is possible doesnt mean its a good idea Abigail-II. Yes Perls OO is flexible. Yes its a good thing that can do Java style OO, but I don't particularly thinks its the best use of the flexibility perl provides. Theres a zillion other perlish OO variants that are more interesting, and actually solve real problems, not just a peevish dislike of using hash key/values or array slots, or glob slots or... as your object base.

        Frankly for me you are conflating two issues here. One is perls OO, the other is whether its a good idea to use dialects of Perl as provided by techniques like the one here, or source filters or the like. Generally I consider such dialects to be a bad idea. They make your code less maintainable, its not sufficient to have a good understanding of Perl, instead you need to have additional skills to work on the code base.


        ---
        demerphq

          First they ignore you, then they laugh at you, then they fight you, then you win.
          -- Gandhi


Re: Overhead vs. ease of use in OOP
by Anonymous Monk on Oct 17, 2003 at 16:33 UTC
    If you *really* want to use features of other languages, Inline lets you actually use them instead of just emulating them:
    use strict; use Inline Ruby => <<'RUBY'; class Person attr_accessor :first, :middle, :last def initialize(first,middle,last) @first = first @middle = middle @last = last end def full_name "#{@first} #{@middle} #{@last}" end def marry(other) "#{@first} married " + other.first end end RUBY my $john = Person->new(qw(John F Jones)); my $sue = Person->new(qw(Suzy P Edwards)); print $john->full_name()."\n"; print $sue->full_name()."\n"; print $john->marry($sue)."\n";

    :-)

Re: Overhead vs. ease of use in OOP
by simonm (Vicar) on Oct 17, 2003 at 20:10 UTC
    You're not the only person to feel this way, and kudos to you for building yourself this tool. (You might also take a look at Object::Lexical for a very different implementation that's attempting to address the same issue.)

    However, I would join the other voices here in suggesting that it might be more practical to invest the time to become comfortable with the more common Perl-ish idioms... Writing $self->{foo} is easy enough, and producing accessor methods is also pretty straightforward.

    Adopting common idioms may also help make your code more accessible to other people, and facilitate your comprehension of code written by them.

Re: Overhead vs. ease of use in OOP
by BrowserUk (Patriarch) on Oct 18, 2003 at 01:18 UTC

    By way of an answer to your actual questions I knocked this up.

    Results:

    P:\test>300051 2>nul Rate Cish Perlish Cish 441/s -- -63% Perlish 1206/s 174% --

    I made a few minor mods to your module in order to track down some warnings that were being issued.

    In terms of the danger of using local, I'm not sure there are any beyond forgeting and typing my $self; instead of local $self; which might not be a problem if you are the only user, but lack of familiarity might give me a problem, at least at first. The danger here is that not localising it causes fairly obscure bugs without any nice warnings to give you a hint what to look for.

    As for whether I would actually use your module, I don't think so. Comparing the two (admittedly simplistic) versions of the modules, I'm not particularly convinced that the benefits outweight the penalties. The volume of typing and indirection involved seems pretty similar to me.

    Whether his would remain true once you'd added some error checking, accesssor methods and the like I can't really visualise, but the reduction in typing would have to be pretty substantial to offset the close to 3x slowdown I think.

    I'm not particularly enamoured with the status quo of perl OO syntax and semantics either. I would prefer verifiable lvalue-able, interpolatable, class members -- be they variables or functions -- but I haven't seen or come up with anything that satisfies all my desires in this regard yet. I think it may have to wait for Perl 6.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Hooray!

      ++ for the useful, objective response. I see that their is definitely a performance hit doing things this way. Also your point about accidently typing "my $self" instead of "local $self" and difficulty in tracking down bugs was something I hadn't thought about, even though I must admit to accidently doing that myself once or twice.
Re: Overhead vs. ease of use in OOP
by fletcher_the_dog (Friar) on Oct 17, 2003 at 20:51 UTC
    I find it interesting how quick people are to judge someone elses background. perl is the only language I have ever used in the real world. Granted that has only been about two years, and there is a lot I don't know about perl, but it seems ironic to me that some would say "don't do it this way because it will mean you won't have flexibility". I did a little bit of java and c++ in school, and I liked the way that they have their object systems. I don't think that it is being disloyal to perl to say that. This is adding another way to do it, not taking away from what already exists. I have used things like $self->{variable} over and over and that is why I hate them. I look forward to perl6 when such access to attributes will be built in. I don't really care if you don't want to use this kind of thing, What I would really like to know is how big of an overhead does using tie really cause? What are some of the risks of using 'local'?
      I don't really care if you don't want to use this kind of thing

      You did ask, though.

      is how big of an overhead does using tie really cause?

      It's at least one more method call per operation, not to mention that it's likely the method is implemented in Perl, not C. There's some overhead there too.

      cause? What are some of the risks of using 'local'?

      You give up a modicum of encapsulation for the potential of scary action at a distance. The members of whichever object you're currently working with are globally accessible and modifiable. You might as well not bless hashes, in that case.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://300051]
Approved by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-19 17:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found