Home > DDD, Patterns > DDD Specifications

DDD Specifications

Specifications is an interesting pattern as it allows reuse of expressions on entities for filtering, querying, validation … going further, it could also be used to present users with smart composite filters in the UI (instead of the usual 'type a filter value for this field').

I was thinking about writing a lenghty post on specifications but others have done it, and probably much better than I could, so … I'm just going to gather some links for you to dig deeper in what specifications are and what they can be used for.

Ok, the Specification pattern looks good … but is it really usefull ? Well, yes ;) If you combine it with a Linq-friendly Repository, it is indeed quite usefull:

SpecificationModel

SpecificationModel

Let me describe the various components that appear on this diagram:

  • ISpecification<TEntity>: This is the base interface for Specification. It has one method 'IsSatisfiedBy' that takes an entity (a class without any other specific constraint) as argument and return a bool indicating if the entity matches the specification or not.
  • ILambdaSpecification<TEntity>: A specialized base interface for Specifications expressed as a Lambda expression. It has members returning the Lambda expression, an equivalent Predicate and a String representation.
  • LambdaSpecification<TEntity>: The implementation class of ILambdaSpecification<TEntity>. Contains implicit conversion operators from & to an untyped Lambda expression.
  • IRepository<TEntity>: The base interface for a Linq-friendly repository … and as Specifications can be expressed as Lambda expressios (= ILambdaSpecification<TEntity>), they can also be used as query filters on the Repository.
  • LambdaSpecificationExtensions: Extension method that allows conversion of a Lambda expression to a ILambdaSpecification<TEntity>.

That's just the base model for Specifications and the link with Repositories. Other aspects such as specification compositions must be taken into account, Linq supporting natively some of the necessary capabilities. Advanced specification concepts such as Subsumtion & Partially satisfied specifications can be implemented if needed only (don't make things more complex than they need to be for your project).

I hope this little introduction on specifications gave you an idea of the level of expressivenes your domain model can reach when using named specifications & specifications-friendly repositories !!! ;)

Categories: DDD, Patterns Tags: , , , ,
  1. Jörgen Andersson
    May 17th, 2009 at 19:18 | #1

    Hello!

    I’ve been looking into your post about LambdaSpecifications. Do you have any examples as to how you use the LambdaSpecification class together with a repository method?

    Regards, Jörgen

  2. Jörgen Andersson
    May 18th, 2009 at 10:41 | #2

    I have been working with your LambdaSecification for a day now and I like a lot of it. One question mark that does turn up though is: doesn’t this model require a great deal of granularity in order to for example being able to tell a client WHAT went wrong when validating an entity according to a specification? I mean for example if I create a lambda expression like: c => c.Address != default(Address) && !string.IsNullOrEMpty(c.FirstName) && (and so on…), where I test more than one thing of a Customer (“c”) entity in this case it gets hard to tell the client which one of these valdations that didn’t go through. In order to make that happen I would need to split my expression above into two (or more) separate expressions and have each one evaluate on its own in order to be able to send meaningful messages to the client.

    Or do you have some other smarter way of handling messaging back to the client?

    Regards, Jörgen

  3. May 26th, 2009 at 10:57 | #3

    @Jörgen Andersson
    Hi Jörgen, what I usually did was to expose specifications as static properties of the entity class (if you have an Invoice entity, expose specs as Invoice.IsApproved for example). An alternate possibility is to regroup the specifications in an inner class like Invoice.Specifications.IsApproved … but some people don’t like it, it’s a matter of taste. In both cases, I was using partial classes for the Entity, Entity Specifications, Entity Validations, …

    You can then query your repository like this : repository.FindAll(Invoice.IsApproved).

  4. May 26th, 2009 at 12:32 | #4

    @Jörgen Andersson
    Hi again Jörgen ;)
    If you want to use your Specifications for both Validation & Querying, you might indeed need to have some granularity in the information returned by the IsSatisfiedBy method of the Specification, that is to say more than just a ‘bool’ value. A solution might be to add an overload to the IsSatisfiedBy method to return a collection of validation messages as out parameter. That way, a specification could return one or more messages indicating why the specification is not met by a particular entity.

  1. No trackbacks yet.