0
\$\begingroup\$

Below I present to you an IQueryable LINQ to SQL query (used with NHibernate). I have tried to simplify this query but I could not do it.
I want to run a query for searching information.

Options:

  1. search on source or target
  2. search with match case or not
  3. search match exact or not

The query it seems to work but there is much if/else branching.

Is it possible to simplify it?

        if (concordanceSearchOptions.SearchInSource)
        {
            if (concordanceSearchOptions.MatchCase)
            {
                if (concordanceSearchOptions.MatchExact)
                {
                    getByQueryable = getByQueryable.Where(p => p.SourceSegment.Equals(concordanceSearchOptions.SearchText));
                }
                else
                {
                    getByQueryable = getByQueryable.Where(p => p.SourceSegment.Contains(concordanceSearchOptions.SearchText));
                }
            }
            else
            {
                if (concordanceSearchOptions.MatchExact)
                {
                    getByQueryable = getByQueryable.Where(p => p.SourceSegment.ToLower().Equals(concordanceSearchOptions.SearchText.ToLower()));
                }
                else
                {
                    getByQueryable = getByQueryable.Where(p => p.SourceSegment.ToLower().Contains(concordanceSearchOptions.SearchText.ToLower()));
                }
            }
        }
        else
        {
            if (concordanceSearchOptions.MatchCase)
            {
                if (concordanceSearchOptions.MatchExact)
                {
                    getByQueryable = getByQueryable.Where(p => p.TargetSegment.Equals(concordanceSearchOptions.SearchText));
                }
                else
                {
                    getByQueryable = getByQueryable.Where(p => p.TargetSegment.Contains(concordanceSearchOptions.SearchText));
                }
            }
            else
            {
                if (concordanceSearchOptions.MatchExact)
                {
                    getByQueryable = getByQueryable.Where(p => p.TargetSegment.ToLower().Equals(concordanceSearchOptions.SearchText.ToLower()));
                }
                else
                {
                    getByQueryable = getByQueryable.Where(p => p.TargetSegment.ToLower().Contains(concordanceSearchOptions.SearchText.ToLower()));
                }
            }
        }
\$\endgroup\$
3
\$\begingroup\$

Naming

Based on the naming guidlines variables/fields should be named "using a noun, noun phrase, or adjective". So getByQuerable should be renamed to something following the guidlines and also meaningful.

Optimization

  • you should extract the searching for Source and Target to separate methods. This helps for readability and makes it easier for Mr.Maintainer in a couple of months.

  • preparing the searchtext before the actual search takes place will speed up the query.
    Right now if concordanceSearchOptions.MatchCase == false you call for each source/target in the where part the ToLower() method of the SearchText property.

Refactoring

    String searchText = concordanceSearchOptions.SearchText;
    if (concordanceSearchOptions.MatchCase)
    {
        searchText = searchText.ToLower();
    }

    if (concordanceSearchOptions.SearchInSource)
    { 
        getByQueryable  = GetBySource(concordanceSearchOptions, searchText);
    }
    else
    {
        getByQueryable  = GetByTarget(concordanceSearchOptions, searchText);
    }


private IEnumerable<T> GetBySource(SearchOptions concordanceSearchOptions,String searchText){

}
private IEnumerable<T> GetByTarget(SearchOptions concordanceSearchOptions,String searchText){

}
\$\endgroup\$
  • \$\begingroup\$ I do have to execute ToLower inside GetBySource and GetByTarget methods. I don't feel that I have gain so much. \$\endgroup\$ – user58778 Nov 24 '14 at 10:38
  • \$\begingroup\$ You don't have to execute concordanceSearchOptions.SearchText.ToLower() everytime. Your methods are doing one thing only (SRP), one calls a query on source the other calls a query on target. \$\endgroup\$ – Heslacher Nov 24 '14 at 10:41
  • \$\begingroup\$ I am referring to the p.SourceSegment.ToLower() or p.TargetSegment.ToLower(). I have to branch the behavior in the GetByTarget/GetBySource. Also \$\endgroup\$ – user58778 Nov 24 '14 at 10:44
  • \$\begingroup\$ Also, I have to maintain now two more methods... \$\endgroup\$ – user58778 Nov 24 '14 at 10:45
  • \$\begingroup\$ That is right. But there seems to be no way arround. \$\endgroup\$ – Heslacher Nov 24 '14 at 10:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy