Creating Fluent finders and repositories part 1

Introduction

This is the first post of this series about implementing fluent finders and repositories, I am going to expand my current repository and finder implementation which is explained here. I recommend that you read this post (precursor) as this series continues on from this post and the code examples.

The objectives for this series are:

  • Create a fluent interface on the finders
    • Chain the find methods so that you can find on more than one method (method chaining).
    • Create an interface for sorting.
    • Create an interface for paginating the results.
  • Allow a service request (coarse grain) to be mapped to a specific fluent-interface call.
    • Based on information provided to a service as a request object, determine the right strategy for satisfying the request.
    • Execute the relevant strategy to perform the relevant queries
    • Return the query results to service method that was called.
    • The service method will return results as a response object.
  • Drive out these behaviours using TDD/BDD.

The outcome of this work will allow you write something like:

repository.find.ByThis(somevalue).AndFind.ByThat(someOtherValue).SortBy(aField, InAscendingOrder).Paginate.WithPageSize(10).ShowPage(1);

Before I start, one of the main benefits of a fluent interface is that you create an API that guides and limits the decisions that can be expressed in a logical order. So the interface needs to limit the options as the expression flows, which ultimately means you need to plan out the branching and the interfaces for each branch and decisions to ensure that public interface is meaningful to its context.

Table of Contents

Precursor

Part 1  (this post)

  • Refactoring the existing interfaces to provide interface segregation.
  • The Query Command
  • Method Routing
  • Method Chaining

Refactoring

Following on from the precursor, I need to stop my “IApplicationUserFinder” from implementing the “IEntityFinder” interface. The reason for this is the the  “IEntityFinder” interface exposes a property called DataSource. The published Fluent interface will want to expose the Find methods but not the DataSource property. So a bit of interface segregation is needed here to expose the right interface to the relevant consumer. While doing this refactoring, I decided that the name of the “IEntityFinder” is not right so I have renamed it to “IQueryableDataStore”. Although I have changed these interfaces around my concrete class  ApplicationUserFinder still need to implement both. So I have created yet another interface called “IQueryableApplicationUserFinder” which implements the “IQueryableDataStore” and “IApplicationUserFinder” interfaces. Now the ApplicationUserFinder class just implements IQueryableApplicationUserFinder. If I have scrambled your brain up, hopefully the code snipets below will make things clear.

    public interface IQueryableDataStore where Entity : EntityBase // was IEntityFinder
    {
        IQueryable DataSource { get; set; }
    }
...
    public interface IQueryableApplicationUserFinder :
        IApplicationUserFinder,
        IQueryableDataStore
    {
    }
...
 public class ApplicationUserFinder : IQueryableApplicationUserFinder
...

Now, how is this used. The ApplicationUserFinder is injected into the ApplicationUserRepository and then exposed via a getter (all by interfaces).  With the “IQueryableApplicationUserFinder” now in play, here is the revised code snippet for the repository (remember to change your IoC container to accommodate these changes).

    public class ApplicationUserRepository : EntityRepository,
        IApplicationUserRepository
    {
        private readonly IQueryableApplicationUserFinder finder;

        public ApplicationUserRepository(IPersistanceRepository repository,
            IQueryableApplicationUserFinder finder) : base(repository)
        {
            this.finder = finder;

            this.finder.DataSource = Query();
        }

        public IApplicationUserFinder Find
        {
            get { return finder; }
        }
    }

At this point, all my unit tests pass and application runs the same as it did before this refactoring.

The Query Command

Regardless of the expression that you can write using the fluent-interface, it needs  an end at some point. The Query Command objects is responsible for executing the query and return the result. I am using “Linq for objects” to write my queries and passing an IQueryable around under the covers, the execution of the queries is deferred until a method is called on it like “ToList()”. Calling the “ToList()” method will execute the underlying query.  I have  created a command object (based on the command pattern) to expose an “Execute” method that is going to return an IEnumerable<Entity>. The reason for returning “IEnumerable<Entity>” is that you have a vast about of extension methods that you use to execute the query. For example “ToList()” and “FirstOrDefault”. We can create the Query Command now and integrate it into the fluent-interface later with out much effort.

    public interface IQueryCommand where Entity : EntityBase
    {
        IEnumerable Execute();
    }

    public class QueryCommand : IQueryCommand
    {
        private readonly IQueryableDataStore queryableDataStore;

        public QueryCommand(IQueryableDataStore queryableDataStore)
        {
            this.queryableDataStore = queryableDataStore;
        }

        public IEnumerable Execute()
        {
            return queryableDataStore.DataSource.AsEnumerable();
        }
    }

So how can the fluent-interface get to this endpoint? Answer: we need an object to return it, so we can call it. I have defined this as “MethodRouter”.

Method Router

The method router exposes the actions that could be performed after a find method is called. As this is based on my previous post Implementing the Repository and Finder Pattern, I am going to change the original unit tests to drive out the method router. Here is the original specification for the “ApplicationUserFinder” class.

    [TestFixture]
    public class When_executing_queries_against_application_users
    {
        private ApplicationUserFinder finder; // subject under test

        [SetUp]
        public void Setup()
        {
            finder = new ApplicationUserFinder();

            finder.DataSource = GetStubbedCollection();
        }

        [Test]
        public void Should_return_a_user_by_login_name_when_supplied_a_known_login_name()
        {
            ApplicationUser result = finder.ByLoginName("Test.User3");

            Assert.That(result.LastName, Is.EqualTo("User3"));
        }

        [Test]
        public void Should_return_a_user_by_token()
        {
            ApplicationUser result = finder.ByToken(Guid.Empty);

            Assert.That(result.LastName, Is.EqualTo("User2"));
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Should_fail_if_supplied_null_login_name()
        {
            IQueryable users = GetStubbedCollection();

            ApplicationUser result = finder.ByLoginName(null);
        }

        private IQueryable GetStubbedCollection()
        {
            List users = new List
            {
                new ApplicationUser { FirstName = "Test", LastName = "User1", LoginName="Test.User1", Token = Guid.NewGuid() },
                new ApplicationUser { FirstName = "Test", LastName = "User2", LoginName="Test.User2", Token = Guid.Empty},
                new ApplicationUser { FirstName = "Test", LastName = "User3", LoginName="Test.User3", Token = Guid.NewGuid()},
                new ApplicationUser { FirstName = "Test", LastName = "User4", LoginName="Test.User4", Token = Guid.NewGuid()},
                new ApplicationUser { FirstName = "Test", LastName = "User5", LoginName="Test.User5", Token = Guid.NewGuid()}
            };

            return users.AsQueryable();
        }
    }

As you can see from the above tests, each find method returns the result as a single domain entity. I now want to return an interface of the Method Router instead. The Method Router at point will expose the QueryCommand so that I still execute the queries and keep the code in a “close to working” state at all times.

To start with, I defined the MethodRouter interface “IApplicationUserFinderActions”

    public interface IApplicationUserFinderRouter
    {
        IQueryCommand Output { get; }
    }

Now, I need to change the return types in the IApplicationUserFinder to now return the IApplicationUserFinderRouter instead.

    public interface IApplicationUserFinder
    {
        IApplicationUserFinderRouter ByLoginName(string loginName);
        IApplicationUserFinderRouter ByToken(Guid token);
    }

At this point, things a little broken, so I need to change the concrete ApplicationUserFinder class to implement the changes made to the interface. To do this the concrete finder will need to know about the Method Router class. The method Router’s responsibility is to act as a hub to link object instances together. With this in mind, the MethodRouter class will need to know about the finder and the QueryCommand class. Still being mindful of the fluent interface and members it exposes, I need to ensure that the QueryCommand knows about the IQuerable instance held in the finder without coupling the objects together. To achieve this, I going to use the same technique I used in the Refactoring effort being the i return different interfaces to different parties. I have created another interface “IFindableApplicationUserFinderRouter” that implements IApplicationUserFinderRouter with an additional member.

Here is the new interface

    public interface IFindableApplicationUserFinderRouter
        : IApplicationUserFinderRouter
    {
        IQueryableApplicationUserFinder Finder { get; set; }
    }

Here is the concrete class ApplicationUserFinderRouter at this point.

    public class ApplicationUserFinderRouter : IFindableApplicationUserFinderRouter
    {
        private IQueryCommand queryCommand;

        public IQueryableApplicationUserFinder Finder { get; set;}

        public IQueryCommand Output
        {
            get
            {
                if (queryCommand == null)
                {
                    queryCommand = new QueryCommand(Finder);
                }

                return queryCommand;
            }
        }
    }

Here is the changed ApplicationUserFinder

    public class ApplicationUserFinder : IQueryableApplicationUserFinder
    {
        private readonly IFindableApplicationUserFinderRouter router;
        private IQueryable users;

	
        public ApplicationUserFinder(IFindableApplicationUserFinderRouter router)
        {
            this.router = router;
            this.actions.Finder = this;
        }
	

        public IQueryable DataSource
        {
            get { return users; }
            set { users = value; }
        }

        public IApplicationUserFinderRouter ByLoginName(string loginName)
        {
            if (string.IsNullOrEmpty(loginName))
            {
                throw new ArgumentNullException("loginName");
            }

	    
            users.Where(u => u.LoginName == loginName).FirstOrDefault();

            return router;
        }

        public IApplicationUserFinderRouter ByToken(Guid token)
        {
            users.Where(u => u.Token == token).FirstOrDefault();

		
            return router;
        }
    }

Here is a snippet of how one of the unit tests is looking.

	[SetUp]
        public void Setup()
        {
            router = MockRepository.GenerateStub();

            finder = new ApplicationUserFinder(router);

            finder.DataSource = GetStubbedCollection();
        }

        [Test]
        public void Should_return_a_user_by_login_name_when_supplied_a_known_login_name()
        {
            ApplicationUser result = finder.ByLoginName("Test.User3").Output.Execute().FirstOrDefault();

            Assert.That(result.LastName, Is.EqualTo("User3"));
        }

At this stage is hard to see the advantage of this apart from separating out code. The next step is to allow the find methods to be chained together (method chaining).

Method Chaining

The IApplicationUserFinderRouter interface is going to allow the finder to be returned from a property. This is pretty simple stuff. Below is the interface with the new property and the concrete class implementing this addition member.

    public interface IApplicationUserFinderRouter
    {
        IQueryCommand Output { get; }
        IApplicationUserFinder AndFind { get; }
    }

    public class ApplicationUserFinderRouter : IFindableApplicationUserFinderRouter
    {
        private IQueryCommand queryCommand;

        public IQueryableApplicationUserFinder Finder { get; set;}

        public IQueryCommand Output
        {
            get
            {
                if (queryCommand == null)
                {
                    queryCommand = new QueryCommand(Finder);
                }

                return queryCommand;
            }
        }
	
        public IApplicationUserFinder AndFind
        {
            get { return Finder; }
        }
    }

This now allows the find methods to be chained so you can write the following code

        [Test]
        public void Should_return_a_user_when_finding_by_Login_name_and_token()
        {
            ApplicationUser result = repository
                .Find.ByToken(Guid.Empty)
                .AndFind.ByLoginName("Test.User2")
                .Output.Execute().FirstOrDefault();

            Assert.That(result.LastName, Is.EqualTo("User2"));
        }

That concludes this post, the next part of this series will cover paginating the results returned from the underlying query.

Advertisements

9 responses to “Creating Fluent finders and repositories part 1

  1. I’m missing something (lots of things, honestly). IQueryableDataStore has a public member DataSource with get/set. So then a finder class also exposes this publicly, right? When I tried what you listed above, repository.Find.[intellisense…] lists DataSource, which is what I thought you were trying to avoid with this refactor?

  2. Nice but don’t you think you will have an explosion of interfaces?? Wouldn’t it be best to stick to using generic interfaces with generic implementations?

    is this just to hide the datastore property in the fluent interface??

    After sometime did you find a better way to refactor this code using generics?

    I would really like source codes also, so that i can play a little with it and see the big picture.

    Anyhow I find your article interesting. Cannot wait to see a refactored version of this code.

    • Actually how about just adding a Where to the IFinder interface where you would pass a predicate that would be routed in the underlying datastore using linq or your own where/predicate processing mechanism if linq isn’t supported)

      this way it would stay generic, so no need to write ByLoginName(string name) when you can write Where(x => x.LoginName == name)

      Actually passing an expression is so much more flexible, + you stay with the LINQ collection interface.

      • Do you think it would be best to offer both ways actually, a way to add a fluent interface to your finders + a generic LINQ way.

        So when you need to add validation and other check like you did in the byloginname you add the functionnality but when you don’t need any validation then you go on generically.

      • Alex, thanks for your feedback, since writing this post a few months ago, I did refactor my implementation and streamlined the interfaces. I have fallen out of love with the fluent finders. Reasons were developers around me, needed some hand-holding to get them to create their own fluent interfaces. When I started the fluent finders I was trying to abstract away from nhibernate 1.2 that our codebase was referencing. Although I achieved this and after some refactoring, it took up to much dev time. In the end I found that Linq gives me most of what I needed. So still use finders, but use linq as the query provider.

  3. Russell,

    Excuses for coming back to such an old topic but I’ve got question.

    For some time facing all those problems and trying to use SoC anywhere I moved along the almost same way – the Finders (to decouple the ‘querying’ part away from repo itself).

    So, it seems like you also passed all the same steps and should have made some decisions that I’m going to. In your last comment you clearly stated that you for a reason “fallen out of love with the fluent finders” and mentioned that you “still use finders, but use linq as the query provider”.

    Could you please pour a lil’ more light on that? How exactly do you use it now? And what is the overall concept of what you use now and how it is contrasted with that “fluent finders” approach?

    Thanks in advance.

    • @Vasilio. I came into a few problems with fluent finders. Firstly the team of developer i was working with found creating fluent interfaces to complex and hard to learn. Some just found it over kill. When i started the fluent finders, I was using NH 1.2 which didn’t support linq, when we moved to NH 2.0 which had linq support we found the working with IQueryables so much easier as linq is ready made fluent interface. In general using linq is just easier. But i do think that in some situations fluent finders do have their place.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s