Вот мое понимание:
При компиляции домен ни от чего не зависит. Поэтому, например, домен не будет зависеть от персистентности проекта. Это будет зависеть от абстракций, определенных внутри самого домена.
Ваше постоянство (например, конкретные репозитории) будет соответствовать зависимостям, определенным в домене. В реальных условиях это обычно означает, что они будут реализовывать интерфейсы, определенные в домене.
Композиция root затем настраивает приложение так, чтобы конкретные реализации соответствовали абстракциям, определенным в домене. Это конфигурация DI.
Это самая простая версия. Вы можете добавить больше сложности к этому, если вам это нужно. Единственная часть, которая не изменится, - это то, что домен является автономным. Вот некоторые другие способы, с помощью которых сложность может возрасти , если необходимо :
- Реализация зависимостей также может быть автономной, как в области. Еще один проект адаптирует их к интерфейсам домена. Таким образом, ваши репозитории не будут напрямую реализовывать доменные интерфейсы.
- Конфигурация абстракций домена - сопоставление их с их конкретными зависимостями - может быть разделена. Другими словами, настройки вашего контейнера могут быть отделены от хоста приложения. В идеале хост приложения должен нести ответственность за чтение значений своей конфигурации или среды и передачу их в эту конфигурацию контейнера. Это предотвращает соединение конфигурации контейнера с такими деталями, как JSON или .config. Это проще для тестирования.
Но важная деталь заключается в том, что в любом случае сам домен является автономным. Мы бы не вставляли интерфейс, определенный вне домена, в класс домена. Домен определяет свои собственные абстракции, и затем классы, определенные вне домена, выполняют эти абстракции.
Ваш API может зависеть от проекта персистентности. Ваш API не является доменом. Ваш запуск API будет зависеть от домена и персистентности, и сконфигурируйте контейнер DI для предоставления классов из проекта персистентности для выполнения зависимостей, определенных в домене.
API подобен противоположности домена. Домен ни от чего не зависит. Другие зависимости указывают внутрь. Репозитории, например, реализуют абстракции, определенные доменом.
API, с другой стороны, в конечном итоге зависит от всего. Он использует конфигурацию DI для предоставления зависимостей (таких как постоянство) в домен, что означает, что он будет зависеть от всех из них.
Вот (на мой взгляд) самое большое изменение в мышлении:
У нас есть тенденция писать конкретные классы для доступа к данным, вызывать внешние API и делать другие вещи, которые являются периферийными по отношению к домену. Затем мы помещаем интерфейсы на них. Эти интерфейсы часто выглядят как запоздалая мысль. Как будто мы просто создаем интерфейсы, которые отражают эти классы. Если мы добавим что-то в класс, мы добавим это в интерфейс.
Затем мы возьмем эти интерфейсы и начнем внедрять их в наш домен. Вот где все становится грязно. Эти интерфейсы не имеют ничего общего с нашим доменом. Это просто зеркальные изображения классов, которые существуют за пределами домена. Это затрудняет тестирование домена. Сегрегация интерфейса нарушена. Мы обнаруживаем насмешливые части интерфейсов, которые не имеют ничего общего с нашим доменом.
Все это исчезнет, если мы создадим абстракции с точки зрения классов доменов, которые от них зависят. Например, если нашему классу домена необходимо извлечь данные из хранилища, мы определяем хранилище, которое моделирует именно то, что нужно этому классу домена - ни больше, ни меньше. Мы не берем какой-то универсальный c универсальный интерфейс репозитория и не вставляем его в наш домен.
У нас все еще может быть универсальный c универсальный репозиторий. Это нормально. Но мы адаптируем его к интерфейсу хранилища доменов. Домен не знает об этом. Все, что он знает, - это абстракция, определенная в домене. Класс предметной области зависит от небольших разделенных абстракций, которые он определяет для своих собственных целей. Он владеет ими. Это делает его простым и делает его действительно простым для тестирования.