Thursday, June 17, 2010

IQueryable and Repositories

One approach for coding repositories that I have seen a couple of times recently is that of exposing IQueryable collections through the repository interfaces. On the one hand this allows an extremely convenient way of exposing a flexible data source to your business layer or controllers. However, it also breaks the Single Responsibility Principle thus creating less reusable and testable solutions.

By allowing your business layer to define queries within its own methods, those methods are taking on two responsibilities, performing data access and performing logic on the results of that data operation. It's all well and good to complain about not hitting some high ideal, but what affect does this have in the real world?

First, if you happen to reuse the same data query in multiple parts of your application, you would have multiple places that you would then need to make changes and test. DRY this isn't.

Second is the testability of this code. In the terms of this afore mentioned white paper, you would need to write your tests for your business layer or controller in such a way that the state is correct as well as the interactions, for each method. As the paper says, testing the state aspect requires a larger set of data. Why would you want to write that extra code for every method in your business layer / controller that uses the same query? If you don't test each one, how do you know they work? How do you know when they break?

The simple solution is to keep your queries in the repositories behind the repository interfaces. Test the state of each one thoroughly and then you only need to test the interactions in your business layer. Yes it requires an extra function call in your business layer, another method in your repository interface and another function declaration in the repository. And while that might be a lot of words, it's only four or five more lines of code for each query (including brackets on their own line in C#.) And if you reuse your queries, you get those extra lines back anyway.

I will certainly concede that no one paradigm fits all of the software problems out there. Maybe what I suggest is overkill. Maybe it's another example of a programmer too set in his ways. But by exposing IQueryable collections through the repository interface, we're ignoring a number of the principles of coding that have been making our lives easier and our code better for a while now.

[Edit]
After a second read through of the article, K. specifically states that enumerables could be returned instead of queryables. Not that this is the only publication I have read where queryables were suggested. Let's just say that now all four of my regular readers know where I stand on the subject.

No comments:

Post a Comment