Removing static calls in your Repositories

I was putting together some code this morning for a demo and saw that my Repositories started to look a little wonky. I wasn't happy with the fact that I had static methods on all of them because this would make for testing difficult. After posting the question to the DDD mailing list, a couple of good ideas came up that I implemented in my solution.

A Repository is a class that represents all objects of a certain type. It's basically a collection (sometimes an in-memory version of a database) but with querying capabilities. The machinery behind how it stores or retrieves them from whatever persistance layer is hidden from the client as it only deals with domain types.

So in our client we would access the repository like so:

   48 public class MyClient

   49 {

   50     public void LoadCustomerList()

   51     {

   52         CustomerCollection coll = CustomerRepository.GetAll();

   53         DataGrid grid = new DataGrid();

   54         grid.DataSource = coll;

   55         grid.DataBind();

   56     }

   57 }

Our client (say a web app but could be anything) needs to display a list of all the customers. It talks to the repository to retrieve that information (in the form of a CustomerCollection object, derived from CollectionBase). This removes the implementation of how a repository retrieves the data request from and we can work with domain objects.

If you're going across multiple tiers, you might return a CustomerCollectionDto, an ArrayList, an Array of Dtos, or whatever you need but for the purpose of this example we're getting a collection of domain objects.

As I started out, my repository looked like this:

   59 public class CustomerRepository

   60 {

   61     public static Customer GetById(int id)

   62     {

   63         CustomerDao dao = new CustomerDao();

   64         Customer obj = dao.FindById(id);

   65         return obj;

   66     }

   67 }

This was typical and would provide me with a way to access whatever persistance layer I implemented in order to reconstitute my domain objects (in this case, as Customer). I started to add more methods but things started to smell.

   31 public class CustomerRepository

   32 {

   33     public static CustomerCollection GetAll()

   34     {

   35         CustomerDao dao = new CustomerDao();

   36         CustomerCollection coll = dao.GetAll();

   37         return coll;

   38     }

   39 

   40     public static Customer GetById(int id)

   41     {

   42         CustomerDao dao = new CustomerDao();

   43         Customer obj = dao.FindById(id);

   44         return obj;

   45     }

   46 }

Now I've got duplication of my calls to my DAO as well as these static methods that are looking a little ugly. I could remove the code duplication by declaring the DAO in the class, but the methods are static so it would have to be static too. Also this is just plain difficult to test because I don't necessarily want to implement a full blown DAL just to test my repository.

Enter the Registry pattern to the rescue. This is a class that acts as a gateway or controller class to all of your repositories (or whatever object you need to talk to). You create static accessors to the inner repositories, but the nice thing is we can use an interface to our repository which allows us to build any kind of registry so we can create some mock test objects without having to drag along extra infrastructure.

Okay, we'll get our registry class started with some .NET plumbing:

   69 public class RepositoryRegistry

   70 {

   71     private static readonly RepositoryRegistry instance = new RepositoryRegistry();

   72 

   73     static RepositoryRegistry()

   74     {

   75     }

   76 

   77     protected RepositoryRegistry()

   78     {

   79     }

   80 

   81     private static RepositoryRegistry GetInstance()

   82     {

   83         return instance;

   84     }

   85 }

Now we've got the beginning of our registry. The static instance variable is how we'll access it (as a singleton) and is set to readonly so it can only be created at startup. A private GetInstance() method allows us to access this as well as a static constructure to keep .NET happy.

With the repository created, now we can add our CustomerRepository. This is done by a) creating a public property to access it and b) creating a protected method to instantiate it.

   69 public class RepositoryRegistry

   70 {

   71     protected CustomerRepository GetCustomerRepository()

   72     {

   73         return new CustomerRepository();

   74     }

   75 

   76     public static CustomerRepository CustomerRepository

   77     {

   78         get { return GetInstance().GetCustomerRepository(); }

   79     }

   80 }

So the property is exposed publically and static (so we can call it from our client) but the implementation of the creation is done in the GetCustomerRepository method. This method is marked as protected so we can subclass the RepositoryRegistry and create say a MockRepositoryRegistry. Then we only have to implement (override) the GetCustomerRepository method and return whatever a CustomerRepository whatever way we want.

Now we have two changes to make this work. First, we have to remove the static calls on our CustomerRepository because we don't need them anymore. Second we have to change our client call to get the collection of customers. Since we're removing the static calls in our Repository, we can remove the duplicate code to the DAL now and clean things up a little. Here's the updated CustomerRepository:

   31 public class CustomerRepository

   32 {

   33     private CustomerDao dao = new CustomerDao();

   34 

   35     public CustomerRepository()

   36     {

   37     }

   38 

   39     public CustomerCollection GetAll()

   40     {

   41         CustomerCollection coll = dao.GetAll();

   42         return coll;

   43     }

   44 

   45     public Customer GetById(int id)

   46     {

   47         Customer obj = dao.FindById(id);

   48         return obj;

   49     }

   50 }

And now we can talk to the Registry class via our Client. Note that we're calling a static property on the class (CustomerRepository) but it's being created internally by the Registry class. So our new client code looks like this (only the call to get the collection has changed):

   86 public class MyClient

   87 {

   88     public void LoadCustomerList()

   89     {

   90         CustomerCollection coll = RepositoryRegistry.CustomerRepository.GetAll();

   91         DataGrid grid = new DataGrid();

   92         grid.DataSource = coll;

   93         grid.DataBind();

   94     }

   95 }

Nice. So we still have a single call in our client (which is nice and readable) but we're getting rich objects returned from our domain and we don't need to know how the Registry is getting us the objects (or how the underlying Repository is either). This is a good way to remove statics from your repositories and keep your domain clean from persistence. It also gives you the flexibility to build any kind of implementation for testing.

Other things you can do here is to build a repository interface and have it returned rather than the concrete class and maybe do something better through calling your persistance layer, but you get the idea.

Many thanks to Ramon Leon, Greg Young, Stephen Molitor, Roger Stasko, and Steve Eichert for contributing to this as they really did the heavy lifting. I just did the grunt work to show you what it would look like in .NET.

Enjoy!

EDIT: Greg Young summed things up very nicely on his blog post recently that I missed (thanks Greg!):

"The starting point to using repositories effectively in a domain is the creation of abstract contracts for the repositories. These abstract contracts should be the only publicly visible forms of our repositories. Internally we only use the abstract contracts to refer to our repositories and in many cases we also allow such things as dependency injection of repositories into our domain, we will generally use either a service locator or a static accessor to an instance. We also at this point create our first unit tests to test the abstract contract of a repository; we can at a later point use these unit tests as integration tests with a repository that is hooked to a real database."

4 Comments

  • We handled ours a different way. We made all of the methods on our Repository classes instance methods. Then we implemented a singleton property called Current.



    This Current property is an instance of the Repository class. It looks something like this:



    List<Customer> customers = CustomerRepository.Current.GetAll();



    This way we can utilize inheritance and reuse more in our Repositories without loosing the "static call feel."



    We use CodeSmith to generate all of our objects into an actively generated layer (no human touches this active generation layer), then we have stub classes which inherit from the actively generated layer.

  • Great post, Bill. I love it when people toss code out there for all to learn.



    If I may ask, why do you have a repository wrapped around a DAO? Seems like the repository is just a pass-thru layer and adds an unnecessary layer of code.



    I am also not sure why you couldn't have fixed the problem of duplicate code by just injecting a CustomerDAO into a constructor:



    public class CustomerRepository

    {

    ICustomerDAO _dao = null;



    public CustomerRepository(ICustomerDAO dao)

    {

    _dao = dao;

    }



    public Customer GetById(int id)

    {

    Customer obj = _dao.FindById(id);

    return obj;

    }



    // ...



    }



    Going with an interface and dependency injection also gives you better testability. Now I might see why your DAO is a good thing... hmm...



    I sent an example to Greg on something that does this, which I also kind of like:



    ICustomerRepository repository = RepositoryFactory.Create<ICustomerRepository>();

    Customer customer = repository.GetByID(1);



    I think I like this better than the RepositoryRegistry, but I am not sure what the RepositoryRegistry is giving you.



    I would love to work with you, Greg, and Steve on some repository examples as I am trying to finalize how I want to create repositories in my applications.



    Regards,



    Dave



  • I see. The registry is essentially a factory method doing the same thing as my RepositoryFactory.Create.



    I also understand the need for the DAO now based on what Greg mentioned. One will need that for crossing a tier. Makes perfect sense in that case.



    I encourage returning an interface, like ICustomerRepository, as opposed to a concrete class. Helps for testing and development.



    Thanks for the clarifications, Greg.



    Regards,



    Dave

  • I once thought that we have to remove all our statics in order to make our code testable. But in the end we either move the static around (in your case you still have a singlton) and that leads to having to know our inner implementation in order to get our tests running which is a code smell.

    Example: in your case the developers must to remember how to mock the RepositoryRegistry and for that they need to know the inner workings of that class. If the class inner workings change, all the tests change. This is bad.

    We then moved to using Extract and Override on the tested code and not on the static code by extracting all static calls to virtual methods that get overriden in the tests. This made our code look really bad and not say everything just once.

    In the end one of my colleges found a nifty Mock Framework called TypeMock (see www.typemock.com) that just lets you mock all the static methods. Now we can decide what the BEST design is without changing it for tests. If we find business value in allowing our methods to be static we can still test our code.
    Although it is a commercial product the community version is Free.

Comments have been disabled for this content.