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

Hello, Is it possible to rename a Perl module while retaining backwards compatibility? In essence, I am trying to rename Old::MyModule to New::MyModule but need to ensure that scripts that use Old::MyModule continue to work. I have thought of using symlinks but that won't work on Windows (and isn't too elegant). Perhaps someone can provide a tip using Exporter/AutoLoader where Old::MyModule transparently calls New::MyModule? Thank you for your assistance - Rajib

Replies are listed 'Best First'.
Re: Rename/Relocate A Module
by ig (Vicar) on Nov 07, 2008 at 02:51 UTC

    If your module is object oriented, you may be able to move your code to the new name then rewrite your old module as an empty subclass of the new module (see 'empty subclass test' in perltoot), depending how it is written.

      Yes! That's exactly what I was looking for. I am now able to create simple subclass of New::Module using following content in Old::Module:
      package Old::Module; use strict; use New::Module; our @EXPORT = (@New::Module::EXPORT); our @ISA = qw(New::Module); 1;
      Thank you very much for the hint.
Re: Rename/Relocate A Module
by ikegami (Patriarch) on Nov 07, 2008 at 03:31 UTC
    You could associate both package names with the same symbol table.
    package New::MyModule; *Old::MyModule:: = \*New::MyModule::; ... 1;

    Update: Added missing trailing colons. Tested:

    use strict; use warnings; BEGIN { package New::MyModule; *Old::MyModule:: = \*New::MyModule::; sub foo { print @_ } 1; } New::MyModule::foo("new\n"); Old::MyModule::foo("old\n");

      Update: After further testing, I don't think this is a good solution. The symbol tables do not behave as I thought they would.

      Or, for more segregation between the old and new modules, you can copy the entire symbol table.

      #!/usr/bin/perl use strict; use warnings; BEGIN { package New::MyModule; *Old::MyModule:: = \*New::MyModule::; %My::Other::Name:: = %New::MyModule::; sub foo { print @_ } 1; } New::MyModule::foo("new\n"); Old::MyModule::foo("old\n"); My::Other::Name::foo("other\n"); $New::MyModule::extra1 = 'set as $New::MyModule::extra1'; $Old::MyModule::extra2 = 'set as $Old::MyModule::extra2'; $My::Other::Name::extra3 = 'set as $My::Other::Name::extra3'; # This is to avoid warnings about the above being used only once my @array = ( $New::MyModule::extra1, $Old::MyModule::extra2, $My::Other::Name::extra3, ); print "\nNew::MyModule:\n"; foreach my $key (keys %New::MyModule::) { print "$key: $New::MyModule::{$key}\n"; } print "\nOld::MyModule:\n"; foreach my $key (keys %Old::MyModule::) { print "$key: $Old::MyModule::{$key}\n"; } print "\nMy::Other::Name:\n"; foreach my $key (keys %My::Other::Name::) { print "$key: $My::Other::Name::{$key}\n"; }

      Which produces:

      new old other New::MyModule: extra2: *New::MyModule::extra2 extra1: *New::MyModule::extra1 foo: *New::MyModule::foo Old::MyModule: extra2: *New::MyModule::extra2 extra1: *New::MyModule::extra1 foo: *New::MyModule::foo My::Other::Name: extra3: *My::Other::Name::extra3 foo: *New::MyModule::foo
Re: Rename/Relocate A Module
by ig (Vicar) on Nov 08, 2008 at 05:19 UTC

    If old programs use Old::MyModule; and new programs use New::MyModule; then you will have to have two .pm files if they are to work without modification and you don't want links.

    One option is to move your code into a third file and use do to load it into both modules.

    Another option is to write one module normally and the other to read the first, changing the package name as it loads, then evaluate it.