I’ve recently been experimenting with making some changes to our domain layer to help simplify our design and reduce the number of useless objects that were cropping up throughout our code base. In our previous model we had “Manager” classes that, well, managed stuff.
Our managers closely followed the Repository pattern as defined in Domain Driven Design.
public class CustomerManager {
ObjectManager objectManager = new ObjectManager();
public SaveObjectResponse SaveCustomer(Customer customer) {
return objectManager.Save(customer);
}
public bool DeleteCustomer(Customer customer) {
return objectManager.Delete(customer);
}
public List<Customer> FindAllCustomers() {
return objectManager.FindAll<Customer>();
}
// etc…
}
What this resulted in was a whole bunch of classes that looked a lot like the above. I’ve used the ActiveRecord pattern a fair amount in the past so in an attempt to simplify our design we ended up adding some methods directly on top of our domain objects so that all of the above code disappeared. To make them dissappear we added a base entity that defines a number of methods for saving, deleting, and finding domain objects.
public abstract class BaseEntity<T> {
static IDatabase<T> db = new Database<T>();
public SaveObjectRespnse Save() {
db.Save(this);
}
public bool Delete() {
db.Delete(this);
}
public static List<T> FindAll() {
db.FindAll();
}
}
public class Customer : BaseEntity<Customer> {}
While this cleaned up our code and made it so we could get rid of a number of objects it has caused one issue. We now have statics, which means we have a testability issue. In order for us to enable things to be tested we needed a way to inject a IDatabase<T> into our Customer class. Since our base entity has static methods that require the database it requires our database instance to be static. This prevents us from using dependency injection to inject our mock database for testing. As a short term solution I added a means for registering and unregistering a database like so:
public static void RegisterDatabase(IDatabase<T> dbToRegister) {
db = dbToRegister;
}
public static void UnRegisterDatabase(IDatabase<T> dbToUnregister) {
if(db == dbToUnregister) {
db = defaultDb;
}
}
While this works its far from ideal.
[Test]
public void DoSomethingThatDoesNotNeedTheRealDatabase() {
MockDatabase<Customer> mockCustomerDb = new MockDatabase<Customer>();
mockCustomerDb.FindAllResult = myDummyCustomerList;
Customer.RegisterDatabase(mockCustomerDb);
try {
// do some stuff that calls Customer.FindAll();
}
finally {
Customer.UnRegisterDatabase(mockCustomerDb);
}
}
As a result of having some ugliness due to the use of statics I think we’ll likely move to having a “Manager” like base class that supports generics. This will have the same advantages of the current implementation and cause less issues when it comes to testing.
public class Repository<T> {
public SaveObjectResponse Save(T item) {…}
public bool Delete(T item) {…}
public List<T> FindAll() {…}
}
I wonder how the folks who are using Castle’s ActiveRecord handle this issue. From browsing through their code base it doesn’t appear that they make it so you can mock out the ActiveRecord’s behavior easily which typically results in a lot more tests hitting the database then necessary.