pajout has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,
I am interest in solution of version-dependant methods in object instances. My idea is that
my $instance1 = MyModule::new('1.0'); print $instance1->version(); #prints '1.0'; my $instance2 = MyModule::new('2.0'); print $instance2->version(); #prints '2.0';
instances are of the same class, with the same methods formally, but with different subroutines (doing different things) realizing these methods.
My current solution is based on declarative global hashref $vers
package MyModule; our $VERSION = '2.0'; our $vers = {'1.0'=>{__PACKAGE__.'::version'=>\&version_1_0}, '2.0'=>{__PACKAGE__.'::version'=>\&version_2_0}};
,blessing proper part of $vers
sub new { my $class = __PACKAGE__; my $version = shift || $VERSION; return bless({methods=>$$vers{$version}},$class); }
and on
sub AUTOLOAD { my $self = $_[0]; return &{$$self{methods}{$AUTOLOAD}}(@_); }
But i feel that AUTOLOADing is dirty for that, I wish some solution without it. Please, have you some hints or criticisms?

Replies are listed 'Best First'.
Re: Howto implement versions of object instances
by Aristotle (Chancellor) on Nov 15, 2005 at 11:58 UTC

    The only good option I can think of is to put your interfaces in MyModule::V1_0 and MyModule::V2_0, respectively, and then bless your object into one of these packages.

    If that’s out of the question, you’ll need some way to hook into the method lookup, and the only way to do that is with AUTOLOAD.

    Okay, there’s another way, but it’s rather brutish: put the methods in different packages as outlined above, then iterate over their symbol tables, picking out the functions, and assign a to the same symbols in MyModule a stub function that routes the call to the right package’s method.

    Makeshifts last the longest.

      Thanks, my other ideas are strolling through very similar ways :)
Re: Howto implement versions of object instances
by jeffa (Bishop) on Nov 15, 2005 at 17:41 UTC

    How about the Factory Pattern?

    Factory.pm

    package Factory; use base qw( Class::Factory ); use Module_1; use Module_2; __PACKAGE__->add_factory_type('1.0' => 'Module_1'); __PACKAGE__->add_factory_type('2.0' => 'Module_2'); 1;
    Module_1.pm
    package Module_1; sub new { bless {}, shift } sub init { shift } sub version { '1.0' } 1;
    Module_2.pm
    package Module_2; sub new { bless {}, shift } sub init { shift } sub version { '2.0' } 1;
    And the driver:
    #!/usr/bin/perl -l use Factory; print $_->version for Factory->new('1.0'), Factory->new('2.0'), ;

    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: Howto implement versions of object instances
by ghenry (Vicar) on Nov 15, 2005 at 11:58 UTC

    Is this for backward compatibility? Or to try and cover a bad interface design ;-) (no insult intended)

    Gavin.

    Walking the road to enlightenment... I found a penguin and a camel on the way.....
    Fancy a yourname@perl.me.uk? Just ask!!!
      And to try and cover a bad interface design, too :)))
      I am not an excellent developer and I am not a clairvoyant, so I sometimes create method with inaccurate args or inaccurate interpretation of args, for instance. And discussed trick gives me freedom to improve the interface in the next versions, without affecting applications using the current one.
      Backward compatibility :)
      I try to develop my mod_perl application framework, and I need coexistency of slightly different versions of it at the same apache, to support applications developed on different $VERSIONs.
        It would be much easier to run two separate mod_perl servers.
Re: Howto implement versions of object instances
by radiantmatrix (Parson) on Nov 15, 2005 at 16:26 UTC

    Hm, I had a brainstorm, but not time to test it. Please correct me if any of this wouldn't work for your mod_perl issues (or if any of my assumptions are wrong).

    Perl traverses @INC in order: as soon as it finds a module that fits a require or use statement, it acts on that and stops looking. (IIRC).

    So, why not do this:

    use lib 'my_modules/old_version'; use lib 'my_modules/new_version'; use MyModule '2.0'; #if you need version 2.

    In theory, Perl would find version 1.0 in 'my_modules/old_version', and because it doesn't match, would keep looking, finding 2.0 in 'my_modules/new_version'. If you didn't ask for version '2.0', you'd see the 1.0 version first and use that.As ikegami points out below, this approach is flawed because Perl has to find and load the module before it knows the version. However, it looks like I was heading down the right path, as his approach (inverting the order of the paths in @INC) does work. Please ++ his post if you have spare votes!

    I don't really know that use $VER works exactly that way... as I said this is a brainstorm. Thoughts?

    <-radiant.matrix->
    A collection of thoughts and links from the minds of geeks
    The Code that can be seen is not the true Code
    "In any sufficiently large group of people, most are idiots" - Kaa's Law
      That doesn't work
      >type v1\AA.pm package AA; our $VERSION = 1.0; 1; >type v2\AA.pm package AA; our $VERSION = 2.0; 1; >type test.pl use lib qw( v1 v2 ); use AA 2; >perl test.pl AA version 2 required--this is only version 1 at test.pl line 4. BEGIN failed--compilation aborted at test.pl line 4.

      By the time Perl figures out the version of the module, the module has already been executed. It is therefore impossible for Perl to continue looking for other versions of the module.

      By the way, if you reverse the order of the libraries (i.e. use lib qw( v2 v1 );), version 2 will always be loaded.

        Ikegami, radiantmatrix,
        thanks for your effort. But I would stress that I need all instances of my objects in the same runtime, paralelly, without choosing of versions on lib-use-require-phase.
        Maybe I am not catching something important, but I think that your advices do not support such parallelism.