Category Archives: Persistence Ignorance

Implementing a Customer Search Service – Part 2

Continuing on from my previous post, let’s start off by coding up the unit tests based on the behaviour scenarios we laid out. To ease my transition towards the BDD-like way of writing tests, I’m using xUnit along with a really handy base class and observation attribute developed by Fredrik Kalseth (check out his blog post here to see how this all works). As a refresher, the scenario I’ll be testing first is:

WHEN searching for customers

GIVEN customers exist matching the search criteria

THEN records matching the criteria will be retrieved from the persistence store AND customer summaries are returned AND the search is successful

And the coded test looks like this:

public class When_Searching_For_Customers 
              : Given_Customers_Exist_Matching_Criteria
{
    private ISearchResult<ICustomerSummary> _result;

    protected override void Observe()
    {
        ICustomerSearchService service = 
           new CustomerSearchService(_repository, _customerSummaryMapper);
        _result = service.Find(_criteria);
    }

    [Observation]
    public void Records_Matching_criteria_are_requested_from_repository()
    {
        Assert.Equal(1, _repositoryInvocationCount);
    }

    [Observation]
    public void Customer_Summaries_are_returned()
    {
        Assert.NotNull(_result.Hits);
    }

    [Observation]
    public void The_Search_is_successful()
    {
        Assert.True(_result.IsSuccessful);
    }
}

Pretty simple stuff. Following the Arrange, Act, Assert pattern for authoring tests, the “arranging” of the test takes place in the base class (which I’ll cover shortly), the “act” takes place by creating and invoking the service,  and finally there is then an assertion for each observation that we are hoping to prove.

The base class that manages the set-up of the test context looks like this:

public abstract class Given_Customers_Exist_Matching_Criteria 
                       : Specification
{
    protected IRepository<Customer> _repository;
    protected ICustomerSummaryMapper _customerSummaryMapper;
    protected ISearchCriteria<Customer> _criteria;
    protected int _repositoryInvocationCount;

    protected override void InitializeContext()
    {
        _repository = GetMockRepository();
       _customerSummaryMapper = GetMockCustomerMapper();
    }

    private static ICustomerSummaryMapper GetMockCustomerMapper()
    {
        var mock = new Mock<ICustomerSummaryMapper>();
        mock.Expect(map => map.MapFrom(It.IsAny<IList<Customer>>()))
            .Returns(new List<ICustomerSummary>());
        return mock.Object;
    }

    private IRepository<Customer> GetMockRepository()
    {
        var mockRepository = new Mock<IRepository<Customer>>();
        var mockCustomers = GetMockCustomers();
        mockRepository.Expect(rep => rep.Find(_criteria))
            .Returns(mockCustomers)
            .Callback(() => _repositoryInvocationCount++);
        return mockRepository.Object;
    }

    private static IList<Customer> GetMockCustomers()
    {
        var mockCustomers = new Mock<IList<Customer>>();
        mockCustomers.Expect(customers => customers.Count).Returns(10);
        return mockCustomers.Object;
    }
}

This class simply creates mocks for the dependencies of the SUT, such that we can test the unit in isolation. The only little extra here is that the mock repository behaves more like a test spy, since it allows us to monitor the number of times that the Find() method has been invoked.

 

Implementing the Service

Since I want to be completely flexible with my search criteria, I want the contract of my service to take in an abstraction of the Customer search criteria, rather than specifying a finite set of inputs. I think the following contract describes this quite well:

ISearchResult<ICustomerSummary> Find(ISearchCriteria<Customer> criteria);

 

I don’t want any of my data retrieval responsibilities leaking into the application layer. This work should be delegated repository. I therefore want my service to pass-through the search parameters into a repository implementation. Rather than making the repository aware of the presentation layer object ISearchCriteria, it is better to use a common, shared abstraction. A suitable abstraction to use here would be to use the specification pattern for the search criteria, and passing this abstraction to the repository.

As discussed briefly in my previous posts (and in detail here), I believe my repository should behave like a collection of entities (rather than serving up a query in the form IQueryable<T>). I also know my repository can only return a reference to entities defined as the root of an Aggregate.

Taking all this into account, I can specify my repository interface as:

public interface IRepository<TAggregateRoot>
    where TAggregateRoot : class, IAggregateRoot
{
    /// <summary>
    /// Find entities by specification.
    /// </summary>
    IList<TAggregateRoot> Find(ISpecificationExpression<TAggregateRoot> criteria);
}

NB: It’s likely that my Repository Interface will later include the ability to save new and updated entities, however as per YAGNI, I won’t include this for the moment.

 

Since my repository can only return a reference to an Aggregate Root, the Customer aggregate root will need to be mapped to the required CustomerSummary presentation object. A suitable interface for this mapper object could be:

ICustomerSummary MapFrom(Customer customer);
IEnumerable<ICustomerSummary> MapFrom(IList<Customer> customers);

All that remains then is to create an implementation of the service based on these interfaces. This is quite simply:

public ISearchResult<ICustomerSummary> Find(ISearchCriteria<Customer> criteria)
{
    var customers = _repository.Find(criteria);

    if (customers == null || customers.Count == 0)
    {
        return new CustomerSearchResult
        {
            IsSuccessful = false,
            FailureReasons = new[] { "No Customers found." }
        };
    }

    var summary = _mapper.MapFrom(customers);

    return new CustomerSearchResult { IsSuccessful = true, Hits = summary };
}

 

All that’s left is to create simple implementations for the remaining objects (CustomerSearchResult, CustomerSummary CustomerSearchCriteria) and we’re ready to rock. Now the logic of the Application Service is created and the tests pass, we can create a repository implementation making use of the Entity Framework sample’s EFPocoAdapter project. I’ll cover this in my next post.

Implementing a Customer Search Service with DDD, BDD and the Entity Framework

I’ve been keeping an eye on the evolution of the Entity Framework since the early VS2008 betas, but it’s lack of POCO support in its V1 release really put me off, especially since this made it particularly awkward to use Test Driven Development (TDD). For me, the final nail in the coffin was its apparent incompatibility with Domain-Driven Design (DDD), or so I thought…

Jaroslaw Kowalski recently posted on his blog about a sample project published on MSDN that allows an adapter layer to be written (generated), which will translate between POCO objects and Entity Framework-aware objects. By doing this, an application service can make use of features like Change Tracking, Lazy Loading, LINQ Queries, and Shadow State, without interfering with our POCO objects. This allows use to create our Domain Model without being distracted by persistence concerns, and even better, our model can be created independently from our database schema.

As you can imagine, this has re-ignited my interest in the Entity Framework, but before I’m sold on the idea, I figured I’d put the sample to the test by trying it out with service implemented following DDD.

Where to begin?

The published sample project (currently on version 1.0.3 at the time of writing) contains some simple POCO classes based on the Northwind database. Some of these POCO objects may be considered to be Entities, such a Product or Customer, and some may be considered to be value objects, such as CommonAddress (which by the way is also immutable). What we are missing in  the example though  (for the purposes of a well-rounded DDD test) is some clear Aggregate Boundaries, some repositories to retrieve references to our Aggregate roots and Services to provide a cohesive set of operations to our client applications.

Assuming an existing Entity, such as customer, can be made the root of its own aggregate, and that we can easily define our own repositories* by writing our own implementation of an EFPocoContext (the code-generated context will have IEntitySet<T> properties for each of our entities, not just the aggregate roots, so is inappropriate for DDD), all that remains to be proven then is a service implementation.

*It’s also debatable whether a repository should return a result in the form IQueryable<TEntity> since this is only a query object, and not the result itself (see this post for further discussion on this).

The Task

What I’d like to do is create a simple Application Service that allows a client application to search for customers. I’d like to extend the simple CustomerSearchService featured here to include the ability to search on a wider set of criteria, and return a collection of search results. The criteria for the search may relate to the  customer itself, the customers order detail, or a combination of criteria. In fact, as a sample range of criteria, lets use those listed by Jimmy Nilsson in his book “Applying Domain-Driven Design and Patterns”:

We should be able to query for customers who:

  • Have a name with “aa” in it. (Hidden Marketing for a Swedish car company.)
  • Ordered something last month.
  • Have orders with a total amount greater than one million.
  • Have a reference person called “Stig.”

Since I also want this example to test the compatibility of the Entity Framework with “modern development approaches”, I will also be test-driving the development following (as closely as I can) to the style of Behaviour Driven Development (BDD). Typically in BDD, the words “Given”, “When” and “Then” are often used to help drive out the scenarios. The word “Given” describes the context of the test, the state of the SUT if you will. The word “When” represents the unit of work or action that you are testing. The word “Then” simply describes each result, or observation expected from the system. For the purposes of this implementation, I shall use the following scenarios:

WHEN searching for customers

GIVEN customers exist matching the search criteria

THEN records matching the criteria will be retrieved from the persistence store AND customer summaries are returned AND the search is successful

GIVEN no customers match the search criteria

THEN the search is unsuccessful AND the client application is notified that no customers match the provided criteria.

 

So this should give me a decent starting point to kick off from. Next time we’ll code up the unit tests for this and crack on with the implementation.

Follow

Get every new post delivered to your Inbox.