2

I have a complex query which needs to be broken into different methods in order to meet NFR code complexity criteria.

I know this is bad just to meet criteria it is desired, but can this query can be broken into smaller chunks?

var query = (from a1 in a 
             join b1 in b
                 on a1.id1 equals b1.id1
             join c1 in c
                 on b1.id equals c1.id
             join d1 in d
                 on c1.id1 equals d1.id
             where (d1.Contains("text"))
             select d1);
jessehouwing
  • 106,458
  • 22
  • 256
  • 341
VSharma
  • 348
  • 2
  • 12

2 Answers2

4

Depending on whether you're using Linq-to-SQL or Linq-to-Entities, the relation may be expressed through code already and you could simply make use of the navigation properties:

from d1 in d 
where d1.C.B.A != null
     && d1.Contains("text")
select d1;

Entity Framework will know to ignore the possible null reference exceptions in the code, since it will express this as a query and will not actually run the code.

If this is not possible, I am assuming you're using Visual Studio 2012 code complexity features, which don't look at the code complexity, but at the IL complexity. A Linq query has the tendency to generate a lot of complexity under the hood, which is not visible in the code.

I'd ignore the complexity warning, as breaking this very readable query down into multiple methods is artificially trying to fix a warning that readability may be an issue, but increasing the complexity of the code at the class level.

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
1

This query can be broken (exactly this, not your real query that is much more complex :-) )

IQueryable<atype> query = a;

IQueryable<btype> query2 = from a1 in query
                           join join b1 in b on a1.id1 equals b1.id1
                           select b1;

IQueryable<ctype> query3 = from b1 in query2
                           join join c1 in c on b1.id1 equals c1.id1
                           select c1;

Each of these can be put in a method that has a signature like:

IQueryable<ctype> JoinQuery2(IQueryable<btype> query2)
{
    IQueryable<ctype> query3 = from b1 in query2
                               join join c1 in c on b1.id1 equals c1.id1
                               select c1;
    return query3;
}

This type of query can be easily broken because after each join you discard the "old" type (so in at the end of query2 you only have select b1, not select a1+b1). If you had to keep both objects, it wouldn't be doable, because you would need new { a1, b1 } that is an anonymous object, that can't be passed around because it's an anonymous object.

Note that perhaps simply splitting the query in multiple variables will solve your NPR problem, because the analyzer won't see the full chain of methods.

var query2 = from a1 in a
             join join b1 in b on a1.id1 equals b1.id1
             select b1;

var query3 = from b1 in query2
             join join c1 in c on b1.id1 equals c1.id1
             select c1;

In this case you can even use anonymous objects, like

var query1 = from a1 in a
             join join b1 in b on a1.id1 equals b1.id1
             select new { a1, b1 };

var query3 = from a1b1 in query2
             join join c1 in c on a1b1.b1.id1 equals c1.id1
             select new { a1b1.a1, a1b1.b1, c1 };

and so on.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 1
    Which is not an improvement of readability. I'd shoot this down. – jessehouwing Mar 14 '15 at 12:19
  • 1
    @jessehouwing The question isn't about complexity. It is `I have a complex query which needs to be broken into different methods in order to meet NFR code complexity criteria.`, so it seems to be "can I cheat the NFR code complexity analyzer and be happy?" – xanatos Mar 14 '15 at 12:39
  • 1
    Yes, but it would then fail the human code review hopefully. In the end cheating on one aspect may fail on the other. – jessehouwing Mar 14 '15 at 12:40
  • @VSharma It is a common problem when you have automated measuring tools. How you solve it depends on how you interact with the human that then does the code review. – xanatos Mar 14 '15 at 13:23