I found myself today working on a LINQ query that, in my opinion violated the DRY principle.
Don’t Repeat Yourself (DRY, also known as Single Point of Truth) is a process philosophy aimed at reducing duplication, particularly in computing. The philosophy emphasizes that information should not be duplicated, because duplication increases the difficulty of change, may decrease clarity, and leads to opportunities for inconsistency. DRY is a core principle of Andy Hunt and Dave Thomas‘s book The Pragmatic Programmer. They apply it quite broadly to include "database schemas, test plans, the build system, even documentation." When the DRY principle is applied successfully, a modification of any single element of a system does not change other logically-unrelated elements. Additionally, elements that are logically related all change predictably and uniformly, and are thus kept in sync.
It’s such a simple principle, and can be really effective if you apply it properly.
In TSQL stored procedures, it was often quite hard to prevent duplication. Consider the following example:
At first, there doesn’t seem to be too much wrong with these queries.
However, they grossly violate the DRY principle. But in TSQL, it’s hard to reduce this duplication. Sure, you can create helpers like views, SQL functions or table valued functions, but it still is quite hard. Unfortunately, this means that some people feel this is a ‘get-out-of-jail-free-card’ to write long and ugly code. If you have ever had to debug a query that spanned 3 pages in the query analyzer, you feel my pain.
Now with C# 3.0 and LINQ, we get the power of a SQL like query language, right in our C# code. Unfortunately, I’ve seen too often that people just ignore the DRY principle again when creating LINQ queries.
Calling methods from LINQ queries
Yes, you can call methods from LINQ queries. For example, I noticed the following lines of code:
And there were 3 other queries just like it. The filter condition was different, but the select statement identical. So what do you do in a case like this? Right, remove the duplication and call a creation method instead:
This makes things a lot cleaner to read 🙂
Composing LINQ queries
Ok, so you can call methods from LINQ. When you create a LINQ query, you are actually creating an expression tree, that will only get resolved the first time you actually execute the query. This allows you to really fun stuff. Look at this example:
In this example, I’m only applying the filter condition if I need to have it applied. Try doing that in TSQL! OK, in this example, I haven’t really improved the code, but with more complicated queries, you can do really cool stuff! You can create several filter methods, which you can reuse and between lots of similar queries.
LINQ might look like SQL, but in fact, it’s much more flexible and much less dry!