Articles

Specification pattern for selection on lists

One thing I really like to use is selection or validation based on the Specification pattern, as originally proposed by Martin Fowler and Eric Evans.

Specifications are a very powerful way to perform selection, searching and validation on any object without putting the logic on the object itself. We would really like a way to reuse our business logic, throughout our application, in several use cases, without cluttering our domain object. We also want a way to generalize the selection criterium on a list kind of structure, instead of writing a wrapper around a list based structure that holds some logic that is needed for our problem domain. We also need a way to explicitly state what our business logic is and make it easily reachable, as business logic changes all the time, depending on the wishes of the client, the users of the application, on the weather and other stuff beyond our control ;). This is where the Specification pattern is a great way of doing business with our application.

Let’s make up an example based on the previously stated requirement of what we want to do. It will be based upon selecting a couple of users from a larger list.

  1. the problem domain: ‘we need a user list that holds information about individual users with their characteristics and be able to select them according to their properties, and the selection criterium needs to be reusable
  2. reuse the business logic throughout the application, several classes that might do a search on the list, need not perform the same/duplicate logic to get the same results: ‘get all users of the female type with red hair that are single’
  3. no code duplication: this is an alternative form of the previously stated requirement
  4. do not clutter the domain objects with methods that are not necessary for the domain object to live and which makes it harder to maintain: in our case ‘Users’ and ‘User’
  5. make the selection generic and not based on a wrapper kind of object around a list: the wrapper in our case is “Users”

To demonstrate how we could do this, let us first take a look at what we might want to change when we look at an example that might already exist.

You see a lot of code like this: a Users class, that keeps track of users (the wrapper around a list based structure), with methods like getUsersByHairColor, getUsersByGender, and getUsersByMaritalStatus(can you see the problem here? hint: what happens when we want to add a new feature?), which is a very local way (bound to the class) of storing our business logic (in this case a selection on the list).
It also suffers from the fact that almost every call made to the Users instance, will be delegated to the actual User instances on the internal list maintained by the Users instance. This means a lot of code duplication in each and every method (’for all users, check if the user has red hair’). The other drawback is that we need to do a subselection outside of the Users class, and on that subselection, do another selection and so forth, depending on the number of selection criteria (’get all red haired users, from that list, select the females, from that resulting list, select the ones that are single’).
The direct consequence is that this is error prone, as you, as a developer, might easily forget (when duplicating the logic) to add the criterium that’ a user must be single’ in another class and therefore might be introducing an error in the process which may have fatal consequences: you will have different selection results! Depending on your preferences, this might or might not be good for you, but is is a wrong selection anyway :). It is also impossible to reuse throughout the application (unless we create a method on Users like ‘getRedhairedSingleWomen’, and even more impossible to reuse in different applications, which is what a lot of coding is all about.

Now, we have clearly painted a picture of what is wrong here… How do we solve it? Simple, by using a (you guessed it) Specification.
In essence a Specification is an object that encapsulates some logic which it tests agains a candidate to see if it satisfies any logic that is inside the Specification object. Since it is an object, a Specification can hold state and can be configured via it’s constructor. The only method that makes it a Specification is the abstract method

public function isSatisfiedBy(candidate:*): Boolean

It checks whether or not a candidate object (untyped, we unfortunately cannot use generics like in Java in actionscript at the moment) satisfies the criteria set in the isSatisfiedBy method. Any concrete specification overrides and implements the isSatisfiedBy method to put in the tests against the business logic. If the method returns “true” it means that the object indeed satisfies the Specifications demands.

In our case we could have a ‘RedHairSpecification’:

public function isSatisfiedBy(candidate : *) : Boolean
{
	return User(candidate).getHairColor() == Color.RED;
}

or for the full deal we want a ‘RedHairedSingleWomenSpecification’:

public function isSatisfiedBy(candidate : *) : Boolean
{
	return User(candidate).getHairColor() == Color.RED && User(candidate).getMaritalStatus() == MaritalStatus.VERY_SINGLE && User(candidate).getGender() == Gender.FEMALE;
}

A little later in this post I will show a more elegant way of solving the same problem with composite specifications.

The business logic is now encapsulated inside the object and easy to change in one single place.
We could use this specification inside the users object:

public function getRedhairedSingleWomen(): Array{
	var user: User;
	var output:Array = new Array();
	var specification: ISpecification = new RedHairedSingleWomenSpecification();
	for(i:int = 0; i< users.length;++i){
		user = users[i] as User;
		if(specification.isSatisfiedBy(user)){
			//we now know the user is what we ask for!
			output.push(user);
		}
	}
	//return the users in an array
	return ouput;
}

which is somewhat better, as the logic about how to select them has it’s own place, but we still need a rather awkward method on the Users class. Up till now we have solved the reusable part and the generic part by creating the Specification interface we can use throughout our code, but we did not solve the problem of cluttering the domain object with unwanted methods and of avoiding the use of an object that basically acts as a wrapper around a list.

The way to solve the problem of de-cluttering the domain object “Users” is to provide only one method for selection:

public function selectBy(specification: ISpecification):Array{
	var user: User;
	var output:Array = new Array();
	for(i:int = 0; i< users.length;++i){
		user = users[i] as User;
		if(specification.isSatisfiedBy(user)){
			output.push(user);
		}
	}
	return ouput;
}

This is already a lot better, but we need a final abstraction. As you can see, we still have some code in the routine that is all about users, we define a User object, and we loop over a users Array.

We can solve the final problem by defining a datastructure with a ’selectBy’ method on it, which is able of storing arbitrary types of data. We did exactly this in our collections package by creating the ISelectable interface which defines this method:

function selectBy(specification : ISpecification) : IList

and by having our IList types implement the ISelectable interface (IList types are LinkedList and ArrayList). By having the method return a new IList, we are able to use other routines on the resulting IList, and take advantage of the power of some methods on those ILists (for example: sorting). A discussion of the IList type is beyond the scope of this post, but more information can be found on the blog or in the source code.

Now, to really use Specifications on nitro, we can use a way to couple seperate specifications into a single one to create powerful combinations that let us go crazy on our selection criteria. To reach this goal we need the “AndSpecification”, the “OrSpecification” and the “NotSpecification” which provides us with logical operators on the Specifications themselves.
The ISpecification interface looks like this:

package nl.dpdk.specifications {
	public interface ISpecification {
		function isSatisfiedBy(candidate : *) : Boolean
		function and(specification : ISpecification) : ISpecification
		function or(specification : ISpecification) : ISpecification
		function not() : ISpecification
	}
}

The Specification Class inside our package implements these methods but leaves isSatisfiedBy as an ‘abstract’ method (there is no formal abstract modifier for methods in actionscript) to be implemented by your subclasses.

The solution to the example would then be implemented in the following way:

//create userlist
var users: IList = new LinkedList();
//users are created and put in the list
users.add(aUser);
//etc...
 
//now we need to select the single redhaired women
var specification: ISpecifaction = new RedHairSpecification();
specification = specifcation.and(new SingleSpecification());
specification = specification.and(new GenderSpecification(Gender.FEMALE));
var womenIMightDate: IList = users.selectBy(specification();
//take massive action
var woman: User;
var subject: String = "hi there";
var body: String = "your catchy phrase here...";
var iterator: IIterator = womenIMightDate.iterator();
while(iterator.hasNext()){
	woman = iterator.next() as User;
	sendEmail(woman, me, subject, body);
}
 
private function sendEmail(to: User, from: User, subject: String, body:String):void{//implementation here}

We now have a flexible, reusable and scalable list based selection procedure that is not invading on domain objects.

And better yet, it is baked into a simple to use package and is easily extendible for use by others :) So give specifications a try and have fun!

The specification pattern can be used as is from the specification package in nl.dpdk.specifications by subclassing the Specification class. There is also an ISelectable interface in the nl.dpdk.collections package, which has a

public function selectBy(specification: ISpecification): IList;

method on it, and diverse classes in the collections package implement this interface.

When you do have a need for extra features on your specific class that also needs list like behaviour, you can always implement the ISelectable interface, and use one of the lists from the package inside your class to delegate the needed list behaviour to. In this way, you have the benefit of tested and working classes and the power of specifications at the same time.

some further references:

0 Responses to “Specification pattern for selection on lists”


  1. No Comments
  1. 1 The collections package at dpdk Open Source
  2. 2 folding, mapping and applying commands on datastructures and collections at dpdk Open Source
  3. 3 Factory for creating ResultSet from an SQLResult in AIR at dpdk Open Source

Leave a Reply