2015-06-24 5 views
3

Как я могу объединить методы ниже? и должен ли я на самом деле сделать это?Объединить два метода в один

public IQueryable<ItemDTO> RepGetMonthItems(string inOut, string planFact, int month) 
{ 
    return GetItemsWithCategory(). 
      Where(i => i.InOut.Equals(inOut)). 
      Where(i => i.PlanFact.Equals(planFact)). 
      Where(i => i.DateTime.Month.Equals(month)); 
} 

public IQueryable<ItemDTO> RepGetYearItems(string inOut, string planFact, int year) 
{ 
    return GetItemsWithCategory(). 
      Where(i => i.InOut.Equals(inOut)). 
      Where(i => i.PlanFact.Equals(planFact)). 
      Where(i => i.DateTime.Year.Equals(year)); 
} 
+1

Надеемся, что различные ответы показали, что они могут быть объединены в один, но в итоге вам становится сложнее читать код, и у вас будет один метод, который делает две вещи. Так что придерживайтесь того, что у вас есть. –

+0

Я не согласен. Вы можете сделать гораздо лучше, не нарушив правило «сделать одну вещь». Сохраняя это так, как сейчас, теперь просто нарушает DRY. – Baldrick

+0

@ Baldrick, DRY необходимо применять с осторожностью, так как не повторяющийся сам ведет к сцеплению.Это пример того, где лучше повторять себя, чтобы все было просто, хотя см. Мой комментарий к вашему ответу. –

ответ

2

Я согласен с принципом «сделай одну вещь». Но я также верю в СУХОЙ.

Итак, методы расширения на помощь!

Имейте основную функцию, чтобы сделать одну вещь (получить элементы отчета) и методы методов расширения на год или месяц.

Объявите класс метод расширения, как это:

public static class QueryExtensions 
    { 
     public static IQueryable<ItemDTO> ForYear(this IQueryable<ItemDTO> query, int year) 
     { 
      return query.Where(i => i.DateTime.Year.Equals(year)); 
     } 

     public static IQueryable<ItemDTO> ForMonth(this IQueryable<ItemDTO> query, int month) 
     { 
      return query.Where(i => i.DateTime.Month.Equals(month)); 
     } 
    } 

Создать урезанную RepGetItems метод, как это:

public IQueryable<ItemDTO> RepGetItems(string inOut, string planFact) 
    { 
     return GetItemsWithCategory(). 
      Where(i => i.InOut.Equals(inOut)). 
      Where(i => i.PlanFact.Equals(planFact)); 
    } 

Usage тогда выглядит следующим образом:

var yearResults = originalQuery.RepGetItems(input, fact).ForYear(2015); 
var monthResults = originalQuery.RepGetItems(input, fact).ForMonth(10); 

или даже:

var yearMonthResults = originalQuery.RepGetItems(input, fact).ForYear(2015).ForMonth(10); 

Общая гибкость, без потери принципа «одной цели».

+0

Отличная идея, но только для «за кулисами». Перетащите весь этот код в рядовых, и он прекрасно справится с растущим числом общедоступных методов. Но это плохо, как общедоступное решение, поскольку оно виновато в распространении ответственности. –

+0

, честно говоря, я полностью отдаю предпочтение этому – tfiwsrets

+0

@DavidArno: хорошо ли для случая с OP точно сказать без контекста кода - это скорее демонстрация того, что вы можете получить гибкое решение, не повторяясь в этом случае. Что публично/частное/обернутое/разоблаченное - другое дело, и зависит от большей информации, чем предоставленный OP :) – Baldrick

0

В запрос можно легко добавить условия .Where.

public IQueryable<ItemDTO> RepGetYearItems(string inOut, string planFact, int monthyear, bool useMonth) 
{ 
    var query = GetItemsWithCategory(). 
     Where(i => i.InOut.Equals(inOut)). 
     Where(i => i.PlanFact.Equals(planFact)); 

    if (useMonth) 
    { 
     query = query.Where(i => i.DateTime.Month.Equals(monthyear)); 
    } 
    else 
    { 
     query = query.Where(i => i.DateTime.Year.Equals(monthyear)); 
    } 

    return query; 
} 

или с помощью int?

public IQueryable<ItemDTO> RepGetYearItems(string inOut, string planFact, int? year, int? month) 
{ 
    var query = GetItemsWithCategory(). 
     Where(i => i.InOut.Equals(inOut)). 
     Where(i => i.PlanFact.Equals(planFact)); 

    if (year != null) 
    { 
     query = query.Where(i => i.DateTime.Year.Equals(year.Value)); 
    } 

    if (month != null) 
    { 
     query = query.Where(i => i.DateTime.Month.Equals(month.Value)); 
    } 

    return query; 
} 

Обратите внимание, что эта версия отличается от одного из @TimSchmelter ... Это не фиксируется (это зависит от «типа» SQL), что происходит если у вас есть в запросе некоторый «мертвый код» (куски запроса, которые не являются «активными», потому что некоторые параметры имеют определенное значение, например, int его запрос). В его запросе явно содержится «мертвый код» (целое i => !year.HasValue || i.DateTime.Year.Equals(year.Value)). Если возможно, я предпочитаю его пропустить.

+0

спасибо за идею. но может быть, более элегантное решение существует? – tfiwsrets

+0

'query = useMonth? query.Where (i => i.DateTime.Month.Equals (monthyear)): query.Where (i => i.DateTime.Year.Equals (monthyear)) ' – xanatos

1

Может быть, вы могли бы использовать Nullable<int> за год и месяц:

public IQueryable<ItemDTO> RepGetItems(string inOut, string planFact, int? year, int? month) 
{ 
    return GetItemsWithCategory(). 
     Where(i => i.InOut.Equals(inOut)). 
     Where(i => i.PlanFact.Equals(planFact)). 
     Where(i => !year.HasValue || i.DateTime.Year.Equals(year.Value)). 
     Where(i => !month.HasValue || i.DateTime.Month.Equals(month.Value)); 
} 
3

Нет, вы не должны. Три ответа, которые я вижу, нарушают правило «сделать одно» Роберта «Дядя Боб» Мартин. Читайте об этом here.

+0

Правильный ответ. –

+0

, и если я хочу иметь метод, который использует как год, а месяц, я должен написать еще один: public IQueryable RepGetMonthAndYearItems (строка inOut, строка planFact, int year, int month)? – tfiwsrets

+2

@sterswift, если этот метод всегда использует оба параметра, да. –

0

Как об использовании необязательного параметра здесь:

public IQueryable<ItemDTO> RepGetMonthItems(string inOut, string planFact, int month, int year = -1) 
    { 
     return GetItemsWithCategory().Where(i => i.InOut.Equals(inOut) 
      && i.PlanFact.Equals(planFact)) && year == -1? 
      i.DateTime.Month.Equals(month) : i.DateTime.Year.Equals(year)); 
    } 

Взгляните на этот пример:

enter image description here

Как вы можете видеть каждый раз, когда вы вызываете метод Где() вы делаете много дополнительной работы.

+0

спасибо, например, за эту конструкцию внутри, где статья не знала этого – tfiwsrets

+0

Кстати, вам это не нужно. Где-то. Где-то – Fabjan

+0

и статья вместо этого? – tfiwsrets

Смежные вопросы