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


S>Это почему? Я заранее не знаю из чего состоит автомобиль и как каждая его часть задействована в езде?

Я же дал вам список примеров. Что именно в них непонятно?
S>Каким образом?
Именно таким. В первой версии колёсам не надо было знать, куда мы поворачиваем, а во второй — надо.

S>Почему придется перекладывать, будут соотв. абстракции, которые будут отвечать за тот или иной аспект. Что и куда перекладывается?

Я же привёл примеры. Попробуйте прикинуть, какие сигнатуры будут у ваших классов для описания автомобиля.

S>Примеры с обратной кинематикой и способы решения диффуров? Это какие-то очень низкоуровневые детали.

Примеры с автомобилем. Мне не жалко, я ещё раз их приведу:

Дальше вы начинаете вызывать методы "Ехать влево" у составляющих агрегат элементов. Вот вы заложились на то, что у руля этот метод нужно вызывать, а у колёс и двигателя — нет.
Завтра к вам приходит заказчик и рассказывает, что в его модели автомобиля задние колёса умеют подруливать, поэтому им тоже нужно "знать" о повороте всего автомобиля влевою
А послезавтра он говорит, что теперь эти колёса должны подруливать интеллектуально — при перестроениях между полосами они должны подруливать в ту же сторону, а при манёврах в ограниченном пространстве в противоположную.
Ещё через неделю выясняется, что нужно контролировать занос — и при потере сцепления с дорогой (о чём "знают" только колёса, да и то при сравнении их данных друг с другом, а не по отдельности) нужно сбрасывать газ на двигателе.
И каждый раз, как поступает новое требование, вам приходится править всю иерархию классов, причём как интерфейс, так и реализацию.


S>Пускай. У кого будет не десяток, а сотня абстракций. Главное, что все они спрятаны за абстракцией Car.

Нет конечно. Нет такой абстракции "Car". Она тут совершенно не нужна. Есть "кинематическая схема", и она никакая не абстрактная, а совершенно конкретная. У неё нет никакого "поведения" в смысле ООП.
Если вам завтра надо будет решать задачу управления катером, а не автомобилем — вы что, будете с нуля писать новую абстракцию Boat?
А зачем? Чем эта абстракция будет отличаться от абстракции Car? Ладно, пусть там будет не Car/Boat, а абстракция Vehicle. Нужны ли будут для кинематики катера и автомобиля классы Boat:Vehicle и Car:Vehicle?
Если да, то зачем?

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

Это не ответ. Сможем ли мы повторно использовать "абстракцию Car" во всех трёх доменах, или придётся всякий раз писать её заново?
Сможем ли мы реализовать в одном конкретном "классе SpecificCar" все три абстракции?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[42]: Как внедряли DDD в Яндекс 360.
От: Miroff Россия  
Дата: 11.02.26 11:30
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


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

S>Вот у нас есть отдел, есть его начальник. "Руководить" — это связь между отделом и сотрудником; она является "свойством" сотрудника в той же степени, что и отдела.


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

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


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

S>Это понятно. Непонятно, почему вы "поведение" приписываете каким-то конкретным концептам из вашего "домена".


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

S>В домене "торговля товаром" обязательство является свойством контрагента, а не какого-то конкретного товара. Это не товар "перемещается" от поставщика к получателю, это кто-то, обладающий свободой воли, перемещает товар.


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

S>Так не бывает. Дизайн очень сильно влияет на реализацию, ни о какой ортогональности речь идти не может.


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

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

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

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


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

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


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