Freitag, 22. August 2014

Folgt der Algorithmus einem Muster?

Entwurfsmuster für Algorithmen

Artikelübersicht
1. Teil Folgt der Algorithmus einem Muster?
2. Teil Mit Strategie zum Erfolg.


In der Reihe Managementaufgaben habe ich mich in zwei Posts mit dem Priorisieren von Artefakten beschäftigt. In dem Post Was soll ich zuerst tun? Die Qual der Wahl wurde beschrieben, wer was nach welchen Kriterien priorisieren sollte. Im Post Prioritäten verteilen ist eine Kunst wurden dann eine Reihe einfacher Priorisierungsmethoden erläutert. Innerhalb des Requirements-Engineering-Prozesses stellt das Priorisieren einen wichtigen Teilschritt des Gesamtprozesses dar. Es ist somit Teil eines Algorithmus. "Ein Algorithmus ist eine eindeutige Folge von Anweisungen, die in endlicher Zeit auf die Lösung eines bestimmten Problems führt." [S.23, HAGG04]

Diese Definition im Kopf, wollen wir uns in der folgenden kleinen Reihe mit Entwurfsmustern beschäftigen und zwar mit solchen, die sich besonders gut eignen mit Algorithmen fertig zu werden. Die Ergebnisse dieser Betrachtungen werden wir dann in der Reihe verwenden, in der ein System zur Anforderungsentwicklung umgesetzt wird. Heute fangen wir mit dem Template Method Pattern an. Im Deutschen kann man dieses Entwurfsmuster auch Schablonenmuster nennen. Es gehört zu den Mustern, die von den Altmeistern Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides in ihrem legendären Buch beschrieben wurden. [GOF11]

Den Zweck dieses Musters definiert die Gang of Four wie folgt: "Definiere das Skelett eines Algorithmus in einer Operation und delegiere einzelne Schritte an Unterklassen. Die Verwendung einer Schablonenmethode ermöglicht es Unterklassen, bestimmte Schritte eines Algorithmus zu überschreiben, ohne die Struktur zu verändern." [S.366, GOF11] Dieses Muster ist ein Verhaltensmuster, welches gleichartige Anweisungsfolgen in eine abstrakte Klasse auslagert. Wie so oft wird Gleichartiges zusammengefasst und Verschiedenes ausgelagert. Die Folge des Algorithmus besteht immer aus den gleichen Teilschritten, die allerdings mit unterschiedlichen Methoden umgesetzt werden können.



Im Bild sehen wir eine abstrakte Klasse (abstractClass). Diese enthält die Schablonenmethode (template method). Die Schablonenmethode ist nicht überschreibbar. Innerhalb der Schablonenmethode rufen wir eine Reihe von Methoden auf, die die Teilschritte des Algorithmus festlegen (operation1, operation2). Die Methoden der Teilschritte sind in abgeleiteten Klassen überschreibbar. Falls die Methoden in der abstrakten Klasse als abstrakte Methoden deklariert wurden, sind wir sogar gezwungen sie zu überschreiben. Auf diese Art und Weise haben wir einen Algorithmus fixiert, der in der Methodik der Teilschritte variabel ist.

In unserem Beispiel soll das Ermitteln und Dokumentieren von Anforderungen immer nach demselben Algorithmus ablaufen. Stellen wir uns vor, wir haben immer die Schritte Ermittlung, Dokumentation, Abstimmung und Priorisierung für unsere Anforderungen durchzuführen. Das soll einen allgemeinen Algorithmus darstellen, der sich nie ändert. Der Teilschritt des Priorisierens kann jedoch beispielsweise mit unterschiedlichsten Methoden erfolgen.



Den immer wiederkehrenden Algorithmus nennen wir Anforderungsprozess (requirementsProcess). Die vier Teilschritte, aus denen der Algorithmus besteht sind das Ermitteln (investigate), das Dokumentieren (document), das Abstimmen (match) und das Priorisieren (prioritize). In der abstrakten Klasse RequirementsProcessTemplate sehen wir die Methode requirementsProcess. Diese Methode enthält den Algorithmus, bestehend aus den Methoden investigate, document, match und prioritize. Zur Umsetzung benutzen wir Java. Deshalb kennzeichnen wir die zentrale Methode requirementsProcess als final. Dadurch ist diese Methode in der Vererbungshierarchie nicht überschreibbar. Wir haben so gesichert, dass unser zentraler Algorithmus unverändert bleibt. Die vier Methoden unseres Algorithmus dagegen sind überschreibbar. Hier wollen wir verschiedene Ausprägungen ermöglichen.

Die Methoden document und match sollen in der Methodik immer gleich sein. Deshalb legen wir den Inhalt dieser Methoden bereits in der abstrakten Klasse RequirementsProcessTemplate fest. In möglichen Unterklassen brauchen wir diese Methode also nicht mehr überschreiben. Sie ist zur allgemeinen Verwendung außerhalb des Package gedacht. Ihre Funktionalität steht uns überall zur Verfügung. Die Methoden investigate und prioritize ändern sich in unserem Beispiel in bestimmten Teamansätzen. Team A hat eine andere Methodik festgelegt als Team B. Deshalb leiten wir von der abstrakten Klasse RequirementsProcessTemplate die Klassen TeamA und TeamB ab. Die Methoden investigate und prioritize sind in der abstrakten Klasse als abstract gekennzeichnet. Somit sind wir gezwungen diese Methoden in den Unterklassen zu überschreiben.

 

public abstract class RequirementsProcessTemplate {
 
 public final void requirementsProcess() {
    investigate();
    document();
    match();
    prioritize();
 }
 
 protected abstract void investigate();
 
 private void document() { }
 
 private void match() { }
 
 protected abstract void prioritize();

}

public class TeamA extends RequirementsProcessTemplate {

 protected void investigate() { }

 protected void prioritize() { }

}

public class TeamB extends RequirementsProcessTemplate {

 protected void investigate() { }

 protected void prioritize() { }

}



Wenn wir einen allgemeinen, schablonenhaften Algorithmus besitzen, ist dieses Entwurfsmuster ein gutes Mittel, diesen herauszulösen, um wiederverwendbaren Code zu gewinnen. Durch die definierte Schrittfolge haben die Programmierer beim Anfertigen der Unterklassen bereits ein Denkmodell im Kopf. Dieses Denkmodell, die Schablone, muss jedoch zuvor erst einmal gefunden werden. Die Erleichterung ist nur so gut wie die gefundene Abstraktion. Die gebildete Schablone macht zudem einen unveränderbaren Eindruck. Der Algorithmus ist in seiner Struktur nicht änderbar, nur in seiner Methodik.

Das Template Method Pattern hat also, wie alles, Vor- und Nachteile. Es sollte nur da angewandt werden, wo es Sinn macht und die Arbeit erleichtert. Ein weiterer, noch nicht betrachteter Vorteil, ist die Einfachheit des Entwurfsmusters. Dadurch sind Fehlinterpretationen im Team geringer und man kann auf langwierige Diskussions- und Lernprozesse verzichten.

Im nächsten Post möchte ich das Strategy Pattern betrachten. Auch dieses Entwurfsmuster beschäftigt sich mit der Handhabung von Algorithmen.

  • [GOF11]: Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: "Entwurfsmuster", deutsche Übersetzung, Addison-Wesley Verlag, Münschen, 2011
  • [HAGG04] Rod Haggarty: "Diskrete Mathematik für Informatiker", Pearson Studium, München, 2004


folgender Post dieses Themas


Print Friendly Version of this page Print Get a PDF version of this webpage PDF

Keine Kommentare:

Kommentar veröffentlichen