Tuesday, May 02, 2006

An idea for Composite Specifications

Several days ago I've written some blog posts about how to work with and implement Specifications.

In particular, I've written one article about how to implement Specifications with Apache Commons Collections.
For a short recalling, we implemented Specifications using Commons Predicate as base interface, which let us combine those specifications using Commons PredicateUtils class.
This approach has two main disadvantages:

  • Force you to use the Commons Predicate interface which, for example, is not generics-enabled

  • Give you a flexibility limited by Commons PredicateUtils capabilities.


What about using a generic composite specification, capable of combining general specifications using logical operators, with a fluent-style interface?

Let us suddenly go with a simple example.

Take one office interface:


public interface IOffice {

void setOfficeId(String officeId);

String getOfficeId();

void addEmployee(IEmployee e);

Set getEmployees();
}


Take one employee interface:


public interface IEmployee extends Serializable {

void setMatriculationCode(String matriculationCode);

String getMatriculationCode();
}


You can create offices and add employees to them, but your boss said you have some business rules:

  • Every office id must begin with the "o" letter, and follow with numbers.

  • You cannot have an office with more than three employees.



Say you want to implement those rules as Specifications (remember, this is an oversimplified example).
Here are your specifications:


/**
* A generics-enabled specification interface.
*/
public interface Specification<T> {
public Boolean isSatisfiedBy(T object);
}

/**
* A specification for the office id.
*/
public class OfficeIdSpecification
implements Specification<IOffice> {
public Boolean isSatisfiedBy(IOffice o) {
return o.getOfficeId().matches("o\\d+");
}
}

/**
* A specification for the office room availability, determining
* if an office is full.
*/
public class FullOfficeSpecification
implements Specification<IOffice> {

private int limit = 3;

public Boolean isSatisfiedBy(IOffice o) {
return o.getEmployees().size() > this.limit;
}
}


And ... here is how would be our composite specification:


public class CompositeSpecification<T> {

public CompositeSpecification(Class<T> specificationClass,
String specificationMethod,
Class specificationObjectClass) {
// ...
}

public CompositeSpecification compose(T specification) {
// ...
}

public CompositeSpecification and(T specification) {
// ...
}

public CompositeSpecification or(T specification) {
// ...
}

public CompositeSpecification and(CompositeSpecification<T> specification) {
// ...
}

public CompositeSpecification or(CompositeSpecification<T> specification) {
// ...
}

public CompositeSpecification andNot(T specification) {
// ...
}

public CompositeSpecification orNot(T specification) {
// ...
}

public CompositeSpecification andNot(CompositeSpecification<T> specification) {
// ...
}

public CompositeSpecification orNot(CompositeSpecification<T> specification) {
// ...
}

public CompositeSpecification not() {
// ...
}

public boolean evaluate(Object object) {
// ...
}
}


I intentionally omitted implementation details because at the moment I'd like to point you out:

  • The generics-enabled interface, which let you specify your own specification to combine.

  • The constructor, where you have to describe the actual specification you'll combine, specifying its class, its specification method (isSatisfiedBy in our example) and the class of the specification object (IOffice in our example).

  • The fluent-style interface methods for applying logical operators to actual specifications or other composite specifications.


Here is an example about how to use such a class:


CompositeSpecification<Specification> compositeSpecification =
new CompositeSpecification<Specification>(Specification.class,
"isSatisfiedBy",
IOffice.class);

OfficeIdSpecification spec1 = new OfficeIdSpecification();
FullOfficeSpecification spec2 = new FullOfficeSpecification();

IOffice office1 = new Office();
IEmployee emp1 = new Employee();

office1.setOfficeId("o1");
emp1.setMatriculationCode("1");
office1.addEmployee(emp1);

// The office has a valid id and is not full:
assertTrue(compositeSpecification.compose(spec1).andNot(spec2).evaluate(office1));


I'll discuss implementation details in another post.
But for now, what do you think about this approach?

Updates:
04/05/2006 : Fixes in code.

9 comments:

Johann said...

I came to a similar conclusion regarding commons-collections predicates. Too bad there are no usable specification implementations out there.

The specifications look nice with the fluent-style interface.

Now, in order for specifications to be really useful, there has to be a way to map them to (alternative?) persistence technology queries. How would you propose to do that?

Lastly, I have found it useful to implement a sort of "Specification.validate" method which creates (or populates) an object with all the ways an object deviates from a specification. This is immensely useful for testing, as you can check what the reason was for an unexpected result much more easily that way.

Sergio Bossa said...

Johann said ...

> I came to a similar conclusion regarding commons-collections predicates. Too bad there are no
> usable specification implementations out there.

I'm working on an open source project which will include a Specification implementation based on the one I told here.
So, your suggestions are welcome and very useful ...

> there has to be a way to map them to (alternative?) persistence technology queries. How would you
> propose to do that?

Sorry, I've missed your point here.
What do you mean?
Do you refer to Specifications used for implementing Criteria-style querying?

Thank you,
Regards,

Sergio B.

Roni Burd said...

I think it is nice and very similar to the one available in commons. The only disadvantage In *not* using commons is that commons has a lot more regarding the use of predicates that simple composite predicates.

If you take a look at the common collections you'll see such Util classes as ollectionUtils.select(java.util.Collection inputCollection, Predicate predicate) that select elements of a collection based on a predicate. There are similar one to creating Bags, Maps and Sets.

Then, there is also the Closure and Transformer operations you can use together with the predicates. Per example, you could create a generic closure operation that visits a list of Offices and make sure they perform with the Specification and if not do an action or return an object.

My point is that Predicates is just a small part of logical programming in commons so you way want to take a look at it and see what else could be interesting to extract.

Sergio Bossa said...

Roni Burd said ...

> I think it is nice and very similar to the one available in commons.

Roni, it is not intended to be a duplicate of Commons Predicate, because with CompositeSpecification you can:

1) Use your own specifications, each with its proper interface.
2) Compose them using a fluent interface.

> The only disadvantage In *not* using commons is that commons has a lot more
> regarding the use of predicates that simple composite predicates.

Yes, you are right.
However, I'm planning to integrate CompositeSpecification with Commons Predicate, in order to be used together with Commons Collections capabilities, without reinventing the wheel.
I see two approaches:

1) Letting CompositeSpecification implement Predicate.
2) Introducing the Predicate interface into CompositeSpecification when needed, via AOP introduction.

What do you think?

Thank you,
Regards,

Sergio B.

Roni Burd said...

If I have to choose I would be inclined to prefer AOP, but it seems you are more capable than I am at using AOP introductions. Is not that I don't like hooking with commons, it's just that I like code that is more "free" of external packeges.

Sergio Bossa said...

Roni Burd said ...

> If I have to choose I would be inclined to prefer AOP

I agree with you.
However we overrated the problem: given that we know both interfaces in advance (the Predicate interface and the CompositeSpecification one) we can use a simple, plain, object adapter.

AOP introduction is instead still useful if we want to adapt the CompositeSpecification interface to specification interfaces provided by developers.
Say you have a method in one of yours business objects:

public setCustomerSpecification(ProprietarySpecification spec);

You cannot use the CompositeSpecification here because you'd have to change the interface.
An AOP mixin could be used to mix the CompositeSpecification interface and the ProprietarySpecification one.

What do you think?

> Is not that I don't like hooking with commons, it's just that I like code that
> is more "free" of external packeges.

Again, I agree with you.
Indeed, CompositeSpecification is implemented under the cover using Apache Commons ... however, they are interface level dependencies to be wrong ... implementation dependencies are another story.

Thanks,
Regards,

Sergio B.

web design company,web designer,web design India,website design,web design said...

Thanks u r information

dpanupam said...

Thats a very interesting post. I have been inspired. Thanks. Web Designer

davit hogg said...

Brilliant article! Thanks for sharing your experiences.




composiet
keramiek
terrazzo
graniet