Archive

Archive for the ‘gcontracts’ Category

GContracts 1.1.3 Released!

November 16, 2010 2 comments

I am proud to announce that GContracts 1.1.3 has just been released and is available now in the Central Maven repository [0] and at Github [1].

The release includes bug fixes and advanced support Spring bean classes annotated with GContracts’ annotations.

Concrete AssertionError types

In parallel with @Invariant, @Requires and @Ensures GContracts 1.1.3 provides separate exception types which all are descendants of AssertionError and I guess do not need further explanation:

ClassInvariantViolation, PreconditionViolation and PostconditionViolation.

Advanced Support for Spring Beans

One of the problems with GContracts is its lack of compatibility especially with Grails artifact classes, i.e. controllers, services, domain classes etc. This topic has been brought to me a few times and if you just want to apply let’s say class invariants on Spring bean classes the Spring application container’s initialization lifecycle can quickly become your enemy.

Let’s consider the following service:

@Invariant({ anotherService != null })
class MyService {

    def anotherService

    static transactional = true

    // ...
}

MyService is a simple Grails service class, annotated with a class invariant which ensures that the reference to anotherService will never be null, during the entire life-time of the MyService bean. Sadly enough, whenever the Spring application container tries to create a new instance of a MyService bean it fails because GContracts checks the class invariant directly after the object’s constructor has completed successfully. By that time, the Spring application container is not yet done with object construction.

From a theoretical perspective throwing a ClassInvariantViolation in this place is completely reasonable since an object’s class invariant needs to be fulfilled by the object instance during its entire life-time. But from a practical perspective, this is kind of pain. It means that you have to duplicate the class invariant to all methods in the service class, e.g.

// avoid invariant checks during construction
class MyService {

    def anotherService

    static transactional = true

    @Requires({ anotherService != null })
    def myServiceMethod()  {
        // ...
    }

    @Requires({ anotherService != null })
    def yetAnotherServiceMethod()  {
        // ...
    }
}

It is not that Design by Contract can not be applied here, it is that Spring simply does define its own rules for object creation and destruction, meaning that whenever an object is created with its constructor the initialization process is not done in the case of the Spring application container.

This circumstance confuses programmers who simply want to apply DbC on their bean classes without thinking about Spring initialization mechanisms and GContracts assertion injection.

GContracts 1.1.3 is the starting point for a bunch of features which are targeted to iron out such integration issues with Spring/Grails applications. Of course it might be questionable whether it makes sense to focus primarily on the Spring framework, but that has been a practical decision (GContracts is for Groovy, Grails uses Groovy, Grails uses Spring…). Furthermore, I tried to make the integration as light as possible without actually introducing a classpath dependency on Spring framework classes.

The first feature which comes with 1.1.3 is a solution for the problem described above: class invariant checks on Spring beans. Henceforth, GContracts will not make class invariant checks on Spring beans during constructor calls, but will create a synthetic @PostConstruct method which overtakes the class invariant check. Since GContracts has no mechanism to know that the given class is a Spring-managed class at runtime, programmers need to annotate their artifact classes with appropriate stereotype annotations [2], e.g. a service class with @Service, a controller with @Controller, etc.

@Service
@Invariant({ anotherService != null })
class MyService {

    def anotherService

    static transactional = true

    // ...
} 

The @Service stereotype annotation above triggers GContracts’ “Spring compliance mode”. Whenever the service bean above has been constructed by the Spring application container it will automatically check the class invariant.

The programmer clearly needs to make a compromise in this case, because the class invariant won’t be checked after a construction call anymore (e.g. in a test-case where the programmer simply creates an instance of this service class). But this is a consequence of outsourcing object creation to the application container.

Hint: GContracts supports the -ea/-da VM parameters [3] which you can use to deactivate assertion checking during application execution, whereas activating assertion checking only during test-cases.

Changes

ISSUE-25: better support for Spring component classes with class invariants
ISSUE-24: wrong class invariant placement with inherited invariant
ISSUE-23: @Requires on constructor with super statement causes compilation error
ISSUE-22: Separate Exception Types for Pre-, Postconditions and Class Invariant
ISSUE-17: remove direct reference to PowerAssertionError

[0] GContracts 1.1.3 in Central Maven Repository
[1] GContracts at Github
[2] Spring Stereotype Annotations and Classpath Scanning
[3] GContracts VM Parameter Support


Flattr this

Advertisements
Categories: gcontracts, groovy, releases

GContracts in JavaMagazin 9.2010 (German)

August 5, 2010 1 comment

In der August Ausgabe 9.2010 des JavaMagazins [0] findet sich ein ausführlicher Artikel über GContracts [1] – eine Groovy Erweiterung für Design by Contract(tm).

Kaufen und glücklich(er) werden!

PS: Wenn du mehr über GContracts und Programming by Contract wissen möchtest, wirf einen Blick auf den Wiki Artikel “An Introduction to Programming by Contract” [2].

[0] JavaMagazin – August Ausgabe 2010
[1] GContracts @ Github
[2] Github Wiki: An Introduction to Programming by Contract

Categories: gcontracts

Github: An Introduction to Programming by Contract

I just added a new page to GContracts wiki on Github: An Introduction to Programming by Contract

Feel free to contribute or leave me any comments here!

Categories: gcontracts, Intro

GContracts 1.1.2 Released!

July 12, 2010 2 comments

I am proud to announce that GContracts 1.1.2 has just been released and is available now in the Central Maven repository [0] and at Github [1].

The release mainly includes internal refactorings, bug fixes and support for Groovy’s power assertions [2].

Therefore, 1.1.2 upwards depends on Groovy 1.7. If there is the demand to maintain a separate Groovy 1.6 branch, I will certainly do that – just let me know.

Groovy Power Assertions & GContracts

Before 1.1.2, GContracts custom handling of assertion messages prevented triggering of Groovy’s power assertion rewriting transformation. Certain parts of GContracts have been rewritten to support power assertions know. The greatest advantage of power assertions are certainly there expressiveness:

import org.gcontracts.annotations.*

@Invariant({ speed >= 0 && speed <= 100 })
class Rocket  {
    int speed
    boolean started

    @Requires({ !started })
    def start() { started = true }

    @Requires({ started })
    @Ensures({ old -> (speed - old.speed) > 0 })
    def accelerate()  { speed += 10 }
}

class BetterRocket extends Rocket {
    @Override
    def accelerate() {
      speed += 20
    }
}

def betterRocket = new BetterRocket()
betterRocket.accelerate()

Output:

Assertion failed: 

<inherited precondition> Rocket.accelerate()

{ started }
  |
  false

	at Rocket.precondition_java_lang_Object_accelerate(ConsoleScript0:11)
	at BetterRocket.super$2$precondition_java_lang_Object_accelerate(ConsoleScript0)

Let’s say we would introduce a bug in BetterRocket‘s implementation that will violate the parent’s postcondition:

class BetterRocket extends Rocket {
    @Override
    def accelerate() {
      speed = 20
    }
}

def betterRocket = new BetterRocket()
betterRocket.start()
betterRocket.accelerate()
// ...
betterRocket.accelerate()

Output:

Assertion failed: 

<inherited postcondition> Rocket.accelerate()

{ old -> (speed - old.speed) > 0 }
          |     | |   |      |
          20    0 |   20     false
                  {speed=20}

	at Rocket.postcondition_java_lang_Object_accelerate(ConsoleScript3:12)
	at BetterRocket.super$2$postcondition_java_lang_Object_accelerate(ConsoleScript3)

The assertion message shows what assertion got violated and has visual pointers to the computed expression values – assertion messages can’t be more readable than that.

Changes

ISSUE-7: use Groovy power asserts as an alternative to AssertionStatement
ISSUE-16: old variables gets cleared on inherited postcondition

[0] GContracts 1.1.2 in Central Maven Repository
[1] GContracts at Github
[2] Groovy Power Assertions

Categories: gcontracts, releases

GContracts: Inheritance of Pre- and Postconditions

June 15, 2010 1 comment


Flattr this
GContracts 1.1.0 [0] introduced inheritance for pre- and postconditions and optimized class invariant inheritance. If you want to know more about GContracts take a look at the wiki [1] or at blog-posts tagged with “gcontracts”.

What about postcondition inheritance?

Postconditions are used to specify what work is guaranteed by the supplier to be done in a specific method, under the condition that the precondition is satisfied. When inheritance comes into play, postconditions of a parent class are inherited by overridden methods of a descendant class.

Imagine a class Stack which provides methods for modifying objects kept in LIFO order.

import org.gcontracts.annotations.*

@Invariant({ elements != null })
class Stack {
    
    private List elements
    
    @Ensures({ is_empty() })
    public Stack()  {
        elements = []
    }
    
    @Requires({ preElements?.size() > 0 })
    @Ensures({ !is_empty() })
    public Stack(List preElements)  {
        elements = preElements
    }
    
    def boolean is_empty()  {
        elements.isEmpty()
    }
    
    @Requires({ !is_empty() })
    def last_item()  {
        elements.last()
    }
    
    def count() {
        elements.size()
    }
    
    @Ensures({ result == true ? count() > 0 : count() >= 0  })
    def boolean has(def item)  {
        elements.contains(item)
    }
    
    @Ensures({ last_item() == item })
    def put(def item)  {
       elements.push(item)
    }
    
    @Requires({ !is_empty() })
    @Ensures({ last_item() == item })
    def replace(def item)  {
        remove()
        elements.push(item)
    }
    
    @Requires({ !is_empty() })
    @Ensures({ result != null })
    def remove()  {
        elements.pop()
    }
    
    def String toString() { elements.toString() }
}

As you can see in the code sample @Requires and @Ensures is used to specify pre- and postconditions in certain methods. Whenever an object of type Stack is used at runtime those assertions will be checked due to hidden code segments injected by GContracts at compile-time (under the assertion that Java’s assert mechanism is activated via the command line argument -ea).

Let’s assume we need an extended Stack that provides us with changed method behavior. For example, we want to add a put method that adds inlining support for lists:

def stack = new Stack()
stack.push(['value1', 'value2', 'value3'])

In order to implement this feature we need to override the put method found in the parent class.

class GroovyStack extends Stack  {

    @Override
    def put(def item)  {
        if (item instanceof List) item.each { super.put(it) }
        else super.put(item)   
    
        return item
    }
}

If we create an instance of GroovyStack and call put with a list as actual parameter, the following assertion violation appears:

[inherited postcondition] in method <put(item:java.lang.Object)> violated. Expression: (this.last_item() == item). Values: item = [1, 2, 3, 4]

A look at the original postcondition shows that this is in fact the case, since our new put method in the descendant flattens the given parameter and for each item in the given list executes the put method once.

Maybe a new postcondition in the descendant will solve this issue:

class GroovyStack extends Stack  {

    @Override
    @Ensures({ item instanceof List ? item.last() == last_item() : item == last_item() })
    def put(def item)  {
        if (item instanceof List) item.each { super.put(it) }
        else super.put(item)   
    
        return item
    }
}

Execution again shows the following assertion:

[inherited postcondition] in method <put(item:java.lang.Object)> violated. Expression: (this.last_item() == item). Values: item = [1, 2, 3, 4]

This leads us to the most important point with rewritten postconditions in descendant classes: you can’t override them.

A postcondition in a descendant class is always joined with the postcondition of the super class, the postcondition of the parent class is said to be strengthened. That means, an overridden method has to implement the postcondition of its parent classes AND its self-defined postcondition.

This might seem awkward at first, but consider the following code:

Stack stack = StackFactory.getInstance()

stack.put([1,2,3,4])

The thing is, if we override the put method in the GroovyStack class the semantic of the code above would change with the type of Stack used at runtime: a Stack instance would push the complete list on the stack, a GroovyStack instance would push the single list items.

Indeed, changing the behavior of an overridden method does not conform to the assertion that inheritance always resembles an is-a relationship. If a GroovyStack should be a Stack, than it has to implement all postconditions of its parent class in overridden methods to conform to the contracts that were specified in the parent and on which clients already might rely on.

Due to inheritance of the parent postcondition we stumbled upon this circumstance and it made us think about how the Stack data-structure could already be used by its clients.

What about precondition inheritance?

Preconditions are used to specify certain conditions which must be fulfilled by a client so that a method call on an object succeeds. So far, GContracts did not support inheritance of preconditions, meaning that whenever a parent class defined a precondition on a method which has been overridden in a descendant, the precondition in the descendant had to be newly defined.

In contrast with postconditions, preconditions weaken the parent’s preconditions. Whenever a parent class defines a precondition on a method, an overridden method might define additional preconditions which might be fulfilled by a client, but don’t have to be.

If we would like to rewrite the replace method in GroovyClass we could specify an additional precondition:

   @Requires({ item != null })
    @Ensures({ item() == item })
    def replace(def item)  {
        super.replace(item)
    }

But that additional precondition weakens the original one, meaning that a call like remove(null) on GroovyStack would still suffice the precondition. In contrast, a put method call on an empty stack would still raise an AssertionError.

Conclusion

Inheritance of pre- and postconditions complements object-oriented mechanisms like polymorphism, dynamic binding and overriding methods and channels those concepts to correct uses. GContracts for Groovy finally supports precondition and postcondition with 1.1.0. Therefore it supports the main principles found in Design by Contract(tm) and allows to apply the full power of contracts to domain models in Groovy/Grails projects.

[0] GContracts Project – http://github.com/andresteingress/gcontracts
[1] GContracts Wiki – http://wiki.github.com/andresteingress/gcontracts/

Categories: basic, gcontracts, Intro

GContracts 1.1.0 Released!

June 12, 2010 1 comment

After a short break, I am happy to tell you that GContracts 1.1.0 has been released and was pushed to the central Maven repository.

Grab GContracts 1.1.0 by defining a Maven dependency [0] or by direct download from github’s download section [1].

This release marks an important milestone since inheritance of class invariants, preconditions and postconditions is supported by now. The basic principles found in Design by Contract(tm) can therefore be fully utilized in Groovy/Grails projects.

GContracts’ test suite currently holds more than 100 test cases for regression and feature testing. There will be is a separate blog post on how to test and implement Groovy AST transformations, with all my experiences so far with GContracts [4].

Changes

GContracts 1.1.0 fixes the following issues:

  • ISSUE-14: fix class invariant inheritance with default class invariant – a class with a class invariant in its heir must be equipped with a default class invariant chaining the method call to the super class invariant.
  • ISSUE-1: pre- and postcondition inheritance – class invariants, pre- and postconditions are now inherited. inheritance support does not include pre/postcondition support in interfaces, but there is a separate ISSUE on this topic. More about pre/postcondition inheritance will follow in a separate blog post [3].
  • ISSUE-10: all uses of getTypeClass() were removed with valid alternatives. this was done due to issues with the Groovy Eclipse plugin.
  • ISSUE-13: Cleanup the generated AST: a few optimizations have been made to the AST node generating components.
  • Bug fixes and a lot more bug fixes.

Special thanks for your contributions!

[0] GContracts – Central Maven Repository
[1] GContracts Available in Central Maven Repository
[2] GContracts – Github Download Section
[3] GContracts: Inheritance of Pre- and Postconditions
[4] Grails Inside – Unit Testing Groovy AST Transformations


Flattr this

Categories: gcontracts, releases

gcontracts 1.0.2 Released!

I am proud to tell you that gcontracts 1.0.2 was released and pushed to the central Maven repository [0].

Grab gcontracts 1.0.2 by defining a Maven dependency [0] or by direct download from github’s download section [1].

Changes

gcontracts 1.0.2 fixes the following issues:

  • ISSUE-5: better AssertionError messages – the closure source of the invariant or pre/postcondition that failed has been added to the AssertionError message.
  • ISSUE-6: line numbers were added in the AssertionError stacktrace. Whenever an assertion fails the last line number guides directly to the condition that caused the AssertionError.
  • Bug fixes.

Special thanks to Hamlet D’Arcy and others for your contributions!

[0] gcontracts – Central Maven Repository
[1] gcontracts Available in Central Maven Repository
[2] gcontracts – Github Download Section


Categories: gcontracts, releases