Unreadable Linq

time to read 2 min | 354 words

Chad Myers has posted about the query objects with the repository pattern. He is trying to solve the problem of reusable pieces of queries that can be combined together. In theory, this gives you a way to compose queries in a way that hide the actual query logic. This is a good thing.

Unfortunately, the syntax leaves a lot to be desired:

_query = new TopCustomersWithLowDiscountQuery()
	.IncludePreferred();

var otherQuery = new DeliquentCustomersQuery()
	.WithPendingLitigation()
	.WithDebtOver(999);

var results = _customers
	.AsQueryable()
	.Where(_query.OrElse(otherQuery));

Note how you compose the queries, that is simply unreadable as the query complexity scale up. At the same time, we don't really have a better way of handling that since the from expression will not accept Expression<T> instances directly. What has me worried is the tendency toward over abstraction that I have seen in a few code bases. In particular, I have seen API that takes several Expression<T> objects and compose them in interesting ways. Here is an example:

var customers = repo.FindBy(
        new TopCustomersWithLowDiscountQuery()
            .IncludePreferred()
            .BelowDiscountThreshold(3)
            .WithMoreSalesThan(500)
        .AndAlso(
            new DeliquentCustomersQuery()
                .WithDebtOver(9999))
            
);

Oh, this is a really neat trick from a programming perspective, but it makes it very hard to read and understand the code. Try to add ordering and projections to this type of query. And then try to understand the code.

I don't have any great solutions for that, unfortunately, but it is a problem that is worth pointing out.

A better solution would be to integrate that with the Linq query provider to support extracting the expression tree from the query, but that is not practical as an overall solution.