Aggregation, Delegation, Dependency Injection

Entwurfsmuster die immer wieder missverständlich sind

Dependency ​Injection ​oder ​wie ​auch ​immer ​wir ​das ​nennen, ​beschreibt ​ein ​einfaches ​Verfahren ​zum ​klassenübergreifenden ​Datenaustausch ​über ​klar ​definierte ​Schnittstellen. ​Dadurch, ​dass ​diese ​Schnittstellen ​als ​aggregierte ​Attribute ​in ​der ​eigenen ​Instanz ​vorliegen, ​sind ​sie ​praktisch ​überall ​verfügbar. ​Gleichermaßen ​sind ​unterschiedliche ​Layer ​sauber ​voneinander ​getrennt. ​Betrachte ​ein ​zentrales, ​eigenes ​Objekt, ​Framework-Instanz ​genannt, ​kurz ​FW.

Aggregation: ​Von ​einer ​nicht ​verwandten, ​also ​fremden ​Klasse ​wird ​eine ​weitere ​Instanz ​erstellt ​und ​als ​Attribut ​in ​der ​FW-Instanz ​eingebaut. ​Beispielsweise ​im ​Konstruktor ​der ​FW-Klasse.

use ​CGI;
$fw ​= ​bless{
 ​ ​CGI ​=> ​CGI->new()
}, ​'FW';

Delegation: ​Die ​eigene ​Instanz ​wird ​dazu ​befähigt, ​eine ​Methode ​der ​fremden ​Klasse ​auszuführen. ​Hierfür ​wird ​eine ​eigene, ​ggf. ​gleichnamige ​Methode ​definiert ​und ​in ​dieser ​Methode ​das ​aggregierte ​Attribute ​verwendet.

sub ​param{
 ​ ​my ​$self ​= ​shift;
 ​ ​return ​$self->{CGI}->param(@_);
}

Lazy ​Delegation ​ist, ​wenn ​die ​Aggregation ​später ​erfolgt, ​zur ​Laufzeit ​also, ​wenn ​die ​eigene ​Instanz ​bereits ​vorliegt. ​Gewöhnlich ​erfolgt ​das ​im ​Rahmen ​einer ​Factory:

sub ​param{
 ​ ​my ​$self ​= ​shift;
 ​ ​if(! ​exists ​$self->{CGI} ​){
 ​ ​ ​ ​require ​CGI;
 ​ ​ ​ ​$self->{CGI} ​= ​CGI->new();
 ​ ​}
 ​ ​return ​$self->{CGI}->param(@_);
}

Beachte ​den ​Unterschied ​zwischen ​use ​und ​require. ​So ​kann ​use ​nur ​dann ​verwendet ​werden, ​wenn ​sich ​die ​Methode ​in ​einer ​ausgelagerten ​Datei ​befindet.

Datei ​param.pm

use ​CGI;
sub ​param{
 ​ ​my ​$self ​= ​shift;
 ​ ​if(! ​exists ​$self->{CGI} ​){
 ​ ​ ​ ​$self->{CGI} ​= ​CGI->new();
 ​ ​}
 ​ ​return ​$self->{CGI}->param(@_);
}

Perls ​AUTOLOAD ​ermöglicht ​das ​Auslagern ​von ​Methoden ​in ​Dateien, ​die ​erst ​zur ​Laufzeit, ​also ​nur ​bei ​Bedarf ​eingebunden ​bzw. ​kompiliert ​werden. ​Das ​empfiehlt ​sich ​für ​Methoden, ​die ​nicht ​immer ​gebraucht ​werden, ​wie ​z.B. ​die ​Methode ​param ​(Nicht ​jeder ​Request ​enthält ​Parameter).

Eine ​Alternative ​zu ​Dependency ​Injection ​ist ​die ​konventionelle ​Vererbung. ​Da ​Perl ​bekanntlich ​auch ​Mehrfachvererbung ​unterstützt, ​könnte ​die ​FW-Klasse ​ja ​die ​Klasse ​CGI ​als ​Superklasse ​haben. ​Man ​sollte ​jedoch ​eine ​Klasse, ​dessen ​Erbschaft ​man ​anzutreten ​gedenkt ​sehr ​genau ​kennen ​um ​vor ​unangenehmen ​Überraschungen ​oder ​Nebenwirkungen ​sicher ​zu ​sein. ​Andererseits ​ist ​eine ​Erbschaft ​auch ​unsinnig, ​wenn ​lediglich ​nur ​eine ​Methode ​der ​anderen ​Klasse ​gebraucht ​wird.

Beachte: ​Die ​Aggregation ​darf ​nur ​einmal ​erfolgen ​über ​den ​gesamten ​Programmverlauf! ​Der ​Grund ​ist ​ein ​mögliches ​statisches ​Verhalten ​fremder ​Instanzen. ​Im ​Beispiel ​der ​CGI-Instanz ​ist ​es ​so, ​dass ​über ​den ​Common ​Gateway ​an ​STDIN ​ankommende ​Daten ​nur ​einmal ​gelesen ​werden ​können. ​Würde ​eine ​Instanz ​der ​Klasse ​CGI ​ein ​zweites ​Mal ​erstellt, ​wären ​sämtliche ​aus ​STDIN ​bereits ​gelesene ​Daten ​verloren.


Anbieter: nmq​rstx-18­@yahoo.de, die Seite verwendet funktionsbedingt einen Session-Cookie und ist Bestandteil meines nach modernen Aspekten in Perl entwickelten Frameworks.