Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
S>>>Для разработчика из видео выше это будет не так -- у него ДДД имеет доказанную пользу. Короче, это субъективщина. G>>Мне кажется ты не понимаешь суть слова "доказанную"...
S>Доказанную в кавычках, согласен. Типа работает. Применил ДДД -- получилось.
насколько я знаю примерно также доказывают "эффективность" гомеопатии.
S>>>Это можно решить в самый последний момент, согласно ДДД. Это детали. G>>Так вот мы пришли к этому моменту. Это одна таблица или нет? S>Ну какая разница-то для данного обсуждения?
Я бы сказал решающая, потому что ответ на этот вопрос это тот самый процесс проектирования, который я предлагаю пройти до конца чтобы проверить что DDD в принципе имеет смысл как методология.
S>>>На мой взгляд, скорее это методология, а не набор готовых рецептов. По-отдельности применять можно, но сложно. Точнее уже разбили на стратегически и тактические паттерны. G>>Пробелма в том, что без "тактических паттернов" методология DDD настолько очевидна, что смысла нет в отдельном названии. G>>Она сводится к трем вещам: G>>1) Универсальный язык для общения с заказчиком. По сути это раздел "термины и определения" из ТЗ по любому стандарту G>>2) Разделение проблемы на области — то что везде называние "модулями" (термин из структурного программирования) или "подсистемами" (термин из системной инженерии). В книге вернона и последующих даже упоминается иерархния (вложенность) областей, также как модули и подсистемы могут иметь вложенность. G>>3) Ограниченные контексты — единицы разработки и\или единицы деплоя. G>>Еще недавно появился EventStorming — по сути обычные брейнштормы, если отвязать их от event sourcing.
S>Да, вполне согласен. Не исключаю, что все эти моменты под одну крышуметодологию запихнули и все. Как-то так оно и есть. S>Потом решили развивать идею дальше, и появились тактические паттерны и тп.
См историю, тактические паттерны появились в начале. Все описал фаулер еще до эванса. Вся суть ДДД с самого начала — натягивание философии на паттерны. Когда модным стал CQRS — он появился в книгах DDD. Когда стали модными микросервисы — они тоже появились в книгах по DDD.
G>>Фактически ничего нового DDD не дает. Мы все это видели например в UML — диграммы компонентов это предметные области, а диаграммы развертывания, диаграммы юзкейсов, процессов и логической структуры. S>Ну тактические все-таки что-то новое, все эти agg root, transaction script, entity, values. А так да, взяли отовсюду понемногу.
Это фаулер описал, до DDD
S>>>Значит тут и репозиторий особо не нужен, обычный DAL. G>>Так это в любой программе так. S>Какой сервис в компании не беру, везде есть Repository. Это уже ~Dal по сути.
Мода — она такая, везде ропозитарии, хотя они не нужны.
S>>>Но опять же, никаких разумных сравнений произведено не было -- loc, сложность поддержки и т.п. Чисто умозрительные вывод. G>>Серьезно? Только что описал почему фактически не было никаких языков кроме ОО, которые имело смысл изучать. Это сейчас есть не(до)-ОО языки, такие как Go, Rust и Kotlin
S>Вкусовщина, типа нраится\ не нраится. Могли бы perl для веба взять. Никаких экспериментов по написанию веб приложения на пхп, а потом на C# не было же?
Книг по perl было на прядок меньше, на фоне C++\java\C# и остальных.
G>>Какой промпт? Напиши кодом то, что ты словами хочешь объяснить. G>>Всего-то надо по-ДДДному сделать проверку остатков. S>1) Каким боком это к дискуссии? S>2) Речь же шла про инвариант класса, а не ДДДшное исполнение чего-то. Инвариант класса и ДДД противоречат где-то?
Как обычно попытка решить нетривиальную задачу проектирования с помощью DDD приводит или к "это другое" или к CQRS и эвентсорсингу.
S>>>А бд не с объектами в памяти работает? G>>нет конечно, она с данными на диске работает. S>Она(бд) эти данные потом в память себе загоняет и работает с ними. Так что в памяти и работает.
Тем не менее "объектами" там не пахнет.
S>>>Ну если у нас данные лежат в бд, то естественно что их надо забрать оттуда. G>>нет конечно, проверка остатков делается без поднятия в память данных. S>Как?
Запросом на уровне базы, который писал выше. Из базы на уровень приложения ничего не попадает.
S>>>Кто-то считает, что 1 млн лок на пхп без ДДД это уже вилка. Ну вот можно от этой цифры отталкиваться. Хотя сколько людей, столько мнений. G>>Очередное мнение, которое подкреплено примерно ничем? S>Чем хуже вашего мнения?
Тем что я не пытаюсь доказать полезность и применимость DDD.
Бремя доказательство обычно возлагается на того кто утверждает, пока он не представил объективные аргументы.
S>>>Возможно. 101 раз повторю -- это вкусовщина. У разработчика из Я. по ссылке выше на этот счет может быть другое мнение. И это нормально. G>>Поэтому и не надо отсылать к мнению и чату ГПТ. Приведи просто пример, хоть свой, хоть из интернета, кода с DDD, который по твоему демонстрирует преимущества и я его перепишу без ДДД и сравним по любым формальным (не зависящим от мнения) характеристикам S>Ну ведь фигней занимаетесь, не будете переписывать огромный софт под 1млн. без ДДД. Ну к чему эта бравада? S>Какое-то детсадовское взятие на слабо. Не серьезно.
Как тогда доказать что-то про ДДД?
G>>Пока выглядит так, что ДДД хорош только потому что он кому-то нравится. G>>Меня интересует более научный подход, когда результат можно как-то измерить.
S>Я говорил, что он не плох, если кому-то не нравится. Ровно в этом моя позиция. Научный подход в ИТ вещь такая себе -- почему написали на C#, когда можно было на С++ или вообще на Си? Это бред и демагогия, не нравится, не пользуйтесь. Я вот избирательно что-то для себя в ДДД подчеркнул и мне
хорош, никакого научного подхода не надо.
Звучит как вера. Вам верить никто не мешает, но нести свою веру другим в целом противопоказано.
S>Блин, ну какой научный подход у agile, рефакторинга и solid?
Есть конечно, исследования всякие.
Насчет solid не знаю, про agile и рефакторинг находил.
Re[24]: Что если не разделять строго dto, entity, bo...
Здравствуйте, amironov79, Вы писали:
A>Здравствуйте, Sinclair, Вы писали:
G>>>Тем более есть проблема: кроме Clean Architecture и DDD в медийном поле вообще не существует других подходов. У альтернативы ДДД даже названия собственного нет, она состоит из применения принципов YAGNI, KISS, DRY, top-down подхода к проектированию и разработке, частично SOLID. S>>Эмм, частично антиподом является anemic model. Термин введён, афаир, как ругательство апологетами DDD, но вполне отражает как минимум часть подхода.
A>Anemic model антипод Rich model, и ничто не мешает ее использовать в DDD.
Точно?
Насколько я знаю основной паттернов DDD является aggregate root — сущность, которая поднимается из бд и все изменения вызываются из нее. То есть мы взываем Root.DoSmth(...), а рут в свою очередь вызывает методы дочерних объектов. Именно рут отвечает за целостность операции
За все затягивание и сохранение отвечает репозиторий (это второй по важности паттерн в DDD), а вызывающий код работает с объектами.
Все остальные паттерны, такие как команды, эвенты, domain services и value object призваны обходить ограничения такого дизайна.
A>У DDD проблема такая же как и у ООП, все про него рассказывают, но действительно понимают границы применения единицы.
ООП люди понимают и применяют, посмотри на любой UI фреймворк на ОО-языке — WPF или, прости господи, WinForms.
А еще можешь посмотреть базовые библиотеки дотнета или жабы, они тоже полны достаточно качественного ООП (со своими особенностями каждая).
Других хорошим применений ООП немного и попытка натянуть на ООП состояние приложения в основном ущербна. На эту тму у товарища Лиипперта есть потрясающая серия статей Wizards and Warriors, которую я даже перевел на хабре
A>Как раз поэтому бездумное следование принципам DDD можно противопоставить принципам YAGNI, KISS.
YAGNI и KISS — первичны, они даже DRY превосходят. Если ваше ООП не соответствует YAGNI, то у вас плохое ООП.
Здравствуйте, Sinclair, Вы писали:
A>>и ничто не мешает ее использовать в DDD S>Тут — спорно. По Фаулеру, она — антипаттерн. S>Рич модель является стандартом DDD; многие вообще считают, что без неё никакого DDD нет.
Мне наоборот казалось, что сейчас большинство склоняются к anemic.
S>Было бы неплохо показать какой-нибудь авторитетный источник, который бы объяснял, где проходят эти границы применимости. S>Как тут верно заметил коллега gangustas, за последние 16 лет не появилось ни одного убедительного примера, который бы показал преимущества DDD при полном его использовании (а не когда мы от него оставляем какой-то несущественный фрагмент).
Нет их, сам всех про такой спрашиваю Я как раз писал о частичной применимости.
Re[25]: Что если не разделять строго dto, entity, bo...
Здравствуйте, gandjustas, Вы писали:
G>Насколько я знаю основной паттернов DDD является aggregate root — сущность, которая поднимается из бд и все изменения вызываются из нее. То есть мы взываем Root.DoSmth(...), а рут в свою очередь вызывает методы дочерних объектов. Именно рут отвечает за целостность операции G>За все затягивание и сохранение отвечает репозиторий (это второй по важности паттерн в DDD), а вызывающий код работает с объектами.
Это всё детали реализации. Что мешает реализовать aggregate root как сервис и dto?
G>ООП люди понимают и применяют, посмотри на любой UI фреймворк на ОО-языке — WPF или, прости господи, WinForms. G>А еще можешь посмотреть базовые библиотеки дотнета или жабы, они тоже полны достаточно качественного ООП (со своими особенностями каждая).
А если взять корпоративные приложения, для которых DDD в первую очередь и предназначен, много там качественного ООП именно в бизнес домене?
Re[34]: Что если не разделять строго dto, entity, bo...
Здравствуйте, gandjustas, Вы писали:
S>>>>Значит тут и репозиторий особо не нужен, обычный DAL. G>>>Так это в любой программе так. S>>Какой сервис в компании не беру, везде есть Repository. Это уже ~Dal по сути. G>Мода — она такая, везде ропозитарии, хотя они не нужны.
Репозиторий как DAL конечно не нужен, здесь ORM нормально справляется. Если же репозиторий как сервис, работающий с внешними данными, и который является частью домена, то почему нет.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Sharov, Вы писали:
S>>Блин, ну он же говорит, что работал в мамбе где было 1млн loc на пхп. И там, например, анкета могла быть в 50 разных контекстах. И если бы S>>не ДДД, то по его мнению, было бы очень и очень плохо. Т.е. окупается поддерживаемостью. S>Похоже, что он словом DDD называет что-то другое, чем Эванс с Фаулером.
Кстати, думается, что не только он, а, наверное, все, кто сталкивается с DDD.
S>Потому что вот эта вот "анкета в разных контекстах" — это либо просто anemic class, позволяющий строгую типизацию таблицы (и каждый потребитель в каждом контексте тащит из неё то, что нужно лично ему), либо про класс, реализующий 50 разных интерфейсов, т.к. в каждом контексте нужно что-то своё.
Я полагаю, что про какие-нибудь Bounded context и Ubiquitous language, типа анкета всплывает в куче разных
контекстов, и чтобы это не был один огромный объект с 50 интерфейсов, а какой-нибудь Agg. Root в BC.
S>>Не знаю. Но в целом может быть, т.к. абстракций там накручивают не мало. S>Дело не в абстракциях, а в архитектуре. В анемике у "объектов" нет никакого поведения, что позволяет описывать бизнес-логику в терминах трансформаций этих объектов. Пример gangustas уже приводил. S>И вот такое описание позволяет напрямую транслировать эту логику с языка, на котором пишет программист-прикладник, в язык нижележащей платформы (например, SQL) и исполнять его прямо там. S>А в DDD поведение описано на какой-нибудь императивной Java. Поэтому мы даже примитивный p.set_LastName() не можем превратить в update person p set p.LastName = — это же чорный ящик!
Так p.set_LastName() к ДДД никакого отношения не имеет, это уже какие-то детали реализации.
S>Вместо этого мы поднимем в память JVM весь этот Person c его сотней полей, потом вызовем Чорный ящик, а потом будем при коммите лихорадочно шерстить список изменений, чтобы сгенерировать update не по исходному коду, а по наблюдаемым побочным эффектам.
Ну да, он про производительность и говорил.
S>>Вы хотели с кем-то пообщаться за 16 лет, вот пожалуйста. Это в любом сообществе так. Идите в группу дотнет и начните рассказывать S>>про преимущества ручной сборки мусора. S>Это всё нерелевантно. Плоскоземельщиков тоже великие толпы. Идти к ним проповедовать — а зачем? Вопрос как раз в том, есть ли чему научиться полезному у плоскоземельщиков.
Ну а как узнать, если не пытаться заговорить, а ходить вокруг да около?
Здравствуйте, Sinclair, Вы писали:
S>>Вашему же я должен довериться, что ДДД не нужен. А его почему-то нет. S>Не, тут работает презумпция ненужности. Каждый раз, когда вам предлагают какую-нибудь новую практику — хоть уринотерапию, хоть методику или парадигму разработки — по умолчанию ответ "обойдёмся". S>Это задача предлагающего доказать, что с ним будет лучше. S>У DDD фундаментальная проблема — многие вопросы в нём неразрешимы совсем. Другие — создают трудности, которых нет в других подходах.
Какие, например?
Кодом людям нужно помогать!
Re[30]: Что если не разделять строго dto, entity, bo...
Здравствуйте, Sinclair, Вы писали:
S>>Детали реализации -- да, скрывает. Добавьте соотв. метод в соотв. интерфейс и всех делов. S>Не получится.
Почему, как репозиторий зависит от физического хранилища?
S>>Проверка инварианта делегируются бд, а класс получает результат этой проверки. В бд можно делать еще lock, если что. S>Нет, это так не работает. Из-за этого примерно все образцы DDD либо не работают вообще, либо чудовищно неэффективны.
А при чем здесь DDD? Здесь побочный разговор на тему проверки инвариантов в случае, когда данные хранятся в бд.
Я так понимал суть вопроса.
S>>>>Вычитать соотв. поля из бд, взяв соотв. лок предварительно, посчитать и в зависимости от, продолжить работу. S>Ну, то есть то, что СУБД обеспечивала из коробки, мы превращаем в закат солнца вручную.
Речь про транзакции? Я не знаю как обеспечивать инваринат класса (домена), если все данные хранятся в бд.
Кроме как неэффективно все лочить ничего придумать не могу, а если использовать бд для этого, то это уже
не инвариант класса получается.
Кодом людям нужно помогать!
Re[34]: Что если не разделять строго dto, entity, bo...
Здравствуйте, gandjustas, Вы писали:
S>>Да, вполне согласен. Не исключаю, что все эти моменты под одну крышуметодологию запихнули и все. Как-то так оно и есть. S>>Потом решили развивать идею дальше, и появились тактические паттерны и тп. G>См историю, тактические паттерны появились в начале. Все описал фаулер еще до эванса. Вся суть ДДД с самого начала — натягивание философии на паттерны. Когда модным стал CQRS — он появился в книгах DDD. Когда стали модными микросервисы — они тоже появились в книгах по DDD.
Может быть, но ДДД очень любят применять при распилах монолита на микросервисы. Работал в таком проекте.
S>>Ну тактические все-таки что-то новое, все эти agg root, transaction script, entity, values. А так да, взяли отовсюду понемногу. G>Это фаулер описал, до DDD
Ну а Эванс добавил стратегические паттерны и превратил все это методологию. Что называется стоял на
плечах гигантов.
S>>Какой сервис в компании не беру, везде есть Repository. Это уже ~Dal по сути. G>Мода — она такая, везде ропозитарии, хотя они не нужны.
Соглашусь. Ну, кстати, и ООП тоже своего рода мода.
S>>Вкусовщина, типа нраится\ не нраится. Могли бы perl для веба взять. Никаких экспериментов по написанию веб приложения на пхп, а потом на C# не было же? G>Книг по perl было на прядок меньше, на фоне C++\java\C# и остальных.
Странно, учитывая что он на 20 лет появился раньше. А на питон почему не смотрели, вроде для него уже
были фреймоврки для веба?
S>>1) Каким боком это к дискуссии? S>>2) Речь же шла про инвариант класса, а не ДДДшное исполнение чего-то. Инвариант класса и ДДД противоречат где-то? G>Как обычно попытка решить нетривиальную задачу проектирования с помощью DDD приводит или к "это другое" или к CQRS и эвентсорсингу.
При чем здеьс обеспечение инварианта и ДДД?
S>>Она(бд) эти данные потом в память себе загоняет и работает с ними. Так что в памяти и работает. G>Тем не менее "объектами" там не пахнет.
Объектами самой бд, типа строки\колонки\талбицы и т.п.
S>>Как? G>Запросом на уровне базы, который писал выше. Из базы на уровень приложения ничего не попадает.
А ответ от базы где и кем анализируется, для чего запрос-то делать, если ответ никуда не попадет, точнее
не попадет в приложение?
G>>>Очередное мнение, которое подкреплено примерно ничем? S>>Чем хуже вашего мнения? G>Тем что я не пытаюсь доказать полезность и применимость DDD.
Я пытаюсь настоять на его полезности хотя бы в рамках распила монолита на микросервисы. Как-то
работает. Все. Про общую пользу я речь не вёл.
G>Бремя доказательство обычно возлагается на того кто утверждает, пока он не представил объективные аргументы.
У меня их нету, выбор языка ОПП C# вы тоже особо не доказывали, а просто вкусовщина или книжек мало.
S>>ДДД утв. что если вы правильно поняли бизнес и модель предметной области, то все должно взлететь. Делайте так и все получится. G>Если есть контрпример, то можно считать утверждение ложным?
Давайте разберем контрпример. Хотя думаю, что мое утверждение выше было чрезмерно сильным.
Возможно ДДД ничего такого не утверждает.
S>>Ну ведь фигней занимаетесь, не будете переписывать огромный софт под 1млн. без ДДД. Ну к чему эта бравада? S>>Какое-то детсадовское взятие на слабо. Не серьезно. G>Как тогда доказать что-то про ДДД?
Не знаю, методом проб и ошибок.
S>>Я говорил, что он не плох, если кому-то не нравится. Ровно в этом моя позиция. Научный подход в ИТ вещь такая себе -- почему написали на C#, когда можно было на С++ или вообще на Си? Это бред и демагогия, не нравится, не пользуйтесь. Я вот избирательно что-то для себя в ДДД подчеркнул и мне G>хорош, никакого научного подхода не надо. G>Звучит как вера. Вам верить никто не мешает, но нести свою веру другим в целом противопоказано.
Блин, ну как тогда любая технология взлетает, если в нее по сути по началу верять пару человек,
если вообще не один? При таком подходе никакого ООП бы не было.
S>>Блин, ну какой научный подход у agile, рефакторинга и solid? G>Есть конечно, исследования всякие. G>Насчет solid не знаю, про agile и рефакторинг находил.
Ну вот про научно доказанную пользу agile я бы почитал.
Кодом людям нужно помогать!
Re[26]: Что если не разделять строго dto, entity, bo...
Здравствуйте, amironov79, Вы писали:
A>Здравствуйте, gandjustas, Вы писали:
G>>Насколько я знаю основной паттернов DDD является aggregate root — сущность, которая поднимается из бд и все изменения вызываются из нее. То есть мы взываем Root.DoSmth(...), а рут в свою очередь вызывает методы дочерних объектов. Именно рут отвечает за целостность операции G>>За все затягивание и сохранение отвечает репозиторий (это второй по важности паттерн в DDD), а вызывающий код работает с объектами.
A>Это всё детали реализации. Что мешает реализовать aggregate root как сервис и dto?
А есть пример такой архитектуры. Я правда не понимаю как это должно выглядеть.
G>>ООП люди понимают и применяют, посмотри на любой UI фреймворк на ОО-языке — WPF или, прости господи, WinForms. G>>А еще можешь посмотреть базовые библиотеки дотнета или жабы, они тоже полны достаточно качественного ООП (со своими особенностями каждая). A>А если взять корпоративные приложения, для которых DDD в первую очередь и предназначен, много там качественного ООП именно в бизнес домене?
Примерно ничего. ООП плох для моделирования связей и ограничений в предметной области.
Re[35]: Что если не разделять строго dto, entity, bo...
Здравствуйте, amironov79, Вы писали:
A>Здравствуйте, gandjustas, Вы писали:
S>>>>>Значит тут и репозиторий особо не нужен, обычный DAL. G>>>>Так это в любой программе так. S>>>Какой сервис в компании не беру, везде есть Repository. Это уже ~Dal по сути. G>>Мода — она такая, везде ропозитарии, хотя они не нужны.
A>Репозиторий как DAL конечно не нужен, здесь ORM нормально справляется. Если же репозиторий как сервис, работающий с внешними данными, и который является частью домена, то почему нет.
Почему для внешних данных нужен репозиторий? Зачастую внешний сервис, это именно сервис. Ты ему запросы, он тебе ответы. Все. Никакого ооп не надо. И заботиться о целостности внешних данных не надо. На то они и внешние.
Re[35]: Что если не разделять строго dto, entity, bo...
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
S>>>Да, вполне согласен. Не исключаю, что все эти моменты под одну крышуметодологию запихнули и все. Как-то так оно и есть. S>>>Потом решили развивать идею дальше, и появились тактические паттерны и тп. G>>См историю, тактические паттерны появились в начале. Все описал фаулер еще до эванса. Вся суть ДДД с самого начала — натягивание философии на паттерны. Когда модным стал CQRS — он появился в книгах DDD. Когда стали модными микросервисы — они тоже появились в книгах по DDD.
S>Может быть, но ДДД очень любят применять при распилах монолита на микросервисы. Работал в таком проекте.
S>>>Ну тактические все-таки что-то новое, все эти agg root, transaction script, entity, values. А так да, взяли отовсюду понемногу.
Абсолютно не связанные между собой вещи. Микросервисы ничего не говорят об архитектуре внутри сервиса.
G>>Это фаулер описал, до DDD S>Ну а Эванс добавил стратегические паттерны и превратил все это методологию. Что называется стоял на плечах гигантов.
Как я и написал ниже он добавил философию.
S>>>Какой сервис в компании не беру, везде есть Repository. Это уже ~Dal по сути. G>>Мода — она такая, везде ропозитарии, хотя они не нужны. S>Соглашусь. Ну, кстати, и ООП тоже своего рода мода.
На ооп мода была в середине девяностых — середине нулевых. Мода прям адская, все что не ООП — было "фу". На волне этой моды ДДД и появилось.
Потом микрософт нанял Эрика Мейера, который до этого Хаскелем занимался и он всех покусал функциональщиной, а в 2011 вышел стандарт с++11, в ктором вся стандартная библиотека была функциональной.
На той волне даже JS голову поднял, в нем давно было то, что в мире ФП ценилось.
S>>>Вкусовщина, типа нраится\ не нраится. Могли бы perl для веба взять. Никаких экспериментов по написанию веб приложения на пхп, а потом на C# не было же? G>>Книг по perl было на прядок меньше, на фоне C++\java\C# и остальных. S>Странно, учитывая что он на 20 лет появился раньше. А на питон почему не смотрели, вроде для него уже были фреймоврки для веба?
Возраст языка не показатель популярности. в 2005 на полках книг по C# и Java было одинаково, даже по C++ было меньше, хотя он старше. А по перлу если одна попадалась на полке, то лежала там несколько лет.
S>>>1) Каким боком это к дискуссии? S>>>2) Речь же шла про инвариант класса, а не ДДДшное исполнение чего-то. Инвариант класса и ДДД противоречат где-то? G>>Как обычно попытка решить нетривиальную задачу проектирования с помощью DDD приводит или к "это другое" или к CQRS и эвентсорсингу. S>При чем здеьс обеспечение инварианта и ДДД?
Видимо это никак не связанные вещи
S>>>Она(бд) эти данные потом в память себе загоняет и работает с ними. Так что в памяти и работает. G>>Тем не менее "объектами" там не пахнет. S>Объектами самой бд, типа строки\колонки\талбицы и т.п.
У слова "объект" в программировании есть вполне конкретное значение. строки\колонки\талбицы не являются объектами с точки зрения работы с БД.
S>>>Как? G>>Запросом на уровне базы, который писал выше. Из базы на уровень приложения ничего не попадает.
S>А ответ от базы где и кем анализируется, для чего запрос-то делать, если ответ никуда не попадет, точнее не попадет в приложение?
Этот запрос меняет состояние в БД. Можно проанализировать его успешность, если что-то пошло не так, то кинуть исключение. Но обсуждению выше отношения не имеет.
G>>>>Очередное мнение, которое подкреплено примерно ничем? S>>>Чем хуже вашего мнения? G>>Тем что я не пытаюсь доказать полезность и применимость DDD.
S>Я пытаюсь настоять на его полезности хотя бы в рамках распила монолита на микросервисы.
Ок, давай примеры чем именно ДДД помогает. А еще было бы неплохо описать "механизм действия", а то может ДДД не при чем.
Или нам поверить что помогает потому что кто-то сказал?
G>>Бремя доказательство обычно возлагается на того кто утверждает, пока он не представил объективные аргументы. S>У меня их нету
Ок, значит просто вера
S>выбор языка ОПП C# вы тоже особо не доказывали, а просто вкусовщина или книжек мало.
мне кажется ты просто проигнорировал все что я написал или просто контекст закончился и старые сообщения не учитываются при генерации новых ответов.
S>>>ДДД утв. что если вы правильно поняли бизнес и модель предметной области, то все должно взлететь. Делайте так и все получится. G>>Если есть контрпример, то можно считать утверждение ложным? S>Давайте разберем контрпример. Хотя думаю, что мое утверждение выше было чрезмерно сильным. Возможно ДДД ничего такого не утверждает.
Допустим разрабатывается система, аля трекер. Заказчик хочет возможность ограничить количество задач для пользователя.
Будут две сущности: Issue и User, связанные много-к-одному.
У Issue есть метод AssignTo, которому надо передать User или его Id, чтобы связать. И надо как-то гарантировать что выполняется условие, что для одного User назначено не более трех Issue/
Какую реализацию нам диктует прагматичный подход (ПП):
Прямо в контроллере, в одной транзакции (!) сделать два запроса:
update issues set user_id = @userid where id = @id;
select count(*)from issues where user_id = @userid
Для PG и других баз с оптимистичными блокировками нужен уровень изоляции serializable и повтор запросов при ошибке, а для SQL Server без RCS и MySQL (и других блокировочников) достаточно read committed
Реализация на C# для postgres может выглядеть так:
var db = ctx.Database;
await db.CreateExecutionStrategy().ExecuteAsync(async ct =>
{
await using var t = await db.BeginTransactionAsync(System.Data.IsolationLevel.Serializable, ct);
await ctx.Issues.Where(i => i.Id == id).ExecuteUpdateAsync(s => s.SetProperty(x => x.UserId, userId), ct);
if (await ctx.Issues.CountAsync(x => x.UserId == userId, ct) > 3) throw new Exception("Auchtung");
}, ct);
С этой же задачей я пошел в рекомендованный тобой чат, попросил показать пример DDD. три дня срачей, рассказов что я не умею требования анализировать, что задача вообще нереальная и не надо её решать итд.
Самое лучшее что один из участников написал пайтоне
То есть прделагают два агрегата. User хранит счетчик issue. Причем в реальности такая логика будет размазана по разным файлам.
1) Во первых код тупо не полный, так как кроме увеличения при назначении надо еще уменьшать при переназначении.
2) Как будет обеспечиваться изоляция транзакций непонятно, этого кода также нет.
А теперь представим что программа у нас развивается и требования чуть усложнились: теперь надо считать не все Issue, а только в нужном статусе.
В варианте на C# добавить фильтр и код проверки вызывать как в методе назначения задачи, так и при смене статуса на нужный.
Что делать в варианте на пайтоне — даже боюсь представить.
Получается что сделали по ДДД максимально хорошо насколько люди поняли ДДД, а получилось раздутое нерасширяемое и скорее всего ненадежное говно.
S>>>Ну ведь фигней занимаетесь, не будете переписывать огромный софт под 1млн. без ДДД. Ну к чему эта бравада? S>>>Какое-то детсадовское взятие на слабо. Не серьезно. G>>Как тогда доказать что-то про ДДД? S>Не знаю, методом проб и ошибок.
А что надо пробовать? Я и предлагаю попробовать две программы с эквивалентными функциями сравнить.
S>>>Я говорил, что он не плох, если кому-то не нравится. Ровно в этом моя позиция. Научный подход в ИТ вещь такая себе -- почему написали на C#, когда можно было на С++ или вообще на Си? Это бред и демагогия, не нравится, не пользуйтесь. Я вот избирательно что-то для себя в ДДД подчеркнул и мне G>>хорош, никакого научного подхода не надо. G>>Звучит как вера. Вам верить никто не мешает, но нести свою веру другим в целом противопоказано.
S>Блин, ну как тогда любая технология взлетает, если в нее по сути по началу верять пару человек, если вообще не один? При таком подходе никакого ООП бы не было.
Серьезно считаешь что ООП родилось из веры?
ООП родилось из решения частных задач, а именно моделирования поведения в агентной системе. Внезапно первый ОО-язык это была в первую очередь агентная система.
Авторы ООП никуда ООП не продвигали. Последователи сами захотели включить его в свои языки, причем сильно по разному.
От появления ООП до первых популярных языков прошло почти 20 лет.
Больше всех ООП популяризировал C++, потому что он по сути добавлял новые фичи в адски популярный тогда С. Возможно если бы не Страуструп то такого хайпа и не случилось бы.
Популярность ООП это скорее череда совпадений и неплохой изначальной идем, которую специально никто не форсил.
А с DDD ровно обратная картина.
S>>>Блин, ну какой научный подход у agile, рефакторинга и solid? G>>Есть конечно, исследования всякие. G>>Насчет solid не знаю, про agile и рефакторинг находил. S>Ну вот про научно доказанную пользу agile я бы почитал.
Да там банальное исследование было: опрос какие практики применяют и считали корреляцию с "успешностью" проектов. Как успешность считали уже не помню.
Здравствуйте, Sharov, Вы писали:
S>Какие, например?
Банальные вопросы вроде "зарезервировать товары заказа на складе".
Потому что в домене есть складские остатки, есть товары, есть заказы. Ни в кого из них запихать метод "зарезервируй" не получается без того, чтобы втащить внутрь этого метода не-доменную логику.
А делать специальный AggregationRoot, который типа и должен всё это делать, противоречит самой идее Ubuquitous Language, т.к. этого рута в "домене" не существует.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[31]: Что если не разделять строго dto, entity, bo...
Здравствуйте, Sharov, Вы писали:
S>Почему, как репозиторий зависит от физического хранилища?
Примерно полностью. Вообще сама по себе идея "мы тут ворочаем доменными сущностями, а весь ваш персистенс — это какая-то внешняя забота" — порочна.
На её основе невозможно написать эффективную реализацию.
Внезапно оказывается, что хранить всю модель домена в JSON-файле, или в RDBMS, или во внешнем REST-сервисе — это три большие разницы.
В первую очередь потому, что эти три вида хранилищ обеспечивают крайне разную асимптотику при выполнении одинаковых запросов. И то, что в одной реализации делалось за O(logN), в другой может упереться в O(N2).
S>А при чем здесь DDD? Здесь побочный разговор на тему проверки инвариантов в случае, когда данные хранятся в бд. S>Я так понимал суть вопроса.
При том, что в DDD предписывается такое место этой проверки инвариантов, что оно требует подъёма половины базы в память для выполнения точечной операции.
S>Речь про транзакции?
Речь про запросы. В БД я могу проверить подобные предикаты, не поднимая в память сервера приложений вообще никаких данных. Часть предикатов я вообще могу проверять декларативно.
Более того — если окажется, что проверка поднимает слишком много данных в память СУБД, то у меня есть богатый набор инструментов по борьбе с этим не нарушая семантики — например, создание индексов, партиционирование таблиц и прочая DBA-магия. В DDD мы тащим всё это туда, где обработка будет иметь максимальную стоимость.
S>Я не знаю как обеспечивать инваринат класса (домена), если все данные хранятся в бд. S>Кроме как неэффективно все лочить ничего придумать не могу, а если использовать бд для этого, то это уже S>не инвариант класса получается.
Совершенно верно. А всё потому, что это — не инвариант класса. Это бизнес-правило, которое относится ко "всей модели", а не к какому-то конкретному классу. ООП хорошо подходит для описания изолированных элементов состояния, у которых есть только локальные инварианты. Ну, плюс ещё GC-системы позволяют вам быть уверенными в том, что ссылки на объекты не указывают на мусор.
А реальный ентерпрайз-бизнес устроен совсем не так. Даже банальный инвариант вроде manager.ManagedDepartments[i].Manager == manager вместо декларативного постулирования требует унизительного императивного кода, который в лучшем случае генерируется, а в худшем — пишется руками (и в нескольких местах!).
А всё потому, что нет никакого "класса", инвариантом которого бы являлся этот предикат.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Банальные вопросы вроде "зарезервировать товары заказа на складе". S>Потому что в домене есть складские остатки, есть товары, есть заказы. Ни в кого из них запихать метод "зарезервируй" не получается без того, чтобы втащить внутрь этого метода не-доменную логику.
Как правило, такие вопросы свидетельствуют о некорректном разделении домена на сущности. К тому же, доменным сущностям не запрещено иметь проекции друг на друга. Скажем, в проекции SKU на склад вполне найдется место для метода "зарезервировать", а в проекции резерва на контрагента найдется место для отгрузочной накладной.
Здравствуйте, Miroff, Вы писали:
M>Как правило, такие вопросы свидетельствуют о некорректном разделении домена на сущности.
Хм. Покажите корректное разделение домена на сущности.
Для взаимопонимания: в качестве домена мы понимаем ER-модель. Она хороша тем, что не отвлекается на детали реализации, вроде иерархии классов или там структуры таблиц. Чисто концептуальная модель предметной области.
Вот у нас есть Товар, есть Склад, есть Заказ.
Есть связь Заказ-Товар (многие-ко-многим, с атрибутом "количество").
Есть связь Товар-Склад (многие-ко-многим, с атрибутами "доступно" и "зарезервировано").
Что здесь сделано некорректно, и как мы поймём, что ошибка есть?
M>К тому же, доменным сущностям не запрещено иметь проекции друг на друга. Скажем, в проекции SKU на склад вполне найдется место для метода "зарезервировать", а в проекции резерва на контрагента найдется место для отгрузочной накладной.
Что такое "проекции друг на друга"? Расскажите подробнее.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[27]: Что если не разделять строго dto, entity, bo...
Здравствуйте, gandjustas, Вы писали:
A>>Это всё детали реализации. Что мешает реализовать aggregate root как сервис и dto? G>А есть пример такой архитектуры. Я правда не понимаю как это должно выглядеть.
Здравствуйте, gandjustas, Вы писали:
G>>>Мода — она такая, везде ропозитарии, хотя они не нужны. A>>Репозиторий как DAL конечно не нужен, здесь ORM нормально справляется. Если же репозиторий как сервис, работающий с внешними данными, и который является частью домена, то почему нет. G>Почему для внешних данных нужен репозиторий? Зачастую внешний сервис, это именно сервис. Ты ему запросы, он тебе ответы. Все. Никакого ооп не надо. И заботиться о целостности внешних данных не надо. На то они и внешние.
Он нужен, если стоит задача в домене абстрагироваться от способа получения данных. Если такой задачи не стоит, то можно и DbContext из сервиса дёргать, а то и прямо из контроллера
Re[37]: Что если не разделять строго dto, entity, bo...
Здравствуйте, amironov79, Вы писали:
A>>>Репозиторий как DAL конечно не нужен, здесь ORM нормально справляется. Если же репозиторий как сервис, работающий с внешними данными, и который является частью домена, то почему нет. G>>Почему для внешних данных нужен репозиторий? Зачастую внешний сервис, это именно сервис. Ты ему запросы, он тебе ответы. Все. Никакого ооп не надо. И заботиться о целостности внешних данных не надо. На то они и внешние. A>Он нужен, если стоит задача в домене абстрагироваться от способа получения данных.
А в каких случаях надо абстрагироваться от способа получения данных? И зачем?
Здравствуйте, Sinclair, Вы писали:
S>Что здесь сделано некорректно, и как мы поймём, что ошибка есть?
Дизайн строится не от данных, а от от операций. Если у тебя не получается логично присунуть метод, значит ты что-то сделал не так. Давай разберем что. В ДДД принято идти от предметной области, а в предметной области нет никаких ER, а есть единица товара, у которой есть SKU, физическая локация (на главном склад, у перевозчика, у покупателя и т.п.) и обязательства (вернуть постащику, сжечь, поставить покупателю и т.п.) И когда ты такую модель строишь у тебя логичным образом возникает поединичный учет и резервирование товара логично превращается в метод sku_item.createObligation(Supplybbligation(Order))
ER модель при этом будет выглядеть так
СКУ, Единица товара, Склад, обязательство, заказ
Связи:
СКУ — единица товара (один-ко-многим)
обязательство — единица товара (один-ко-многим)
заказ — обязательство (один-ко-многим)
СКУ — склад (многие-к-одному)
При этом логичным образом решаются и другие задачи, вроде "посчитать себестоимость хранения товара на складе" или "посчитать ущерб от уничтоженного товара находившегося на сгоревшем складе"
S>Что такое "проекции друг на друга"? Расскажите подробнее.
Это из функционального программирование пришло. В данном случае это обратимое преобразование F(Товар, Склад, Заказ) -> (Товар, Остаток, Резерв)
Ты можешь рассматривать проекции как DB view только не с точки зрения БД, а с точки зрения классов.