Archive

Archive for the ‘basic’ Category

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

Domain Patterns in Enterprise Projects


If I had to separate projects I’ve been in, i would difference between data manipulation and enterprise projects.

Data manipulation projects mainly consist of a set of forms needed to alter data which is stored in some persistent store (most of the time a relational database). In these projects, there is not much domain logic to be found. There might be some validation logic, some jobs running in the background, but that’s mainly it with domain logic.

Enterprise projects are all about domain logic and integration of external systems. Most of the time a project starts with implementing all the views and domain classes which are considered to be simple, that is, not much domain knowledge has to be available in order to implement those views. But as time goes by, domain logic creeps in and classes which seemed pretty small and granular for data manipulation style grow to be oversized monsters.

Web frameworks like Grails make it easy to implement data manipulation style applications: if project members have a clear picture how to model the domain classes, they write the domain classes and all the view and controller stuff comes automatically with it.

If your project is moving towards being an enterprise project, there are some patterns that helped in my projects to deal with additional domain logic and complexity i want to share with this article.

The Birth of Objects

The birth of an object is a special event: it is the time the object’s data starts to exist in memory. In order to create an object, one of the object’s constructors is used. A constructor is a special creation procedure which encapsulates object initialization and which ensures that at the end of the constructor call an object is in a state that satisfies the class invariant.

Okay, that is rather academic you might think, which is true for classes which resemble active records [0] – but not for real domain classes found in larger projects. If you are writing an enterprise project with Grails, you have to know that Grails per se is not ment to be used in projects like that, but rather in data manipulation projects.

Let’s assume one of our domain classes is a Customer domain class. If we create a Customer class with

grails create-domain org.ast.domain.entity.Customer

we’ll get a class that looks like

class Customer {
	
	

	static constraints = {
		
	}
}

At this point we could add all the properties that resemble a customer and we could think we’re done. But what would happen?

We would build nothing more than a class that resembles the active record pattern – at runtime instances of that class mainly are treated like database records and all the domain logic will be put in Grails service classes. But service classes are not ment to be the place are central business logic happens, because we would distribute business logic over multiple service classes, where as each service holds several procedures that modify our active records – such a design screams for better object-orientation design enforcing information hiding, inheritance, dynamic binding and polymorphism.

Let us come back to our Customer domain class and add some properties to it:

class Customer {
	
	String name
	Status status
	Account account

	static constraints = {
		name(blank: false)
		status(nullable: false)
		account(nullable: false)
	}
}

Clients of that class could now create customer objects in arbitrary ways:

def c = new Customer()
def c = new Customer(name: 'Max')
def c = new Customer(status: null)
def c = new Customer(status: Status.NEW, account: null)
// ...

If we are serious about object-orientation and the role of creation procedures, we should not support creating objects in ways that generate objects which are in an invalid state after object creation, e.g. creating a customer without a state. In order to support a more object-oriented design we could modify the Customer class like this:

@Invariant({ name?.size() > 0 && status && account })
class Customer {
	
	String name
	Status status
	Account account
	
	def Customer(String name, Account account)  {
		this.name = name
		this.status = Status.NEW
		this.account = account
	}

	void setName(final String other) { name = other }
	void setStatus(final Status other)  { status = other }
	void setAccount(final Account other) { account = other } 


	// Grails Specific 
	private def Customer() {}

	static constraints = {
		name(blank: false)
		status(nullable: false)
		account(nullable: false)
	}
}

First of all, we’ve redeclared setter methods to be only visible in package scope. This comes in handy if you modularize your domain logic in separate packages and want e.g. services to change the state of customer objects.

In addition, a custom constructor was added which is a way to create a Customer object being in a valid state after the constructor call. As it turns out, more complex classes would be candidates for factory methods [1]

@Invariant({ name?.size() &gt; 0 && status && account })
class Customer {
	
	// ...
	
	def static Customer create(final String name, final Account account)  {
		return new Customer(name, account)
	}

	// ...
}

or the Builder pattern [2].

Well-defined creation procedures/constructors/factory methods/etc. are great, because there is a predefined way on how to create a fully initialized, valid object. If we should write an integration test for the Customer class and wanted some customer test instances, we would need to know what it takes to create a “valid” customer object – it might be simple in this case, but with more complex classes programmers could simply give up to write test-cases based on the simple fact that it is not obvious to them who to create instances of some type.

Domain Logic comes in…

In the previous section, the Customer class has been modified to be created with a custom constructor. Let as assume that the following business requirement comes in:

After 30 days, if the customer is in state REGISTERED, the application needs to send an e-mail to the customer, telling that the test-period ends in 5 days.

Is is pretty obvious that we need to have a job that checks for customer accounts existing >= 30 days. In addition, the application needs to have a way to integrate with an external SMTP server, which is a rather technological issue we don’t care about now (although I did in the last blog post [3]). What’s interesting in this place is where to put the additional domain logic.

A first naive approach would be to create a service class CustomerService which implements the business requirement:

class CustomerService {	
	
	static transactional = true
	
	def void sentTestPeriodEndsMail(final Customer customer)  {
		
		if (customer.state != State.REGISTERED) return
		if (!(customer.created + 30 &gt;= new Date()))  return
		
		customer.state = State.REGISTERED_WARNED
		customer.save()
		
		sendMailMessage(customer)
	}
	
	// ...
}

The code above exactly implements the business requirement, which is a good thing. But what if more domain logic creeps in? Let’s say there is a more privileged type of users, FriendOfMineCustomer from which instances should never receive those mails. We would have to change our service class method to something like:

class CustomerService {	
	
	static transactional = true
	
	def void sentTestPeriodEndsMail(final Customer customer)  {
		
		if (customer instanceof FriendOfMineCustomer) return // <-- more domain logic comes in...
		if (customer.state != State.REGISTERED) return
		if (!(customer.created + 30 &gt;= new Date()))  return
		
		customer.state = State.REGISTERED_WARNED
		customer.save()
		
		sendMailMessage(customer)
	}
	
	// ...
}

Now we start to feel that this is obviously not a good design. Just assume we need to check if a customer object is a candidate for receiving reminder messages in another service – we would need to duplicate the code above and put in that place. What is the reason that we slipped into this design? The reason was that we treated customers as active records and created a service procedure that implemented the business requirement in first place with pure procedural design.

A better approach would be to put the additional domain logic in the Customer class itself:

@Invariant({ name?.size() &gt; 0 && status && account })
class Customer {
	
	def boolean isTestPeriodEmailCandidate()  {
		return state == State.REGISTERED && created + 30 &gt;= new Date()
	}

	// ...
}

than we could simply modify FriendOfMineCustomer to:

class FriendOfMinCustomer extends Customer {
	
	def boolean isTestPeriodEmailCandidate()  {
		return false
	}

	// ...
}

and the CustomerService class would simply be the integrational glue between the core domain class and the messaging component:

class CustomerService {	
	
	static transactional = true
	
	def void sentTestPeriodEndsMail(final Customer customer)  {
		
		if (!customer.isTestPeriodEmailCandidate()) return
		
		customer.state = State.REGISTERED_WARNED
		customer.save()
		
		sendMailMessage(customer)
	}
	
	// ...
}

As you can see, code for the service class does not feel that complicated anymore. Changing the customer’s state should be externalized to another domain class like CustomerWorkflow:

class CustomerWorkflow {	
	
	State state
	Customer customer
	
	// ...
}

This would simplify the service class’ method code to:

class CustomerService {	
	
	static transactional = true
	
	def void sentTestPeriodEndsMail(final Customer customer)  {
		
		if (!customer.isTestPeriodEmailCandidate()) return
		
		customer.workflow.mailMessageSent()
		
		sendMailMessage(customer)
	}
	
	// ...
}

Keep in mind that there is no single best way on how to treat domain logic in enterprise applications, but one should at least know some basic patterns found in [4] or [5].

Entities vs. Value Objects

Another thing which is important for larger Grails projects is to recognize the difference between entities and simple value objects.

In Grails, each generated domain class is an entity – it can be uniquely identified. On the other side, value objects do not have an identity, are immutable and interchangeable. Value object classes could be enumerations, but also separate GORM domain classes. GORM supports embedding domain classes within other domain classes. The decision whether a certain class is a value object class or entity class can change from domain to domain. It could be that an address is a value object, but put in another context an address is an entity.

Defining value objects with domain classes is usually done with the static embedded property:

class Customer {	
	
	// ...
	Address homeAddress
	
	static embedded = ['homeAddress']
}

class Address  {
	
	String street
	// ...
}

Embedding classes has the advantage that developers don’t have to care about cascading CRUD operations, since data is directly embedded in the parent table at the database level. Therefore, value object classes simplify domain class relationships.

The Role of Repositories

A repository is responsible for loading persistent objects from arbitrary data stores. In Grails, this functionality is mostly encapsulated with GORM generated methods, available as static methods in each domain class:

def customers = Customer.findAllByState(State.NEW, [max: 10])
// ...

To be honest, outsourcing data accessing logic in a separate repository class does not seem to be reasonable with GORM. At least one use case would justify separate repository classes: complex data graph deletion.

If the domain model has complex relationships the best strategy is to define Aggregate objects. An aggregate object is the root object of a graph of associated objects. Clients of that class access objects in the aggregates graph only through accessor methods in the aggregate object. It is not possible to modify objects in the data graph directly without using aggregate methods.

This pattern simplifies relationships within the domain model and therefore reduces complexity to handle the object graphs and relationships between them. Overall, modification/deletion operations are hidden and encapsulated by the root entity of the aggregate.

Conclusion

This article does not claim to offer a complete overview of best practices in Grails enterprise projects, but reflects best-practices that i have found useful in projects i participated in.

I would be happy to discuss other views or other patterns in the comments section of this article.

[0] Active Record Pattern – http://martinfowler.com/eaaCatalog/activeRecord.html
[1] Factory Method Pattern – http://en.wikipedia.org/wiki/Factory_method_pattern
[2] Builder Pattern – http://en.wikipedia.org/wiki/Builder_pattern
[3] Integration and Grails – https://andresteingress.wordpress.com/2010/05/11/integration-and-grails/
[4] Domain Driven Design – Eric Evans
[5] Patterns of Enterprise Application Architecture – Martin Fowler

Categories: basic, grails, patterns