in reply to Re^2: Your favorite objects NOT of the hashref phylum
in thread Your favorite objects NOT of the hashref phylum

<flameRetardent>
First let me say that I think that all the ways of making objects discussed here are good choices in many situations.
</flameRetardent>

I just wanted to make a comment that many systems do just deal with a relatively small number of objects at once - most web based systems for example.

I once used an in-house object system similar to what Moose sounds like, but with even more features and overhead (it also included automatic RDBMS mapping etc). It worked fine in the web based system, but then we had to make some batch jobs using the same objects for migration. We had a few hours to build, modify and then tear down hundreds of thousands of objects.

The system was too slow - it was going to take about 2 days! But wait - theres more! I spent a few days profiling the code and came up with a few smallish changes. I tweaked the most used methods to use more efficient mechanisms. Some methods were being run literally millions of times - in those cases I threw niceness to the wind and removed lexically scoped variables, reached into objects bypassing accessors etc. The were mostly small methods and I made up for the ugliness with large wads of code comments and POD to ensure that the code remained maintainable.

2 days of execution then became 2 hours. I also did some major tweaking on the RDBMS side, but at least half of the performance gain was due to the perl code changes.

My point is that you should normally not throw out a code model that benefits your developers because of concerns with future scalability. Unless the model is stupid there is usually a way to make it fast after the fact. This is not always true in other languages where you are contstrained in your options, but in Perl there is always a way to optimise more. If you really need to, you can do wacky things like manipulate the runtime tables or rewrite your most often used methods in XS, but I've never had to do that (which is a pity because it could be fun).

  • Comment on Re^3: Your favorite objects NOT of the hashref phylum

Replies are listed 'Best First'.
Re^4: Your favorite objects NOT of the hashref phylum
by BrowserUk (Patriarch) on Mar 27, 2006 at 11:03 UTC
    First let me say that I think that all the ways of making objects discussed here are good choices in many situations.

    No need for the flame retardant, I completely agree with you. If you look again at the post, I was responding to the "bold statements" I quoted only.


    If I have an application that will benefit from OO, I use OO as I suggested in my example above.

    If I have an application that needs a blessed hash, I'll use a blessed hash. Or a blessed, array or a blessed scalar, or a blessed glob.

    If I write a module that I think might be usefully sub-classed, and especially if I think that it might be be useful to others via cpan, I'd probably opt for the former, simply because it's what most people are used to and would be least likely to cause surprises.

    But I do not feel obliged to make all modules OO, just be cause OO is cool, and I certainly don't feel obliged to wrap an OO facade around those parts of my code that are fundamentally not OO, just to satisfy the dogma of OO purism.

    For example, the 'singleton pattern' is a farce. It is a dogmatic wrapper to conceal a global variable. It is used because in the dogmatic world of OO purity, globals are not OO, therefore globals are bad.

    IMO, to use a quaint old phrase my grandmother would resort to on the rare occasions that something really made her angry--that is just so much stuff and nonsense.

    OO is a tool--not a philosophy, way of life, or mandatory way of programming. And like any other tool, you should use it when it benefits your application, and not when it doesn't.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Fun with Farcical Factories (Was: Re^4: Your favorite objects NOT of the hashref phylum)
by aufflick (Deacon) on Mar 28, 2006 at 13:56 UTC
    Now whose being dogmatic ;)

    The singleton pattern is often used in that way by those who have not been taught better (or who are simply lacking in mental horsepower).

    Singleton objects (or similar) can be useful however. Because they hide the fact that there is only one, it can be changed later to have more than one. Say for example your program logs to a logfile, so you use a singleton object factory to return a thin class with a file handle and a print_to_log method. Later you want to use a different logfile depending on the name of the method (or whatever) - the object factory can be changed to return you a different logger object based on your criteria. You're still caching file handles, just a number of them instead of only one. If you used a global variable you would have to change every point where you print to that filehandle to achieve the same effect.

      Although you've responded to your own post rather than me, I'll assume the guilt for 'now being dogmatic' :) I'll also accept the judgement that I'm "simply lacking in mental horsepower" to see how this works?

      Following on from your logger example. Each place in your application you have something like

      package Some::Class; use Logger; sub new { ... $self->{logger} = Logger->new; ... } sub print_to_log { my $self = shift; $self->{logger}->( @_ ) } sub someMethod { my( $self ) = @_; ... $self->print_to_log( 'some stuff' ); ... } sub someOtherMethod { my( $self ) = @_; ... $self->print_to_log( 'some other stuff' ); ... }

      Could you explain to me how you would arrange for the logging from someMethod to go to one file, and the logging from someOtherMethod to go to a different file without changing Some::Class?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        I would create the new singleton instance when you need it, rather than in the initialiser, but I'll use your example where you create the object once in the initialiser.

        In your example $self->{logger}->( @_ ) I will assume you meant something like $self->{logger}->log( @_ )

        package Logger; my $singleton_object; sub new { my $class = ref $_[0] || $_[0]; $singleton_object ||= bless $singleton_object, $class; } sub logfile_handle_for_method { my $self = shift; my ($package, $subroutine) = @_; # not cross-platform... $package =~ s!::!/!g; my $filename = "/var/log/$package/$subroutine.log"; return $self->{filehandles}{$filename} if $self->{filehandles}{$fi +lename}; my $fh; open $fh, ">$filename" | die; $self->{filehandles}{$filename} = $fh; } sub log { my $self = shift; my ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, $is_require, $hints, $bitmask) += caller(1); my $fh = $self->logfile_handle_for_method($package, $subroutine); print $fh, @_; }
        Now you could correctly point out that the same could be achieved with a file scoped hash and a package sub (rather than using OO). But if you had just used a global filehandle with a print statement at every log point (as I often see in code) you would not be able to extend it.

        And that's really one reason why drilling rules like "use Singletons not globals" into younger or less skilled developers - it may not often buy them much, but it might prevent them from doing something stupid. You would hope that you could teach them about how to decide when to apply abstraction (which is all this really is about) but experience tells me that an abstract concept like abstraction is not universally understood by people wanting to be programmers.