Thinking about repositories

time to read 2 min | 360 words

For a long time, I have used the idea of IRepository<T> as my main data access method.

image It is a very good approach, and I have used a static gateway to be able to resolve that effectively. The code to use that read like this:

Repository<Account>.Save(account);

But, I have an issue with that, because this is an opque dependency. I don't have a way to look at the declaration and just get what this needs. It makes testing a lot harder than it should be, because you now need to do indirect dependency injection.

There is the additional problem of the actual IRepository<T> interface:

image

That is an interface with 40 methods. And most of those methods are dealing directly with the data access code.

When I first to move away from this approach, I started to inject the IRepository<Account> into my services, which worked well. The code looked like this:

public class AccountService
{
	public AccountService(IRepository<Account> accountsRepository)
	{
		//...
	}
}

The problem with that is readability, take a look at the usage:

accountsRepository.FindAll(
     Where.Account.LastActivity < DateTime.Now.AddDays(-60)
);

Can you tell me what the meaning of this is? It express what it is doing really well, I think, but not what the meaning of it.

So, I started with the idea that I have domain repositories and infrastructure repositories. So I introduced this interface:

image

And then I can call:

accountsRepository.FindAllInvactiveAccounts()

I didn't really like that, because infrastracture repository doesn't really sit well with me. There is another issue, which is the implementation of IAccountsRepository implementation:

image

I have the IAccountRepository depending on IRepository<Account>, but that is... a smell. Then I thought about this approach:

image

But that doesn't sit very well with me either.

Eventually, I got to this design:

accountsRepository.FindAll(
	new InactiveAccountQuery()
);

Where the accountsRepository is a IRepository<Account> implementation. A better syntax for that is probably this:

accountsRepository.FindAll(
	Accounts.Inactive
);

That looks much better, and where I am going to stop for now