Re[44]: Как внедряли DDD в Яндекс 360.
От: Miroff Россия  
Дата: 12.02.26 03:25
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Непонятно. Сущность не может быть свойством другой сущности.


С чего бы? Колеса это свойство автомобиля в значении part of.

S>Этот объект совершенно точно не может быть отдельным. Потому что без сотрудника он невозможен, как и без отдела. Можно усложнять доменную модель, которую я предложил — например, так, как предложили вы.


Роль может существовать и без сотрудника и без отдела. Например, ТКРФ определяет роль "представитель профсоюза" необходимую для решения трудовых конфликтов. У тебя в компании может не быть ни профсоюза, ни сотрудников, но роль такая есть в силу закона. А из твоего утверждения следует, что раз в компании нет профсоюза, то и представителей профсоюза не бывает.

S>Просто тогда в модели вместо бинарной связи "быть начальником" между сотрудником и отделом появляется тернарная связь "исполнять роль", в которой участвуют отдел, сотрудник, и роль.


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


Именно это и означает. Вам даже государство прямым текстом говорит через честный знак: ребята, надо переходить на поединичный учет. Пора уже, ну сколько можно?

S>Вот например, я продаю кому-то 0.435 кг изюма. Что такое "обязательство"? Что тут будет "предметом, выделяемым из кучи однотипных"? 1380 изюминок?


Это на самом деле операция производства: из единицы хранения ящик изюма ты выделяешь 435г в упаковку и эта упаковка становится новой товарной единицей.

S>Всё верно. Это означает, что подход, в котором "цена" является свойством "товара", непригоден. Даже если мы это свойство делаем вычисляемым. Сам товар не может знать, почём его продают — потому что ценообразование динамическое, и оно зависит и от товара, и от наличия этого товара на складе сейчас, и от покупателя и его предыстории, и от соседних товаров в том же заказе.

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

Именно! Если мы пересматриваем модель ценообразования, нам нужно глубоко анализировать домен, в котором эта цена вычисляется. Нас буквально ЗАСТАВЛЯЮТ отвечать на "неудобные" вопросы, вроде: из чего складывается цена? Каким образом она складывается? Различимы ли с точки зрения цены красная шляпа один, красная шляпа два и черная шляпа три? Должна ли история продаж лапсердаков влиять на цену красных шляп? Сама архитектура провоцирует глубокую аналитику и ресерч, а не просто копировать одни и те же таблички из проекта в проект.

S>То, что вы используете общепринятые термины в необщепринятом смысле, только затрудняет коммуникацию.


Очень трудно говорить с человеком, который ментально застрял где-то в 2006 году)

Я рекомендую тебе попробовать сделать какой-нибудь проект на принципиально новом для тебя стеке, например на Scala c CATS/ZIO. Там у тебя будут нормальные функциональные монады, множественное наследование, частичное наследование, богатая система типов, частичные вычисления и богата система типов. Такой опыт сильно расширит твой архитектурный кругозор пониманием, что вовсе не обязательно ограничиваться двумя отношениями is_a и part_of.

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

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

2. Выделение сервисов происходит либо строго по границам доменных сущностей, что эквивалентно рич модели с точностью до положения методов. Либо сервисы выделяются произвольным образом безотносительно реального мира. Индикатором этого служат затруднения разработчиков в именовании сервисов случающиеся у разработчиков. Это как в философии, если ты не можешь что-то поименовать, то этого не существует. И даже если ты выделил сервис по акторам реального мира то со временем в эти сервисы просочатся нехарактерные для этих акторов методы просто потому что так удобнее. И в силу размытости ответственности сервисов из п1. разработчики легко натянут аргументацию почем именно этот метод должен быть именно в этом сервисе. Потому что на самом деле в какой из MiscService класть метод вообще не важно.

3. В силу п.2, иерархии сервисов не коррелируют с иерархиями доменной модели. Это приводит к тому, что сервисы изобилуют проверками сущностей, с которыми они взаимодействуют. Это еще один источник багов, прямо по Аллену. К тому же, это даже не ООП, а откат к процедурному программированию.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.