Re[43]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.26 17:05
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Здесь нет связей, здесь есть именно свойства сущностей.

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

M>Это не связь, а совершенно отдельный доменный объект — "роль". У сотрудника может быть много ролей в одном отделе, эти роли могут пересекаться или активироваться по каким-то особым критериям. Вплоть до того, что роль может быть вакантной.

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

M>Единица товара это атомарный субъект транзакции учета: пачка молока, красная шляпа, автомобиль. Ведь в реальности ты продаешь покупателю не -1 из строчки количество красных шляп, а конкретный предмет со собственными свойствами и историй. И при наступлении опредленного этапа жизненного цикла заказа у тебя появляется обязательство этот предмет выделить из кучи однотипных и передать его в пользование покупателю.

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

M>Потому что поведение выражается через свойства доменных сущностей. Поведения в отрыве от сущностей не существует. Т.е. первичный сущности и только относительно сущностей мы можем определять поведение.

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

M>В домене торговля никого "обладающего свободой" нет и быть не может. В торговле царствуют алгоритмы имеющие силу закона. Ты не можешь взять товар и переместить его вместо покупателя на свалку просто потому что тебе так захотелось.

Чего это вдруг? Запросто перемещу. Для этого мне достаточно оформить накладную на списание. И какое там "поведение" у этого товара мне наплевать — процесс списания регламентируется приказом по компании, и сегодня он один, завтра другой, а послезавтра он зависит от цвета шляпы. Бежать внедрять код логики списания внутрь класса, объектом которого является "красная шляпа" — это последнее, что стоит делать. Именно по этой причине.

M>Реализация МОЖЕТ влиять на дизайн, но задача DDD это как раз избежать этого влияния моделируя предметную область в отрыве от искуственных ограничений. Ты можешь сделать дизайн чтобы самые частые операции выполнялись быстрее всего. Например сложить товары и заказы в одну базу. Но такой дизайн всегда получается очень хрупким, непригодным к расширению домена и при изменении требований такой дизайн быстро разваливающийся под собственной тяжестью.



M>К тому же, в современных системах не принято при выполнении доменной операции сразу бежать и что-то менять в хранилищах. Вместо этого операции накапливаются, а потом материализуются пачкой. Это могут транзакции в БД, CQRS,

M>функциональные эффекты или старый добрый паттерн Команда из GoF. Тебе никто не мешает в момент материализации переопределить порядок операций и применить любые мыслимые оптимизации, на которые у тебя хватит фантазии. Например, заменять пару SELECT/UPDATE на in place update или вообще на вызов хранимой процедуры которая генерируется из того же DSL


M>Атомарность заказа это на самом деле плохое требование. Оно сложное в реализации, плохо влияет на производительноть и, главное, не приносит прибыли маскируя проблему. Если мы не продали что-то потому что оно закончилось у нас на складе, это прямой УБЫТОК, потому что мы упустили прибыль. И современные системы строятся так, чтобы такое происходило как можно реже. Поэтому в приоритете динамической ценообразование, предсказание продаж, автоматическое пополнение и другие продвинутые процессы. В тех редких случаях когда такая ситуация произошла, дешевле вернуть покупателю деньги за недоставленный товар чем закладываться на этот сценарий.

Всё верно. Это означает, что подход, в котором "цена" является свойством "товара", непригоден. Даже если мы это свойство делаем вычисляемым. Сам товар не может знать, почём его продают — потому что ценообразование динамическое, и оно зависит и от товара, и от наличия этого товара на складе сейчас, и от покупателя и его предыстории, и от соседних товаров в том же заказе.
Никакая из этих "доменных сущностей" не подходит для размещения логики определения цены. Только какой-то внешний по отношению к этому домену "динамический ценообразователь", который, как правило, стейтлесс.
Вот он скорее всего будет построен по принципам ООП — там тебе и наследование, и полиморфизм, и агрегация, и паттерны Policy, и Factory Method и все лучшие наработки. А вот в "доменных сущностях" (в терминологии ER-модели) никакой логики не будет.

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


M>Ну да, REST широко использует проекции данных. Это неудивительно, ведь все что мы делаем, в конечном итоге сводится к машине Тюринга на конечной ленте, а в ней ничего кроме данных не существует.


S>>Вот я взял и добавил связь между сотрудником и департаментом — и это привело к определённому результату, независимо от того, оформил ли я это через department.Employees += e или через e.Deparment = department. А может, так вообще нельзя, и нужно создать экземпляр EmployeeContractAddendum, который после подписания обеими сторонами автоматически отразит изменения штатного расписания департамента и должности у сотрудника.


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

То, что вы используете общепринятые термины в необщепринятом смысле, только затрудняет коммуникацию.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.