FÕ Ò ŃÔ PŎ ÑŇÒ P ÌM Œ PÑǾ PÒ PÕ Ñ Œ PŘÕ Ñ GContracts Programming by Contract with Groovy Andre Steingress
Andre FÕ Ò ŃÔ PŎ ÑŇÒ P ÌM Œ PSteingress ÑǾ PÒ PÕ Ñ Œ PŘÕ Ñ Independent Software Dev @sternegross, @gcontracts Groovy, Grails, JEE, Spring Portfolio, Android http://blog.andresteingress.com GroovyMag, JavaMagazin (German) 2
FÕÒŃÔPŎÑŇÒPÌ Motivation MŒPÑǾPÒPÕÑŒPŘÕÑ Programming is about assumptions, mental models and knowledge. 3
Motivation FÕ Ò ŃÔ PŎ ÑŇÒ P ÌM Œ PÑǾ PÒ PÕ Ñ Œ PŘÕ Ñ Contracts help to externalize mental models and formalize implicit assumptions. How to formalize assupmtions? Logic is the formal study of correct reasoning Boolean Algebra is the tool of choice 4
FÕÒŃÔPŎÑŇÒPÌ Basic Terms MŒPÑǾPÒPÕÑŒPŘÕÑ Supplier implements a software element (e.g. a class) Client references the software element 5
FÕÒŃÔPŎÑŇÒPÌ Basic Terms MŒPÑǾPÒPÕÑŒPŘÕÑ A contract consists of pre- and postconditions for each public method Precondition expresses the constraints under which a method call will function properly Postcondition expresses properties of the state resultung from a method s execution ContractViolation is thrown if the contract is broken 6
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ Design by Contract (tm) for Groovy Version 1.2.1 Compile-Time Contract Injection Power Assert Support Maven Central Repository pure Java library, no dependencies gcontracts-core-1.2.1.jar 7
FÕÒŃÔPŎÑŇÒPÌ Groovy MŒPÑǾPÒPÕÑŒPŘÕÑ dynamic jvm language power features from Ruby, Smalltalk, Python et. al. reducing Java boilerplate code DSL friendliness with closures seamless integration with Java libraries and classes 8
FÕÒŃÔPŎÑŇÒPÌ Prerequisites MŒPÑǾPÒPÕÑŒPŘÕÑ contracts are specified applying annotations Groovy supports closures def c = { println "hello world" } c.call() Annotation Closures only syntactically supported in Groovy 1.7 officially supported in Groovy 1.8 @RunIf({ jdkversion >= 6 }) 9
FÕÒŃÔPŎÑŇÒPÌ MŒPÑǾPÒPÕÑŒPŘÕÑ Demo 10
FÕÒŃÔPŎÑŇÒPÌ Internals MŒPÑǾPÒPÕÑŒPŘÕÑ Groovy AST Transformation modifies the abstract syntax tree (AST) during compilation runs Uses closures as annotation arguments only syntactically supported in Groovy 1.7 officially supported in Groovy 1.8 Compiles annotation closures to closure classes References compiled closure classes in annotation args Groovy AST Browser shows the outcome! 11
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Class Invariants 12
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Contract Inheritance import org.gcontracts.annotations.* abstract class Stack { protected internal = [] } @Requires({ item!= null &&!contains(item) }) @Ensures({ last() == item }) def push(def item) { internal << item } //... class StackImpl extends Stack { //... } 13
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Contract Inheritance Precondition gets weakened Postcondition gets strengthened 14
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Interface Contracts import org.gcontracts.annotations.* interface Stack { @Requires({ item!= null &&!contains(item) }) @Ensures({ last() == item }) def push(def item) @Requires({!isEmpty() }) def pop() } def last() boolean isempty() boolean contains(def item) 15
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Labels @Requires({ not_empty:!isempty() }) @Ensures({ not_full:!isfull() descrease_counter: old.count == count - 1 }) 16
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Module gcontracts-grails Spring Integration import org.gcontracts.annotations.* import org.springframework.stereotype.* @Component @Invariant({ property?.size() > 0 }) class MySpringBean { protected property } def MySpringBean(def somevalue) { property = somevalue } 17
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Module gcontracts-doc GroovyDoc extension 18
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Reusing Contracts: Annotation Contracts import org.gcontracts.annotations.meta.* import java.lang.annotation.* @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) @Precondition @AnnotationContract({ it!= null }) public @interface NotNull {} 19
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 Reusing Contracts: Annotation Contracts class BankAccount { @Requires({ amount > 0.0 }) BigDecimal withdraw(@notnull BigDecimal amount) { if (balance >= amount) { balance -= amount; return amount; } else // Withdrawal not allowed return 0.0; } //... 20
FÕÒŃÔPŎÑŇÒPÌ GContracts MŒPÑǾPÒPÕÑŒPŘÕÑ 1.2.1 More... VM Args to Enable/Disable Contract Checking Domain Model Custom Annotation Processors Cyclic Call Detection Gradle Multi-Build Project... 21
FÕÒŃÔPŎÑŇÒPÌ IDE Support MŒPÑǾPÒPÕÑŒPŘÕÑ IntelliJ Groovy Eclipse Plugin Snapshot for Groovy 1.8 includes support for annotation closures 22
MythBusters FÕ Ò ŃÔ PŎ ÑŇÒ P ÌM Œ PÑǾ PÒ PÕ Ñ Œ PŘÕ Ñ Don t know how to apply contracts in my application! My Methods are too complicated for contracts! I write unit tests, let s go bowling! 23
FÕÒŃÔPŎÑŇÒPÌ Where MŒPÑǾPÒPÕÑŒPŘÕÑ to get it? BSD license Github project (source/binaries) Available in the Central Maven Repo @Grab( group='org.gcontracts', module='gcontracts-core', version='[1.2.1,)' ) Ivy Maven Gradle Lighthouse Issue Tracking Feel free to contribute! Follow @gcontracts 24
FÕÒŃÔPŎÑŇÒPÌ Any Questions? MŒPÑǾPÒPÕÑŒPŘÕÑ 25
FÕÒŃÔPŎÑŇÒPÌ MŒPÑǾPÒPÕÑŒPŘÕÑ Thank you! me@andresteingress.com @sternegross @gcontracts 26