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' } }
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.
Hinterlasse einen Kommentar