Как стать автором
Обновить

Комментарии 18

Изолированная модель предметной области — это модель, операции над которой закрыты в рамках ее сущностей и объектов значений

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


Рекомендую обращать внимание на то, как адепты DDD реализуют обработку событий домена: там вылезут все фатальные недостатки подхода.


Пока вы не дорастёте до DSL/кодогенерации (никогда), полная изоляция предметной области недостижима. В рамках DDD на трейд-оффы этой изоляции принято не обращать внимания.


Ответ, как всегда, заключается в том, чтобы бороться со сложностью

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


"Чистота семантики" обойдётся очень дорого: сложность при DDD не снижается, а размазывается.


Продаваемая адептами DDD "простота" достигается не тем, что сложное становится проще, а тем, что всё становится примерно одинаково сложно. Не сложные задачи решаются быстрее, а легкие дольше.


"Вау-эффект", который обычно показывают на графиках (где x — время, y — сложность, и сложность в какой-то момент перестаёт расти) заключается именно в этом: уменьшается волатильность "сложности", из-за чего возникает иллюзия, что DDD делает сложное проще, хотя всё ровно наоборот.


DDD — это когда стабильно сложно для разработчика, и стабильно дорого для бизнеса, в этом весь трюк.


Заголовок спойлера

Процесс разработки не стабилен, и это не нравится бизнесу: трудно управлять, трудно строить прогнозы и планы. DDD создаёт иллюзию стабильности на графиках (и это даже может где-то сработать), но скорее всего, просто сделает дороже для бизнеса и сложнее для разработчика. На дистанции проект неизбежно станет более хрупким (фактор автобуса+сложность кодовой базы) и менее управляемым (из-за масштаба проекта).

Я пришёл к тому, что у домена не должно быть логики, не должно быть интерфейсов, домен - это только сущности, любые действия над сущностями выполняются на уровне сервисов и бизнес логики. Исключение стандартные методы и интерфейсы, ToString, GetHashCode, IComparable и т. п. Любые попытки запихнуть логику в домен непременно вызывали проблемы, что на каком то этапе требовалось прокинуть сервис в домен, а это не правильно

Нет, у меня вполне могут быть чистые функции например различные конвертеры, но даже они реализуют интерфейс IConverter<T, TResult> и являются по сути сервисом и внедряются через DI

Статья интересная. Сам постоянно задумываюсь над тем, что зависимость от интерфейса не даёт настоящей инверсии зависимостей.

Но примеров не хватает, как изолировать модель? Как в модели Address правильно избавиться от location API? Сразу принимать zip code в конструктор, насколько я понимаю?

Да, сразу принимать zip code. В обязанности Address не входит взаимодействие с внешним миром. На уровне слоя приложения получить zip code по api и передать в конструктор (ну или фабричный метод).

А ZipCodeProvider можно принять?

Нет. ZipCodeProvider может быть только в доменном сервисе и лучше в виде интерфейса.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

 всегда невозможно

А может возможно?

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

НЛО прилетело и опубликовало эту надпись здесь

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

НЛО прилетело и опубликовало эту надпись здесь

Мне кажется, что один лишь факт использования репозитория доменом не указывает на нарушение изоляции доменного слоя, т.к. паттерн репозиторий по задумке представляет инверсию зависимостей между слоем домена и слоем доступа к данным. Главное - чтобы все методы репозитория и их сигнатуры определялись исходя исключительно из потребностей домена и выражались через его (домена) терминологию.

Я не понял, как это будет материализоваться из базы и сохраняться? Мне кажется появится тонна водопроводного кода, чтобы поддерживать эту изоляцию.

В исходной статье есть пример работающего приложения с базой?

В общем случае - вручную. Т.е. в реализации get-метода репозитория необходимо забрать данные из какого-то хранилища (например, из БД) и затем на основании этих данных последовательно воссоздать агрегат через вызов соответствующих конструкторов/фабрик/методов. Аналогично - при сохранении.

В частных случаях это можно переложить на ORM, описав правила через fluent API. При этом ORM может либо уметь использовать конструкторы с параметрами, либо устанавливать значения свойств в обход бизнес-правил через рефлексию.

А можно пример такого кода? Я все никак не могу придумать как красиво делать DI при инстанцировании классов данных.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории