Softwarearchitektur Qualitätssicherung

22.11.2019

Einführung

Die Softwarearchitektur ist eine wichtige Voraussetzung für die Verständlichkeit und Veränderlichkeit von Code, sowie für die Einhaltung von Software Qualitätszielen. Drei Ziele der Softwarearchitektur sind Wartbarkeit, Austauschbarkeit und Erweiterbarkeit. Durch die Einführung von Mustern und Konventionen können die Ziele erreicht werden. Diese werden vom gesamten Entwicklungsteam definiert.

Doch wie kann jetzt sichergestellt werden, dass die Muster und Konventionen eingehalten werden?

Oft werden dafür in regelmäßigen Abständen aufwändige Code Reviews durchgeführt. Im Zeitraum zwischen den Reviews können sich jedoch viele technische Schulden ansammeln. Die Behebung dieser Verstöße kann dann viel Zeit in Anspruch nehmen.

Tools wie ArchUnit und jQAssistant helfen solche Konventionsverstöße schon bei der Entwicklung zu vermeiden. Im nachfolgenden werden diese Tools miteinander verglichen und eine Empfehlung ausgesprochen.

jQAssistant

jQAssistant analysiert den Code und speichert Daten darüber in einer Neo4j-Graphdatenbank. Als Knoten werden dabei unter anderem Dateien, Klassen, Interfaces, Packages, Felder, Methoden und Annotationen angelegt. Verbindungen werden durch Schlüsselwörter wie CONTAINS, DEPENDS_ON, INVOKES, DECLARES, IMPLEMENTS und RETURNS abgebildet. Durch Plugins kann der Graph nochmals erweitert werden. Zum Beispiel um Code-Coverage, Informationen aus der Git-Historie, JUnit-Testergebnisse und vieles mehr. Außerdem kann jQAssistant durch eigene Plugins oder Regeln erweitert werden.

Beispiel Regeln:

  • Namenskonventionen prüfen z.B. EJBs, JPA Entities, Test Klassen, Packages etc.
  • Abhängigkeiten zwischen Modulen überprüfen
  • API und Implementation Packages trennen
  • Probleme identifizieren z.B. zyklische Abhängigkeiten, Tests ohne Assertions etc.
  • Vererbungshierarchien anzeigen
  • Kennzahlen analysieren: Anzahl-Methoden in einer Klasse

 

Um einen Eindruck vom zu analysierenden bzw. zu validierenden System zu verschaffen, kann ein Neo4j-Server samt GUI gestartet werden. Dann können über den Browser, Abfragen gegen die Datenbank ausgeführt werden:jQAssistant Bowser View

Einrichtung

Kommandozeile

  1. jQAssistant herunterladen und entpacken
  2. Es können verschiedene Tasks ausgeführt werden (Details: hier )

 

Beispiel:
Ordner oder Dateien scannen:

  • Windows: .\jqassistant.cmd scan -f folderpath/file
  • Linux: ./jqassistant.sh scan -f folderpath/file

 

Maven

  1. jQAssistant-Plugin zur pom.xml hinzufügen (https://jqassistant.org/get-started/)
  2. Innerhalb des Moduls ein neues Verzeichnis „jqassistant“ mit einem rules.xml anlegen (dort können Regeln definieren werden).
  3. Ein Maven Build führt die jQAssistant Prüfung aus.
  4. Wenn gegen eine Regel verstoßen wird, bricht der Build

 

Definition der Regeln

Regeln werden als Queries in Cypher definiert (in XML oder AsciiDoc Files). Es können aber auch Skriptsprachen wie JavaScript, Ruby oder Groovy verwendet werden.

Beispiel mit XML und Cypher:

<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">
   <constraint id="my-rules:TestClassName">
        <requiresConcept refId="junit4:TestClass" />
        <description>All JUnit test classes must have a name with suffix "Test".</description>
        <cypher><![CDATA[
            MATCH
                (t:Junit4:Test:Class)
            WHERE NOT
                t.name =~ ".*Test"
            RETURN
                t AS InvalidTestClass
        ]]></cypher>
    </constraint>

    <group id="default">
        <includeConstraint refId="my-rules:TestClassName" />
    </group>
</jqa:jqassistant-rules>

ArchUnit

ArchUnit ermöglicht es den Java Code und seine Strukturen mit jedem Java-Unit-Testframework zu testen. Mit ArchUnit können Regeln für die statischen Eigenschaften der Architektur wie den folgenden implementieren:

  • Prüfungen der Package Abhängigkeit
  • Überprüfung der Abhängigkeiten von Klassen
  • Vererbungprüfungen
  • Annotationsprüfungen
  • Layerprüfungen
  • Zyklusprüfungen

 

Einrichtung

Die ArchUnit Dependency zur Parent pom.xml hinzufügen (https://www.archunit.org/userguide/html/000_Index.html)

Definition der Regeln

Die „Regeln“ werden in Form von UnitTests erstellt:

@Test
public void Services_should_only_be_accessed_by_Controllers() {
    JavaClasses importedClasses = new ClassFileImporter().importPackages("com.mycompany.myapp");

    ArchRule myRule = classes()
        .that().resideInAPackage("..service..")
        .should().onlyBeAccessed().byAnyPackage("..controller..", "..service..");

    myRule.check(importedClasses);
}

Annotationen reduziert den Code noch auf die Regeldefinition:

@AnalyzeClasses(packages = "com.mycompany.myapp")
public class MyArchitectureTest {

    @ArchTest
    public static final ArchRule myRule = classes()
        .that().resideInAPackage("..service..")
        .should().onlyBeAccessed().byAnyPackage("..controller..", "..service..");

}

Fazit

Sowohl jQAssistant als auch ArchUnit sind OpenSource. ArchUnit ist mit Apache License V2 und jQAssistant GPLv3 lizenziert.

Mit ArchUnit lässt sich die statische Architektur von Java-Projekten auf entwicklerfreundliche Art und Weise automatisiert testen. Es benötigt hierzu keine weitere Infrastruktur und kann als Library in jedes beliebige Java-Projekt eingebunden werden. Zudem bietet ArchUnit eine mächtige API, um eigene Regeln zu definieren.

jQAssistant ist etwas schwergewichtiger und man muss sich zuerst die Skriptsprache Cypher aneignen. Jedoch bietet die Neo4j Datenbank mit den Informationen zur Systemarchitektur viele weitere Möglichkeiten. Zum Beispiel nach verschiedenen Abhängigkeiten zu suchen und diese dann gezielt aufbrechen. Außerdem ist ein automatisiertes Reporting von Strukturen in sicherheitsrelevanten Umfeldern möglich.

Ich würde ArchUnit für jedes professionelle Java Projekt empfehlen. Die Integration ist sehr schnell durchgeführt und die wichtigsten Regeln sind schnell definiert. Bei größeren Projekten und Monolithen würde ich eher auf jQAssistant setzen. Hier ist auch eine manuelle Analyse mittels der Neo4j Datenbank möglich.

 

Quellen:

https://blogs.oracle.com/javamagazine/unit-test-your-architecture-with-archunit

https://www.archunit.org

https://jqassistant.org

https://blog.seibert-media.net/blog/2018/01/12/werkzeuge-zur-architektur-und-code-validierung-jqassistant

https://blog.jdriven.com/2018/10/testing-the-architecture-archunit-in-practice/

Zurück zur Übersicht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*Pflichtfelder

*