Assertfail

Data Specifications in Java and .net

07 Apr 2023

Background

In dotnet-architecture/eShopOnWeb I noticed the interesting usage of Specification classes. When I did some digging, I found that these are implemented through ardalis/Specification For those who are more familiar with the Java world we have Data Specifications. If you read Implementing Domain Driven design in the bibliography you find a reference to Martin Fowlers paper.

Sample based on Wikipedia

So if we look at Wikipedia we can infer the following code:

public class OverDueSpecification : ISpecification<Invoice>
{
    public bool IsSatisfiedBy(Invoice entity)
    {
        return entity.PayDeadline < DateTime.Now;
    }
}
// ...
var overDue = new OverDueSpecification();
var noticeSent = new NoticeSentSpecification();
var inCollection = new InCollectionSpecification();

var sendToCollection = overDue.And(noticeSent).And(inCollection.Not());

Higher level abstractions

We see that Ardalis Specifications collects System.Linq.Expression (note the lambda):

public class OverDueSpecification : Specification<Invoice>
{
  public OverDueSpecification()
  {
    Query.Where(entity => entity.PayDeadline < DateTime.Now);
  }
}

This can be seen as an alternative API to the interfaces used by EF like IDbSet<> and IQueryable<>.

Modules

Since the point of the pattern is that you should be able to separate the query specification from the data you could argue that the pattern is satisfied by having a module of specifications where you create the specification instances through method calls:

public static class InvoiceSpecifications
{
  public static IQueryable<Invoice> OverDue(this IQueryable<Invoice> query)
  {
    return query.Where(entity => entity.PayDeadline < DateTime.Now);
  }
}
public class InvoiceSpecifications
{
  public static JPAQuery<Invoice> overDue(JPAQuery<Invoice> query)
  {
    QInvoice invoice= QInvoice.invoice;
    return query.from(invoice).where(invoice.payDeadline.lastname.lt(LocalDateTime.now());
  }
}

Conclusion

The choice of using a class for a single specification or a method depends on how visible you want these specifications to be. By having a class in a separate file with a single specification, it becomes possible to browse in file system viewer. Some might argue that this introduces ceremony, but that depends on the preferences of the team (as can be seen in the eShopOnWeb example).

Tags


Comments

Do you want to send a comment or give me a hint about any issues with a blog post: Open up an issue on GitHub.

Do you want to fix an error or add a comment published on the blog? You can do a fork of this post and do a pull request on github.