Sep 042007
 

Dieser Artikel zeigt einen Ansatz, wie man in Java-Software-Projekten unerlaubte Abhängigkeiten zwischen Klassen / Paketen / Subsystemen / Layern erkennt und frühzeitig während der Entwicklung anzeigt. Dieser Ansatz verwendet AspectJ um Compile-Warnungen für Abhängigkeitsverletzungen zu definieren.


Die Paketierung von Artefakten (zum Bsp. Java-Klassen) innerhalb eines Systems, sowie das Management der Abhängigkeiten zwischen den Paketen ist eine der Herausforderungen für einen IT-Architekten. Oft erscheint diese Aufgabe als dauernder Kampf zwischen Architekt und Entwicklern in einem Team. Dies muss natürlich nicht sein. Daher ist es sehr wichtig die Paketierung des Software-Systems in einer frühen Phase des Projektes vorzugeben und klar an das Team zu kommunizieren.

Mindestens genauso wichtig ist die permanente Überwachung der Abhängigkeiten zwischen Klassen und Paketen innerhalb des Systems. Für Java-Systeme kann diese Überwachung durch bekannte Tools wie JDepend oder weniger bekannte Tools wie Dependometer (welches von der BMW Group eingesetzt wird) realisiert werden. Allerdings sollte die Überwachung von Abhängigkeiten idealerweise immer beim Erstellen der Abhängigkeit in der Entwicklungsumgebung geprüft werden, damit sofort klar ist, dass eine Abhängigkeit erlaubt oder nicht erlaubt ist. Dies leisten die genannte Tools leider nicht.
Durch die Definition von Compiler-Warnungen mittels AspectJ “declare warning” wird beim Kompilieren in der Entwicklungsumgebung für jeden Match eines Pointcuts eine entsprechende Warnungen angezeigt. In Eclipse tauchen diese Compiler-Warnungen komfortabel neben der entsprechenden Code-Zeile auf.

Nachdem das Layering des Systems definiert ist, verwende ich einen Aspect für jeden Layer. Um die Abhängigkeiten des Layers “Presentation” zu definieren verwende ich zum Beispiel “AspectArchPresentation.aj”. Dieser Aspekt definiert Compiler-Warnungen für Abhängigkeitsverletzungen.

package com.openwishes.aspects.architecture;

/**
 * For declaring compile warnings and errors to state
 * forbidden outgoing dependencies from layer 'presentation'.
 *
 * @author Marc Neumann
 */
public aspect ArchitectureLayerPresentationOut {

  private pointcut withinLayer() : within(com.openwishes.presentation..*);

  private pointcut forbiddenIntegrationAccess() :
    get(* (com.openwishes.integration..*).*) ||
    set(* (com.openwishes.integration..*).*) ||
    call(* (com.openwishes.integration..*).merge(..)) ||
    call(* (com.openwishes.integration..*).refresh(..)) ||
    call(* (com.openwishes.integration..*).persist(..)) ||
    call(* (com.openwishes.integration..*).remove(..)) ||
    call(* (com.openwishes.integration..*).deleteAll(..));

  private pointcut forbiddenDependency() : withinLayer() &&
    forbiddenIntegrationAccess();

  declare warning : forbiddenDependency() :
    "forbidden outgoing dependency (see aspect ArchitectureLayerPresentationOut)";

}

Im Aspekt wird definiert, dass Zugriffe von Klassen im Layer “Presentation” keine schreibenden DAO-Methoden im “Resource Integration Layer” aufrufen dürfen. Schreibende Zugriffe über DAOs sollen immer über das “Business Service Layer” und nicht von der Presentation direkt erfolgen. Durch das Layering soll die Trennung zwischen Präsentationslogik und präsentationsunabhängiger Business-Logik erreicht werden.

Wird eine unerlaube Abhängigkeit, zum Beispiel der Aufruf von “DAO.persist(Object)” im Layer “Presentation” verwendet, so wird unmittelbar in Eclipse eine Warnung für die Code-Zeile angezeigt:

AspectJ Architekturverletzung Warnung

Bisher habe ich noch nicht ausreichende Erfahrung beim Einsatz dieses Vorgehens in Software-Projekten mit sehr großen Quellcode-Umfängen gesammelt. Leider ist es oft noch schwierig AspectJ im alltäglichen Großprojekt-Umfeld einzusetzen. Es stellt sich mir die Frage, welche Auswirkungen das AspectJ Pointcut-Matching für diese Art der Architekturüberwachung auf die Performance des Builds in den Entwicklungsumgebungen hat. In einem kleineren Projekt hat sich dieses Vorgehen als nützlich erwiesen und es sind keine negativen Auswirkungen auf die Compile-Zeit bewusst geworden.

Fazit: Mittels AspectJ ist es möglich, unerlaubte Abhängigkeiten im Java-Code zu erkennen und so permanent, frühzeitig die Architektur des Software-Systems abzusichern. Dies ist eine wesentliche Komponente um auf Dauer die Wartbarkeit von Software-Systemen zu gewährleisten.

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>