Использование шаблона спецификации - PullRequest
2 голосов
/ 24 марта 2010

Как и любой шаблон проектирования, Шаблон спецификации является отличной концепцией, но допускает чрезмерное использование энергичным архитектором / разработчиком.

Я собираюсь начать разработку нового приложения (.NET & C #), и мне действительно нравится концепция шаблона спецификации, и я стремлюсь в полной мере использовать его. Тем не менее, прежде чем я начну использовать все орудия, мне было бы интересно узнать, может ли кто-нибудь поделиться болевыми точками, которые испытывались при использовании шаблона спецификации при разработке приложения.

В идеале я смотрю, есть ли у других проблемы в

  • Написание юнит-тестов по шаблону спецификации
  • Решение о том, в каком слое должны находиться спецификации (Репозиторий, Сервис, Домен и т. Д.)
  • Использование его везде, когда простой оператор if справился бы с работой
  • и т.д.

Заранее спасибо

Ответы [ 3 ]

14 голосов
/ 05 ноября 2010

Я не верю, что LINQ - это замена шаблона спецификации. Помните, что спецификацию лучше всего использовать для инкапсуляции бизнес-логики. Поэтому, если одно из моих бизнес-требований заставит меня привлечь всех ценных клиентов для нескольких функций, мое заявление Linq может выглядеть следующим образом:

var valuedCustomers = Customers.Where(c => c.Orders.Count > 15 && c.Active).ToList();

Я могу напечатать это заявление по всей своей заявке, но что, если я хочу добавить это правило, к которому клиент должен был присоединиться до определенной даты? Что ж, теперь мне нужно пройтись по моему заявлению и изменить Linq. Или если мой объектный граф изменится (хотя это не должно быть единственной причиной для использования шаблона). Когда вместо этого я мог просто сделать что-то вроде этого

var valuedCustomers = Customers.Where(new ValuedCustomerRule.IsSatisfied()).ToList();

Я согласен с тем, что шаблон чрезмерно используется, но он очень полезен для бизнес-правил, которые появляются во всей вашей системе, поэтому вы не будете укушены при изменении этих правил. Для меня это все равно, что оставлять SQL-запросы по всему коду приложения.

9 голосов
/ 24 марта 2010

Как отметил Дэвид в своем комментарии, многое из того, что полезно в спецификации, теперь может быть более кратко достигнуто с помощью подобных LINQ.

Вместо нового типа спецификации вы можете создавать произвольные спецификации на лету: GetCustomers().Where(customer => customer.IsActive && customer.City == "Oakland");

Однако это не полная замена спецификации по нескольким причинам:

  1. Сортировка / фильтрация происходит в классе потребления после возвращения всех клиентов. Если вы имеете дело с чем-то, кроме объектов в памяти, это неоптимально (LINQ-to-SQL и тому подобное являются исключениями, потому что они компилируют и оптимизируют запросы и выполняют их на стороне сервера / удаленной стороны, возвращая только желаемые результаты ).
  2. Ваш API широко открыт для любого запроса, если вы выставляете коллекции и оставляете спецификацию для запросов LINQ. Если вы хотите ограничить то, что или сколько можно получить, вам понадобится набор спецификаций для запроса.

Конечно, нет необходимости использовать его повсюду, и вполне возможно, что он вам вообще не понадобится; Я не знаю ваш домен или над чем вы работаете.

Думаю, лучший совет - не смотреть , чтобы использовать его. Вы увидите, когда это оправдано, скорее всего, когда вы начнете писать класс, который выглядит как первый пример в статье, на которую вы ссылались.

Просто храните его в своем хранилище мысленных паттернов, чтобы иметь его, если вам это нужно; если вы никогда не используете его, это только означает, что он вам не нужен, и это нормально.

Выбор слоя зависит от спецификаций и условий использования. Во многих случаях они являются помощниками в поддержке уровня обслуживания, но в некоторых случаях они инкапсулируют доменную логику.

Что касается модульного тестирования, помните, что ваши спецификации являются единицами измерения или содержат единицы измерения. Не тестируйте метод, который принимает спецификацию со всеми возможными комбинациями спецификации; проверьте сами спецификации, чтобы убедиться, что они ведут себя так, как ожидалось, и затем вы можете с уверенностью использовать одни и те же спецификации во многих методах и классах.

Надеюсь, это немного полезно.

1 голос
/ 02 сентября 2015

Обновленный ответ: Я согласен с Wix, LINQ не является заменой для шаблона спецификации. У меня недостаточно репутации, чтобы добавить комментарий к ответу Wix, я просто отвечаю как ответ.

Согласно спецификации этой статьи в основном используются для сопоставления объекта домена с оператором. Хотя спецификации возвращают true / false при сопоставлении с доменным объектом, но это означает, что спецификации предложил инкапсулировать любое логическое условие в вашем коде.

Я продолжу ответ Викса дальше. Если у вас есть определенная спецификация ValuedCustomer, тогда вы можете использовать правило по-разному:

   var valuedCustomer = new ValuedCustomerSpecification();
   //1. You can use this statement to check if a customer is valued or not in your domain
   Customer customer = ....
   if(valuedCustomer.IsSatisfiedBy(customer))

   //2. You can use it to get just valued customers from repository, 
   var valuedCustomers = repository.Get(valuedCustomer);

   //3. You can combine it with other specifications to create composite specifications. Following syntax can vary with implementation
   var seniorValuedCustomer = valuedCustomer.And(seniorCustomer)

Насколько я понимаю из бумаги , пользователь может взаимодействовать со спецификациями для достижения своих целей при условии, что это необходимо, а пользовательский интерфейс вашего приложения позволяет это.

В вышеупомянутой статье также упоминается, когда не следует использовать шаблоны спецификаций.

...