Design by Contract mit Groovy - JAXenter

Design by Contract mit Groovy

Voraussetzung für die Verwendung von GContracts ist Groovy ab Version 1.6 und Java ab Version 1.4. GContracts selbst hat keine Abhängigkeiten zu externen Bibliotheken und ist komplett in Java umgesetzt. Bezogen werden kann die Groovy-Erweiterung entweder über Build-Management Tools wie Maven2, Ivy, Gradle oder Download über die github-Projektseite [1].

Um GContracts in ein Projekt einzubinden, muss sich die Datei gcontracts-x.x.x.jar (Versionsnummer im Mai 2010 ist 1.0.2) im Klassenpfad des Projekts befinden. Da die eigentliche Funktionalität von GContracts auf AST-Transformationen beschränkt ist, muss die Datei nur während der Groovy-Kompilierung im Klassenpfad vorhanden sein. Zur Laufzeit wird die JAR-Datei in keiner Weise benötigt.

Grails und GContracts

Um GContracts in Grails-Projekten als Abhängigkeit zu definieren, kann seit Grails 1.2 die Konfigurationsdatei BuildConfig.groovy verwendet werden. In diesem Fall muss (falls das Projekt nicht im lokalen Maven-Verzeichnis vorhanden ist), das zentrale Maven Repository aktiviert und eine Referenz auf GContracts eingefügt werden:

grails.project.dependency.resolution = {
    inherits( "global" ) {}
    log "warn"
    repositories {        
        grailsPlugins()
        grailsHome()
        grailsCentral()

        mavenLocal()
        mavenCentral() // Aktivierung des öffentlichen Maven Repository
    }
    dependencies {
        compile 'org.gcontracts:gcontracts:1.0.2'
    }
}
Da GContracts nur während der Kompilierung vom Groovy Compiler benötigt wird und die eingefügten Annotationen nicht im final generierten Bytecode referenziert werden, kann als Build-Phase compile angegeben werden.

Nun können die Annotationen @Requires, @Ensures und @Invariant in allen Grails-Artefakten verwendet werden. Besondere Vorsicht sei dabei im Zusammenhang mit Klasseninvarianten und Standardkonstruktoren bei Domain-Klassen geboten. Da Hibernate als Persistenzframework verwendet wird muss ein parameterloser Konstruktor in einer Domain-Klasse vorhanden sein. Es reicht jedoch aus, diesen als private zu deklarieren – GContracts überprüft Klasseninvarianten nur bei öffentlichen Methoden und Konstruktoren.

@Invariant({ . } )
class Customer {
    // mit Klasseninvariante
        def Customer(String firstName, String surName)  {
     this.firstName = firstName
      this.surName = surName
    } 

    
    // Hibernate Konstruktor
    private Customer() {}  // ohne Klasseninvariante

    static constraints = { . }
} 
Groovy & GContracts

Mit AST Transformationen in Groovy 1.6 wurde auch die @Grab-Annotation eingeführt. Diese Annotation kann benutzt werden, um in Groovy-Skripten Abhängigkeiten zu weiteren Bibliotheken anzugeben, die zur Laufzeit von Groovy basierend auf Ivy aufgelöst werden:

import org.gcontracts.annotations.Invariant

@Grab(group='org.gcontracts', module='gcontracts', version='1.0.2')
@Invariant({ true })
class Worker {
     public void do_something() { println "busy..." }
}

worker = new Worker()
worker.do_something()
Zusammenfassung und Ausblick

GContracts bietet eine einfache Möglichkeit, ein auf Groovy basierendes Projekt um Design by Contract zu erweitern. Die Bibliothek ist gänzlich in Java implementiert und unter einer BSD-Lizenz auf github [1] oder über das öffentliche Maven Repository zu beziehen [6]. Design by Contract vervollständigt in der domänengetriebenen Entwicklung Domain-Klassen um exakte Schnittstellendefinitionen und Laufzeitüberprüfung und steht in direktem Gegensatz zu defensiver Programmierung. In Kombination mit einer testgetriebenen Entwicklung können Tests anhand von Verträgen zielgerichteter formuliert werden und Testlogik kann sich auf Spezialfälle konzentrieren.

Auf der Roadmap für nächste GContracts-Versionen des 1.0-Zweigs stehen die Unterstützung von GroovyDoc, die Vererbung von Vor- und Nachbedingungen in Klassenhierarchien, die Verwendung von Vor- und Nachbedingungen in Interfacedefinitionen und die Verwendung von Groovy Power Asserts. Längerfristig wird Augenmerk auf Testfallgenerierung und automatisiertes Testen von Komponenten gelegt.

Andre Steingress ist freiberuflicher Entwickler und beschäftigt sich in seinen Projekten mit domänengetriebener Entwicklung von Enterpriseanwendungen im JEE-Umfeld. Er ist Projektleiter von GContracts und beschäftigt sich in seinem Blog „Grails Inside“ (blog.andresteingress.com) ausschließlich mit Thematiken rund um Groovy und Grails.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.