Использование шаблона спецификации
-
22-09-2019 - |
Вопрос
Как и любой шаблон дизайна, Шаблон спецификации это отличная концепция, но нетерпеливый архитектор / разработчик может ею злоупотребить.
Я собираюсь начать разработку нового приложения (.NET & C #), и мне действительно нравится концепция шаблона спецификации, и я стремлюсь в полной мере использовать ее.Однако, прежде чем я пущусь во все тяжкие, мне было бы действительно интересно узнать, может ли кто-нибудь поделиться болевыми точками, которые возникли при использовании Шаблон спецификации при разработке приложения.
В идеале я хочу посмотреть, были ли у других проблемы в
- Написание модульных тестов на основе шаблона спецификации
- Принятие решения о том, на каком уровне должны размещаться спецификации (Репозиторий, Сервис, Домен и т.д.)
- Используя его везде, когда простой
if
заявление сделало бы свое дело - и т.д.?
Заранее благодарю
Решение
Как отметил в своем комментарии Дэвид, многое из того, что полезно в спецификации, теперь можно более кратко реализовать с помощью LINQ.
Вместо нового типа спецификации вы можете «на лету» создавать произвольные спецификации:GetCustomers().Where(customer => customer.IsActive && customer.City == "Oakland");
Однако это не полная замена спецификации по нескольким причинам:
- Сортировка/фильтрация происходит в классе-потребителе после возврата всех клиентов.Если вы имеете дело с чем-либо, кроме объектов в памяти, это неоптимально (LINQ-to-SQL и т.п. являются исключениями, поскольку они компилируют и оптимизируют запросы и выполняют их на стороне сервера/удаленно, возвращая только желаемые результаты). ).
- Ваш API широко открыт для любой запрос, если вы предоставляете коллекции и оставляете спецификацию запросам LINQ.Если вы хотите ограничить, что и сколько можно получить, вам понадобится набор спецификаций для запроса.
Конечно, нет необходимости использовать его везде, и вполне возможно, что он вам вообще не понадобится;Я не знаю ни вашего домена, ни над чем вы работаете.
Я думаю, лучший совет – не смотреть чтобы использовать его.Вы увидите, когда это оправдано, скорее всего, когда вы начнете писать класс, похожий на первый пример в статье, на которую вы дали ссылку.
Просто сохраните его в своем хранилище мысленных шаблонов, чтобы он был у вас под рукой, если он вам понадобится;если вы никогда им не пользуетесь, это означает лишь то, что он вам не нужен, и это нормально.
Выбор слоя зависит от характера технических характеристик и использования.Во многих случаях они помогают поддерживать уровень обслуживания, но в некоторых случаях они инкапсулируют логику предметной области.
Что касается модульного тестирования, помните, что ваши спецификации являются модулями или содержат модули.Не тестируйте метод, который принимает спецификацию со всеми возможными комбинациями спецификаций;протестируйте сами спецификации, чтобы убедиться, что они ведут себя должным образом, а затем вы сможете с уверенностью повторно использовать одни и те же спецификации во многих методах и классах.
Надеюсь, это немного полезно.
Другие советы
Я не считаю, что LINQ является заменой шаблона спецификации.Помните, что спецификацию лучше всего использовать для инкапсуляции бизнес-логики.Итак, если одно из моих бизнес-требований требует, чтобы я привлек всех ценных клиентов для нескольких функций, мое заявление Linq может выглядеть следующим образом:
var valuedCustomers = Customers.Where(c => c.Orders.Count > 15 && c.Active).ToList();
Я могу напечатать это заявление по всему своему приложению, но что, если я захочу добавить к этому правилу, что клиент должен присоединиться к какой-то дате?Что ж, теперь мне нужно просмотреть все свое приложение и изменить файл Linq.Или если мой граф объекта изменится (хотя это не должно быть единственной причиной использования шаблона).Когда вместо этого я мог бы просто сделать что-то вроде этого
var valuedCustomers = Customers.Where(new ValuedCustomerRule.IsSatisfied()).ToList();
Я согласен, что этот шаблон слишком часто используется, но он очень полезен для бизнес-правил, которые появляются во всей вашей системе, чтобы вы не пострадали, когда эти правила изменяются.Для меня это похоже на то, как если бы SQL-запросы распространялись по всему коду вашего приложения.
Обновленный ответ:Я согласен с 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)
Мое понимание из бумага заключается в том, что пользователь может взаимодействовать со спецификациями для достижения своих целей при условии, что в этом есть необходимость и пользовательский интерфейс вашего приложения позволяет это.
В вышеупомянутом документе также упоминается, когда не следует использовать шаблоны спецификаций.