File Coverage

blib/lib/ClassLoader.pm
Criterion Covered Total %
statement 27 30 90.0
branch 6 8 75.0
condition n/a
subroutine 7 7 100.0
pod n/a
total 40 45 88.8


line stmt bran cond sub pod time code
1             package ClassLoader;
2              
3 1     1   457 use strict;
  1         1  
  1         25  
4 1     1   3 use warnings;
  1         1  
  1         394  
5              
6             our $VERSION = 1.10;
7              
8             # -----------------------------------------------------------------------------
9              
10             =encoding utf8
11              
12             =head1 NAME
13              
14             ClassLoader - Load Perl classes automatically
15              
16             =head1 SYNOPSIS
17              
18             use ClassLoader;
19            
20             my $obj = My::Class->new; # loads My/Class.pm
21              
22             =head1 DESCRIPTION
23              
24             =head2 Zweck
25              
26             Müde, C-Anweisungen für das Laden von Perl-Klassen zu schreiben?
27              
28             Dieses Modul reduziert das Laden aller Klassen auf eine
29             einzige Anweisung:
30              
31             use ClassLoader;
32              
33             Danach werden alle Klassen automatisch mit ihrem ersten
34             Methodenaufruf geladen. Dies geschieht bei jeder Methode,
35             gleichgültig, ob Klassen- oder Objektmethode.
36              
37             =head2 Vorteile
38              
39             =over 2
40              
41             =item *
42              
43             Man muss keine C-Aufrufe mehr schreiben
44              
45             =item *
46              
47             Es werden nur die Klassen geladen, die das Programm tatsächlich
48             nutzt
49              
50             =item *
51              
52             Die Startzeit des Programms verkürzt sich, da später benötigte
53             Klassen erst später geladen werden
54              
55             =item *
56              
57             Das Programm benötigt unter Umständen weniger Speicher, da Klassen,
58             die nicht genutzt werden, auch nicht geladen werden
59              
60             =back
61              
62             =head2 Was ist ein Klassen-Modul?
63              
64             Unter einem Klassen-Modul verstehen wir eine .pm-Datei, die
65             gemäß Perl-Konventionen eine Klasse definiert, d.h. die
66              
67             =over 4
68              
69             =item 1.
70              
71             ein Package mit dem Namen der Klasse deklariert,
72              
73             =item 2.
74              
75             unter dem Namen des Package gemäß den Perl-Konventionen im
76             Dateisystem abgelegt ist,
77              
78             =item 3.
79              
80             ihre Basisklassen (sofern vorhanden) selbständig lädt.
81              
82             =back
83              
84             =head2 Beispiel
85              
86             Eine Klasse I wird in einer Datei mit dem Pfad C
87             definiert und irgendwo unter C<@INC> installiert. Sie hat den Inhalt:
88              
89             package My::Class;
90             use base qw//;
91            
92            
93            
94             1;
95              
96             Hierbei ist die Liste der Basisklassen und
97             der Quelltext der Klasse (einschließlich der
98             Methodendefinitionen). Das Laden der Basisklassen-Module geschieht
99             hier mittels C. Es ist genauso möglich, die
100             Basisklassen-Module per C oder direkt per C zu laden
101             und ihre Namen C<@ISA> zuzuweisen, was aber umständlicher ist.
102              
103             Eine .pm-Datei, die diesen Konventionen genügt, ist ein
104             Klassen-Modul und wird von I<< ClassLoader >> automatisch beim ersten
105             Methodenzugriff geladen.
106              
107             =head2 Wie funktioniert das?
108              
109             I<< ClassLoader >> installiert sich als Basisklasse von I und
110             definiert eine Methode C, bei der sämtliche
111             Methodenaufrufe ankommen, die vom Perl-Interpreter nicht aufgelöst
112             werden können. Die AUTOLOAD-Methode lädt das benötigte
113             Klassen-Modul und ruft die betreffende Methode auf. Existiert das
114             Klassen-Modul nicht oder enthält es die gerufene Methode nicht, wird
115             eine Exception ausgelöst.
116              
117             Die AUTOLOAD-Methode, die I<< ClassLoader >> definiert, ist recht einfach
118             (Fehlerbehandlung hier vereinfacht):
119              
120             sub AUTOLOAD {
121             my $this = shift;
122             # @_: Methodenargumente
123            
124             my ($class,$sub) = our $AUTOLOAD =~ /^(.*)::(\w+)$/;
125             return if $sub !~ /[^A-Z]/;
126            
127             eval "use $class";
128             if ($@) {
129             die "Modul kann nicht geladen werden\n";
130             }
131            
132             unless ($this->can($sub)) {
133             die "Methode existiert nicht\n";
134             }
135            
136             return $this->$sub(@_);
137             }
138              
139             Lediglich der erste Methodenaufruf einer noch nicht geladenen
140             Klasse läuft über diese AUTOLOAD-Methode. Alle folgenden
141             Methodenaufrufe der Klasse finden I statt, also ohne
142             Overhead! Methodenaufrufe einer explizit geladenen Klasse laufen
143             von vornherein nicht über die AUTOLOAD-Methode.
144              
145             =head2 Was passiert im Fehlerfall?
146              
147             Schlägt das Laden des Moduls fehl oder existiert die Methode
148             nicht, wird eine Exception ausgelöst.
149              
150             Damit der Ort des Fehlers einfach lokalisiert werden kann, enthält
151             der Exception-Text ausführliche Informationen über den Kontext des
152             Fehlers, einschließlich Stacktrace.
153              
154             Aufbau des Exception-Texts:
155              
156             Exception:
157             CLASSLOADER-:
158             Class:
159            
160             Method:
161             ()
162             Error:
163            
164             Stacktrace:
165            
166              
167             =head2 Kann eine Klasse selbst eine AUTOLOAD-Methode haben?
168              
169             Ja, denn die AUTOLOAD-Methode von I<< ClassLoader >> wird I dem Laden
170             der Klasse angesprochen. Alle späteren Methoden-Aufrufe der Klasse
171             werden über die Klasse selbst aufgelöst. Wenn die Klasse eine
172             AUTOLOAD-Methode besitzt, funktioniert diese genau so wie ohne
173             I<< ClassLoader >>.
174              
175             =cut
176              
177             # -----------------------------------------------------------------------------
178              
179             # Klasse als Basisklasse von UNIVERSAL installieren
180             unshift @UNIVERSAL::ISA,'ClassLoader';
181              
182             # -----------------------------------------------------------------------------
183              
184             =head1 METHODS
185              
186             =head2 AUTOLOAD() - Lade Klassen-Modul
187              
188             =head3 Synopsis
189              
190             $this->AUTOLOAD;
191              
192             =head3 Description
193              
194             Die Methode lädt fehlende Klassen-Module und führt ihren ersten
195             Methodenaufruf durch. Die Argumente und der Returnwert entsprechen
196             denen der gerufenen Methode. Schlägt das Laden des Klassen-Moduls fehl,
197             löst die Methode eine Exception aus (siehe oben).
198              
199             Die AUTOLOAD-Methode implementiert die Funktionalität des
200             Moduls ClassLoader. Sie wird nicht direkt, sondern vom
201             Perl-Interpreter gerufen, wenn eine Methode nicht gefunden wird.
202              
203             =cut
204              
205             # -----------------------------------------------------------------------------
206              
207             # Interne Hilfsmethode für Exception-Generierung
208              
209             my $die = sub {
210             my ($class,$sub,$error,$msg) = @_;
211              
212             # Generiere Stacktrace
213              
214             my @frames;
215             my $i = 1;
216             while (my (undef,$file,$line,$sub) = caller $i++) {
217             # $file =~ s|.*/||;
218             push @frames,[$file,$line,$sub];
219             }
220              
221             $i = 0;
222             my $stack = '';
223             for my $frame (reverse @frames) {
224             my ($file,$line,$sub) = @$frame;
225             $sub .= "()" if $sub ne '(eval)';
226             $stack .= sprintf "%s%s [%s:%s]\n",(' 'x$i++),$sub,$file,$line;
227             }
228             chomp $stack;
229             # $stack .= " <== ERROR"; # markiere letzten Stackframe mit Fehlerhinweis
230             $stack =~ s/^/ /gm;
231              
232             # Generiere Meldung
233              
234             my $str = "Exception:\n $msg\n";
235             $str .= "Class:\n $class\n";
236             $str .= "Method:\n $sub()\n";
237             if ($error) {
238             $str .= "Error:\n $error\n";
239             }
240             $str .= "Stacktrace:\n$stack\n";
241              
242             # Wirf Exception
243              
244             die $str;
245             };
246              
247             sub AUTOLOAD {
248 4     4   1165 my $this = shift;
249             # @_: Methodenargumente
250              
251 4         19 my ($class,$sub) = our $AUTOLOAD =~ /^(.*)::(\w+)$/;
252 4 50       9 if (!defined $sub) {
253 0         0 warn "OOPS: AUTOLOAD=$AUTOLOAD\n";
254             }
255 4 50       9 return if $sub !~ /[^A-Z]/;
256              
257 1     1   265 eval "use $class";
  0     1   0  
  0     1   0  
  1     1   737  
  1         90  
  1         14  
  1         3  
  1         1  
  1         11  
  1         419  
  1         67  
  1         13  
  4         192  
258 4 100       10 if ($@) {
259 1         6 $@ =~ s/ at .*//s;
260 1         2 $die->($class,$sub,$@,
261             q{CLASSLOADER-00001: Modul kann nicht geladen werden});
262             }
263              
264 3 100       19 unless ($this->can($sub)) {
265 2         4 $die->($class,$sub,undef,
266             q{CLASSLOADER-00002: Methode existiert nicht});
267             }
268              
269 1         3 return $this->$sub(@_);
270             }
271              
272             # -----------------------------------------------------------------------------
273              
274             =head1 CAVEATS
275              
276             =over 2
277              
278             =item *
279              
280             Der Mechanismus funktioniert nicht, wenn der Modulpfad anders
281             lautet als die Klasse heißt. Solche Module müssen explizit
282             per use geladen werden.
283              
284             =item *
285              
286             Sind mehrere Klassen in einer Moduldatei definiert, kann das
287             automatische Laden logischerweise nur über eine dieser Klassen
288             erfolgen. Am besten lädt man solche Module auch explizit.
289              
290             =item *
291              
292             Über Aufruf der Methode C ist es nicht möglich, ein
293             Modul automatisch zu laden, da Perl bei Nichtexistenz von
294             C C nicht aufruft, sondern den Aufruf
295             ignoriert. Man kann durch C<< $class->import() >> also nicht
296             das Laden eines Klassen-Moduls auslösen.
297              
298             =item *
299              
300             Module, die nicht objektorientiert, sondern Funktionssammlungen
301             sind, werden von I<< ClassLoader >> nicht behandelt. Diese sollten
302             per C geladen werden. Es gibt im Perl-Core ein Pragma C,
303             das alternativ zum automatischen Laden von Funktionen verwendet
304             werden kann.
305              
306             =back
307              
308             =head1 VERSION
309              
310             1.10
311              
312             =head1 AUTHOR
313              
314             Frank Seitz, L
315              
316             =head1 COPYRIGHT
317              
318             Copyright (C) 2016 Frank Seitz
319              
320             =head1 LICENSE
321              
322             This code is free software; you can redistribute it and/or modify
323             it under the same terms as Perl itself.
324              
325             =cut
326              
327             # -----------------------------------------------------------------------------
328              
329             1;
330              
331             # eof