Home > gcontracts, groovy, releases > gcontracts 1.0 released

gcontracts 1.0 released

I am happy to tell you that gcontracts version 1.0 has just been released and is available for download on github, licensed under BSD.

Bugs, enhancements and feature requests should be reported over github’s issue tracking system.

About gcontracts

As I’ve already mentioned in a previous blog-post “Contract-Oriented Programming with Groovy”, I started a github project called gcontracts which aims to enable “contract-oriented” programming aka “design by contract” in Groovy. This is done by relying on Groovy’s ability to transform the abstract syntax tree (AST) during the compilation process and is mainly based on intelligent injection of  Java assert statements.

If you aren’t familiar with contract-oriented programming, I advice to take a look at my blog-post Contracts in the Domain Model [0] which explains the principle idea of contracts, assertions and todays role of contract-oriented programming in software development processes.

Be warned, there is still a long way ahead, especially in fields of performance improvements, configurability and more advanced topics like loop invariants, pre- and postcondition inheritance and configurability, although the basic features are tested and working.

Features

gcontracts comes with a set of Java annotations whereas each annotation represents a particular assertion type. Each annotation has a single parameter which is used at declaration-time to specify a closure with a boolean expression, representing the assertion on the actual object’s state. gcontracts 1.0 comes with the following assertion type annotations:

  • Class-Invariants with @Invariant

    In order to specify a class-invariant use the @Invariant annotation e.g.

    @Invariant({ someProperty.size() > 0 && anotherProperty == someMethod() })

    An @Invariant annotation’s closure has access to:

    instance variables instance variables of any scope
    methods methods of any access scope (although it is recommended to use public methods only)
    static fields static fields of any access scope
    static methods static methods of any access scope
  • Preconditions with @Requires

    In order to specify preconditions on methods, use the @Requires annotation e.g.

    @Requires({ someProperty.size() > 0 && anotherProperty == someMethod() })

    A @Requires annotation’s closure has access to:

    instance variables instance variables of any access scope
    methods methods of any access scope (although it is recommended to use public methods only)
    static fields static fields of any access scope
    static methods static methods of any access scope
    arguments all arguments of the current method scope
  • Postconditions with @Ensures

    In order to specify postconditions on methods, use the @Ensures annotation e.g.

    @Ensures({ someProperty.size() > 0 && anotherProperty == someMethod() })

    An @Ensures annotation’s closure has access to:

    instance variables instance variables of any access scope
    methods methods of any access scope (although it is recommended to use public methods only)
    static fields static fields of any access scope
    static methods static methods of any access scope
    arguments all arguments of the current method scope
    method result the method’s return value (if not void) is available as closure parameter result. Thus, to access the return value of the current method specify a closure parameter result, e.g.

    @Ensures({ result -> result >= 0 })
    old attribute values a map containing all attribute values before method execution is available as closure parameter old. Thus, to access the value of instance variables before method execution, specify a closure parameter old, e.g.

    @Ensures({ old -> old.field1 != field1 })

    Of course, the variable map does not contain copies of you domain’s entity classes, it works with Java’s built-in data types only, e.g. primitive values, reference types like Integer, Boolean, Calendar, Date and so on.

    By the way, you can even use both closure parameters in the same closure, e.g.

    @Ensures({ old, result -> old.field1 != field1 && result != field1 })

    or

    @Ensures({ result, old -> old.field1 != field1 && result != field1 })
  • Class-Invariant Point Cuts

    In the case of pre- and postconditions the validation is done either at a method’s start or end. In the case of class-invariants, gcontracts injects the invariant’s condition at multiple point cuts.If a class contains a class-invariant definition, at run-time the class-invariant is checked at the following pointcuts:

    1. at the end of each constructor call
    2. at the end of each method call
    3. at the beginning of each method call
  • Class-Invariant Inheritance

    Whenever class A specifies a class-invariant and class B extends A and specifies a class-invariant again, A’s class-invariant is said to be inherited to class B’s class invariant. In this context inherited means that A’s invariant and B’s invariant are logically combined with a boolean AND.Class Invariant Inheritancegcontracts analyses the class inheritance line and links all class-invariants appearing in there. E.g. in the class inheritance line C – B – A (from bottom to top), C’s class-invariant is linked with B and A ( C AND B AND A), B’s class-invariant is linked with A’s (B AND A).

gcontracts > 1.0

Upcoming features in next versions of gcontracts will include:

  • bug fixes
  • pre- and postcondition inheritance
  • performance tweaking
  • configurability

Using gcontracts in your project

The easiest way of getting a gcontracts.jar is to get it from github’s download section. In addition, the project’s root directory provides a Maven pom.xml for comfortable generation of the gcontracts.jar file. The library itself will be published to a public Maven repository soon.

Once you got a copy of the jar, add it to the project’s classpath. This should be enough to let the Groovy compiler detect it and execute it during compilation.

Hint: If you decide to pull the repository from github, take care that you can’t compile gcontracts and your project in a single compilation pass. This means, you need to ensure that your build process (let it be your IDE, or Ant, or Maven, …) already has access to a compiled gcontracts.jar!

[0] Contracts in the Domain Model
[1] gcontracts wiki on github

Categories: gcontracts, groovy, releases
  1. No comments yet.
  1. No trackbacks yet.

Leave a comment