Простые вопросы по DDD

Обсуждаем, как правильно строить приложения
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Простые вопросы по DDD

Сообщение samdark »

Хороший пример реализации cqrs+es - twitter.
Мне так не кажется. Во первых, CQRS тут как-бы не при чём. Во-вторых, twitter и не представишь по другому.

Хороший пример — это денежный счёт. Можно записывать только сумму на текущий день. Это у нас будет «обычный» подход. Можно вести бухгалтерию в виде множества операций прихода и расхода. Это у нас будет ES.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

yiijeka писал(а):На гитхабике uuid от ramsey надо выпилить из core-ddd, в другой модуль и оставить только интерфейсы :)
он в инфрастуктуре, которая именно для реализаций. А т.к. сам по себе сервис маленький и скорее всего не будет по другому реализоан, то и выделять его не имеет смысла. Или ты что-то другое имеешь в виду?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

Sam Dark писал(а):
Хороший пример реализации cqrs+es - twitter.
Мне так не кажется. Во первых, CQRS тут как-бы не при чём. Во-вторых, twitter и не представишь по другому.

Хороший пример — это денежный счёт. Можно записывать только сумму на текущий день. Это у нас будет «обычный» подход. Можно вести бухгалтерию в виде множества операций прихода и расхода. Это у нас будет ES.
я имел в виду скорее cqrs, так как ES под капотом и его не видно.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Простые вопросы по DDD

Сообщение samdark »

На основе чего делается вывод о том, что в твиттере обязательно должен быть реализован CQRS?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

Sam Dark писал(а):На основе чего делается вывод о том, что в твиттере обязательно должен быть реализован CQRS?
из презентаций ) + cqrs так или иначе работает практически на всех крупных проектах, работающих с богатым представлением контента - фронт берет денормализованную инфу из быстрого хранилища.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

Sam Dark писал(а):По поводу общих частей сущностей и геттеров-сеттеров вместо property.

Есть у нас, допустим, Article, Comment, Post. Они немного разные, но у всех есть тело, автор, даты создания и изменения. У нас есть некоторый объект бизнес-логики, который с телом, автором и датой будет работать. Ему всё равно, какой это объект. Как быть? Создать абстрактный Content? Ввести интерфейс ContentInterface? Как быть, если у нас используются property напрямую?
HasContent, HasAuthor, HasCreatedDate => ContentEntity (abstr.)
Проперти не используются напрямую никогда в сущностях, только через геттеры.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Простые вопросы по DDD

Сообщение samdark »

Проперти не используются напрямую никогда в сущностях, только через геттеры.
В PHP. Потому что не могут быть частью интерфейса. А жаль.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Простые вопросы по DDD

Сообщение samdark »

Ещё вопрос напрашивается. Какой модификатор использовать для свойств ContentEntity? private или protected? Почему?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

Sam Dark писал(а):
Проперти не используются напрямую никогда в сущностях, только через геттеры.
В PHP. Потому что не могут быть частью интерфейса. А жаль.
в ddd, так как модель у нас не-анемичная, а значит богата поведениями, поэтмоу как раньше говорил, геттер (и сеттер) могут включать в себя различные проверки и оптимизации.
С интерфейсами понятно.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

Sam Dark писал(а):Ещё вопрос напрашивается. Какой модификатор использовать для свойств ContentEntity? private или protected? Почему?
php-кейс. Стандартно, private, при необходимости повышаем.
Аватара пользователя
yiijeka
Сообщения: 3103
Зарегистрирован: 2012.01.28, 09:14
Откуда: Беларусь
Контактная информация:

Re: Простые вопросы по DDD

Сообщение yiijeka »

cкорее всего не будет по другому реализоан, то и выделять его не имеет смысла. Или ты что-то другое имеешь в виду?
Можно и не выделять отдельно, но навязывать его в core не стоит - поэтому пихаем его в suggest composer.json. Кому надо сам добавит.
Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: Простые вопросы по DDD

Сообщение slavcodev »

Sam Dark писал(а):1. Всегда ли надо DDD?
Вопрос похож на "Нужен ли нам фреймворк, если можно на чистом PHP писать", разве нет?
DDD - используется там где требуется разработать приложение с множеством бизнес-правил, когда нужно смоделировать область с определенной бизнес-логикой. Т.е. не всегда это нужен. А когда нужен, то не обязательно. Но рекомендуется, т.к. концентрирует внимание на проблеме, в не на реализации. Например тот же блог. Если это простой CRUD над статьей, тут DDD не нужен. Если же имеются какие бизнес-правила, например, статьи должны публиковаться не чаще одна в день, иначе они попадают в очередь, или уведомить о новом прочтении, уже можно применять :)
Sam Dark писал(а):2. Зачем мне DDD?
Понятия не имею зачем он тебе. А вообще DDD, как я понимаю, это принцип разработки с концентрацией на поставленной проблеме а не на реализации. Чем больше проект, чем богаче бизнес-логика, тем ощутимее.
Sam Dark писал(а):3. Как я пойму, что мне надо DDD?
Само собой приходит, конечно если интересуешься темой, знаком что это такое, пробовал и чувствуешь преимущества.
Sam Dark писал(а):4. Я не понял, что мне надо DDD, а теперь надо. Что делать?
Переделывать.
1. Разбить на контексты
2. В Каждом контексте выделить сущности и корневые сущности.
3. Покрыв тестами модель, считай дело сделанным.
4. Написать инфраструктурные сервисы и адаптеры, а также сервисы, адаптеры приложения.
5. При хорошем раскладе UI не по требуется сильно переделывать.
Sam Dark писал(а):5. Что такое CQRS? Зачем оно? Какие проблемы решает? Можно ли реализовать DDD без CQRS?
CQRS - принцип разделения read and write данных. Команды - это запись данных, изменения состояние ваших моделей. Query - чтение. Операции не пересекаются, что означает что может иметь разное хранилище, даже модели могут быть разные.
DDD без CQRS, кстати только C относится к DDD, только команды работают с Доменом. Чтение, на сколько я могу судить работает напрямую с инфраструктурой.
Sam Dark писал(а):6. Что такое ES? Зачем оно? Какие проблемы решает? Если мне не надо аудит, есть ли плюсы в ES? У нас вроде PHP без shared-памяти, точно есть плюсы?
Event Sourcing - принцип хранения не состояния моделей, а очередь событий, важных для вашего бизнеса, произошедшие с моделью. Зачем и какие проблемы решает, не могу сказать, мало опыта. Но хранение проще, схема банальна, легко использовать документо-ориентированную СУБД, возможен откат, аудит.
Sam Dark писал(а):6. Что такое Entity, Value Object? Что делать когда в Entity 100 полей? Что пихать в конструктор, для чего делать сеттеры? Как генерить ID? Как данные запихнуть в модель из базы? Надо ли их валидировать?
Entity -модель какой-то сущности. Имеет идентификатор, т.е уникальная в рамках одного контекста. Имеет жизненный цикл, т.е. может менять состояние, и это состояние сохраняется, что вытекает из того что ее можно идентифицировать в системе.
Value Object - модель значение. Такой объект имеет поведение он не имеет состояния (Immutable).
Одна и та же модель, в разных контекстах может быть и сущность и значением. Пример деньги (Money). В контексте баланса пользователя это просто комплексное значение (сумма, валюта). В контексте банка который занимается эмиссией денег, это сущность. Имеет уникальный номер, имеет жизненный цикл (печать, эмиссия, утилизация).
Если в Entity 100 полей, ничего с этим не делать. Если ваш UL говорит вам что часть этих полей, должны быть выделены в другую Entity/ValueObject то выделяете.
Основное правило, но это даже не DDD навязывает, объекты не должны быть в неверном состоянии. Через конструктор передаются значение, устанавливающие объект в его начальное но верное состояние. Простой пример, сущность, которая не может быть без идентификатора.
DDD это про Rich-model, DDD категорически против Anemic-model, поэтому слова гетер/сеттер, стоит выкинуть из обихода. Модели в DDD, "богаты" поведениями. При этом если UL, требует то методы могут начинаться с "get"/"set", но смысл их другой: поменять состояние модели, или выполнение какого-то поведения.
ИД генерируется в зависимости от поставленной задачи. UUID - не панацея, он удобен т.к. уникален для всех типов сущностей в системе. Но его использовать не обязательно. И даже повсеместное использование, ИМХО, нарушает принципы DDD. DDD требует идентификтаор сущности, как идентифицировать сущность это проблема UL. Если эксперт говорит Вам, что идентификатор инвойса, это порядковый номер, то разбейте себе лоб об стену, Вам не получится убедить его что нужно использовать UUID. ИД сущности это уникальное для них значение (комплекстное значение - ValueObject), формат предстоит выбрать. ИД даже не обязательно генерируется, это может быть установлено вручную, если контекст требует и это значение уникально.
Данные из базы "пихаются" по разному. Для ES это восстановление на базе событие. Обычное хранение, нужен ОРМ. Даже ActiveRecord подойдет :) Хотя я бы не стал, т.к. это дает Вам, вашим коллегам, или будущим программистам, шанс пойти по ложному пути и сломать архитектуру. Именно поэтому ActiveRecord считается анти-патерном в интерпрайз-приложениях.
Нужна ли валидация чего? Данных из базы? В идеале нет, т.к. сущности не могут находиться в неверном состоянии, то и в БД сохранятся только валидное состояние. Хотя если бизнес-правила поменялись, вы поменяли сущность, и забыли обработать существующие данные, то жди проблем.
Sam Dark писал(а):7. Что такое командная шина? Для чего она нужна? Можно ли без неё?
Командная шина - механизм объединения разных контекстов. Команда - одинаковое сообщение нескольким контекстам, на которое они каждый по свойму реагируют. Например, два контекста, "Отдел безопасности", "Бахгалтерия". На сообщение от юристов "Нанят новый работник", один выписывает создает электронный пропуск, другой, открывает новый заработный счет. Обойтись можно, но тогда у вас появится кандидат в God-object. :) С другой стороны, на собственной шкуре знаю что такое использование шины не по назначению, а везде где попало в приложении. с этими шинами, за всеми этими командами очень сложно уследить, а когда их куча, это дурдом.
Жду Yii 3!
Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: Простые вопросы по DDD

Сообщение slavcodev »

Sam Dark писал(а):По поводу общих частей сущностей и геттеров-сеттеров вместо property.

Есть у нас, допустим, Article, Comment, Post. Они немного разные, но у всех есть тело, автор, даты создания и изменения. У нас есть некоторый объект бизнес-логики, который с телом, автором и датой будет работать. Ему всё равно, какой это объект. Как быть? Создать абстрактный Content? Ввести интерфейс ContentInterface? Как быть, если у нас используются property напрямую?
Эмм. Очень сложно говорить в рамках DDD, о вот таких абстрактных задачах. Нет UL, нет DDD.
Жду Yii 3!
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Простые вопросы по DDD

Сообщение samdark »

Спасибо за дополнения. Про ID важный момент.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

кстати, аргумент отказа от uuid - медленные выборки из БД по строкам.
На хабре была статья с тестами, которая показала примерную 50% просадку по времени запроса по uuid по сравнению с integer. Но генеря последовательные uuid (на основе даты например), мы сокращаем просадку до 10%.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Простые вопросы по DDD

Сообщение samdark »

Для последовательных ID нужен атомарный sequence.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

Sam Dark писал(а):Для последовательных ID нужен атомарный sequence.
поясни мысль
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Простые вопросы по DDD

Сообщение samdark »

Такие ID надо откуда-то получать. Источник не должен ни под каким видом отдавать один и тот же ID два раза. То есть операция отдачи ID должна быть синхронна и атомарна. Генерить их на каждом из независимых серверов не представляется возможным.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Простые вопросы по DDD

Сообщение zelenin »

Sam Dark писал(а):Такие ID надо откуда-то получать. Источник не должен ни под каким видом отдавать один и тот же ID два раза. То есть операция отдачи ID должна быть синхронна и атомарна. Генерить их на каждом из независимых серверов не представляется возможным.
мы и юзаем для этого uuid, чтобы на клиенте генерить гарантированно уникальное значение. Если мы получаем uuid откуда-то, то смысла в этом нет.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Простые вопросы по DDD

Сообщение samdark »

Так я про последовательные int-ы говорил.
Закрыто