Domain Driven Design - просто о сложном. Дмитрий Науменко.
Вставка
- Опубліковано 11 вер 2024
- Доклад Дмитрия Науменко на Съесть собаку #8. PHP. 20/04/17
Для всех участников восьмой встречи “Съесть собаку” и наших подписчиков Дима собрал список из 4 ресурсов и книг, которые точно пригодятся в работе.
1. Книга «Domain-Driven Design: Tackling Complexity in the Heart of Software» Эрика Эванса: www.amazon.com...
Очень рекомендую к прочтению. Книга об организации и систематизации принципов построения логической структуры предметной области.
2. Книга «Domain Driven Design Quickly» Эйбла Аврама и Флойда Маринеску: www.infoq.com/...
По сути, эта книга кратко пересказывает то, о чем писал Эрик Эванс в «DDD».
3. Книга Гради Буч «Объектно-ориентированный анализ и проектирование с примерами приложений на С++ »: www.helloworld....
Хорошо описана теория и практичные советы, касающиеся вопросов анализа, проектирования, реализации и оптимального управления проектами.
4. Uncle Bob. The Clean Architecture: 8thlight.com/b...
Кратко почитать о правилах построения чистой архитектуры в блоге Роберта Мартина.
DTO используется для передачи данных между слоями. Ок.
Пример "AddressDto" имеет метод "fromRequest". В каком слое должен тогда лежать такой DTO?
Если его положить в слой контроллеров, то получается слои, расположенные ниже, будут знать о DTO из уровня контроллеров (фактически слоя инфраструктуры раз мы уже знаем о реквесте). Если его положить в какой то слой ниже, то слой ниже должен знать о деталях имплементации слоя выше включая как именно данные будут передаваться (POST). То есть если мы надумаем передавать данные через GET, то изменения затронут не только уровень инфраструктуры, а и уровень апликейшена (доменных сервисов).
Я думаю правильная имплементация подобного DTO должна содержать только метод "load(array $data)", а использоваться в контроллере "(new AddressDto())->load($request->post())".
Сам по себе метод fromRequest указывает на вышележащий request. Возможно, имеет смысл отвалидировать request->post и передать в Dto аргументы по-отдельности (country, city, zip и lines).
@@vlad_covers На самом деле DTO НЕ используется для передачи данных между слоями. Такой подход называется "local DTO" и является антипатерном. Докладчик просто этого не знал. DTO используется для передачи данных между сервисами, хороший примером является gRPC. Дальше на уровне транспортейшн лейера DTO конвертируется во внутренние какие то данные, а DTO выбрасывается. "и передать в Dto аргументы по-отдельности (country, city, zip и lines)" - это правильно.
@@vadymradvansky1569 Вадим, благодарю за развёрнутое уточнение! 🙏
@@vadymradvansky1569 Используется. На то он и Transfer Object. Хранится он в том слое который получает данные.. например в UseCase это Command или Query которая лежит рядом с handler.. или ServiceActionNameDTO если это сервисы, которые инстенсит контроллер.. слои ниже ничего не знают (не должны) о реквесте, а получают все необходимое через DTO или как параметры вызова.
в домене положить interface IAddress и при создании класса AddressDto implements IAddress
Оператору незачёт, докладчик крупным планом, код издалека - ничего не разобрать.
докладчик хорош не идеал и видно что волнуется но старается ! А второму челу который задал вопрос, хочется сказать научись задавать вопросы и думай что там человек тоже волнуется. А третьи чел задавал крутые вопросы и правильно их задавал спасибо ему !
Хотел бы выступить в защиту докладчика.
Третий чел протупил в своем первом вопросе, он предъявляет претензию, что раз заказчик не владеет техникой DDD, не пользуется единым языком.и пр., то это значит, что зря разработчики взяли ее за основу и что они ее не используют.
А что, они должны провести семинары для заказчиков, или все-таки кодить должны? Он предлагает сменить заказчиков на более умных? А им это понравится?
Это бизнес, в нем надо подстраиваться под желания и возможности бизнеса, а не пальцы гнуть.
@@zond_amond , задававший вопрос совсем не это имел ввиду, а то что разработчики должны подстраиваться под заказчиков (так как наоборот невозможно сделать =)), об этом как раз и гласит основополагающая идея Ubiquitous Language (единая терминология) в DDD, и он своим вопросом намекнул, что мол докладчик использует DDD без его основной идеи, а соответственно можно сделать вывод что это не DDD, а пародия.
P.S. смотрел видос и думал как же просто и понятно объясняет докладчик, а потом услышав вопросы этого самого чела - мое мнение реверсивно изменилось, так как я понял, что в его докладе лишь имитация DDD.
@@user-tu7bt9ye4u а ты посмотри видео этого чела, который задает этот вопрос. У нас все наоборот устроено на 180 градусов.
Услышал у него в том числе сказочные истории про то, как он обычно указывает бизнесу свои требования.
Спасибо, Дмитрий. все коротко и по делу, без лишней воды.
Хорошее введение в DDD. Спасибо за доклад!
Прекрасный доклад и интересные вопросы к нему. Спасибо
В конце понравилось что меня раскусили. Попробовал смотреть на 1.75 и решил что хочу кайфануть, потому 1.25 использовал. Немного триггерило слово итем. :) Но со временем смирился с таким вариантом, будем считать это частью диалекта. :) Лайк тебе за доклад.
Лучший доклад по ддд что я видел !!!
Как зовут гения, который много лет использует DDD, задает интересные вопросы по взаимодействию с заказчиком и одет в черное?
ua-cam.com/video/_CK5Kag7enw/v-deo.html
Эрик
Мартин Фаулер
Чарльз Бэббидж
Елена Беркова
Очень интересно, но нет последовательности, вначале говорилось что Client это Entity, потом он вдруг стал агрегатом? Что за?
хороший доклад, но объясняет лишь часть подхода DDD. Тот чел, который в конце доклада задавал вопросы про основополагающие идеи DDD прям в точку бил, ведь в примере доклада они никак не представлены
4:53
Вопросы:
- почему связи задом-наперед;
- почему клиент не может существовать без счета;
- почему у клиента не определены типы данных.
Стоит ли смотреть дальше?
У вас на UML диаграмме направление отношения агрегации неверное
отличные вопросы и нормальный доклад
Самое адекватное объяснение DDD, на мой взгляд.
пугает фраза "в далеких 2000x"
Меня одного смутило на 4:54 что UML не верно записан и направление агрегации и композиции обратное?
Я на этом моменте пошел в гугл перепроверил что я правильно помню в какую сторону стрелки рисуются )))
Вот и я так же. Нельзя так пугать людей
Блин, а я то всё думал, что меня в этой картинке раздражает..
не, не тебя одного. но по uml тоже хороших докладчиков не хватает...
@@epuremath ну а что быть докладчиком по тому что во-первых не меняется поколениями, а во-вторых не имеет реального применения? Почти всегда используются semi-formal виды
А можно будет все эти примеры как-то посмотреть текстом, если есть?
Спасибо за доклад
Отличный доклад, спасибо!
47:40 - В 2017-м поисковых систем не было по-моему ещё, если не ошибаюсь... GPT уж точно не было чтоб спросить о разнице (как 2024-м). :)
Хорошая подача материала, но есть один момент интересный, рассматривались простые action и использование в них сервисов, но как поступить в случае, когда есть просто action для вывода gridview и внутри этого action необходимо отдать на view dataProvider - в таком случае если делать сервис, который делает выборку данных и отдает затем ActiveDataProvider немножко выглядит странным. Этот вопрос из серии когда толстый контроллер пробую сделать тонким через сервис.
return $this->render('index', [
'dataProvider' => $this->serviceData->getActiveDataProvider(),
.................
public function getActiveDataProvider() : ActiveDataProvider
{
$dataProvider = new ActiveDataProvider([
'query' => $this->getData(),
]);
return $dataProvider;
}
Валидация не должна быть на уровне Entity, потому что это нереально. Допустим надо проверить существует ли имейл в базе. Без запроса в базу это сделать не получится, а Entity не может обращаться напрямую в базу, так как в его слое базы как бы и не существует еще. Невалидные данные в Entity должны вываливать эксепшн, который должен ловить уровень инфраструктуры, логировать его, а девелоперы должны анализировать эти логи, находить как невалидные данные докатились до уровня Entity и править код, что бы этого больше не повторилось.
Многослойная валидация - тоже не выход. Это приведет либо к неконсистентным валидационным ошибкам, от которых пользы конечному юзеру будет мало. Либо к тому, что контейнер для валидационных ошибок будет гоняться по куче слоев.
Валидироваться должны входящие данные на самом верхнем уровне. Как возможное решение каждый кусок бизнес логики (фактически каждый метод сервиса) должен всегда принимать DTO наполненный волью обджектами, а вот сам DTO должен валидироваться. Если валидация DTO написана неправильно и невалидные данные просочились ниже по слоям - только Exception спасет отца русской демократии, а валидацию DTO нужно улучшить.
валидация разная бывает, валидировать можно формат данных, тип данных, валидации бизнес логики.
Man6524 формат данных - это не валидация. Это в пыхыпы ларавельщики пишут валидаторы типа «маст бы стринг», к валидации это не имеет отношения никакого. Неправильная структура данных - это тоже не валидация. Сначала данные надо привести к нормальному формату и структуре (нормализация), а потом уже валидировать.
Поэтому надо писать тесты и проблем не будет
@@rugleb
"Поэтому" - это к чему относится? Какие именно тесты? Каких проблем не будет? Это о чем вообще было?
Здесь как бы не детский сад, все выше описанное подразумевает ситуацию, когда тесты уже написаны. Что снова приводит к выводу, что валидация на уровне Entity - это уже слишком поздно. Потому что Entity как бы тестами напрямую не покрываются, даже не смотря на то, что в них может быть какая то бизнес логика.То есть что бы добраться тестами к валидации в энтити, надо будет влезать через игольное ушко и за этим ушком обнаружить дивный сад, а скорее зоопарк, багов ))).
@@vadymradvansky1569 если не детский сад, то очевидно, что тесты нужно писать на каждый слой, а не на одну узкую точку входа.
По хорошему валидация должна быть тоже на каждом слое, возможно она даже будет отличаться во формату исключений или ещё чём-нибудь. Вы это все тестируете хорошо и никаких проблем, клиент не увидит ошибок, который не должен увидеть.
Если для вас это слишком сложно. То доверяйте валидация на самом верхнем слое и внутри делайте вид, что кто-то сверху уже провалидировал.
я так и не понял, DDD это просто набор шаблонов и советов которые можно применять как душе угодно?
Спасибо, очень просто и понятно!
Очень доходчиво. Спасибо!
Очень хороший доклад!
Доклад в чём-то неплохой (в плане теории), но согласен с одним из комментаторов, что вы создали не DDD, а анемичную функциональную модель, а надо было до конца следовать принципам ООП. Почему так? Советую посмотреть видео по ссылке с времени 22.16: ua-cam.com/video/JOy_SNK3qj4/v-deo.html
кпц недовольные некоторые зрители, 0 уважения, типо "понятно ты не знаешь, идем дальше".
Мужик в черном в конце правильно все подметил. Науменко явно не понимает суть DDD и интерпретирует многие вещи как ему хочется. Это уже не DDD.
DDD это не закон, это, внезапно, набор рекомендаций.
Если вы евангелист, не пытайтесь идеализировать понятия. DDD -- это подход, который описан для решения каких-то задач. Сказочники в книгах (к примеру тот же Роберт Мартин с чистым кодом) живут в идеальном мире, где доменный эксперт хочет общаться с вами по DDD, где цветочки цветут и розы пахнут. И очень забавно наблюдать, как идеалисты пытаются писать код по книжке. Но, как правильно подметил автор, DDD хорош тем, что его не нужно использовать полностью. Если команда говорит, что использует DDD в работе -- это значит, что они хотя бы 1% от подхода применяют у себя. И более того, если человек начинает применять полностью паттерны там, где не нужно или писать идеально чистый код во вред скорости разработки и работы с бизнесом -- скорее всего этот человек застрял с переходном возрасте
Хороший доклад, только не понравилось что пропущена тема сабдоменов и ограниченного контекста.
В данном примере домен выбран неправильно, скорее всего работа со счетом это такой сабдомен.
Домен же - это весь бизнес, который содержит в том числе и выставление счета.
Чаще всего, но не всегда, домен - это вся деятельность компании в конкретной области.
Но я повторю, доклад достаточно хороший и очень подробный!
Поделитесь, пожалуйста, ссылкой на презентацию
Всё супер, но мне не понятно если например у нас тот же самый Client или Item понадобится где-то в другом домене, вот так получилось что структура класса Client для этого домена такая же как и у другого домена, копипастить?
И по поводу независимости домена от базы данных и неизменяемости VO. Предполагается что при инициализации домена, мы уже передали в него всю необходимую информацию и на время работы с доменом вообще не обращаемся к базе данных?
И если Position это Entity, то почему у него нет идентификатора?
Ну по сути да, копипастить. Предполагается, что разные контексты общаются друг с другом через Domain Events. Домен Client'а просто посылает событие, а кто его обработает в другом домене его совершенно не должно волновать.
Про инициализацию домена... Да, агрегат лучше сразу инициализировать. Но не надо по каждому случаю создавать агрегат, например, при вытаскивании из базы 50 записей не нужно доставать 50 агрегатов. Ну и сами агрегаты не стоит делать слишком большими.
Я имею исключительно негативный опыт DDD на реальных проектах, но рекомендую почитать статьи и книги Vaughn Vernon'а. Оригинальная концепция DDD сильно недоработанная, Vernon многие подобные практические вопросы пытается прояснить.
@@nikitagusev2215 пересматривал и заметил еще один момент - Position у него Entity, но при этом в классе Position нет свойства для идентификатора, получается что это не Entity, а Agregate, так как свои идентификаторы есть только у Item, которые внутри Position или я что-то не так понял?
Не помню про position. Но вообще агрегат это корневой entity, то есть идентификатор у агрегатов должен быть.
Поищите статьи Effective aggregate design by Vaughn Vernon.
@@mclotos У агрегата есть айди также как и у Entity. А если айди нет, то это Value Object.
Не совсем понял пример с купюрой. Что значит "криминалист должен различать их по идентификатору"? Что в данной ситуации выступает идентификатором? В том числе и для кассира есть какой-то идентификатор у купюры?
На каждой купюре уникальный номер.
Помимо этого разный год выпуска, разные подписи глав банка.
Да и просто у криминалиста на каждую купюру может быть наклеен стикер с номером дела, к примеру.
Не знают про понятия Симпл домейн модел от Рич домейн модели.
Крутой доклад. А value-object и DTO это ведь одно и то же?
нет это разные вещи, DTO не содержит логики и может быть мутабельным (теоретически) VO - не изменяемые и могут содержать поведение
почему у него Poistion это Entity а не агрегат ?
Тоже непонятно
четко!
Всё хорошо, но человеку который переключает камеры, руки бы оторвал.
Пока не досмотрел до конца, чтобы не забыть задам вопрос - почему Item агрегат, и он входит в состав Entity position? Разве агрегат может входить в состав entity? Вроде агрегат на то и агрегат чтобы агрегировать в себе сущности (entity)?
Агрегаты не могут входить в состав сущностей, но сущности могут ссылаться на другие агрегаты.
А может делать скидки через паттерн декоратор?
Не совсем понимаю как это можно сделать через декоратор. Скидки есть часть бизнес логики - часть бизнес модели. Значит этот механизм должен быть намертво встроен в контексте добавления товара заказ. При каждом добавлении товара должна вызываться операция определения скидки (стратегия) и пересчитываться корзина.
48:28 - вот здесь те самые вопросы, которые раскрывают проблему представленного метода DDD.
Дмитрию очень далеко до CTO, а он уже им стал.
Бедная, бедная компания.
Сколько же денег потеряет компания ...
Но, это уже проблема найма 😊
Как-то все в кучу и много воды
не знаю, что хорошего в тотальном чтении того, что написано на слайдах безо всяких пояснений, примеров и интерпретаций....вышел прочитал свою же статью - ну ок, так прочитать любой может....ты тонкие места покажи, где могут возникать трудности, приведи примеры удачного и неудачного использования данной технологии ...и не по 100 слов в минуту, а с расстановкой и осознанием.....
Спасибо.
Yii и DDD в принципе не сочетаются, такое впечатление что докладчик сам не понимает, что говорит.
вть
ужасный рассказчик - зазубрил, своего понимания мало
Задающим вопросы лень встать? Что за неуважение к докладчику?
Вам важна суть вопроса и ответа, или уважение к докладчику решит проблемы вашего клиента? Что это за совдепский подход?
@@driversti2 Это элементарные нормы приличия...
@@rugleb это субъективно. Я не обижусь, если передо мной не встанут. И в моем окружении никто этого не требует, даже сразу говорят, что вставать не надо.
Эти "элементарные нормы приличия" навязаны советским подходом, где к старшему (по возрасту, званию, должности и и.д.) нужно было их проявлять. Ценность в дискуссии и решении проблем клиента, а не в том кто перед кем встал. Я не навязываю свое мнение, это реакция на вашу реакцию. Только
дядька вконце набомбил вопросами, унизил🤣