Aggregation und Delegation sinnvoll nutzen für Objektübergreifenden Datenaustausch

Klassenübergreifende Kommunikation zwischen Objekten zweckmäßig organisieren

Oft besteht die Aufgabe, dass Instanzen nicht verwandter Klassen kommunizieren müssen. Sei es dass ein Request-Objekt eine Header-Instanz benötigt oder ein Data Access Layer angesprochen werden muss. Damit das funktioniert, müssen selbstverständlich die Schnittstellen einer Klasse bzw. Instanz nach draußen klar definiert sein. Unschön und in Multiprozessumgebungen möglicherweise fehlerhaft ist es, wenn Instanzen nicht verwandter Klassen global definiert und beim Funktionsaufruf übergeben werden. Da sowas auch schlecht zu debuggen ist, beschreibt der folgende Artikel ein effizienteres Verfahren anhand eines konkreten Beispiels.

Wesentlich ist, dass Methoden nicht verwandter Klassen über eigene Methoden gekapselt werden.

Aggregation

Aggregation heißt, dass bereits beim Erstellen der Instanz die Kommunikation berücksichtigt wird. Die Kommunikation selbst wird stets über eine Methode der eigenen Instanz (hier eine Instanz der Klasse Fahrzeug) abgewickelt, wobei Instanzen nicht verwandter Klassen bereits im eigenen Konstruktor als Attribute aggregiert werden:

# erstelle gleich mal 2 Instanzen
# Fahrzeugführer ID wird durchgereicht
   $pkw = Fahrzeug->new(ffid => 1);
   $suv = Fahrzeug->new(ffid => 2);

# Wenn der Fahrer gecheckt werden soll, ruft die Fahrzeug-Instanz eine eigene Methode
   $pkw->check;
   $suv->check;


# Anwendungsklasse
package Fahrzeug;

# Argumente für die Konstruktoren nicht verwandter Klassen werden durchgereicht
# für Debugzwecke wird die gesamte Konfiguration in der eigenen Instanz mitgeschleift
sub new{
   my $class = shift;
   my %cfg = (
      ffid => '', # Fahrzeugführer ID
      # ggf. weitere Defaults
   @_);
   my $self = bless{
      Fahrer   => Fahrer->new( $cfg{ffid} ),
      Polizist => Polizei->new,
      CFG      => \%cfg,
   ), $class;
}

# Delegation in eine eigene Methode
# mit eigener Fehlerbehandlung
sub check{
   my $self = shift;

   my $fuehrerschein = $self->{Fahrer}->fuehrerschein();
   $self->{Polizist}->check( $fuehrerschein) ||
      $self->fehlerbehandlung();
}

Delegation

Wesentlich ist also, dass innerhalb der eigenen Anwendung keine Instanzen nicht verwandter Klassen erstellt werden, weil das bereits im Konstruktor der eigenen Instanz erfolgt. Somit werden auch keine Instanzen anderer Klassen übergeben sondern nur die relevanten Daten, im Beispiel die ID des Fahrzeugführers womit das Fahrzeugführerobjekt in der Lage ist, sämtliche Daten des Führerscheins zu liefern. Letzere werden dann an das Polizeiobjekt übergeben. Die gesamte Kommunikation findet also in einer eigenen Methode bzw. in Methoden der eigenen Anwendungsklasse statt. In dieser eigenen Methode also, und nur ebenda, greift die eigene Instanz auf die Schnittstellen der anderen Instanzen zu.

Lazy Delegation

Heißt lediglich, dass die Instanzen der nicht verwandten Klassen erst in einer eigenen Methode hinzugefügt werden. Z.B. so:

sub check{
   my $self = shift;
   my $ffid = shift || $self->{CFG}{ffid};

   $self->{Fahrer}   = Fahrer->new( $ffid ) unless $self->{Fahrer};
   $self->{Polizist} = Polizei->new unless $self->{Polizist};


   my $fuehrerschein = $self->{Fahrer}->fuehrerschein();
   $self->{Polizist}->check( $fuehrerschein) ||
      $self->fehlerbehandlung();
}

Somit verbirgt sich hinter Lazy Delegation eine Lazy Aggregation. Über Perls AUTOLOAD lässt es sich weiterhin einrichten, dass der hier zugehörige Code erst dann compiliert wird, wenn es erforderlich ist.


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