В OO DDD объект домена обращается к репозиторию напрямую?

В OO DDD объект домена обращается к репозиторию напрямую?
В OO DDD объект домена обращается к репозиторию напрямую? - brittaniburns @ Unsplash

Очень короткий ответ: Да, вроде как, не совсем.

Итак, в ОО объекты не являются пакетами данных. Так что говорить о «сохраняющихся объектах» уже как-то не положено. Если у меня есть объект Customer, у которого есть метод freezeCreditCards(), как мне «сохранить» этот объект извне? Чего я вообще ожидал от этого?

Это означает, что текущее понимание того, что такое «Репозитории», уже расходится с ООП. По нескольким причинам:

  1. Пункт выше об объектах, не являющихся пакетами данных.
  2. Даже если у объекта есть некоторые внутренние данные, которые изменяются, и даже если эти данные каким-то образом соответствуют некоторым данным в базе данных, не должно быть никакого способа, которым внешний объект может просто принудительно извлечь из него эти данные, будь то геттеры, отражение или что-нибудь еще. Это было бы полным нарушением границ объекта и инкапсуляции.
  3. Репозитории не являются частью Ubiquitous Language. Это технические артефакты, следовательно, накладные расходы.
  4. Немного более прагматично, наш объект никак не может измениться, не изменив вместе с ним Repository. Так что вещи, которые меняются вместе, не вместе.

Это то, что я пытаюсь кратко упомянуть на Слайде 29.

Хорошо, и что теперь? Что ж, настойчивость — это побочный продукт бизнес-функции. Обычно. Поэтому, когда я звоню freezeCreditCards(), я, очевидно, ожидаю, что это будет постоянным/настойчивым.

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

На слайдах я перечисляю два варианта, которые я использовал в прошлом:

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

Опять же, в большинстве случаев подразумевается настойчивость. Поэтому методы CRUD не должны быть видны. Вообще. Я приведу еще один пример, который я использовал в прошлом, где есть конкретная реализация интерфейса Customer на основе SQL. Он запускает прямой оператор SQL для всего своего поведения. Я использую подобные конструкции, когда поведение должно передаваться другим службам или системам. Но опять же, это не родовая вещь, часто не подходит.

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

Но. Эти соавторы не должны вытягивать данные из нашего объекта. Это никогда не должно случиться. Так может ли быть java.sql.Connection? Конечно, почему бы и нет. Может ли быть CustomerDBRepository? Нет, по вышеуказанным причинам.

В разговоре я также упоминаю, что не вижу смысла в Services. Вообще. Я просмотрел Репозиторий Вона Вернона , чтобы посмотреть, что он делает с Услугами. Я не нашел ни одного, где я не мог бы найти для него гораздо лучшего места. См. пример PasswordService. Я считаю, что он существует только потому, что «сущности» не могут быть постоянными, поэтому им нужен еще один «слой», который сделает это за них. В основном обходной путь для ошибки дизайна.

Я надеюсь, что это делает вещи, по крайней мере, яснее, даже если, вероятно, не проще.

Обновление: при каких обстоятельствах Repositories действительно имеет смысл?

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


LetsCodeIt, 5 января 2023 г., 04:58