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."