Re[9]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.20 05:53
Оценка: +1
Здравствуйте, takTak, Вы писали:
T>для таких целей того же чувака, который с использованием ddd работал, нанимают на пару недель или месяцев: или ты думаешь, что кто-то бесплатно будет тебе рассказывать то, что именно тебе нужно?
Конечно. Для этого и нужны форумы.
Мне вот почему-то нетрудно на пальцах показать, как проектируется anemic data model, или как сделать REST для сервиса, который на первый взгляд работает только через RPC-style.
А DDD, оказывается, требует чудовищных затрат даже на то, чтобы обсудить крошечный пример.
Стоит ли его рассматривать дальше, или его стоимость для задач реального масштаба будет вообще неподъемной?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: DDD для небольших проектов.
От: takTak  
Дата: 11.02.20 06:09
Оценка:
T>>для таких целей того же чувака, который с использованием ddd работал, нанимают на пару недель или месяцев: или ты думаешь, что кто-то бесплатно будет тебе рассказывать то, что именно тебе нужно?
S>Конечно. Для этого и нужны форумы.
S>Мне вот почему-то нетрудно на пальцах показать, как проектируется anemic data model, или как сделать REST для сервиса, который на первый взгляд работает только через RPC-style.
S>А DDD, оказывается, требует чудовищных затрат даже на то, чтобы обсудить крошечный пример.
S>Стоит ли его рассматривать дальше, или его стоимость для задач реального масштаба будет вообще неподъемной?

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

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

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

но, по крайней мере, при подобном подходе с заказчиком хотя бы часто и регулярно общались, чего , как правило, не происходит, ни при одном айти-проекте вплоть до того момента, как показывают уже "готовый" продукт
Re[11]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.20 06:41
Оценка:
Здравствуйте, takTak, Вы писали:

T>хорошо, вот давай на пальцах... что дешевле: потратить несколько месяцев на имплементацию рест-архитектуры, чтобы по прошествии нескольких месяцев понять, что ни одного клиента внутренняя архитектура приложений не интересует?! или всё таки лучше формализованно провести несколько дней с клиентом, понять, какие события на уровне бизнес-логики происходят, поделить эти события на кластеры независимых друг от друга событий, слабо или сильно связанных событий, разделив тем самым приложение на несколько независимых предметных сфер, и начать в соответствии с этими проектировать отдельные предметные сферы, пользуясь языком заказчика для отражения той модели, которая у заказчика в голове?!

Если на пальцах, то мы говорим об ортогональных вещах. DDD — это дизайн; REST — это реализация.
T>ведь ясно же, что для совсем рудиментарных вещей подобным не занимаются...
Давайте сначала попробуем применить DDD для рудиментарной вещи. Если он даже для неё не подходит, то как мы будем применять его к реальным задачам?

T>и понятно, что успеха ни одна методология сама по себе не гарантирует: при ддд , в частности, в команде несколько дней в неделю проводит и кто-то, кто представляет заказчика: именно к нему приходят, когда хотят понять, как же всё-таки правильно, и если этот человек- не тоРт, то успех будет больше зависеть от тех программистов , кто даже из него сможет вюдить ту информацию, которая критически важна, но если и со стороны исполнителей таких людей не найдётся, то успеха не будет

Вот вы сейчас, простите, очень похожи на продавца snake oil. При наличии компетентных разработчиков и доступного заказчика любая методология имеет риск привести к хорошей реализации.
T>но, по крайней мере, при подобном подходе с заказчиком хотя бы часто и регулярно общались, чего , как правило, не происходит, ни при одном айти-проекте вплоть до того момента, как показывают уже "готовый" продукт
По-моему, вы путаете DDD с Agile. Аgile как раз во главу угла ставит возможность интервьюировать "представителя заказчика" в процессе разработки. Но Agile не навязывет никакого конкретного подхода к дизайну — он может быть DDD, может быть TDD, можно рожать Anemic Object Model, можно рожать Rich Object Model.

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

Вот я и предлагаю кому-то, кто хорошо разобрался в DDD, провести мастеркласс на маленьком изолированном примере. Вот он я — "представитель заказчика". Могу приходить в этот тред несколько раз в неделю, отвечать на вопросы.
Первичное интервью было уже проведено (упомянутые мной объекты предметной области описаны в документах, датированных 2016 годом).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: DDD для небольших проектов.
От: takTak  
Дата: 11.02.20 06:57
Оценка:
T>>хорошо, вот давай на пальцах... что дешевле: потратить несколько месяцев на имплементацию рест-архитектуры, чтобы по прошествии нескольких месяцев понять, что ни одного клиента внутренняя архитектура приложений не интересует?! или всё таки лучше формализованно провести несколько дней с клиентом, понять, какие события на уровне бизнес-логики происходят, поделить эти события на кластеры независимых друг от друга событий, слабо или сильно связанных событий, разделив тем самым приложение на несколько независимых предметных сфер, и начать в соответствии с этими проектировать отдельные предметные сферы, пользуясь языком заказчика для отражения той модели, которая у заказчика в голове?!
S>Если на пальцах, то мы говорим об ортогональных вещах. DDD — это дизайн; REST — это реализация.
T>>ведь ясно же, что для совсем рудиментарных вещей подобным не занимаются...
S>Давайте сначала попробуем применить DDD для рудиментарной вещи. Если он даже для неё не подходит, то как мы будем применять его к реальным задачам?

T>>и понятно, что успеха ни одна методология сама по себе не гарантирует: при ддд , в частности, в команде несколько дней в неделю проводит и кто-то, кто представляет заказчика: именно к нему приходят, когда хотят понять, как же всё-таки правильно, и если этот человек- не тоРт, то успех будет больше зависеть от тех программистов , кто даже из него сможет вюдить ту информацию, которая критически важна, но если и со стороны исполнителей таких людей не найдётся, то успеха не будет

S>Вот вы сейчас, простите, очень похожи на продавца snake oil. При наличии компетентных разработчиков и доступного заказчика любая методология имеет риск привести к хорошей реализации.
T>>но, по крайней мере, при подобном подходе с заказчиком хотя бы часто и регулярно общались, чего , как правило, не происходит, ни при одном айти-проекте вплоть до того момента, как показывают уже "готовый" продукт
S>По-моему, вы путаете DDD с Agile. Аgile как раз во главу угла ставит возможность интервьюировать "представителя заказчика" в процессе разработки. Но Agile не навязывет никакого конкретного подхода к дизайну — он может быть DDD, может быть TDD, можно рожать Anemic Object Model, можно рожать Rich Object Model.

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


S>Вот я и предлагаю кому-то, кто хорошо разобрался в DDD, провести мастеркласс на маленьком изолированном примере. Вот он я — "представитель заказчика". Могу приходить в этот тред несколько раз в неделю, отвечать на вопросы.

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

DDD ни к каким технологиям или реализациям не привязан, хотя его часто используют с CQRS & messaging queuing

не вижу никакого противоречия между DDD vs Agile, никто не запрещает использовать это вместе: просто это намного удобнее, когда всегда где-то недалеко есть человек, у кого можно спросить, как же оно нужно, а не ждать целого месяца непонятно чего

да, интересно, как это без формализованного опроса заказчика и без постоянного общения должно возникнуть общее понимание предметной области...
Re[13]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.20 07:22
Оценка: +1
Здравствуйте, takTak, Вы писали:
T>не вижу никакого противоречия между DDD vs Agile, никто не запрещает использовать это вместе: просто это намного удобнее, когда всегда где-то недалеко есть человек, у кого можно спросить, как же оно нужно, а не ждать целого месяца непонятно чего
Это не противоречие — просто вы почему-то подменяете одно другим.
T>да, интересно, как это без формализованного опроса заказчика и без постоянного общения должно возникнуть общее понимание предметной области...
Зачем вы уводите дискуссию в сторону?
На конкретный вопрос "как применить DDD к маленькой модельной задаче" вы сначала предлагаете потратить 3 часа на просмотр видео; потом пишете, что DDD сам по себе ничему не помогает; потом, что DDD требует постоянного присутствия представителя заказчика на месте разработки, и при этом он ещё и должен корректировать архитектурные ошибки, сделанные командой.

Изо всего этого решительно непонятна ни суть подхода DDD, ни его отличия от других подходов к дизайну, ни преимущества. Хотелось бы какой-то конкретики, а не вот этой воды.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: DDD для небольших проектов.
От: takTak  
Дата: 11.02.20 07:35
Оценка:
T>>не вижу никакого противоречия между DDD vs Agile, никто не запрещает использовать это вместе: просто это намного удобнее, когда всегда где-то недалеко есть человек, у кого можно спросить, как же оно нужно, а не ждать целого месяца непонятно чего
S>Это не противоречие — просто вы почему-то подменяете одно другим.
T>>да, интересно, как это без формализованного опроса заказчика и без постоянного общения должно возникнуть общее понимание предметной области...
S>Зачем вы уводите дискуссию в сторону?
S>На конкретный вопрос "как применить DDD к маленькой модельной задаче" вы сначала предлагаете потратить 3 часа на просмотр видео; потом пишете, что DDD сам по себе ничему не помогает; потом, что DDD требует постоянного присутствия представителя заказчика на месте разработки, и при этом он ещё и должен корректировать архитектурные ошибки, сделанные командой.

S>Изо всего этого решительно непонятна ни суть подхода DDD, ни его отличия от других подходов к дизайну, ни преимущества. Хотелось бы какой-то конкретики, а не вот этой воды.


я просто не вижу какой-то иной возможности понять то, что нужно абстрактному заказчику, без постоянного общения с ним...

какая ещё конкретика? я же вроде описывал: вначале требования заказчика систематизируются и дробятся на несколько несвязанных или связанных между собой предметных областей, это типа стратегическое решение, и если это — правильное разделение, то это и залог успеха,

потом уже тактика: внутри предметной области определяются aggregates, они отвечают за всё : валидацию, обработку событий и т.д.

предметные области напрямую между собой не связаны

что этим достигается: loose coupling and high cohesion, причём в рамках логики заказчика, а не какого-то программиста васи, который сам себе что-то придумал, если приходит требование заказчика: а вот прикрутите плюшку Х к сфере системы скидок, то программист вася смотрит: где же предметная сфера скидок и там добавляет то, что нужно, не ломая ни сферу заказов ни маркетинговый модуль
Re[15]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.20 07:58
Оценка:
Здравствуйте, takTak, Вы писали:

T>я просто не вижу какой-то иной возможности понять то, что нужно абстрактному заказчику, без постоянного общения с ним...

Что вам мешает понять, что нужно абстрактному заказчику, проведя однократный (пусть и длинный) сеанс общения с ним в начале проекта?

T>какая ещё конкретика? я же вроде описывал: вначале требования заказчика систематизируются и дробятся на несколько несвязанных или связанных между собой предметных областей, это типа стратегическое решение, и если это — правильное разделение, то это и залог успеха.

Давайте вернёмся на 12 уровней выше. Смотрите, вот на что вы отвечаете: https://rsdn.org/forum/design/7654465.1
Автор: Sinclair
Дата: 10.02.20

Тут уже описана предметная область.
T>потом уже тактика: внутри предметной области определяются aggregates, они отвечают за всё : валидацию, обработку событий и т.д.
Ну, вы можете определить aggregates внутри предметной области, которую я описал в сообщении https://rsdn.org/forum/design/7654465.1
Автор: Sinclair
Дата: 10.02.20
?
T>что этим достигается: loose coupling and high cohesion, причём в рамках логики заказчика, а не какого-то программиста васи, который сам себе что-то придумал, если приходит требование заказчика: а вот прикрутите плюшку Х к сфере системы скидок, то программист вася смотрит: где же предметная сфера скидок и там добавляет то, что нужно, не ломая ни сферу заказов ни маркетинговый модуль
Давайте сначала применим эти принципы высокой морали к конкретной простой задаче, а потом уже посмотрим, что ими достигается. Потому что в абстрактных рассуждениях-то у всех loose coupling, high cogesion, и прочие maximizing the stakeholders value. Без конкретных приёмов и решений это просто bullshit.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: DDD для небольших проектов.
От: takTak  
Дата: 11.02.20 09:03
Оценка: 5 (1)
S>Давайте сначала применим эти принципы высокой морали к конкретной простой задаче, а потом уже посмотрим, что ими достигается. Потому что в абстрактных рассуждениях-то у всех loose coupling, high cogesion, и прочие maximizing the stakeholders value. Без конкретных приёмов и решений это просто bullshit.

ну а немного погуглить-то тоже времени нет?
вот: https://hackernoon.com/making-a-case-for-domain-modeling-17cf47030732
https://softwareengineering.stackexchange.com/questions/129305/should-i-put-calculation-logic-in-an-entity-or-in-the-business-layer/129307

в приведённом примере я увидел , по крайней мере, 3 аггрегата: товары, скидки, ценоборазование, ну или можно сделать два: товары + скидки/цены
Re[17]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.02.20 04:48
Оценка:
Здравствуйте, takTak, Вы писали:
T>ну а немного погуглить-то тоже времени нет?

T>вот: https://hackernoon.com/making-a-case-for-domain-modeling-17cf47030732

T>https://softwareengineering.stackexchange.com/questions/129305/should-i-put-calculation-logic-in-an-entity-or-in-the-business-layer/129307
Ну, вот это как раз примеры из области "обнять и плакать". Вторая статья ни о чём — там нет конкретики.
А в первой видно, как малейшее изменение бизнес-правил приводит к неконтролируемому расползанию изменений в коде. Например: лимит овердрафта зависит от "типа" счёта (обычный/премиум). Ну, то есть исходный пример там нифига не anemic, т.к. логика определения политики овердрафта вшита внутрь класса "счёт". В анемике такого быть не должно — в худшем случае у ентити "account" будет атрибут overdraftLimit (вы заметили, что в исходном примере переменная limit берётся ниоткуда?). В более прямом — будет отдельный метод getOverdraftLimit(accountId) в интерфейсe MoneyTransferService, который уже можно перегружать в зависимости от наших потребностей.
Так вот, в "DDD" варианте у автора политика овердрафта является полем счёта. С одной стороны, это хорошо — мы можем иметь несколько вариантов политики овердрафта на всю систему, и все счета будут ссылаться на один из вариантов. И мы можем одной транзакцией увеличить или уменьшить значения лимитов для целой группы счетов.
С другой стороны, у нас единственный способ отличить дебитовый счёт от кредитного — это поднять в память счёт, и его policy.
Политика овердрафта пришивается к счёту при его создании, и потом её изменение потребует update в базу.
Попробуйте реализовать в этом сервисе правило типа "лимит овердрафта по кредитному счёту клиента определяется статусом клиента".
Ой. Надо делать mass update в таблицу счетов.
Попробуйте реализовать в этом сервисе правило типа "лимит овердрафта по кредитному счёту клиента равен половине суммы балансов всех его счетов".
Ой, теперь вообще всё посыпалось — policy надо конструировать на лету, причём непонятно как. Ей придётся бегать в MoneyTransactionService, чтобы запросить все счета клиента — имеем кольцевую зависимость.
При этом ломать существующую систему нельзя — наверняка для каких-то клиентов (или отдельных счетов) у нас будут сохранены фиксированные лимиты.

В анемике все изменения, касающиеся политики овердрафта, спрятаны в метод getOverdraftLimit(). У него может быть расширен список параметров — например, мы будем передавать туда accountId, customerId, managerId.
И в первой реализации у нас будет простая логика, которая возвращает значение атрибута Account.overdraftLimit. Во второй — комплексная логика с запросом баланса клиента из базы.
В третьей — у нас будет что-то вроде:
IEnumerable<IOverdraftRule> overdraftRules = from accRule in AccountOverdraftRules where accRule.Match(accountId) select accRule;
overdraftRules = overdraftRules.Concat(from custRule in CustomerOverdraftRules where custRule.Match(customerId) select custRule);
overdraftRules = overdraftRules.Concat(from mgrRule in ManagerOverdraftOverrideRules where mgrRule.Match(managerId) select mgrRule);
return overdraftRules.OrderBy(r=>r.Priority).FirstOrDefault().Limit()

И всё это — не трогая иерархию entities и другие сервисы. В DDD придётся править и entities, и сервисы, и служебные классы. Нуинахрена? Не говоря уже о том, что производительность окончательного решения будет гарантированно хреновой.
T>в приведённом примере я увидел , по крайней мере, 3 аггрегата: товары, скидки, ценоборазование, ну или можно сделать два: товары + скидки/цены
Отлично. Давайте двигаться дальше: какие будут методы у этих агрегатов?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[18]: DDD для небольших проектов.
От: takTak  
Дата: 12.02.20 06:39
Оценка:
ты сделал замечательный обзор двух моих первых ссылок из гугла, но давай, пожалуйста,

во-первых, вначале вернёмся на один шаг назад:
этот пример с товарами и скидками полностью условный или это тот случай, где кто-то уже что-то сделал, но заказчик остался недоволен? если это — второй случай, то что именно не понравилось ?

во-вторых, касательно самого примера предлагаю обозначить мыслимые варианты моделирования одной проблемы, типа есть один сценарий: пользователь изменил скидку на товар ХХХ на ХХ процентов, после этого
1) продукт сам подсчитал себе цену, когда клиент его запросил
2) сервис подхватил продукт, клиента, вытянул скидку для него, потом он высчитал товарную группу, применил скидку для неё и т.д. и выдал цену (перед или после того, как клиент запросил цену)
3) сущность "скидка" отправила броадкастное сообщение, что она с такими-то параметрами изменилась, подписчики на это событие, а именно сервис или сущность "цена" обработала событие путём дополнительного изменения к уже имеющимся куммулятивным изменениям и установила конечную цену (перед или после того, как клиент запросил цену)
я что-то ещё забыл?
Re[19]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.02.20 08:26
Оценка:
Здравствуйте, takTak, Вы писали:

T>ты сделал замечательный обзор двух моих первых ссылок из гугла, но давай, пожалуйста,


T>во-первых, вначале вернёмся на один шаг назад:

T>этот пример с товарами и скидками полностью условный или это тот случай, где кто-то уже что-то сделал, но заказчик остался недоволен? если это — второй случай, то что именно не понравилось ?
Этот пример полностью реальный. И да, кто-то что-то уже сделал. Не понравилось то, что
1. Пользоваться реальным продуктом оказалось неудобно
2. Внесение изменений выходит шибко дорого. Добавить поддержку сценария "задать наценку на группу продуктов, независимую от продавца" оказывается технически сложно.

T>во-вторых, касательно самого примера предлагаю обозначить мыслимые варианты моделирования одной проблемы, типа есть один сценарий: пользователь изменил скидку на товар ХХХ на ХХ процентов, после этого

T>1) продукт сам подсчитал себе цену, когда клиент его запросил
T>2) сервис подхватил продукт, клиента, вытянул скидку для него, потом он высчитал товарную группу, применил скидку для неё и т.д. и выдал цену (перед или после того, как клиент запросил цену)
T>3) сущность "скидка" отправила броадкастное сообщение, что она с такими-то параметрами изменилась, подписчики на это событие, а именно сервис или сущность "цена" обработала событие путём дополнительного изменения к уже имеющимся куммулятивным изменениям и установила конечную цену (перед или после того, как клиент запросил цену)
T>я что-то ещё забыл?
1. Для начала хочется понять, что такое "пользователь изменил скидку на товар XXX" — это мы говорим в рамках требования №5 "иногда мы можем захотеть сделать скидку на конкретный заказ", или в рамках какого-то другого требования?
2. Не очень понятно, что такое "сущность скидка". Какие примерно будут атрибуты у этой сущности, чтобы я мог её сопоставить с доменной моделью?
3. Не очень понятно, что такое сущность "цена". Цена является частью конкретной позиции конкретного заказа. До заказа её не существует, после оформления заказа изменять её нельзя. Так что третий вариант я вообще не понимаю.

Перед тем, как выбирать между всеми мыслимыми вариантами моделирования, хотелось всё же понять структуру доменной модели. Описание в терминологии заказчика я уже изложил — в их мире существует 6 существительных (товар, группа, продавец, позиция прайс-листа, позиция заказа, заказ). Существует 5 "сценариев", или "требований", которые не выражены в терминах отдельных сущностей доменной модели, а сформулированы в рамках задачи "рассчитать отпускную цену для позиции заказа".
Нам нужно, в первую очередь, спроектировать информационную архитектуру — если нужны какие-то сущности, отсутствующие в оригинальной доменной модели (описанной непрофессионалом в IT), то их надо добавить.
Затем нужно добавить сценарии, которых не хватает для полного решения — очевидно, помимо сценария "рассчитать стоимость заказа" должны быть ещё какие-то сценарии, которые заказчик самостоятельно не формулирует.
Ну, и потом можно перейти уже к моделированию архитектуры — то ли это будет сервис, то ли набор агрегатов, то ли у нас где-то будет Command Log и Query, то ли ещё что.
Как решать задачу в терминах анемик архитектуры мне понятно от и до. Она же влияет (косвенным образом) на информационную архитектуру, и на UI сценарии, в которых мы эту архитектуру выставляем.

А в рамках данной дискуссии мне интересно, к какому решению мы придём через DDD.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: DDD для небольших проектов.
От: takTak  
Дата: 12.02.20 09:23
Оценка:
у меня почему-то осталось в памяти, что основная проблема была со скидками, прочём все события были перечислены именно в том ключе, что типа сделали скидку на товарную группу, сделали скидку на товар, сделали скидку в зависимости от клиента или продавца, поэтому для меня это и было сигналом того, что надо создавать отдельный аггрегат "скидка", со сущностью же "скидка" внутри,

сценарий я выбрал для начала самый простой, варианты моделирования получились из твоего следующего ответа на мои две ссылки из гугла, причём я просто попытался очертить варианты в том ключе, то
1) есть rich domain model, где каждый объект сам решает все проблемы
вот тут тоже на эту тему, вроде: https://www.baeldung.com/ddd-double-dispatch
2) имеет место быть transaction script + anemic model, где какой-то сервис всё делает за всех
в применении к ддд, когда его не поняли, проскакивает и такое, как domain service
3) никакого центрального места, где всё за всех высчитывается, нет, каждая сущность делает только то, что ей по чину и рангу положено и не тянет на себя одеяло, как это имеет место быть при варианте 1)

ну ок, с заказом будет немного по-другому, я напишу чего-нибудь потом ... и ещё : т.е. скидка и цена сама по себе не существует до того, как оформляется заказ? если взять какой-нибудуь амазон, то пользователь после логина видит цену уже со скидкой, в вашей системе это не так?

кстати, вот тут есть какое-то похожее описание на твой случай:
https://www.researchgate.net/publication/221321492_Agile_enterprise_software_development_using_domain-driven_design_and_test_first
Re[21]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.02.20 10:35
Оценка:
Здравствуйте, takTak, Вы писали:

T>у меня почему-то осталось в памяти, что основная проблема была со скидками, прочём все события были перечислены именно в том ключе, что типа сделали скидку на товарную группу, сделали скидку на товар, сделали скидку в зависимости от клиента или продавца, поэтому для меня это и было сигналом того, что надо создавать отдельный аггрегат "скидка", со сущностью же "скидка" внутри,

Зачем память, если все ходы записаны
Автор: Sinclair
Дата: 10.02.20
.
В задаче фигурируют не скидки, а наценки.
То есть отпускная цена позиции формируется по формуле Cost*(1+Markup).
Скидка, как таковая, появляется только в конце — это если менеджер оформляет заказ для продавца (реселлера), и ему "не нравится" окончательная цена, рассчитанная по правилам, то он хочет её корректировать.
Основное отличие от скидок — наценка бывает только одна на каждую позицию. Нам не нужно комбинировать наценки друг с другом.
Если дефолтная наценка — 4%, а для данного продавца — 5%, то в результате цена будет равна Cost*(105%), а не Cost*1.05*1.04.

T>сценарий я выбрал для начала самый простой, варианты моделирования получились из твоего следующего ответа на мои две ссылки из гугла, причём я просто попытался очертить варианты в том ключе, то

T>1) есть rich domain model, где каждый объект сам решает все проблемы
T> вот тут тоже на эту тему, вроде: https://www.baeldung.com/ddd-double-dispatch
T>2) имеет место быть transaction script + anemic model, где какой-то сервис всё делает за всех
T> в применении к ддд, когда его не поняли, проскакивает и такое, как domain service
Я правильно понимаю, что https://hackernoon.com/making-a-case-for-domain-modeling-17cf47030732 это как раз "ддд, когда его не поняли"? Там же в DDD фигурирует domain service.
T>3) никакого центрального места, где всё за всех высчитывается, нет, каждая сущность делает только то, что ей по чину и рангу положено и не тянет на себя одеяло, как это имеет место быть при варианте 1)

T>ну ок, с заказом будет немного по-другому, я напишу чего-нибудь потом ... и ещё : т.е. скидка и цена сама по себе не существует до того, как оформляется заказ? если взять какой-нибудуь амазон, то пользователь после логина видит цену уже со скидкой, в вашей системе это не так?

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

По простому: есть каталог на 10000 наименований; есть 10000 покупателей. Потенциально мы говорим о 10^8 возможных ценах, которые могут появиться в заказе.
Но у нас нет никаких ста миллионов "сущностей цена", которые могли бы подписаться на оповещения вроде "изменилась скидка для пользоватееля xxx" или "изменилась себестоимость для товара yyy" и отреагировать на них.
Такая штука была бы нужна в случае наличия материализованного "прайс листа" со 10000 колонок — по одной на пользователя.

T>кстати, вот тут есть какое-то похожее описание на твой случай:

T>https://www.researchgate.net/publication/221321492_Agile_enterprise_software_development_using_domain-driven_design_and_test_first
Ну да, похоже. Правда, там объём проекта в сотни раз больше. Но что-то похожее есть.
Я так до конца и не понял, как работает их система. Как связаны PricingConcept c PriceFormulaElement неясно. Кто там на ком стоял, кто из них entity, а кто сервис — хз. Понятно, вроде бы, что у них там есть агрегат типа Deal, который сам себе цену вычисляет. Непонятно, применимо ли это в нашем случае — слишком много кода вырезано, а то, что осталось, не является валидным.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: DDD для небольших проектов.
От: Буравчик Россия  
Дата: 12.02.20 11:51
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вот мне интересно, какие объекты будут появляться в DDD, и как они будут работать. Будет ли rich object model, или анемика?


А в анемике как будет?

P.S. Мне просто интересно сравнить, как бы я спроектировал
Best regards, Буравчик
Re[2]: DDD для небольших проектов.
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 12.02.20 12:46
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Sharov, Вы писали:


S>>нормально будет? Или он только хорош, когда у нас есть n (например, n=100) сущностей?

S>Я вообще хотел бы посмотреть на применение DDD к какому-нибудь небольшому и понятному проекту. Всё, что я видел из практики до сих пор — это кровавые слёзы, убедительно доказывающие "так делать не надо".
S>Вот, прямо сейчас пилю информационную архитектуру для простенькой системы онлайн-заказов. Вроде бы почти всё уже в голове сложилось, но мучают сомнения:
S>1. А правильно ли я всё придумал
S>2. Как к этому правильному прийти через DDD

S>Вкратце: в домене (по описаниям отдела продаж) есть

S>- товары
S>- группы товаров (товар входит в 1, 2 или 3 группы)
S>- реселлеры (продавцы)
S>- позиции прайслиста. Каждая позиция сопоставляет "базовую цену" одному товару.
S>- заказы. Заказ — как обычно: продавец, покупатель, 1..N позиций: (товар, количество, отпускная цена).

...
  Смотришь на это и берет тоска


-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[22]: DDD для небольших проектов.
От: takTak  
Дата: 12.02.20 19:14
Оценка:
T>>2) имеет место быть transaction script + anemic model, где какой-то сервис всё делает за всех
T>> в применении к ддд, когда его не поняли, проскакивает и такое, как domain service
S>Я правильно понимаю, что https://hackernoon.com/making-a-case-for-domain-modeling-17cf47030732 это как раз "ддд, когда его не поняли"? Там же в DDD фигурирует domain service.

просто всегда велик соблазн сделать по привычке, поэтому народ вместо того, чтобы делать rich domain model по-кошерному, пишет процедуру, которая всё за всех делает, называя её, однако, domain service

ок, обратно к нашим баранам,
получается, что для калькуляции цен на лету нужна совокупная информация: товарная группа, сам товар (если наценка -скидка только на него), покупатель (с каким-то статусом или без оного), продавец, вот вроде и всё,

получается, что наш "заказ" содержит в себе проекции этих перечисленных сущностей с необходимыми нам атрибутами,
теперь по поводу реализации: мне лично нравится идея с формулировкой правил подсчёта цены в виде fluent api, что то типа такого https://github.com/NRules/NRules/wiki/Getting-Started, https://stackoverflow.com/questions/42529694/how-to-implement-specification-pattern
т.е. "заказ" после инициализации может отсканировать имеющиеся в системе спецификации и применить к себе подходящие, на выходе получаем цену, как такая идея?

да, динамики нет, если вдруг нужно формулировать новое правило для надценки, то придётся ручками писать новую спецификацию,

я не совсем понял роль того, кто может применить к заказу произвольную скидку, это тоже надо как-то учитывать, но по идее, будет какое-то пользовательское действие\событие, на него надо будет реагировать
Re[23]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.02.20 03:55
Оценка:
Здравствуйте, takTak, Вы писали:


T>ок, обратно к нашим баранам,

T>получается, что для калькуляции цен на лету нужна совокупная информация: товарная группа, сам товар (если наценка -скидка только на него), покупатель (с каким-то статусом или без оного), продавец, вот вроде и всё,
Ну, вроде бы да.

T>получается, что наш "заказ" содержит в себе проекции этих перечисленных сущностей с необходимыми нам атрибутами,

T>теперь по поводу реализации: мне лично нравится идея с формулировкой правил подсчёта цены в виде fluent api, что то типа такого https://github.com/NRules/NRules/wiki/Getting-Started, https://stackoverflow.com/questions/42529694/how-to-implement-specification-pattern
T>т.е. "заказ" после инициализации может отсканировать имеющиеся в системе спецификации и применить к себе подходящие, на выходе получаем цену, как такая идея?
В целом неплохо. Но интересны детали. Пример этого fluent api крайне далёк от моего понимания — либо там очень хитрая инверсная семантика, либо он нежизнеспособен.
Типа запустили правило, оно там что-то просканировало, что-то изменило, кого-то оповестило. Кастомер давно свой заказ оплатил и получил — зачем ему эта нотификация?
Наверное, там просто пример и описание решительно невнятное. Потому что сходу неясно, почему нельзя было просто написать всё то же самое на linq2objects и не изобретать горы велосипедов.
var ordersToDiscount = from c in Customers 
  from o in Orders
  where c.IsPreferred && o.Customer = c && o.IsOpen() && !o.IsDiscounted()
  select o;

  ordersToDiscount.Set(o=>o.PercentDiscount, 10.0);

Если я правильно понял, то у нас будет какой-то метод у класса Order, который наш агрегат. Можете набросать примерную сигнатуру и устройство этого метода?


T>да, динамики нет, если вдруг нужно формулировать новое правило для надценки, то придётся ручками писать новую спецификацию

Ну, совсем без ручной работы не получится — вопрос в изоляции изменений.

T>я не совсем понял роль того, кто может применить к заказу произвольную скидку, это тоже надо как-то учитывать, но по идее, будет какое-то пользовательское действие\событие, на него надо будет реагировать


Вот то-то и оно, что DDD провоцирует думать в неверном направлении. Какие события? Какие действия?
"Действий" у нас, по большому счёту, два с половиной:
1. Рассчитать предполагаемую отпускную цену для каждой позиции. (Показываем проект заказа в UI)
2. Сохранить заказ с заданными отпускными ценами
И ещё пол-сценария: если пользователь имеет уровень менеджера, то мы предлагаем ему возможность скорректировать цены между п.1 и п.2 вручную. Всё.

Никаких "событий", никаких "циклов в поисках кастомеров". Все эти циклы и прочие fluent прекрасны тогда, когда у нас есть система уравнений, и мы её решаем в удобном для нас порядке. В реальной системе основные события порождаются пользователями, ну и плюс асинхронными системами. Вот эта вот идея про "запихать в доменную модель всех покупателей и их заказы и запустить все правила" — как она бы реализовалась, скажем, у Амазона?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[24]: DDD для небольших проектов.
От: takTak  
Дата: 13.02.20 06:49
Оценка:
этот "заказ" в приведённом разрезе, наверное, должен обладать методами "подсчитай цену" и "сохрани", сигнатура void, без аргументов, так как вроде всё, что нам надо для подсчётов, уже в агрегате есть, другой метод "скорректируй цену", реагирует на событие "менеджер изменил цену", аргументы тут те, которые нужны: цена или процент(непонятно что он набивает), может, userId- если это как-то протоколируется

внутри "подсчитай цену" будет либо отсылка к какой-то rule engine, либо, как у тебя в примере, какой-то собственный алгоритм калькуляции, вызываться этот метод будет после событий "покупатель добавил товарную позицию" или "покупатель изменил количество"

идея с fluent api мне нравится тем, что эти спецификации можно легко прилепить к имеющемся в цепочку; ты же в примере привёл лишь использование только одной, как ты будешь формулировать, если у тебя 3, 5, 7 формул подсчёта надценки? с if else? кроме того, сама реализация должна быть где-то в репозитарии или ты будешь DbContext тащить прямо в агрегат?

у амазона это раньше было сделано так, что для товаров, цен были свои отдельные предметные области, продукт тащился своим микросервисом, цена- своим микросервисом, композиция происходила на уровне UI (composite ui), т.е. могло теоретически быть и так, что , например, продукт сразу прогрузился, а цена- чуть позднее, ну или наоборот
Отредактировано 13.02.2020 6:51 takTak . Предыдущая версия .
Re[25]: DDD для небольших проектов.
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.02.20 07:03
Оценка:
Здравствуйте, takTak, Вы писали:

T>этот "заказ" в приведённом разрезе, наверное, должен обладать методами "подсчитай цену" и "сохрани", сигнатура void, без аргументов, так как вроде всё, что нам надо для подсчётов, уже в агрегате есть, другой метод "скорректируй цену", реагирует на событие "менеджер изменил цену", аргументы тут те, которые нужны: цена или процент(непонятно что он набивает), может, userId- если это как-то протоколируется

Спасибо.
Пока что всё плохо.
1. У нас в классе "заказ" есть уже две обязанности — "сохрани" и "подсчитай цену". Уже плохо. То есть тащим как бизнес-логику, так и DbContext.
2. Опять непонятно, что за событие такое "менеджер изменил цену", и почему есть какой-то отдельный метод "скорректируй цену". Для чего это нужно?
3. Непонятно, как работает этот агрегат с позициями заказа.

T>внутри "подсчитай цену" будет либо отсылка к какой-то rule engine, либо, как у тебя в примере, какой-то собственный алгоритм калькуляции, вызываться этот метод будет после событий "покупатель добавил товарную позицию" или "покупатель изменил количество"

Тут, по-видимому, неявно предполагается, что заказ у нас существует в состоянии "проект", когда его можно менять, и в состоянии "отправлен", когда фиксируются количества и цены.
По мне так это плохая идея. Потому, что пересчитывать цены надо не только тогда, когда пользователь что-то добавил или изменил в заказе, но и при изменении списка правил. Кто какие события будет порождать, и кто на какие события будет подписываться? Мне проще вообще не иметь заказов в "предварительном" состоянии.
Тем не менее — давайте всё же посмотрим на тело "подсчитай цену" в агрегате "заказ". Все необходимые требования в топике приведены.

T>идея с fluent api мне нравится тем, что эти спецификации можно легко прилепить к имеющемся в цепочку; ты же в примере привёл лишь использование только одной, как ты будешь формулировать, если у тебя 3, 5, 7 формул подсчёта надценки? с if else? кроме того, сама реализация должна быть где-то в репозитарии или ты будешь DbContext тащить прямо в агрегат?

Я вообще против агрегатов и rich модели — она даже на hello-world примерах сосёт как пылесос.
Прелесть анемиков как раз в том, что нет мучений вроде обратных зависимостей агрегатов от DbContext. Все entity — POCO, все сервисы — stateless.

T>у амазона это раньше было сделано так, что для товаров, цен были свои отдельные предметные области, продукт тащился своим микросервисом, цена- своим микросервисом, композиция происходила на уровне UI (composite ui), т.е. могло теоретически быть и так, что , например, продукт сразу прогрузился, а цена- чуть позднее, ну или наоборот

Я вам к тому, что "цена" в Амазоне — сущность эфемерная. Изменение тарифа где-то в одном углу системы не вызывает каскад миллиардов событий "скорректировать цену", как в Excel.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[26]: DDD для небольших проектов.
От: takTak  
Дата: 13.02.20 08:06
Оценка:
T>>этот "заказ" в приведённом разрезе, наверное, должен обладать методами "подсчитай цену" и "сохрани", сигнатура void, без аргументов, так как вроде всё, что нам надо для подсчётов, уже в агрегате есть, другой метод "скорректируй цену", реагирует на событие "менеджер изменил цену", аргументы тут те, которые нужны: цена или процент(непонятно что он набивает), может, userId- если это как-то протоколируется
S>Спасибо.
S>Пока что всё плохо.
S>1. У нас в классе "заказ" есть уже две обязанности — "сохрани" и "подсчитай цену". Уже плохо. То есть тащим как бизнес-логику, так и DbContext.
S>2. Опять непонятно, что за событие такое "менеджер изменил цену", и почему есть какой-то отдельный метод "скорректируй цену". Для чего это нужно?
S>3. Непонятно, как работает этот агрегат с позициями заказа.

пока я ещё вроде ничего про реализацию"сохрани" не говорил: мы что используем: как ты когда-то намекал на Log / Query, т.е. Write & ReadModel, как понимаю, или обычную персистенцию в базу данных ? внутренне будет установлен флажок, что ни изменение цены (в том числе и менеджером), ни добавление или удаление позиций недопустимо, в принципе, может, стоит метод переименовать в "оформить заказ"

ты сам вроде упомянул, что если пользователь- менеджер, то он может изменить цену или я что-то не так понял?

этот агрегат может реагировать на события "добавили позицию" , "удалили позицию", ну или ,можно, наверное, эти методы добавить к агрегату напрямую

T>>внутри "подсчитай цену" будет либо отсылка к какой-то rule engine, либо, как у тебя в примере, какой-то собственный алгоритм калькуляции, вызываться этот метод будет после событий "покупатель добавил товарную позицию" или "покупатель изменил количество"

S>Тут, по-видимому, неявно предполагается, что заказ у нас существует в состоянии "проект", когда его можно менять, и в состоянии "отправлен", когда фиксируются количества и цены.
S>По мне так это плохая идея. Потому, что пересчитывать цены надо не только тогда, когда пользователь что-то добавил или изменил в заказе, но и при изменении списка правил. Кто какие события будет порождать, и кто на какие события будет подписываться? Мне проще вообще не иметь заказов в "предварительном" состоянии.

т.е. цена может быть изменена задним числом? чего-то я этого не понимаю, это как?

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

я исхожу из того, что агрегат обладает внутренним состоянием, которое позволяет ему рассчитать цену, не обращаясь самому к базе данных, т.е. при инициализации и изменении состояния он получает всё необходимую для расчётов информацию

T>>идея с fluent api мне нравится тем, что эти спецификации можно легко прилепить к имеющемся в цепочку; ты же в примере привёл лишь использование только одной, как ты будешь формулировать, если у тебя 3, 5, 7 формул подсчёта надценки? с if else? кроме того, сама реализация должна быть где-то в репозитарии или ты будешь DbContext тащить прямо в агрегат?

S>Я вообще против агрегатов и rich модели — она даже на hello-world примерах сосёт как пылесос.
S>Прелесть анемиков как раз в том, что нет мучений вроде обратных зависимостей агрегатов от DbContext. Все entity — POCO, все сервисы — stateless.

если мы ограничим агрегат только тем, что ему нужно: внутренним состоянием, никакого DbContext ему не нужно

T>>у амазона это раньше было сделано так, что для товаров, цен были свои отдельные предметные области, продукт тащился своим микросервисом, цена- своим микросервисом, композиция происходила на уровне UI (composite ui), т.е. могло теоретически быть и так, что , например, продукт сразу прогрузился, а цена- чуть позднее, ну или наоборот

S>Я вам к тому, что "цена" в Амазоне — сущность эфемерная. Изменение тарифа где-то в одном углу системы не вызывает каскад миллиардов событий "скорректировать цену", как в Excel.

это я тоже не понял, что значит: "не вызывает каскадных изменений" ? если сегодня скидка на трусы на 20 %, а завтра — на всё бытовую технику, а послезавтра — на пылесосы фирмы ххх, то что значит: " без каскадных изменений"
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.