Probleme mit base.pm

Max Maischein

Frankfurt.pm

Überblick

  • Was ist base.pm?

  • Welche Probleme macht base.pm?

  • Was sind die Konsequenzen?

Was ist base.pm

  • base.pm wird verwendet, um @ISA zu modifizieren:

  • z.B. use base 'Foo';, um von der Klasse Foo zu erben

  • base.pm wird seit Perl 5.004 mit Perl ausgeliefert

Was macht base.pm?

Laut der Dokumentation ist:

 1:  use base qw(Mama Papa);

Was macht base.pm?

Laut der Dokumentation ist:

 1:  use base qw(Mama Papa);

im Wesentlichen äquivalent zu

 1:  BEGIN {
 2:      require Mama;
 3:      require Papa;
 4:      push @ISA, qw(Mama Papa);
 5:  };

Wo ist das Problem?

  • base.pm tut viel mehr, als die Dokumentation sagt

  • Problem durch Unterstützung von fields.pm

$VERSION wird gesetzt

base.pm setzt $VERSION, falls vorher keine definiert war.

 1:  package Blurgh;
 2:  # keine $VERSION

$VERSION wird gesetzt

base.pm setzt $VERSION, falls vorher keine definiert war.

 1:  package Blurgh;
 2:  # keine $VERSION
 3:  package Foo;
 4:  sub VERSION { 1 };

$VERSION wird gesetzt

base.pm setzt $VERSION, falls vorher keine definiert war.

 1:  package Blurgh;
 2:  # keine $VERSION
 3:  package Foo;
 4:  sub VERSION { 1 };
 5:  package Baz;
 6:  $VERSION = 2;
 7:  
 8:  package Bar;
 9:  use base qw'Foo Baz Blurgh';

$VERSION wird gesetzt

base.pm setzt $VERSION, falls vorher keine definiert war.

 1:  package Blurgh;
 2:  # keine $VERSION
 3:  package Foo;
 4:  sub VERSION { 1 };
 5:  package Baz;
 6:  $VERSION = 2;
 7:  
 8:  package Bar;
 9:  use base qw'Foo Baz Blurgh';
10:  
11:  package main;
12:  for $p (qw(Foo Baz Blurgh)) {
13:      printf "%s: VERSION(): %s\t\$VERSION: %s\n",
14:           $p, $p->VERSION, 
15:           ${$p\::VERSION};
16:  }

$VERSION wird gesetzt

Module

 1:  package Blurgh; # keine $VERSION
 2:  sub schlomp { 1 };
 3:  package Foo; sub VERSION { 1 }; sub schlomp { 42 };
 4:  package Baz; $VERSION = 2;

$VERSION wird gesetzt

Module

 1:  package Blurgh; # keine $VERSION
 2:  sub schlomp { 1 };
 3:  package Foo; sub VERSION { 1 }; sub schlomp { 42 };
 4:  package Baz; $VERSION = 2;

Ausgabe

 1:  Foo: VERSION(): 1       $VERSION: -1, set by base.pm
 2:  Baz: VERSION(): 2       $VERSION: 2
 3:  Blurgh: VERSION(): -1, set by base.pm   $VERSION: -1, set by base.pm

base.pm lädt nicht alle Module

Unter Perl 5.6 lädt base.pm kein Modul, dessen $VERSION schon mal angefasst wurde:

 1:  # Foo ist nicht geladen
 2:  BEGIN {
 3:      print "Debug: Foo VERSION: $Foo::VERSION";
 4:  }

base.pm lädt nicht alle Module

Unter Perl 5.6 lädt base.pm kein Modul, dessen $VERSION schon mal angefasst wurde:

 1:  # Foo ist nicht geladen
 2:  BEGIN {
 3:      print "Debug: Foo VERSION: $Foo::VERSION";
 4:  }
 5:  
 6:  use base 'Foo';
 7:  Foo->schlomp;
 8:  # Cannot locate method "schlomp" via package 'Foo' at ...

"Datei nicht gefunden" wird unterdrückt

 1:  use base 'ExistiertNicht';

"Datei nicht gefunden" wird unterdrückt

 1:  use base 'ExistiertNicht';

liefert den Fehler

 1:  Base class package "ExistiertNicht" is empty.
 2:      (Perhaps you need to 'use' the module
 3:          which defines that package first.)

"Datei nicht gefunden" wird unterdrückt

  • Das ist schlecht!

  • Es versteckt die eigentliche Fehlerursache

  • Netzwerkfehler

  • Berechtigungsproblem,

  • Fehlende Datei

"Datei nicht gefunden" wird unterdrückt

  • Nur, damit das Folgende funktioniert:

     1:  use Tie::Hash;
     2:  use base 'Tie::StdHash';
  • Es gibt keine Datei Tie/StdHash.pm

  • Tie::StdHash lebt in Tie/Hash.pm

base.pm hat viel zu viel Code

base.pm hat mindestens 100 Zeilen Code, nur um das folgende zu erreichen:

 1:  sub import {
 2:    my $class = shift;
 3:  
 4:    my $inheritor = caller(0);

Teil 2

 1:    if ( @_ and $_[0] eq '-norequire' ) {
 2:        shift @_;
 3:    } else {
 4:        for ( my @filename = @_ ) {
 5:            if ( $_ eq $inheritor ) {
 6:                warn "Class '$inheritor' tried to inherit from itself\n";
 7:            };
 8:  
 9:            s{::|'}{/}g;
10:            require "$_.pm"; # dies if the file is not found
11:        }
12:    }

Update von @ISA

 1:    {
 2:        no strict 'refs';
 3:        # This is more efficient than push for the new MRO
 4:        # at least until the new MRO is fixed
 5:        @{"$inheritor\::ISA"} = (@{"$inheritor\::ISA"} , @_);
 6:    };
 7:  };
 8:  
 9:  "All your base are belong to us"

parent.pm

  • Leider will M. Schwern die Featureitis von base.pm nicht mehr zurückdrehen.

  • Ich habe parent.pm geschrieben, ein Modul, dem ich mehr vertraue.

  • Code siehe oben.

Geplante Features von parent.pm

  • ...

  • KEINE!

Danke

Fragen?