Шаблон спецификации для объектов EF или объектов домена

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

  1. Метод внутреннего хранилища

  2. Услуги Inside Domain / Сервисы приложений.

Но это будет работать только в том случае, если сущности EF и объекты Domain совпадают. И я думаю, что это не считается хорошей практикой (использование объектов EF для объекта домена). Теперь мой вопрос -

Должны ли мы написать разные правила спецификации для объекта домена и сущности EF, или есть способ повторно использовать одно и то же правило для обоих? Я думаю, что если мы не будем использовать выражение C# и использовать отражение, мы сможем как-то достичь этого.

2 ответа

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

Спецификация применительно к объектам домена немного отличается от используемой в качестве запросов, но довольно близка. "QuerySpecification" должен иметь язык запросов, который целевая реализация репозитория (EF) может принимать и выполнять в базе данных и возвращать 0 или более совпадений.

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

Я с уважением не согласен с предложением Зорана. Возвращение IQueryable означает, что вы даете коду приложения (возможно, чьему-либо приложению) возможность напрямую запрашивать данные в вашем хранилище данных. Lazy vs Eager loading тоже становится настоящей путаницей. Я думаю, вы теряете инкапсуляцию, а также изоляцию реализации.

Помните также, что EF представляет реализацию Repository и UnitOfWork. DbContext - это единица работы, а DbSet - хранилище. Ваша цель в применении ваших собственных интерфейсов DDD состоит в том, чтобы убедиться, что ваш домен не зависит от реализации EF, поэтому ваш код интеграции должен быть довольно маленьким.

Итак, прямой ответ.

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

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

Основная идея спецификации заключается в том, чтобы отделить утверждение о том, как сопоставить кандидата, с объектом-кандидатом, с которым он сопоставляется. Помимо полезности при выборе, он также полезен для проверки и построения заказа ( https://www.martinfowler.com/apsupp/spec.pdf).

Смотрите также https://matt.berther.io/2005/03/25/the-specification-pattern-a-primer/

Помните, что при работе с репозиториями EF у вас уже есть опция по умолчанию - пусть возвращаются репозитории IQueryable<T> скорее, чем IEnumerable<T>, Многие программисты опасаются этого, но если сделать это таким образом, LINQ станет вашей спецификацией на уровне инфраструктуры.

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

Существуют и другие методы, но это сочетание, которое я обычно применяю в своих проектах.

Другие вопросы по тегам