Re[7]: Что если не разделять строго dto, entity, bo...
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.12.25 17:36
Оценка: +2 :))
Здравствуйте, gandjustas, Вы писали:

G>То есть вы против dry на клиенте, потому что создание повторно используемого кода это сложно?

G>Может на сервере делать также? Просто скопипастить код в контроллерах, и поменять запросы?
Ну так это же и есть основной способ. Смотрите, как у нас всё классно — мы фигачим чотко по плану, два с половиной контроллера в человеко-день!
На каждую фичу нужно пять контроллеров, один DTO, один Entity, один репозиторий, один этот, как его, Aggregation Root, пять хранимых процедур.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 04.12.25 17:27
Оценка: 5 (1) -1 :)
Здравствуйте, Kernan, Вы писали:

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


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


K>В чём тогда серебряная пуля? Где граница применимости и как понять когда всё, приехали и "абстракции" давят и наоборот когда код превратился в набор спагетти? Все DDD, CA и т.п. было зря?



Ключевое прекрасно описано вот в этом посте: https://www.teamten.com/lawrence/programming/write-code-top-down.html

Процитирую основную мысль:

Существует два подхода к проектированию программ и написанию кода: «сверху вниз» и «снизу вверх».

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

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

Правильный подход к проектированию и написанию программы — «сверху вниз». Это не вопрос вкуса или предпочтений. Подход «снизу вверх» в корне ошибочен, и его не следует использовать.


Если вы со старта проекта начинаете применять архитектурные паттерны, то вы фактически занимаетесь проектированием «снизу вверх».

На каждом уровне существует стремление в программировании «снизу вверх». Избегайте этого. Вместо этого начните с верхнего уровня, с main() или его эквивалента, и пишите так, как будто все части уже написаны. Добейтесь правильного вида. Вставьте заглушки или хардкод отдельных частей пока не добьетесь компиляции и запуска. Затем медленно продвигайтесь вниз, стараясь максимально упростить все. Не пишите ни строчки кода, которая не решает проблему, с которой вы столкнулись прямо сейчас. Тогда у вас может появиться шанс написать большую, работоспособную и долговечную программу.

Re[21]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.01.26 00:28
Оценка: 128 (2)
Здравствуйте, Sharov, Вы писали:

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



S>1)Сразу оговорюсь, я не апологет DDD. Я ни одно книжки по DDD не прочитал, и много знаю по касательной.

А я прочитал

0) Архитектура Корпоративных Программных Приложений (АКПП) Мартина Фаулера (2002 год), там первый раз в популярной литературе появился термин Domain Model (модель предметной области), но еще никакого DDD не было.

Базовых книг по DDD, которые в принципе определяют что такое DDD, всего две:
1) Domain Driven Design Эрика Эванса (2003 год), а также товарищ Эванс выпустил несколько книг с тем же по сути контентом в 2006, 2013 и 2015 годах.
2) Implementing Domain-Driven Design Вона Вернона (2013 год), который также выпустил справочник на основе своей книги в 2015. Он дополняет DDD событийно-ориентированной архитектурой, CQRS и натягивает это все на Hibernate
Была еще пара книг:
3) Applying DDD (2006 год), там убрали всю философию и попытались сделать примеры кода, но примеры получились настолько невнятные, что практическая ценность книги околонулевая,
4) Patterns, Principles, and Practices of Domain-Driven Design (2015 год), с качественными примерами на .NET и современным, на тот момент, паттернами. По своим идеям и подходам она не приносит ничего нового в DDD по сравнению с книгой Вернона (2).
И все

Я не утрирую, с 2002 по 2017 год было всего два визионера про DDD, и одна достойная книга про DDD, не на Java, и Фаулер, который активно это все пиарил в своем блоге.

А потом пришел Роберт Мартин, который очень любит слово "Clean" и выпустил свою Clean Architecture, где по сути постулировал, что Clean Architecture = Onion\Hexagon Architecture, которые являются вариантами (разными?) layered arhitecture, у которых в центре Domain Model, поэтому всем нужно DDD, а еще Bounded Contexts в DDD отлично соотносятся с микросервисами.
И после этого материалы по DDD\Clean\Microservices посыпались как из рога изобилия.

Можете и сами проследить вот тут https://github.com/tdonker/domain-driven-design-links

Поэтому я, возможно, чуть лучше разбираюсь в DDD. Кстати Фаулера я прочитал в 2008, а Эванса в 2009, и еще тогда многие подходы мне показались сомнительными.

S>Я просто не считаю правильным отмахивать от DDD, как о бесполезной штуке. Оно большое, и люди частями или целиком его вполне успешно применяют.

А чем измеряется успех? В том что программа работает? В том что заказчик платит денег? Может это успех вопреки? Может без DDD денег было бы больше, а программа правильнее?
Без сравнения в равных условиях мы не узнаем.



S>2)

S>

S> То есть "модель предметной области" это типизированное описание схемы БД,

S>Что в этом плохого и кто с этим спорит? В DDD есть паттерн Repository, как раз и отвечает за сохранение главных
S>доменных сущностей, наверное и таблицы соотв. должны были быть.
Ты не на тот вопрос отвечаешь. Вопрос такой: является ли набор классов без логики, с которыми работает ORM, "моделью предметной области" в понимании ДДД (по книгам)? Я могу однозначно сказать что нет.

G>>А кто сказал что отсутствие "объектов доменной модели" автоматически приводит к плохому решению задачи?

S>Никто не сказал, просто это, кхм, странно. Задача софта эмулировать соотв. процессы. Как можно эмулировать что-то без соотв. сущностей?
Еще раз. DDD как набор паттернов, говорит нам:
— Domain Model это набор классов с данными поведением, которые соответствуют существительным в едином языке, выработанным между бизнесом и командой разработки
— Вся бизнес-логика (Core Domain) должна быть описана как взаимодействие этих объектов

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


G>>И кто сказал что наличие "объектов доменной модели" автоматически приводит к хорошему решению задачи?


S>Никто не сказал. Но вот вопрос -- что лучше, плохо написанная программа, которая прилично решает соотв. проблему предметной

S>области, или хорошо написанная программа, которая плохо решает заявленную проблему? Вы лично за какую бы программу заплатили бы
S>деньги?
Я не очень понимаю критериев оценки "хорошо или плохо". Программа может проблему решать или не решать. Мне как пользователю совершенно без разницы есть там "модель предметной области" или нет. Если две программы одинаково решают мою (не какой-то абстрактной предметной области) проблему, то выберу ту, которая дешевле по совокупной стоимости владения.

S>Я вообще не вижу противоречия между хорошим кодом и объектами доменной модели. Это прям какая-то странная дихотомия.

Я тоже не вижу. Качество программы и наличие в ней domain model — вещи ортогональные, то есть независимые друг от друга.

S>>>Ну и самый главный вопрос, а как всему вышеперечисленному мешает оперирование объектами доменной модели?

G>>Никак не мешает и никак не помогает. Хотя зависит от того, что входит в понятие "оперирование объектами доменной модели", так как это может давать ограничения
G>>Например код вида
G>>
G>>ctx.Stock.Where(s => s.Wharehouse == id).ExecuteUpdate(x => x.SetProperty(s => s.Quantity, s => s.Quantity - s.Reserved).x.SetProperty(s => s.Reserved, 0))
G>>

G>>Является "оперированием объектами доменной модели"?
S>Скорее оперирование представлением в бд.
То есть не соответствует DDD никак, да еще и ужасную вещь делает с точки зрения Clean Architecture — прибивает бизнес-логику к инфраструктуре.
Причем этот код решает задачу "сделать отгрузку товаров со склада X", которую крайне сложно описать в DDD, особенно чтобы была изоляция. Внезапно еще и "отгрузка" никак не фигурирует в моделях БД.


S>>>Делаю какой-нибудь реалистичны автотренажер или игру для машин, есть в стандартной библиотеке класс автомобиль, мотор и т.п.?

G>>Мы тут вроде как корпоративные приложения рассматриваем, которые оперируют данными в бд в многпользовательском режиме.
S>Какая разница, софт есть софт.

У Эрика Липперта — он написал гораздо больше и полезнее, чем Фаулер, Эванс и Вернон вместе взятые и вообще крутой программист и инженер — есть потрясающая серия статей Wizards and Warriors, которую я даже перевел на хабре

В пятой части он сформулировал тезис:

Программа должна поддерживать согласованное состояние перед лицом попыток пользователя (клиента) изменить это состояние


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


S>Вот цитата Б. Мейера отсюда -- https://bertrandmeyer.com/2012/11/27/why-so-many-features/

S>

S>It is easy to complain about software bloat, and examples of needlessly complex system abound. But your bloat may be my lifeline, and what I dismiss as superfluous may for you be essential. To paraphrase a comment by Ichbiah, the designer of Ada, small systems solve small problems. Outside of academic prototypes it is inevitable that a successful software system will grow in complexity if it is to address the variety of users’ needs and circumstances. What matters is not size but consistency: maintaining a well-defined architecture that can sustain that growth without imperiling the system’s fundamental solidity and elegance.

S>Апологет DDD какай-то такой целью и задавались. На сколько вышло --
Очень сложно проверить насколько им удалось придумать архитектуру, которая сохраняет целостность и элегантность длительное время.

S>Народ использует, конференции ежегодные проводят, значит кому-то заходит.

Это вообще не показатель. Я пережил столько хайпов в ИТ уже, и после каждого еще долго оставались толпы фанатов "кому заходит".
Тем более есть проблема: кроме Clean Architecture и DDD в медийном поле вообще не существует других подходов. У альтернативы ДДД даже названия собственного нет, она состоит из применения принципов YAGNI, KISS, DRY, top-down подхода к проектированию и разработке, частично SOLID.
Многое кстати было описано в книге Pragmatic Programmer Ханта и Томаса (2000 год), то есть за пар лет до фаулера-эванса и там нет такой категоричной упоротости на ООП. Несмотря на то, что части сведений в книге устарели я, с вашего позволения, буду называть подход — Прагматичным Программированием или Прагматичным Проектированием, сокрушённо ПП



G>>Сколько нам нужно функций, чтобы DDD с его паттернами стало давать какой-то профит?

S>Какой-то дурацкий вопрос, если честно. Типа сколько нужно людей, чтобы лампочку вкрутить. Вы какую-то цифру ждете?
S>Она, скорее всего, у каждого будет своя.
Любую теорию, например теорию о полезности DDD, можно считать научной если существует хотя бы один эксперимент, который может теорию опровергнуть, даже если он еще не проведен. Это называется критерий фальсифицируемости поппера.
А если такого эксперимента не существует, то это уже не теория, а вера.

Я посмотрел историю избранных другими моих сообщений. Я холиварю против DDD с 2009 года (видимо сразу после того как книгу прочитал), с тех пор НИ ОДНОГО ПРИМЕРА, демонстрирующего превосходства DDD над ПП в рамках этого форума. Я даже для прикола брал ndddsample и переписывал на код без DDD — получалось компактнее при том же функционале. Жалко код уже утерян.
Re[10]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 04.12.25 18:19
Оценка: 83 (2)
Здравствуйте, Pauel, Вы писали:


P>Разделение, изоляция итд, это дополнительная работа. Собственно, почти всё, разве что кроме веб фронтенда, можно писать в одной единственной функции main без каких либо других функций, классов, интерфейсов итд. Буквально.

P>Собственно, если внимать словам gandjustas, то здесь нужно остановиться и прекратить заниматься ерундой — 1 файл + 1 main, и больше ничего.
Можешь показать где я такое говорил?
Я говорил что надо уменьшить количество строк.
Во-первых отсутствие декомпозиции тебе непременно количество строк увеличит из-за дублирования.
Во-вторых на любом достаточно сложном коде у тебя количество сложенных иф_ов, и циклов превысит размер, умещаемый на экране по горизонтали.
В-третьих тебе код надо не только писать, но и читать, а для этого нужна навигация по коду, которую без структуры очень сложно сделать.
В-четвертых некоторые приемы уменьшения кода: наследование, полиморфизм, функциональная композиция, вынуждают тебя делать структуру из классов или функций.
В-пятых фреймворки за счет DI и встроенных паттернов заставляют тебя делать структуру. Не сделать структуру = написать больше кода.

Поэтому нет, в произвольной программе все в main написать решительно невозможно из практических соображений, я никак не мог рекомендовать такое.

P>То есть, для маленьких приложений, буквально хватит 1 файл + 1 main.

С этим наверное вообще никто спорить не будет.

P>Но чем больше и сложнее, приложение, тем больше и глубже будет разделение на внутренние компоненты.

Не очень понятно где от одного файла и все в main перейти к domain model.

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

Если ты заранее генерируешь ДТО на каждый слой, то тебе уже нужен маппер.


P>Например, у вас сервис работает с несколькими стораджами/провайдерами/итд, у всех разные дто. Очевидно, что в этом случае мапперы помогают вам защитить ядро приложения от лишних изменений.

P>Если у вас 1 бд, 1 ui, и ничего больше — от мапперов толку мало.
Апологеты DDD скажут что толк есть, негоже на UI отдавать доменные объекты.

P>А если у вас вспомогательная утилитка "скопировать 5 юзеров из той бд в эту" то вам вообще хватит 1 файл + 1 main.

Если программу изначально создавать как большую, то и получится большая, с кучей мапперов и ДТО, если по итогу она только 5 юзеров копирует.

Я всегда говорил, что нужно в каждый момент времени писать минимум кода для решения задачи, которая есть в данный момент. ИМХО в таких условиях вероятность появления domain model и DTO стремится вообще к нулю.
Re[13]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.12.25 08:26
Оценка: 10 (1) +1
Здравствуйте, gandjustas, Вы писали:

G>Когда код делает +\- одно и то же и может быть написан без архитектурных паттернов, то по формальным метрикам...


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

P>>А вот с мапперами вам почему то непонятно

G>Потому что мапперы это не корень проблемы, а следствие. Если вам нужен маппер, то вероятно, что вы сильно ранее свернули не туда.

Маппер нужен в том случае, если приемник требует свою форму. Например, в ui вы отдаёте плоский компактный объект, а в бд у вас иерархия таблиц-объектов-коллекций-итд.
В этом случае вы развязываете изменения в бд и ui. Например, другая фича потребует изменение в структуре бд. Опаньки — дальше маппера это изменение не пролезет.

P>>Любой концепт — класс, функция, интерфейс, итд, это то самое разделение.

P>>Если бенефитов нет, см ваши "во-первых..." то добавление класса, функции, интерфейса, итд смысла не имеет. Мапперы, паттерны здесь ничего не меняют.
G>Еще раз:
G>1) Без разделения скорее всего кода станет больше

Важно не количество кода, а способность его мейнтейнить, читать, менять итд. И отталкиваться нужно от этого, а не от ваших формальных метрик.

G>Рецепт как вводить изменения вовремя уже многократно дан — ты пишешь максимально простой код чтобы решить ту задачу, которая у тебя есть в данный момент и не пишешь код, который к решению задачи не относится.


Это все добросовестные разработчики так делают. Просто видение что к чему относится или нет, у всех разное. Держать в фокусе только краткосрочную перспективу — идея очень так себе. Так что буквально ваш совет не работает.

P>>А если изначально большую писать как маленькую, то есть чудовищно огромный шанс или утопить, или вырастить монстра, или убить весь бюджет на один только рефакторинг.

G>Вот что-то я такого не видел. Усложнять всегда просто, упрощать — сложно.

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

P>>Ой да ладно. Вы подразумеваете какой то свой набор приложений-проектов. Озвучьте уже его.

G>Да любые корпоративные многопользовательские приложения.

Корпоративные приложения очень разные. Например, практически везде разделяют дто ui и дто базы данных. А у вас это сходу "свернули не туда"
Re[9]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.12.25 15:01
Оценка: 9 (2)
Здравствуйте, Kernan, Вы писали:

K>Однако, тезисы Ганджустата как-то говорят о том, на мой взгляд, что домены это хорошо, но пиши как знаешь и проще, всё равно по метрикам на большом проекте это не даёт особого профита. Вот как быть?


А что вас смущает? Он собрал какую то свою статистику на каких то ему одному известных проектах. Как это переиспользвать — вероятно, что никак.

Разделение, изоляция итд, это дополнительная работа. Собственно, почти всё, разве что кроме веб фронтенда, можно писать в одной единственной функции main без каких либо других функций, классов, интерфейсов итд. Буквально.

Собственно, если внимать словам gandjustas, то здесь нужно остановиться и прекратить заниматься ерундой — 1 файл + 1 main, и больше ничего.

Штука в том, в разделение/изоляция/абстрагирование имеют свою цену, что очевидно.

То есть, для маленьких приложений, буквально хватит 1 файл + 1 main.

Но чем больше и сложнее, приложение, тем больше и глубже будет разделение на внутренние компоненты.

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

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

Если у вас 1 бд, 1 ui, и ничего больше — от мапперов толку мало.

А если у вас вспомогательная утилитка "скопировать 5 юзеров из той бд в эту" то вам вообще хватит 1 файл + 1 main.
Re[38]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 29.01.26 09:33
Оценка: 6 (1) +1
Здравствуйте, TG, Вы писали:

TG>А в каких случаях надо абстрагироваться от способа получения данных? И зачем?


Когда работаешь с несколькими источниками однотипных данных, которые могут отличаться как по протоколу, так и по схеме данных. Интерфейс у репозитория описывается в терминах домена, реализация для каждого источника своя.
Re: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 12:46
Оценка: +1 -1
Здравствуйте, Shmj, Вы писали:

S>Вопрос такой.


S>Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.


S>Но задумался — а какие реальные бонусы?

Реальные бонусы для кого?

Если для заказчика/стейкхолдера/пользователя, то очевидно никаких. Тому кто платит деньги и конечному пользователю без разницы сколько у вас слоев, дто и мапперов.

Для разработчика зачастую бонусы есть:
— возможность написать много кода, с разумным оправданием. Программисты зачастую испытывают удовольствие от написания кода и создания «архитектуры», даже если мела ной потребности в этом нет
— возможность дороже продать свою работу. написать одну строку стоит в 10 раз дешевле, чем написать 10 строк.
— возможность применить больше хайповых паттернов и библиотек, чтобы написать в резюме. В одну строку много паттернов не запихнешь, а в 10 уже можно.
Re[18]: Что если не разделять строго dto, entity, bo...
От: Sinclair Россия https://github.com/evilguest/
Дата: 31.12.25 14:07
Оценка: +1 :)
Здравствуйте, gandjustas, Вы писали:

G>Что там является "моделью предметной области", в чем её ценность, и как она влияет на остальные части кода?

Да вот же она: https://github.com/gandjustas/habr-post-stock-api/blob/main/Model.cs
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[24]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.01.26 13:29
Оценка: 123 (1)
Здравствуйте, 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, то у вас плохое ООП.

Кстати про DRY тоже есть у Липперта
Re[3]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 14:32
Оценка: 78 (1)
Здравствуйте, Shmj, Вы писали:

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


G>>Если для заказчика/стейкхолдера/пользователя, то очевидно никаких. Тому кто платит деньги и конечному пользователю без разницы сколько у вас слоев, дто и мапперов.


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


А откуда мнение что код с кучей dto и мапперов менее запутанный и проще поддерживается чем без него?
Я вот проводил замеры maintainability index для кода с разделением и без и не код с разделением стабильно проигрывал.
Это потом что maintainability index зависит от halastead volume, по сути от нормированного количества строк.

В целом я не понимаю как увеличение количества кода может положительно сказываться на стоимости поддержки.

S>И что заказчику делать, если разработчик три дня исправляет простой баг а после исправления создает новый баг? Выгонять?

Чтобы ответить на этот вопрос надо понимать почему так происходит.

S>Ок, выгнал (а скорее тот сам ушел еще до того, как проблема стала очевидной). Берет нового — новый говорит что нужно все переписывать с нуля. Берет другого — тот делает вид что работает, месяц делает вид, два — говорит что еще разбирается в проекте. А потом начинает работать еще медленнее.

Если ты заказчик, который не разбирается в процессе, то плати только за результат, а не за время
Re[31]: Что если не разделять строго dto, entity, bo...
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.01.26 03:32
Оценка: 6 (1)
Здравствуйте, 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 вместо декларативного постулирования требует унизительного императивного кода, который в лучшем случае генерируется, а в худшем — пишется руками (и в нескольких местах!).
А всё потому, что нет никакого "класса", инвариантом которого бы являлся этот предикат.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[38]: Как внедряли DDD в Яндекс 360.
От: Miroff Россия  
Дата: 29.01.26 07:52
Оценка: 6 (1)
Здравствуйте, Sinclair, Вы писали:

S>Что здесь сделано некорректно, и как мы поймём, что ошибка есть?


Дизайн строится не от данных, а от от операций. Если у тебя не получается логично присунуть метод, значит ты что-то сделал не так. Давай разберем что. В ДДД принято идти от предметной области, а в предметной области нет никаких ER, а есть единица товара, у которой есть SKU, физическая локация (на главном склад, у перевозчика, у покупателя и т.п.) и обязательства (вернуть постащику, сжечь, поставить покупателю и т.п.) И когда ты такую модель строишь у тебя логичным образом возникает поединичный учет и резервирование товара логично превращается в метод sku_item.createObligation(Supplybbligation(Order))

ER модель при этом будет выглядеть так

СКУ, Единица товара, Склад, обязательство, заказ

Связи:
СКУ — единица товара (один-ко-многим)
обязательство — единица товара (один-ко-многим)
заказ — обязательство (один-ко-многим)
СКУ — склад (многие-к-одному)

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

S>Что такое "проекции друг на друга"? Расскажите подробнее.


Это из функционального программирование пришло. В данном случае это обратимое преобразование F(Товар, Склад, Заказ) -> (Товар, Остаток, Резерв)
Ты можешь рассматривать проекции как DB view только не с точки зрения БД, а с точки зрения классов.
Re[37]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 31.01.26 21:10
Оценка: 6 (1)
Здравствуйте, Sharov, Вы писали:

S>Я так и думал -- correlation doesn't imply causation. (с) Т.е. никакого научного обоснования, а такая же веря как с ДДД.


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

Напомню что про DDD вообще нет ни одного исследования, которое хоть какие-то измеримые результаты дает. Там все "доказательства" это просто мнения людей. Причем изначально довольно небольшой группы. Сейчас люди часто приводят пример из книги Эванса (которой уже 20+лет), а когда доходит до примеров реалистичных и актуальных — уже не так хорошо даже на них ДДД работает.

Так что вера ДДД гораздо сильнее, чем вера в ООП или agile.
Re[9]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.12.25 08:35
Оценка: 5 (1)
Здравствуйте, Qulac, Вы писали:

Q>Clean Architecture не мешает разрабатывать в любом направлении. Вот TDD — подход с верху в низ, но работают здесь с моделью.


TDD и снизу-вверх тоже отлично совмещаются. При этом вы сначала пишете компоненты нижнего уровня, начинаете размером с функцию-класс и постепенно доходите до самого приложения.

С подходом снизу вверх есть шанс что вы попадёте не туда. С подходом сверху вниз есть шанс что затратите хрен знает сколько времени и ресурсов.

Сверху вниз лучше работает, когда вы знаете большую часть требований.
Здесь вы прорабатываете наличие компонентов, взаимодействие, но решение о проработки внутрянки компонентов принимается максимально поздно.
Недостаток — если в итоге вам из всего что было сделано, понадобится только маленькое приложение, то сперва родите монстра.

Снизу вверх лучше работает, когда вы почти ничего и не знаете. Понадобилася эндпоинт — добавили. Понадобился еще один — дописали. БД не нужна — вы её и не добавляете. Нужна будет бд, или будете работать сервисов — будет ясно потом.
В этом случае есть компонент, или нет его, как он будет взаимодействовать с остальной частью приложение — такие решения принимаются максимально поздно, по мере проработки внутрянки компонента.
Недостаток — если в итоге вам нужно большое приложение, то вы затратите хрен знает сколько времени выращивая его эволюционно.

Правила большого пальца:
1. нужно маленькое приложение — пишите как маленькое
2. нужно большое — пишите как большое.
3. в любом случае нужно прояснять ситуацию, что бы не ошибиться с принятием решения.
Отредактировано 05.12.2025 8:36 Pauel . Предыдущая версия .
Re: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 28.11.25 19:05
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>Вопрос такой.


S>Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.


S>И у меня сейчас проект, который нужно дорабатывать. Там этой парадигмы разделения не придерживались строго, так что в ui проникают как dto, так и entity. Проект пока не большой, около 25 тыс. строк кода, т.е. за пару-тройку дней можно разделить и добавить мапперы.


S>Но задумался — а какие реальные бонусы? Вот что пишет зазнайка:


S>

S>Если использовать DTO в Домене: Ваша бизнес-логика становится зависимой от API-контрактов. Если фронтенд попросит переименовать поле в JSON для удобства отображения, вам придется менять это поле в бизнес-логике, что может повлечь ошибки в расчетах. Внешний мир начинает диктовать правила внутреннему.

S>Если использовать Entity в Домене: Ваша бизнес-логика зависит от схемы базы данных. Если вы решите денормализовать таблицу для производительности или сменить PostgreSQL на MongoDB, вам придется переписывать бизнес-правила.

S>Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.

Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

S>Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.

Можно и руками.

S>Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.

Ни чего не понял.

S>Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.

Да хоть в 10 местах, что это меняет, откуда такая мания экономить на спичках?

S>Далее. Если добавим тесты и фейковые реализации сервисов — то что мешает в этих фейковых реализациях использовать уже существующие классы для объектов, ведь у них есть конструктор...

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

S>По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.


Ну не применяй.
Программа – это мысли спрессованные в код
Re[4]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 18:19
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>А откуда мнение что код с кучей dto и мапперов менее запутанный и проще поддерживается чем без него?

G>Я вот проводил замеры maintainability index для кода с разделением и без и не код с разделением стабильно проигрывал.
G>Это потом что maintainability index зависит от halastead volume, по сути от нормированного количества строк.

G>В целом я не понимаю как увеличение количества кода может положительно сказываться на стоимости поддержки.


Ну на счет разделения объектов (для каждого слоя свой набор объектов) + мапперы — вижу только один смысл — когда над каждым слоем работает отдельный человек и чтобы не ждать пока Вася изменит свой слой — Петя может уже создавать и тестировать. А уже отдельный чел. занимается исключительно мапперами и интеграцией слоев в единую систему.

Других плюсов особо не видно. Т.е. если у вас нет строгого разделения труда — то нет смысла и в строгом разделении объектов. Но когда несколько человек работают над системой одновременно и каждый занимается своим слоем — появляется смысл все-же.

А вот строгость в придерживании архитектуры, как то принято писать ViewModel — но ты для отдельных форм это не применяешь (а просто напрямую вызываешь api-методы и базу из обработчика кнопки) — тут есть минус. А именно, код становится сложнее поддерживать, сложнее дорабатывать.

S>>И что заказчику делать, если разработчик три дня исправляет простой баг а после исправления создает новый баг? Выгонять?

G>Чтобы ответить на этот вопрос надо понимать почему так происходит.

Порядок. Вот в вещах порядок — можно все разложить по коробочкам (особенно поймут электронщики). А можно как бы не заморачиваться и все вывалить в одну большую кучу.

Когда тебе нужно найти деталь — то по коробочка найдешь сразу (при грамотном структурировании). А кучу нужно перебирать каждый раз с нуля.

S>>Ок, выгнал (а скорее тот сам ушел еще до того, как проблема стала очевидной). Берет нового — новый говорит что нужно все переписывать с нуля. Берет другого — тот делает вид что работает, месяц делает вид, два — говорит что еще разбирается в проекте. А потом начинает работать еще медленнее.

G>Если ты заказчик, который не разбирается в процессе, то плати только за результат, а не за время

Но тогда ты просто перекладываешь проблему разработки и чистоты кода на чужие плечи. А проблема эта никуда не ушла. Лучше разберись сам и научить чистоте кода без привлечения посредников.
Re[5]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.11.25 03:27
Оценка: +1
Здравствуйте, Shmj, Вы писали:

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


G>>А откуда мнение что код с кучей dto и мапперов менее запутанный и проще поддерживается чем без него?

G>>Я вот проводил замеры maintainability index для кода с разделением и без и не код с разделением стабильно проигрывал.
G>>Это потом что maintainability index зависит от halastead volume, по сути от нормированного количества строк.

G>>В целом я не понимаю как увеличение количества кода может положительно сказываться на стоимости поддержки.


S>Ну на счет разделения объектов (для каждого слоя свой набор объектов) + мапперы — вижу только один смысл — когда над каждым слоем работает отдельный человек и чтобы не ждать пока Вася изменит свой слой — Петя может уже создавать и тестировать. А уже отдельный чел. занимается исключительно мапперами и интеграцией слоев в единую систему.

Это возможно если для реализации требований нужно менять верхние слои, при этом не трогая нижние . Но при разделением как рекомендует domain model или onion/hexagon/clean architecture это невозможно, так как почти каждое значимое изменение требований приведет к изменению не только представления, но и хранимых данных, и, соответственно, всех слове между ними.


S>Других плюсов особо не видно. Т.е. если у вас нет строгого разделения труда — то нет смысла и в строгом разделении объектов. Но когда несколько человек работают над системой одновременно и каждый занимается своим слоем — появляется смысл все-же.

На практике удобнее не горизонтальное, а вертикальное деление. Например asp.net identity. Показывает как можно сделать отдельную функциональность, котрая содержит как работу с базой, так и часть представления, при этом достаточно хорошо кастомизируется и интегрируется с другими частями

Но конечно в asp.net identity вы не найдете паттерном clean archtecture

S>А вот строгость в придерживании архитектуры, как то принято писать ViewModel — но ты для отдельных форм это не применяешь (а просто напрямую вызываешь api-методы и базу из обработчика кнопки) — тут есть минус. А именно, код становится сложнее поддерживать, сложнее дорабатывать.


Я, честно, не видел современных приложений построенных по такому принципу. За счет того что везде есть data binding проще иметь промежуточный объект, к которому привязывается форма, а внутри него уже дергать методы БЛ. А если мокать бл для объекта, то можно удобно тесты писать

S>>>И что заказчику делать, если разработчик три дня исправляет простой баг а после исправления создает новый баг? Выгонять?

G>>Чтобы ответить на этот вопрос надо понимать почему так происходит.

S>Порядок. Вот в вещах порядок — можно все разложить по коробочкам (особенно поймут электронщики). А можно как бы не заморачиваться и все вывалить в одну большую кучу.

Если бы «раскладывание по коробочкам» было бесплатно, то все бы так делали. Но почему-то нет. См тот же asp.net identity

S>Когда тебе нужно найти деталь — то по коробочка найдешь сразу (при грамотном структурировании). А кучу нужно перебирать каждый раз с нуля.

Мне кажется это миф, все равно надо читать код и делать go to definition. И чем меньше кода и перекладываний объектов, тем проще. По крайней мере я на себе ни разу не замечал улучшение чтения от разделения.

S>>>Ок, выгнал (а скорее тот сам ушел еще до того, как проблема стала очевидной). Берет нового — новый говорит что нужно все переписывать с нуля. Берет другого — тот делает вид что работает, месяц делает вид, два — говорит что еще разбирается в проекте. А потом начинает работать еще медленнее.

G>>Если ты заказчик, который не разбирается в процессе, то плати только за результат, а не за время

S>Но тогда ты просто перекладываешь проблему разработки и чистоты кода на чужие плечи. А проблема эта никуда не ушла. Лучше разберись сам и научить чистоте кода без привлечения посредников.

Далеко не каждый сам способен разобраться
Re[11]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 04.12.25 18:50
Оценка: +1
Здравствуйте, Qulac, Вы писали:

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


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


Q>>>Clean Architecture не мешает разрабатывать в любом направлении.

G>>Честно до сих пор не понимаю что такое CA.
G>>Если я написал контроллер из которого вызвал EF и данные в базу записал это уже clean или еще нет?
G>>Если мне для Clean Architecture еще что-то сделать, то это уже программирование «снизу вверх».

Q>Нет не CA.

Тогда оно не очень нужно.

Q>Лучше книжку почитать, самому поэкспериментировать.

Спасибо, обойдусь.
Re[11]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.12.25 07:15
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>Я говорил что надо уменьшить количество строк.


Смотрите сам, что вы пишете "кода с разделением и без и не код с разделением стабильно проигрывал"

G>Во-первых

G>Во-вторых
G>В-третьих
G>В-четвертых
G>В-пятых

На примере 1 файл 1 main вам вроде бы понятно, какие последствия если отказаться от того самого разделения.
А вот с мапперами вам почему то непонятно
Любой концепт — класс, функция, интерфейс, итд, это то самое разделение.
Если бенефитов нет, см ваши "во-первых..." то добавление класса, функции, интерфейса, итд смысла не имеет. Мапперы, паттерны здесь ничего не меняют.

P>>Но чем больше и сложнее, приложение, тем больше и глубже будет разделение на внутренние компоненты.

G>Не очень понятно где от одного файла и все в main перейти к domain model.

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

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

G>Если ты заранее генерируешь ДТО на каждый слой, то тебе уже нужен маппер.

А кто говорил, что надо заранее? Любое разделение обязанностей, см ваши пункты про main, нужно вводить вовремя. Слишком рано — утяжеляем и замедляем разработку. Слишком поздно — хаос.

P>>Если у вас 1 бд, 1 ui, и ничего больше — от мапперов толку мало.

G>Апологеты DDD скажут что толк есть, негоже на UI отдавать доменные объекты.

Да, есть люди, у которых инструмент важнее задачи. Что это доказывает? Это во всех методологиях ровно так же.

P>>А если у вас вспомогательная утилитка "скопировать 5 юзеров из той бд в эту" то вам вообще хватит 1 файл + 1 main.

G>Если программу изначально создавать как большую, то и получится большая, с кучей мапперов и ДТО, если по итогу она только 5 юзеров копирует.

А если изначально большую писать как маленькую, то есть чудовищно огромный шанс или утопить, или вырастить монстра, или убить весь бюджет на один только рефакторинг.

G>Я всегда говорил, что нужно в каждый момент времени писать минимум кода для решения задачи, которая есть в данный момент. ИМХО в таких условиях вероятность появления domain model и DTO стремится вообще к нулю.


Ой да ладно. Вы подразумеваете какой то свой набор приложений-проектов. Озвучьте уже его.
Re[9]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.12.25 16:25
Оценка: +1
Здравствуйте, Kernan, Вы писали:

G>>Процитирую основную мысль:

G>>

G>>При проектировании снизу вверх вы начинаете с компонентов, которые вам хорошо видны, но пока неясно, как они сочетаются друг с другом. Вы пишете компоненты по отдельности, тестируете их, а затем собираете в целую программу.

K>Не совсем понятно как это работает, если честно.


K>Со старта я начинаю собирать сценарии использования

Сценарий использования это набор форм и или методов апи — создай эти формы\методы для начала
На формах есть поля, у методов есть входные и выходные данные. Сделай валидацию входных данных, сделай заглушку для возвращаемых данных.
Далее если одна функция данные сохраняет, а вторая возвращает, то напиши код который это делает самым простым способом — вызови напрямую ef\dapper\sqlclient что проще.
Повтори процедуру для других форм и методов. Устрани противоречия. Сделай рефакторинг, вынеси повторяющийся код в отдельные функции\классы. Только тут могут появиться простые паттерны GoF. До DDD и прочих архитектурных излишеств не дойдет если не пытаться решать задачи, которых нет.

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

Мне кажется программисты слишком заморочены на "модели предметной области", как-будто есть в этом ценность.
Re[10]: Что если не разделять строго dto, entity, bo...
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 05.12.25 17:19
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

K>>Со старта я начинаю собирать сценарии использования

G>Сценарий использования это набор форм и или методов апи — создай эти формы\методы для начала
А лучше начать с тестов...
G>Повтори процедуру для других форм и методов. Устрани противоречия. Сделай рефакторинг, вынеси повторяющийся код в отдельные функции\классы. Только тут могут появиться простые паттерны GoF. До DDD и прочих архитектурных излишеств не дойдет если не пытаться решать задачи, которых нет.
Не получилось бы так, чтобы всё написанное не пришлось бы переписать полностью после неудачных решений по-месту.
G>Мне кажется программисты слишком заморочены на "модели предметной области", как-будто есть в этом ценность.
Проще работать с моделями и метафорами чем с набором примитивных типов.
Sic luceat lux!
Re[14]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.12.25 17:53
Оценка: +1
Здравствуйте, Shmj, Вы писали:


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


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

Сохранять простоту кода при разработке нетривиальных программ — сложный навык: требует концентрации, чтения существующего кода, постоянного изучения новых библиотек. Но эти затраты многократно окупаются на поддержке.
Если хорошо натренировать всегда выдавать максимально простой код, то это будет сильно быстрее, чем то, что фигачат DDD-программисты и всякие ИИ. Потому что есть предел количества строк отлаженного продуктивного кода, который может выдавать программист в единицу времени. И он почти не зависит ни от языка, ни от архитектуры.
Re[14]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.12.25 10:52
Оценка: -1
Здравствуйте, Pauel, Вы писали:

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


G>>В этом случае конечно второе. Но это уже последствие.

G>>Ведь кто-то изначально написал эти 10к ЛИШНИХ строк, потратив кучу времени и денег.
G>>А если бы с самого начала не занимались этим, то вариант 2 не возник бы никогда.

P>Почему обязательно лишних, и потратив кучу времени и денег? Может оказаться что всё ровно наоборот.

P>Например, на момент написания эти 10к строк решали конкретные требования которые со временем отжили своё. Или, например, срочность изменений в требованиях была настолько высокой, что другого варианта, кроме как строчить и копипастить, вообще не было.
P>То есть, чаще всего вот эти "лишние" строки становятся такими только со временем. Это если отказаться от варианта "все дураки"
Тогда в чем проблема удалить код, который вообще не используется? Это же требует примерно 0 усилий.

Проблема удаления кода возникает когда он используется, на него много зазвано.

Например напрмиер предполагали высокую нагрузки и сразу же сделали систему "масштабируемой" за счет CQRS, а оказалось что нагрузка вполне приличная, а CQRS не обеспечивает транзакционность в нужных сценариях. Но вся бизнес-логика уже заточена на CQRS. И новые требования, касающиеся транзакционности, можно реализовать или навесив глобальный лок на таблицу, а можно выкинуть CQRS и сделать обычную транзакцию. Причем выкинуть локально, в одном методе, CQRS не получится, так как БЛ не может работать без него, надо или дополнительные связи в проект прокидывать или переписывать BL.

Причем мы же прекрасно понимаем, что в момент когда кто-то решил что нужно CQRS, то никакой явной потребности в этом не было.

P>Поэтому вопрос в том, какая у нас перстпектива в проектировании:

P>Если краткосрочная, "главное сделаить", тогда нужно строчить, копипастить и срезать углы, или просто лепить однострочники абы кода было поменьше.
P>Или же среднесрочная-долгосрочная, тогда нужно определиться какие же актуальные цели кроме "главное сделать".
Это же две альтернатиы, а целый континуум. Я предлагаю делйствовать как завещал Кент Бек: Make it work, make it right, make it fast.
То есть сначала делаем "главное чтобы заработало", потом устраняем ошибки в corner cases, очевидные code smells, вписываем в сущствующую архитектуру, делаем оптимальным.
Главное фокусироваться на одной задаче, а не заниматься проектированием системы. То есть не трогать ничего, что напрямую не касается данной задачи.

P>Например, реанимировать проект краткосрочными интервенциями "главное сделать" не получится. Скорее всего, он именно и зашел в тупик благодаря "главное сделать".

Как раз наоборот, в тупик заходят проекты, "проектируют наперед". Потому что если ты каждый раз делаешь минимум кода для решения задачи, то по какой причине у тебя появится тонна ненужного, но используемого кода?
Re[16]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.12.25 13:42
Оценка: +1
Здравствуйте, Sharov, Вы писали:

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


G>>Если хорошо натренировать всегда выдавать максимально простой код, то это будет сильно быстрее, чем то, что фигачат DDD-программисты и всякие ИИ. Потому что есть предел количества строк отлаженного продуктивного кода, который может выдавать программист в единицу времени. И он почти не зависит ни от языка, ни от архитектуры.


S>Я ни разу не апологет DDD, ни одной (пока) книги не прочитал, хотя тему изучал. Так вот, люди его не зря ценят, начиная от определенного объема

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

Я заявления эти тоже слышал, но на практике подтвердить не могу.

Любое тестовое приложение ограниченного объема без ДДД оказывается проще и быстрее, чем с DDD.
Найти два эквивалентных приложения одно с ДДД, а другое без для сравнения невозможно.
Некоторые парттерны DDD в некоторых условиях заведомо хуже работают, при этом явная выгода от них отсутствует.

Поэтому все что я видел глазами это то, что DDD несет большую сложность без какой-либо выгоды в небольшом приложении (условно до 10к строк), а какая выгода в большом — мне не ясно.
Re[15]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.12.25 15:36
Оценка: +1
Здравствуйте, Sharov, Вы писали:

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



S>>>Считается, что первое достигается при помощи второго.

G>>Не понимаю логики:
G>>1) считается что без "модели предметной области" не бывает хорошей структуры кода? Это мягко говоря неправда
G>>2) считается что наличие "модели предметной области" всегда приводит к хорошей структуре? Это еще большая неправда

S>Понимание модели предметной области помогает достигать качественного кода -- все по папочка и т.п., а не в одном большом

S>методе main.

Вы сейчас пытаетесь сказать, что не бывает хорошего структурированного кода без "модели предметной области"? Я еще раз повторю что это неправда, предлагаю перестать об этом говорить.
Могу показать примеры хорошего структурированного кода, где нет ничего, что можно было было назвать "моделью предметной области". Опять-таки можно сказать что это простые примеры, но я не видел сложных примеров с ДДД, где везде хороший структурированный код.
Re[17]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.12.25 10:27
Оценка: +1
Здравствуйте, Sharov, Вы писали:

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


G>>Вы сейчас пытаетесь сказать, что не бывает хорошего структурированного кода без "модели предметной области"? Я еще раз повторю что это неправда, предлагаю перестать об этом говорить.


S>А какую проблему решает хороший код, если он даже не пытается моделировать предметную область, т.е. не оперирует необходимыми абстракциями?

1) Уменьшает дублирование кода
2) Уменьшает количество связей и сайд-эффектов
3) Уменьшает цепочку вызовов и количество промежуточных слоев между вызовов и действием
4) Увеличивает быстродействие
5) Уменьшает неявную передачу данных и изменение стояния
Это все вещи связанные, но в некоторых местах могут противоречить друг другу, поэтому хороший код это баланс.


S>По-моему, даже на не ООП языках типа С люди стараются оперировать абстракциями в коде.

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

G>>Могу показать примеры хорошего структурированного кода, где нет ничего, что можно было было назвать "моделью предметной области". Опять-таки можно сказать что это простые примеры, но я не видел сложных примеров с ДДД, где везде хороший структурированный код.

S>Давайте, а то мне кажется мы говорим о разном, подразумевая "модель предметной области".
Начнем с простого, позже смогу вырезать кусок из реального проекта.
Недавно делал пример для статьи на Хабре https://github.com/gandjustas/habr-post-stock-api, АПИшка для резервации заказов, работает с базой, содержит очень важную для бизнеса логику. Это как маленький кусок большого приложения
Там даже есть абстракция — очередь запросов (она не шибко полезная в целом)

Что там является "моделью предметной области", в чем её ценность, и как она влияет на остальные части кода?
Re[18]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 02.01.26 01:37
Оценка: -1
Здравствуйте, Pauel, Вы писали:

G>>Обычно мертвый код выглядит как классы которые нигде не создаются, находятся тремя-четырьмя кликами в студии.


P>Необязательно. Чаще всего они могут создаться, вызываться итд по недостижимым путям. У вас нет абсолютно точного синтаксического анализатора, который выдаст всё на блюдечке — проблема останова мешает.

Если у вас код запускается недостижимыми путями (что бы это не значило), то проблемы в архитектуре гораздо серьезнее, чем лишний код.


P>>>Это всё крайне растяжимое. У каждого своё видение, насколько глубоко это всё надо делать.

G>>Рамки задачи всегда можно сохранить. Просто задавай себе вопрос: "как это влияет на ту задачу, которую мне сейчас необходимо решить?". Если никак, то не надо этого делать.
P>Вы в слова играете. У каждого своё видение, что именно относится к задаче.
В итоге все сойдутся на мнении лида и оно станет одно.


G>>Кроме того, я изначально писал что нужно заниматься проектированием и программированием "сверху вниз", тогда контролировать скоуп несложно.

P>Это общие слова.
Это волне конкретный порядок действий, я не буду сюда очередной раз копипастить контент статьи.

P>>>Одна единственная задача это только краткосрочная перспектива.

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


P>>>Пример — думали хватит чисто эндпоинта таскать из ui в базу и обратно, а после первого релиза вылезло такое...

G>>Ну так после первого релиза и поправьте. Никто ведь заранее не знал, что вылезет после релиза, а если бы пытались угадать, то вероятнее всего не угадали бы.
P>В этом и есть проектирование — выяснить, какие у вас цели, абы сделать, или глянуть чуть дальше, те самые среднесрочные-долгосрочные цели.
У меня есть эпичный пример на этот счет.
Был такой один проектировщик. Он даже ен ИТшник был, а фин менеджер. Проектировал процесс согласования. Говорил что должно быть строго три согласующих, потому что так уже 7 лет в компании было. И буквально на следующий день, как выпустили процесс, согласующих стало 2.
Как бы красиво не называли, это все попытка угадать будущее. И чаще всего люди не угадывают. Поэтому единственный универсальный способ — написать сегодня настолько мало, чтобы завтра было не жалко выкинуть.
Как только вы начинаете проектировать наперед, то создаете кучу ограничений и потом сложнее отказаться от написанного, ибо работает когнитивная ошибка невозвратных затрат, да и просто обосновать зачем столько делали становится сложнее.


P>>>Я вам уже привел пример Хорошее проектирование это не только здесь и сейчас, за что вы топите, но прежде всего и адеватный горизонт планирования.

G>>Практика показывает что занимаясь проектированием "только здесь и сейчас" почти всегда получается компактный код, который легко поддерживать.

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

Зачем нужна обратная совместимость?
1) если добавляется необязательное поле, то старый код продолжает работать
2) если поле обязательное, то старый код в любом случае сломается
3) если происходят более значимые изменения, то просто создается новый метод (возможно с номером версии в сегменте пути, querystring или заголовке)

P>Или вы предлагаете сначала сломать, а потом, если у когото утекут миллионы, завести тикет и начать фиксить?

Если задача создать новый метод не поломав старый, то она решается целиком. А не так, что сначала создается новый, а потом чинится старый. Некоторые изменения в системах должны быть атомарны — это и будет одна задача для одного программиста.
Re[19]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.01.26 12:41
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

P>>Необязательно. Чаще всего они могут создаться, вызываться итд по недостижимым путям. У вас нет абсолютно точного синтаксического анализатора, который выдаст всё на блюдечке — проблема останова мешает.

G>Если у вас код запускается недостижимыми путями (что бы это не значило), то проблемы в архитектуре гораздо серьезнее, чем лишний код.

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

P>>Вы в слова играете. У каждого своё видение, что именно относится к задаче.

G>В итоге все сойдутся на мнении лида и оно станет одно.

Или не сойдутся, например, лид в отпуске, на больничном, на мите, на собесе, а надо срочно, итд итд итд. А может просто часть вещей делегировал не тем людям.

G>>>Это именно краткосрочная.

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

Не надо будущее угадывать. Есть вещи, которые известны наверняка. Например, при написании логирования вы точно знаете, что логи нужно будет где то собирать, смотреть, мониторить, читать, анализировать и тд.
Соотвественно, нужно включать голову и писать ровно то, что точно понадобится позже, а не в момент X заводить тикет "в логах херня ничо не ясно"

G>Как бы красиво не называли, это все попытка угадать будущее. И чаще всего люди не угадывают. Поэтому единственный универсальный способ — написать сегодня настолько мало, чтобы завтра было не жалко выкинуть.


Браво — у вас та самая попытка угадать будущее, предположение что всё нахрен не надо. Так себе идея. Обычно при проектировании учитывают как минимум известные риски. Например, закладывают некоторую ожидаемую нагрузку.
А если вас буквально воспринять, то такими глупостями вообще заниматься не надо. А что — пока проект не стартовал, нагрузка неизвестна.

P>>>>Я вам уже привел пример Хорошее проектирование это не только здесь и сейчас, за что вы топите, но прежде всего и адеватный горизонт планирования.

G>>>Практика показывает что занимаясь проектированием "только здесь и сейчас" почти всегда получается компактный код, который легко поддерживать.

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

Как минимум, код должен быть поддерживаемым, читабельным, сопровождаемым. Иначе вы его даже выбросить не сможете, хоть и сильно-сильно захотите. А это именно то самое будущее которое, по вашему, никак не доступно, ужос-ужос.

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

G>Зачем нужна обратная совместимость?
G>1) если добавляется необязательное поле, то старый код продолжает работать

Необязательно

G>2) если поле обязательное, то старый код в любом случае сломается


Необязательно

G>3) если происходят более значимые изменения, то просто создается новый метод (возможно с номером версии в сегменте пути, querystring или заголовке)


Необязательно

Вы шота держитесь за какой то свой вариант

G>Если задача создать новый метод не поломав старый, то она решается целиком. А не так, что сначала создается новый, а потом чинится старый. Некоторые изменения в системах должны быть атомарны — это и будет одна задача для одного программиста.


Важно не то, как вы будете создавать, а как вы будете деливерить. Многие вещи будут слишком большим изменением на одного программиста.
Re[23]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.01.26 16:21
Оценка: +1
Здравствуйте, Sharov, Вы писали:

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



G>>Я не утрирую, с 2002 по 2017 год было всего два визионера про DDD, и одна достойная книга про DDD, не на Java, и Фаулер, который активно это все пиарил в своем блоге.


S>А сколько визионеров надо, что технология взлетела? У ООП много было визионеров, тоже 2-3 человека.

Считаем:
1) Создатели языка Simula, где впервые появилось слово class — Оле-Йохан Даль и Кристен Нюгор, оба профессора
2) Алан Кей, который придумал сам термин ООП и язык Smalltalk, который под воздействием Simula получил понятия "класс" и "объект"
3) Бьёрн Страуструп, который идею классов и объектов натянул на С++, дав начало большей части современных ОО-яызыков

Каждый из них в отдельности имеет больше достижений, написал больше статей и больше создал кода, чем все авторы по DDDвместе взятые.


S>По DDD уже много лет конференции проводят -- https://www.youtube.com/@ddd_eu

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


S>>>Я просто не считаю правильным отмахивать от DDD, как о бесполезной штуке. Оно большое, и люди частями или целиком его вполне успешно применяют.

G>>А чем измеряется успех? В том что программа работает? В том что заказчик платит денег? Может это успех вопреки? Может без DDD денег было бы больше, а программа правильнее?
S>Ну какая-то статистика и выборка же есть, этим не одна компания занимается. Метрики такие, например, что сложный софт развивается.
S>Т.е. заказчик деньги платит не зря.
Повторить аргумент про лженауки?

G>>Без сравнения в равных условиях мы не узнаем.

S>Ну такой себе странный аргумент. Лишних денег ни у кого нету. Разве что у крупняка типа ibm, которые могут себе позволить несколько назависимых отделов
S>для решения одной проблемы.
То есть просто вера, что DDD помогает? Верить не мешает. Но для участия в научном споре одной веры недостаточно.


S>>>Что в этом плохого и кто с этим спорит? В DDD есть паттерн Repository, как раз и отвечает за сохранение главных

S>>>доменных сущностей, наверное и таблицы соотв. должны были быть.
G>>Ты не на тот вопрос отвечаешь. Вопрос такой: является ли набор классов без логики, с которыми работает ORM, "моделью предметной области" в понимании ДДД (по книгам)? Я могу однозначно сказать что нет.
S>Без логики не является, и? ORM это не тот уровень, на котором стоит обсуждать DDD.
Почему? Меня интересует только подход к проектированию и написанию кода. Если DDD не про это, то я не понимаю о чем говорить.

S>Он там спрятан за паnтерном Repository.

И какой интерфейс выставляет этот Repository?


G>>>>А кто сказал что отсутствие "объектов доменной модели" автоматически приводит к плохому решению задачи?

S>>>Никто не сказал, просто это, кхм, странно. Задача софта эмулировать соотв. процессы. Как можно эмулировать что-то без соотв. сущностей?
G>>Еще раз. DDD как набор паттернов, говорит нам:
G>>- Domain Model это набор классов с данными поведением, которые соответствуют существительным в едином языке, выработанным между бизнесом и командой разработки
G>>- Вся бизнес-логика (Core Domain) должна быть описана как взаимодействие этих объектов
S>Там вроде, все строится вокруг взаимодействия AggregateRoot'ов, которые несколько больше чем просто "набор классов с данными поведением".
Если для реализации поведения вам нужны Order, Line и Product, то они попадут в один агрегат.

G>>Я сейчас не буду говорить о том, насколько корректно так проектировать программы, но без этого DDD не будет считаться DDD.

S>Я пока понять не могу, что в этом плохого?
Если программа НЕ будет соответствовать паттернам DDD она будет лучше, чем если будет им соответствовать.



S>Это уход от ответа на конкретный вопрос. Речь не про одинаково. Программа написана хорошо, но не покрывает большую часть use-case'ов или делает это криво. У другой все наоборот.

То есть одна программа не решает проблему пользователя, а другая решает.
Только от наличия "модели предметной области" это не зависит. Может быть модель и не решать проблему, а может не быть и решать.

S>Какой программист больше заработает денег?

Зависит от разницы в цене и насколько пользователь готов пожертвовать решением за эту разницу


S>>>Я вообще не вижу противоречия между хорошим кодом и объектами доменной модели. Это прям какая-то странная дихотомия.

G>>Я тоже не вижу. Качество программы и наличие в ней domain model — вещи ортогональные, то есть независимые друг от друга.

S>Ну т.е. можно использовать excel в качестве бд, написан хорошо, данные хранить может. Или все же возьмем что-то другое для данной задачи?

Ты про мой пример? Там конечно эксель не подойдет, ибо нужны ACID транзакции, которые работают конкурентно. Эта задача решается в РСУБД из коробки, даже писать ничего не надо.
Для других задач может и эксель подойти, но он не обеспечивает sql-совместимого интерфейса и не может использоваться с существующими библиотеками, поэтом маловероятно.


G>>>>Является "оперированием объектами доменной модели"?

S>>>Скорее оперирование представлением в бд.
G>>То есть не соответствует DDD никак, да еще и ужасную вещь делает с точки зрения Clean Architecture — прибивает бизнес-логику к инфраструктуре.
G>>Причем этот код решает задачу "сделать отгрузку товаров со склада X", которую крайне сложно описать в DDD, особенно чтобы была изоляция. Внезапно еще и "отгрузка" никак не фигурирует в моделях БД.
S>Этот код может и ракету в космос запустить, дальше что?
Интересное утверждение. Каким образом он может ракету запустить?



G>>Когда у нас программа работает на компьютере пользователя, в одном процессе (адресном пространстве) и её состояние существует столько, сколько существует процесс, то требования будут одни. Если состояние программы хранится во внешнем хранилище, к которому надо обращаться по ненадежной сети, причем обращаться могут несколько пользователей из разных экземпляров программы, то требования получатся совершенно другие. И подходы к проектированию и реализации программы будут разные.

S>Инвариант класса называется, которое Б. Мейер лет 40 назад ввел в обиход. При чем здесь бд или сеть?
Инвариантность класса не помогает обеспечить целостность состояния во внешнем хранилище.


G>>Любую теорию, например теорию о полезности DDD, можно считать научной если существует хотя бы один эксперимент, который может теорию опровергнуть, даже если он еще не проведен. Это называется критерий фальсифицируемости поппера.

G>>А если такого эксперимента не существует, то это уже не теория, а вера.
S>Я не понимаю о чем идет речь и к чему эти странные вопросы и ответы с отсылками на Поппера. Возьмите какой-нибудь проект по DDD и подсчитай в нем ф-ии.
И как это поможет доказать что DDD имеет какие-то преимущества?

S>Если так подходить, то сколько надо строк кода, чтобы ООП давал выхлоп?


вот минимальный пример:
abstract class CollectionBase<T>
{
    public int Count { get; private set; }

    protected virtual void AddCore(T item)
    public void Add(T item) 
    {
         AddCore(item);
         Count+=1;
    }

    protected virtual T GetCore(int index);
    public T Get(int index)
    {
       ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, Count);
       ArgumentOutOfRangeException.ThrowIfNegative(index);
       return GetCore(index);  
    }
}

Тут и наследование, и инкапсуляция, и полиморфизм, и OCP, и LSP.
Попытка получить от кода те же свойства без наследования, инкапсуляции и полиморфизма ни к чему хорошему не приведут.

А если взять чуть побольше пример, как в GoF про паттерн Composite, то ООП то там еще лучше получается.


S>Может < писать на Си или ФЯ? Но почему-то для простейших задачи на сотни строк кода все равно используют ООП. Странно, правда?

Мне кажется что осмысленно говорить, что кто-то использует ООП, только когда есть наследование, инкапсуляция и полиморфизм.
Я видел много кода на C#, который с точностью до синтаксиса и названия библиотек\неймспейсово\классов\методов можно переписать на Rust. Использует ли такой код на C# ООП? Я считаю что нет.
Отредактировано 07.01.2026 17:48 gandjustas . Предыдущая версия .
Re[25]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 13.01.26 08:24
Оценка: +1
Здравствуйте, Sharov, Вы писали:

S>Все это так, но речь не об этом. Все это ученые и компиляторо писатели. А Эрик Эванс вроде разрабатывал бизнес приложения, и вроде (но не точно) работал в ibm.

Честно говоря я вообще не знаю чем ванс занимался до написания книги и есть и значимые проекты в его истории. После он начал заниматься консалтингом.


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

Вроде ты сам пытался сравнить DDD и ООП.

S>>>По DDD уже много лет конференции проводят -- https://www.youtube.com/@ddd_eu

G>>Это вообще не показатель. Люди астрологией и гомеопатией занимаются, гораздо больше лет конференции проводят. Программисты тоже подвержены влиянию всяких лженаук.
S>Ну не скажите, там иногда читают очень достойные доклады. Вот например:
S>https://www.youtube.com/watch?v=KTy4rqgPOjg
Не понял что в этом докладе интересного. Целый час только ради одного слайда с одной мыслью

Pain = Strength * Volatility * Distance.

Reduce one of them to 0 to minimize the pain of necessary coupling.


S>>>Ну какая-то статистика и выборка же есть, этим не одна компания занимается. Метрики такие, например, что сложный софт развивается.

S>>>Т.е. заказчик деньги платит не зря.
G>>Повторить аргумент про лженауки?

S>В чем проблема найти компании и продукты у которых работает DDD? Спросите нейронку какую-нибудь. Наверняка что-то есть из докладов по ссылке выше.

Еще раз повторить аргумент про лженауки? У кого-то и астрология "работает".
Единственный способ доказать что что-то работает — провести эксперимент. Для ДДД это простой эксперимент — берем любой код с DDD, делаем эквивалентный без DDD и сравниваем объективные показатели — объем кода, количество связей между классами итд.

Важно взять именно работающий код, решающий задачу от начала до конца.

S>>>Ну такой себе странный аргумент. Лишних денег ни у кого нету. Разве что у крупняка типа ibm, которые могут себе позволить несколько назависимых отделов

S>>>для решения одной проблемы.
G>>То есть просто вера, что DDD помогает? Верить не мешает. Но для участия в научном споре одной веры недостаточно.
S>А в ООП тоже верят? Ведь есть проекты для которых он избыточен, но все равно будет написано с 95% на каком-нибудь ООП языке.
Некоторые не верят, но что это меняет? Современные языки используют ОО-парадигму и часто базовые библиотеки реализованы как библиотеки классов. То есть ты любом случае будешь использовать ООП, даже если сам не придерживаешься ОО-парадигмы.

S>>>Без логики не является, и? ORM это не тот уровень, на котором стоит обсуждать DDD.

G>>Почему? Меня интересует только подход к проектированию и написанию кода. Если DDD не про это, то я не понимаю о чем говорить.
S>Он не про ORM и таблицы в бд.
А про что?
Меня интересует подход к проектированию от начала до конца, а не просто в какой-то части, делая вид что других не существует.


G>>>>- Вся бизнес-логика (Core Domain) должна быть описана как взаимодействие этих объектов

S>>>Там вроде, все строится вокруг взаимодействия AggregateRoot'ов, которые несколько больше чем просто "набор классов с данными поведением".
G>>Если для реализации поведения вам нужны Order, Line и Product, то они попадут в один агрегат.
S>Вероятно и у приложения будет один Bounded Context и один микросервис. Что не так?
Если order, line и product в одном агрегате, где root это order, то как получить список "лидеры продаж" с топ 30 товаров за месяц.

S>>>Я пока понять не могу, что в этом плохого?

G>>Если программа НЕ будет соответствовать паттернам DDD она будет лучше, чем если будет им соответствовать.
S>Зависит от сложности. Ну найдите людей у которых все по DDD и поговорите с ними. Писать калькулятор по DDD странно, но какой-нибудь банковский софт, где требования регулярно меняются вполне может быть ок. Как обычно -- it depends.
См выше про эксперимент. Мнение интересует в последнюю очередь.


S>>>Инвариант класса называется, которое Б. Мейер лет 40 назад ввел в обиход. При чем здесь бд или сеть?

G>>Инвариантность класса не помогает обеспечить целостность состояния во внешнем хранилище.
S>Если сохранять класс, когда у него все ок с инвариантами, то почему нет?
Потому что в рамках одного класса нельзя сделать контроль остатков.

S>Для пользователя класса у него всегда должны быть инварианты, пользователь затем может этот класс сохранить.

Как описать инвариант: остаток товаров на складе должен быть не меньше суммы зарезервированных?

S>>>Я не понимаю о чем идет речь и к чему эти странные вопросы и ответы с отсылками на Поппера. Возьмите какой-нибудь проект по DDD и подсчитай в нем ф-ии.

G>>И как это поможет доказать что DDD имеет какие-то преимущества?
S>А как это может доказать обратное? Зачем вообще что-либо подсчитывать?
Затем что нужны объективные измеримые показатели преимуществ того или иного подхода: объем, цикломатическая сложность, вложенность вызовов. Иначе это вера, а не инженерный подход.

S>А как люди с коллекциями на Си работали и работают?

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

S>Тем не менее пишут же зачем-то на C#.

Потому C# и дотнет предоставляет много готовых согласованных между собой библиотек для решения прикладных задач.
Re[27]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.01.26 08:01
Оценка: +1
Здравствуйте, Sharov, Вы писали:

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


S>>>Все это так, но речь не об этом. Все это ученые и компиляторо писатели. А Эрик Эванс вроде разрабатывал бизнес приложения, и вроде (но не точно) работал в ibm.

G>>Честно говоря я вообще не знаю чем ванс занимался до написания книги и есть и значимые проекты в его истории. После он начал заниматься консалтингом.

S>Я тоже не знаю. Но он как и Фаулер или дядя Боб -- что-то поделали в самом начале, потом решили лопаты продавать книги писать.

Товарищ Мартин свой опыт описывает во множестве книг, например он участвовал в разработке Rational Rose в IBM, где видимо и упорролся в "компонентность", что легло в основу его книги clean architecture. Фаулер не был выдающимся инженером, но он был "computer scientist" — изучал существующие методики, и придумывал новые, о чем очень много писал статей в доинтернетную эпоху. Он стоял у истоков Agile вместе с Беком и фактически ввел в обиход термин "рефакторинг".

А что касается Эванса — я вообще не нашел историю чем он занимался до книги и каких-то достижений после публикации тоже нет. Других книг он не выпускал.
Мне кажется что товарищ эванс вообще является подставным лицом, и DDD придумал Фаулер, но по причине неполного содержания книги, несвойственного Фаулеру, выпустил не под своим именем, а нашел соавтора.


S>>>В чем проблема найти компании и продукты у которых работает DDD? Спросите нейронку какую-нибудь. Наверняка что-то есть из докладов по ссылке выше.

G>>Еще раз повторить аргумент про лженауки? У кого-то и астрология "работает".
G>>Единственный способ доказать что что-то работает — провести эксперимент. Для ДДД это простой эксперимент — берем любой код с DDD, делаем эквивалентный без DDD и сравниваем объективные показатели — объем кода, количество связей между классами итд.
G>>Важно взять именно работающий код, решающий задачу от начала до конца.

S>Мне это не интересно. Вам интересно, вы и делайте.


S>Я хочу донести мысль, что огульно выкидывать ДДД не стоит -- для кого-то на каких-то проектов он работает.

Это опять слепая вера. Если хотите сказать что DDD работает лучше чем нажимать рандомные кнопки на клавиатуре, то конечно работает. Как и любая методика проектирования и любые паттерны. Если мы говорим о применении конкретных паттернов, то появляются вопросы эффективности, но которые уже 20 лет нет ответа.

S>Я работал в компании, которая распиливала монолит на микросервисы по ДДД. Использовали стратегические паттерны.

Какие паттерны?

S>>>Он не про ORM и таблицы в бд.

G>>А про что?
S>101 раз говорю, что там все эти детали скрыты за паттерном Репозиторий. ДДД, кажется, не об этом.
А о чем тогда? Ну это смешно: как только в обсуждении DDD доходит до деталей, то "DDD не об этом". Что DDD в любой программе касается 10% не самого важного кода. Поэтому чтобы такие спекуляции исключить я и предлагаю взять пример, который от начала до конца работает.


G>>Меня интересует подход к проектированию от начала до конца, а не просто в какой-то части, делая вид что других не существует.

S>Это подход к проектировании на основе проблем бизнеса, а не про орм или таблицы.
В результате ведь получается код, который рабоает с таблицами в БД и, вероятнее всего, с помощью ORM. Или нет?

S>>>Вероятно и у приложения будет один Bounded Context и один микросервис. Что не так?

G>>Если order, line и product в одном агрегате, где root это order, то как получить список "лидеры продаж" с топ 30 товаров за месяц.
S>Какой-то метод добавить в репозиторий, наверное.
Это тот самый репозитрий, который скрывает детали? То есть важнейшее требования — это "детали", которые надо "скрывать"?
И кто вызывать будет этот репозиторий?


S>>>Зависит от сложности. Ну найдите людей у которых все по DDD и поговорите с ними. Писать калькулятор по DDD странно, но какой-нибудь банковский софт, где требования регулярно меняются вполне может быть ок. Как обычно -- it depends.

G>>См выше про эксперимент. Мнение интересует в последнюю очередь.

S>Сдается мне, на ООП языках вы стали писать без всяких экспериментов. На основе чьего-то мнения, скорее всего. И, наверное, до сих пор полет нормальный.

Я писать на ОО языках начал потому что выбора не было. Сейчас сложно найти мейнстримный язык без ООП, а когда я начинал таких вообще не было.

S>>>Если сохранять класс, когда у него все ок с инвариантами, то почему нет?

G>>Потому что в рамках одного класса нельзя сделать контроль остатков.
S>Почему?
По факту. Работа с объектами в памяти не обеспечивает изоляцию транзакций, когда есть более одного экземпляра процесса.

S>>>Для пользователя класса у него всегда должны быть инварианты, пользователь затем может этот класс сохранить.

G>>Как описать инвариант: остаток товаров на складе должен быть не меньше суммы зарезервированных?
S>Вычитать соотв. поля из бд, взяв соотв. лок предварительно, посчитать и в зависимости от, продолжить работу.
Два пользователя параллельно пытаются зарезервировать товар.
Один процесс считает данные из базы и считает предварительно. У него ок.
Второй процесс (на другом сервере) параллельно также считывает данные из базы и у него тоже ок.
Оба процесса создают резрвы товаров и сумма резервов получается больше остатка.

S>>>А как это может доказать обратное? Зачем вообще что-либо подсчитывать?

G>>Затем что нужны объективные измеримые показатели преимуществ того или иного подхода: объем, цикломатическая сложность, вложенность вызовов. Иначе это вера, а не инженерный подход.
S>См. выше про ООП -- что такое проделывали?
Конечно, я даже пример минимальный скидывал, который иллюстрирует преимущества. Любые подходы без ООП увеличивают объемы дублирующегося кода кода, при той же функцинальности.

S>Еще раз -- я не агитирую за ДДД, я против огульного откидывания подходов, мол "не нравится", "не встречал" и т.п. Это субъективщина.

S>Наверняка можно найти человека с обратным опытом.
Так давайте найдем, пусть пример покажет. Мы же не только что прочитали про DDD, напомню что я уже 16ый год участвую в эти дискуссиях и пока НИ РАЗУ не увидел примера приложения, сделанного 100% по DDD, чтобы оно не содержало дублирования, множества лишних связей, проблем быстродействия и ошибок несогласованности данных.
Re[31]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 16.01.26 22:47
Оценка: +1
Здравствуйте, Sharov, Вы писали:

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


S>>>Чем DDD хуже истоков agile и термина рефакторинг?

G>>Тем что рефакторинг и agile имеет доказанную пользу, а DDD — нет.

S>Для разработчика из видео выше это будет не так -- у него ДДД имеет доказанную пользу. Короче, это субъективщина.

Мне кажется ты не понимаешь суть слова "доказанную"...


S>>>>>Я работал в компании, которая распиливала монолит на микросервисы по ДДД. Использовали стратегические паттерны.


G>>>>Какие паттерны?

S>>>https://habr.com/ru/articles/787460/
G>>Это не про код, а про какую-то философию, тут вообще сложно что-либо оценивать. Меня именно код интересует.
G>>Ну вот мы сделали два разных класса Employee. У меня сразу вопрос: это одна таблица в системе или нет? Если
S>Это можно решить в самый последний момент, согласно ДДД. Это детали.
Так вот мы пришли к этому моменту. Это одна таблица или нет?


G>>Как быть если ЗА начинает зависеть от skills (они в разных моделях)?

G>>И вообще calculateWageWithoutTax в employee выглядит крайне сомнительно, для расчета ЗП и налогов нужно такое количество данных подтянуть из всей системы, из-за которых сама система и делает, что прокинуть это все в один Employee выглядит неразумным.
S>Значит нужен какой-то другой agg root.
Какой? Почему в этом примере именно Employee? Что этот пример должен был нам сказать?
Может нам наоборот стоит нарезать задачу контексты по другому? напрмиер на расчет зряплаты, грейдирование, итд. В каждом будут свои "root", а Employee как раз получится один для всех, так как он по сути просто справочник, который точно хранится в одной таблице.
Я тут не фантазирую, конфигурация 1С ЗУП так устроена. В 1С кстати заложена архитектура Event Sourcing и оптимизации темпоральных запросов (даже проверка остатков прекрасно решается), но в ней нет Domain Model (вернее эта модель полностью соответствует таблицам в БД) и Bounded Context (одна баз — один bounded context).

G>>DDD это набор паттернов, которые вроде как должны хорошо работать в каких-то сценарияхх, но на проверку они все плохо работают.

G>>В любой книге про DDD 80% это паттерны и 20% это какие-то философские вещи.

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

Пробелма в том, что без "тактических паттернов" методология DDD настолько очевидна, что смысла нет в отдельном названии.
Она сводится к трем вещам:
1) Универсальный язык для общения с заказчиком. По сути это раздел "термины и определения" из ТЗ по любому стандарту
2) Разделение проблемы на области — то что везде называние "модулями" (термин из структурного программирования) или "подсистемами" (термин из системной инженерии). В книге вернона и последующих даже упоминается иерархния (вложенность) областей, также как модули и подсистемы могут иметь вложенность.
3) Ограниченные контексты — единицы разработки и\или единицы деплоя.
Еще недавно появился EventStorming — по сути обычные брейнштормы, если отвязать их от event sourcing.

Фактически ничего нового DDD не дает. Мы все это видели например в UML — диграммы компонентов это предметные области, а диаграммы развертывания, диаграммы юзкейсов, процессов и логической структуры.

G>>Функционал нужен пользователю. Пользователь нажимает кнопки, кнопки вызывают хэндлеры. Вызывать репозиторий из хэндлера? А где тогда DDD?

S>Значит тут и репозиторий особо не нужен, обычный DAL.
Так это в любой программе так.

S>>>Помилуйте, были Си (процедурный язык), Lisp\Ocaml (фп языки), prolog (лп). Языков тьма. Тот же Erlang был. Но вот почему-то был выбран один из ООП языков. Почему?

G>>Потому что в середине двухтысячных были современные языки: C#, Java, Delphi (еще живой был, но только десктоп)), С++ (который был в глубочайшем кризисе)
G>>Для веба был еще PHP, но он даже на фоне Delphi выглядел как наколеночная поделка.
G>>Так как я знал делфи и хотел развиваться в сторону веба, то выбор был C# или Java — оба ОО-языки.

S>Но опять же, никаких разумных сравнений произведено не было -- loc, сложность поддержки и т.п. Чисто умозрительные вывод.

Серьезно? Только что описал почему фактически не было никаких языков кроме ОО, которые имело смысл изучать. Это сейчас есть не(до)-ОО языки, такие как Go, Rust и Kotlin

S>Вот для кого-то и ДДД выглядит интересно.

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

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

G>>Покажешь пример кода, как это сделать?
S>В транзакции что-то посчитать? Закиньте соотв. промт в чатбот.
Какой промпт? Напиши кодом то, что ты словами хочешь объяснить.
Всего-то надо по-ДДДному сделать проверку остатков.


S>>>Ну так переделайте на read-write, а не просто read. И используйте соотв. уровень изоляции, например read commited.

G>>На read commited это и происходит.
G>>Можно for update локи вешать в начале, если меняется та же запись, но на практике есть остаток на складе и список реезрвов, там уже serializable надо.
G>>Но мы уже ушли от работы с объектами в памяти. Что собственно и демонстрирует что в таком режиме самые важные инварианты реализовать нельзя. Надо с базой работать.

S>А бд не с объектами в памяти работает?

нет конечно, она с данными на диске работает.

S>Ну если у нас данные лежат в бд, то естественно что их надо забрать оттуда.

нет конечно, проверка остатков делается без поднятия в память данных.


S>>>Не серьезно -- вы приложили опереточный пример, а в случае DDD речь может идти о 10 или 100 тыс. строк кода минимум.

G>>Это опять вера, что на каком-то количестве строк DDD обязательно сработает. Но примеров нет.
G>>Почему-то все работающие методики работают даже на очень малых примерах.
S>Кто-то считает, что 1 млн лок на пхп без ДДД это уже вилка. Ну вот можно от этой цифры отталкиваться. Хотя сколько людей, столько мнений.
Очередное мнение, которое подкреплено примерно ничем?

S>>>Не одно и то же. Одно дело сравнить алгоритм сортировки на Си vs С#, другое дело какое-нибудь годами разрабатываемое десятками людей ПО.

G>>Любое ПО декомпозируется на отдельные компоненты, о чем говорят все методики и DDD в том числе. если в рамках одного простого компонента нет преимуществ, то почему кто-то думает, что на большом масштабе преимущества появятся?
S>https://ru.wikipedia.org/wiki/%D0%AD%D0%BC%D0%B5%D1%80%D0%B4%D0%B6%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D1%81%D1%82%D1%8C
А почему такое же свойство не может проявиться у достаточно большой системы без DDD? В чем особенность именно DDD?


S>>>Попросите у чатбота какого-нибудь пример приложения, написанного по DDD.

G>>Я спрашивал, все примеры содержат очень сомнительные решения, которые без паттернов DDD были бы проще и надежнее.
S>Возможно. 101 раз повторю -- это вкусовщина. У разработчика из Я. по ссылке выше на этот счет может быть другое мнение. И это нормально.
Поэтому и не надо отсылать к мнению и чату ГПТ. Приведи просто пример, хоть свой, хоть из интернета, кода с DDD, который по твоему демонстрирует преимущества и я его перепишу без ДДД и сравним по любым формальным (не зависящим от мнения) характеристикам

Пока выглядит так, что ДДД хорош только потому что он кому-то нравится.
Меня интересует более научный подход, когда результат можно как-то измерить.
Re[31]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.01.26 07:44
Оценка: +1
Здравствуйте, Sharov, Вы писали:

S>Блин, ну он же говорит, что работал в мамбе где было 1млн loc на пхп. И там, например, анкета могла быть в 50 разных контекстах. И если бы

S>не ДДД, то по его мнению, было бы очень и очень плохо. Т.е. окупается поддерживаемостью.
Похоже, что он словом DDD называет что-то другое, чем Эванс с Фаулером.
Потому что вот эта вот "анкета в разных контекстах" — это либо просто anemic class, позволяющий строгую типизацию таблицы (и каждый потребитель в каждом контексте тащит из неё то, что нужно лично ему), либо про класс, реализующий 50 разных интерфейсов, т.к. в каждом контексте нужно что-то своё.

S>Не знаю. Но в целом может быть, т.к. абстракций там накручивают не мало.

Дело не в абстракциях, а в архитектуре. В анемике у "объектов" нет никакого поведения, что позволяет описывать бизнес-логику в терминах трансформаций этих объектов. Пример gangustas уже приводил.
И вот такое описание позволяет напрямую транслировать эту логику с языка, на котором пишет программист-прикладник, в язык нижележащей платформы (например, SQL) и исполнять его прямо там.
А в DDD поведение описано на какой-нибудь императивной Java. Поэтому мы даже примитивный p.set_LastName() не можем превратить в update person p set p.LastName = — это же чорный ящик!
Вместо этого мы поднимем в память JVM весь этот Person c его сотней полей, потом вызовем Чорный ящик, а потом будем при коммите лихорадочно шерстить список изменений, чтобы сгенерировать update не по исходному коду, а по наблюдаемым побочным эффектам.

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

S>про преимущества ручной сборки мусора.
Это всё нерелевантно. Плоскоземельщиков тоже великие толпы. Идти к ним проповедовать — а зачем? Вопрос как раз в том, есть ли чему научиться полезному у плоскоземельщиков.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.01.26 07:54
Оценка: +1
Здравствуйте, Sharov, Вы писали:

S>Вашему же я должен довериться, что ДДД не нужен. А его почему-то нет.

Не, тут работает презумпция ненужности. Каждый раз, когда вам предлагают какую-нибудь новую практику — хоть уринотерапию, хоть методику или парадигму разработки — по умолчанию ответ "обойдёмся".
Это задача предлагающего доказать, что с ним будет лучше.
У DDD фундаментальная проблема — многие вопросы в нём неразрешимы совсем. Другие — создают трудности, которых нет в других подходах.

ООП, кстати, хороший пример. От фанатского Smalltalk, где объектами было вообще всё, мы потихонечку перешли на современные мультипарадигменные языки.
Где в программе по решению квадратного уравнения мы не конструируем никаких классов, и даже не конструируем объектов, а пользуемся уже готовыми.
И для умножения двух чисел мы пишем a*b, а не new MultiplierFactory.get_default_multiplier().set_first(a).set_second(b).execute().get_result();
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.01.26 11:57
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

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


G>>Тем более есть проблема: кроме Clean Architecture и DDD в медийном поле вообще не существует других подходов. У альтернативы ДДД даже названия собственного нет, она состоит из применения принципов YAGNI, KISS, DRY, top-down подхода к проектированию и разработке, частично SOLID.

S>Эмм, частично антиподом является anemic model. Термин введён, афаир, как ругательство апологетами DDD, но вполне отражает как минимум часть подхода.

Это касается только "модели", когда мы просто создаем классы, соответствующие таблицам в БД, но этот термин никак не описывает все остальные аспекты проектирования.
Эта пропасть в понятиях помогает апологетам ДДД спекулировать. Они приводят в пример адский говнокод с anemic model и образцово показательный DDD на каком-то простом примере и начинают рассказывать что anemic и является причиной говнокода.
Собственно собеседники в этой теме проявляли те же самые привычки.
Re[35]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.01.26 22:13
Оценка: :)
Здравствуйте, 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. три дня срачей, рассказов что я не умею требования анализировать, что задача вообще нереальная и не надо её решать итд.
Самое лучшее что один из участников написал пайтоне
class User(DomainEntity[UserId]):
    def __init__(self, entity_id: UserId, issue_count: int) -> None:
        super().__init__(entity_id)
        self._issue_count = issue_count

    def take_issue(self) -> None:
        MAX_ISSUE_COUNT = 3
        self._issue_count += 1
        if self._issue_count > MAX_ISSUE_COUNT:
            raise TooManyIssues


class Issue(DomainEntity[IssueId]):
    def __init__(self, entity_id: IssueId, metadata: str, user_id: UserId | None):
        super().__init__(entity_id)
        self._metadata = metadata
        self._user_id = user_id

    def assign_to(self, user: User) -> None:
        if self._user_id:
            raise IssueIsAlreadyAssigned

        user.take_issue()
        self._user_id = user.entity_id


То есть прделагают два агрегата. 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 я бы почитал.
Да там банальное исследование было: опрос какие практики применяют и считали корреляцию с "успешностью" проектов. Как успешность считали уже не помню.
Re[39]: Как внедряли DDD в Яндекс 360.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.01.26 17:26
Оценка: +1
Здравствуйте, Miroff, Вы писали:

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


S>>Что здесь сделано некорректно, и как мы поймём, что ошибка есть?


M>Дизайн строится не от данных, а от от операций. Если у тебя не получается логично присунуть метод, значит ты что-то сделал не так. Давай разберем что. В ДДД принято идти от предметной области, а в предметной области нет никаких ER, а есть единица товара, у которой есть SKU, физическая локация (на главном склад, у перевозчика, у покупателя и т.п.) и обязательства (вернуть постащику, сжечь, поставить покупателю и т.п.) И когда ты такую модель строишь у тебя логичным образом возникает поединичный учет и резервирование товара логично превращается в метод sku_item.createObligation(Supplybbligation(Order))


У нас в Order несколько Lines, каждая из которых ссылается на товар.
Когда пользователь нажимает кнопку "купить" заказ бронируется на складе до оплаты.

Как это предлагается реализовывать?
Допустим так:
foreach(var line in order.Lines)
{
    line.Item.CreateObligation(new Supplybbligation(order))
}

Уже выглядит сомнительно именно такой API
А что будет внутри CreateObligation?

Но давайте дальше:
При бронировании проверяется что количество забронированных товаров на складе не превышает свободный остаток.
Куда надо включить эту проверку? В метод CreateObligation?
Для этого надо получить состояние склада. Получение состояния это тоже внутри CreateObligation происходит? По одному элементу склада на каждой итерации цикла?
В каком классе будет доступ к БД?

И напоследок:
Бронирование должно происходить транзакционно, то есть или забронирован весь заказ, или не забронирован целиком. Другой заказ не должен увидеть любое промежуточное состояние.
Код выше можно завернуть в транзакцию, но сработает она только на уровне serializable, иначе можно забронировать больше чем есть на складе.
Re[30]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 31.01.26 16:36
Оценка: +1
Здравствуйте, Qulac, Вы писали:

Q>>>Мы имеем то что имеем, хоть с ооп хоть без ооп. Я бы выбрал приведеный пример с дженериками.

G>>Он же в итоге не полностью описывает ограничения предметной области.
Q>Где не полностью?

abstract class Player<TWeapon>  where TWeapon : Weapon
{
  TWeapon Weapon { get; set; }
}
sealed class Wizard : Player<Staff> { }
sealed class Warrior : Player<Sword> { }

Ты про этот пример:
Любой метод, который принимал Player теперь не сможет принять Wizard или Warrior.
Это не будет масштабироваться. Если добавить требования «игрок может носить доспехи, а волшебник может носить только мантию», и «игрок может читать книги, а воин может читать только немагические книги», то все быстро развалится.


G>>>>А в реальности ДДД мы разве не прибиваем домен к "общему языку" и фактически не можем менять произвольно модель?

Q>>>Фраза:"Игроку дали оружие" не имеет смысла в не контекста. Кто дает? Если про игру то это возможно какой другой игровой персонаж. Тогда проблема решается перегрузкой методов или шаблоном "визитер"
G>>А ты дальше второй части читал? Там есть и перегрузка и визитер.
Q>Ну и хорошо.
Ничего хорошего в итоге не получилось. Куча кода и dynamic dispatch в рантайме, никакого контроля оишбков на уровне системы типов, то есть того, ради чего система типов и затевалась.
Re[37]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 31.01.26 21:04
Оценка: +1
Здравствуйте, Sharov, Вы писали:

S>На питоне как-то солиднее решение, да делать дольше и сложнее, но надолгосрок будет проще.

Эт, в принципе, резюмирует всю дискуссию.
С такой точкой зрения идеальный код для 2*2 будет new MultiplierFactory.get_default_multiplier().set_first(a).set_second(b).execute().get_result(); Он гораздо солиднее.

Напомню для остальных читателей темы, что нет ни одного свидетельства о том, что более длинный код будет "проще на долгосрок". Множество свидетельств обратного.
Но вера в "солидность" непоколебима и видимо никакие разумные аргументы не могут её разрушить.
Re[38]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 31.01.26 22:32
Оценка: :)
Здравствуйте, gandjustas, Вы писали:

S>>На питоне как-то солиднее решение, да делать дольше и сложнее, но надолгосрок будет проще.

G>Эт, в принципе, резюмирует всю дискуссию.
G>С такой точкой зрения идеальный код для 2*2 будет new MultiplierFactory.get_default_multiplier().set_first(a).set_second(b).execute().get_result(); Он гораздо солиднее.

Речь про долгосрок, про подстелить себе салому, а не дурака валять с ООП. Все-таки на долгий срок
если выбирать, то питон решение выглядит солиднее, чем sql скрипт + обвязка на C#. Во втором случае скорее
всего во что-то упретесь и придется переписывать с нуля, а в первом добавить немного кода.

G>Напомню для остальных читателей темы, что нет ни одного свидетельства о том, что более длинный код будет "проще на долгосрок". Множество свидетельств обратного.

G>Но вера в "солидность" непоколебима и видимо никакие разумные аргументы не могут её разрушить.

Также напомню читателям, что моделировать модель предметную область гораздо лучше, чем обновлять соотв. строки в бд.
Да, дольше и сложнее, но на долгосрок самое то.
Кодом людям нужно помогать!
Re[45]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 01.02.26 15:47
Оценка: +1
Здравствуйте, amironov79, Вы писали:

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


G>>Вы же говорили что использовали внешний сервис, который вообще не РСУБД. Или я что-то не понял?

A>Я говорил, что не не РСУБД, а в том числе и не РСУБД.
Я спрашивал про не РСУБД. Было такое на практике?

G>>Использование двух баз с разными схемами и провайдерами в рамках EF решается просто, даже без класса репозитария

G>>Простой способ:
G>>1) Делаете один базовый абстрактный класс контекста со всеми свойствами и классами сущностей и два наследника, в каждом свою модель пилите под свой провайдер
G>>2) Делаете ОДИН класс контекста, в котором модель переключаете так: https://learn.microsoft.com/en-us/ef/core/modeling/dynamic-model, и используете KeyedService для подстановки, но если вы заходите миграции, то придется еще отдельный код для этого написать.

A>Каша какая-то.

Это разные способы

2)Проще 2 отдельных контекста сделать.
Это п1

В обоих случаях вызывающий код будет прост ссылку на класс наследник DbContext принимать ссылку и работать с ним.
Re[43]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.02.26 08:23
Оценка: +1
Здравствуйте, Sharov, Вы писали:

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



G>>>>Для этого утверждения нет никаких доказательств.

S>>>Был неточен -- не обновлят строки в бд, а править BL vs правки, по сути, sql скрипта.
G>>Но и этому тоже нет никаких доказательств.

S>Вы и дальше будете писать bl на sql?

Я и не начинал, я запросы на C# пишу. Только если на C# никак невозможно выразить то, что я хочу, то прибегаю к SQL.

S>Пока вся логика на стороне бд. Вроде от этого давно ушли.

Логика на стороне приложения, исполняется в бд в основном та часть, которая требует сохранения конситстентности.
Re[42]: Как внедряли DDD в Яндекс 360.
От: Miroff Россия  
Дата: 11.02.26 11:30
Оценка: -1
Здравствуйте, Sinclair, Вы писали:

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


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

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


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

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


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

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


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

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


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

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


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

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

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

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


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

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


Не всегда проекция возможна, это верно. Но ты и сам разрешил это противоречие добавив новую сущность.
Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 28.11.25 17:47
Оценка:
Вопрос такой.

Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.

И у меня сейчас проект, который нужно дорабатывать. Там этой парадигмы разделения не придерживались строго, так что в ui проникают как dto, так и entity. Проект пока не большой, около 25 тыс. строк кода, т.е. за пару-тройку дней можно разделить и добавить мапперы.

Но задумался — а какие реальные бонусы? Вот что пишет зазнайка:

Если использовать DTO в Домене: Ваша бизнес-логика становится зависимой от API-контрактов. Если фронтенд попросит переименовать поле в JSON для удобства отображения, вам придется менять это поле в бизнес-логике, что может повлечь ошибки в расчетах. Внешний мир начинает диктовать правила внутреннему.

Если использовать Entity в Домене: Ваша бизнес-логика зависит от схемы базы данных. Если вы решите денормализовать таблицу для производительности или сменить PostgreSQL на MongoDB, вам придется переписывать бизнес-правила.

Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.


Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.

Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.

Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.

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

По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.
Отредактировано 28.11.2025 17:53 Shmj . Предыдущая версия .
Re[2]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 07:11
Оценка:
Здравствуйте, Qulac, Вы писали:

S>>Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.

S>>[/q]
Q>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

Это на серверной части. А у клиента основная сложная логика — это авторизация, смена пользователя — важно чтобы приложение правильно эту логику отработало.

Остальное у клиента — это практически дергание API и базы а так же синхронизация данных API, базы и UI.

Из частых проблем может быть — на форме обновили значение суммы (допустим) а в общем балансе забыли обновить — но это состояние приложения.

S>>Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.

Q>Можно и руками.

Я не о том что руками — вопрос в объектах. Что если не создавать ViewModel и даже не создавать business object для domain-слоя — а тупо в UI применять dto, который отдало API. В чем минус такого подхода?

Минус вижу один — не получится отвязать физически слои в разные библиотеки и тестировать из независимо. Но на практике это и не нужно, как бы это уникальный случай, когда над каждым слоем работает отдельный человек, а взаимодействие на основе контрактов.

S>>Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.

Q>Ни чего не понял.

Ну если внешней сервис изменил имя поля в ответе — как то было WokrTime а стало WorkTime — один хрен, даже если ты создал dto, bo, entity — придется менять dto + в маппере dto->bo и скорее всего в маппере dto->entity. Это 3 изменения кода. Если не создавал отдельно bo — то сразу меняешь в dto и в ui — два изменения кода. Получается не создавать объекты + мапперы — меньше работы и нет особых минусов

S>>Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.

Q>Да хоть в 10 местах, что это меняет, откуда такая мания экономить на спичках?

Чем меньше монотонной работы — тем лучше. Всегда лучше изменить в одном месте чем 4 местах, ибо раздражает, тратится время. А плюс в чем?

S>>Далее. Если добавим тесты и фейковые реализации сервисов — то что мешает в этих фейковых реализациях использовать уже существующие классы для объектов, ведь у них есть конструктор...

Q>Зачем фейковые сервисы,если они только не являются сторонними к проекту. Фейковыми должны быть репозитории.

Так сервисы же есть внешние (которые связывают с API) и сервисы domain-слоя (бизнес логика). Можно мокать и внешние и бизнес слоя. Бизнес слойные сервисы мокают если хотят протестить один из сервисов, независимо от других — другие заменяют моками/фейками.

S>>По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.

Q>Ну не применяй.

Но все же хочется понять — почему принято делать 3 похожих типа объектов, если нет реальных плюсов:

1. dto — в виде, который отдает внешний сервис.
2. entity — в виде, который хранится в таблице базы данных.
3. business object — в виде, который представлен в бизнес-логике — domain-слое.
(4). Иногда добавляют view model — в виде, который отображается пользователю на форме.

+ еще и мапперы между каждым из слоев

Просто что всех так по учебникам учили?
Re[3]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 08:03
Оценка:
Здравствуйте, Shmj, Вы писали:

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


S>>>Правило архитектуры: Зависимости должны быть направлены внутрь. Слой Домена (бизнес-логика) должен быть самым стабильным и не зависеть ни от Базы Данных, ни от UI/API.

S>>>[/q]
Q>>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

S>Это на серверной части. А у клиента основная сложная логика — это авторизация, смена пользователя — важно чтобы приложение правильно эту логику отработало.


S>Остальное у клиента — это практически дергание API и базы а так же синхронизация данных API, базы и UI.


S>Из частых проблем может быть — на форме обновили значение суммы (допустим) а в общем балансе забыли обновить — но это состояние приложения.


S>>>Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.

Q>>Можно и руками.

S>Я не о том что руками — вопрос в объектах. Что если не создавать ViewModel и даже не создавать business object для domain-слоя — а тупо в UI применять dto, который отдало API. В чем минус такого подхода?


S>Минус вижу один — не получится отвязать физически слои в разные библиотеки и тестировать из независимо. Но на практике это и не нужно, как бы это уникальный случай, когда над каждым слоем работает отдельный человек, а взаимодействие на основе контрактов.


S>>>Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.
Q>>Ни чего не понял.

S>Ну если внешней сервис изменил имя поля в ответе — как то было WokrTime а стало WorkTime — один хрен, даже если ты создал dto, bo, entity — придется менять dto + в маппере dto->bo и скорее всего в маппере dto->entity. Это 3 изменения кода. Если не создавал отдельно bo — то сразу меняешь в dto и в ui — два изменения кода. Получается не создавать объекты + мапперы — меньше работы и нет особых минусов


S>>>Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.

Q>>Да хоть в 10 местах, что это меняет, откуда такая мания экономить на спичках?

S>Чем меньше монотонной работы — тем лучше. Всегда лучше изменить в одном месте чем 4 местах, ибо раздражает, тратится время. А плюс в чем?


S>>>Далее. Если добавим тесты и фейковые реализации сервисов — то что мешает в этих фейковых реализациях использовать уже существующие классы для объектов, ведь у них есть конструктор...

Q>>Зачем фейковые сервисы,если они только не являются сторонними к проекту. Фейковыми должны быть репозитории.

S>Так сервисы же есть внешние (которые связывают с API) и сервисы domain-слоя (бизнес логика). Можно мокать и внешние и бизнес слоя. Бизнес слойные сервисы мокают если хотят протестить один из сервисов, независимо от других — другие заменяют моками/фейками.


S>>>По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.

Q>>Ну не применяй.

S>Но все же хочется понять — почему принято делать 3 похожих типа объектов, если нет реальных плюсов:


S>1. dto — в виде, который отдает внешний сервис.

S>2. entity — в виде, который хранится в таблице базы данных.
S>3. business object — в виде, который представлен в бизнес-логике — domain-слое.
S>(4). Иногда добавляют view model — в виде, который отображается пользователю на форме.

S>+ еще и мапперы между каждым из слоев


S>Просто что всех так по учебникам учили?



Еще раз повторю: проекты валятся не из-за того, что в 10 местах переменную переименовать нужно, а из-за того, что в БЛ в в том виде в котором она реализована, становится невозможно вносить изменения, а баги начинают жить вечно. Это вопрос собственно какую ценность мы выбираем: проект или код в котором не нужно менять в трех местах переменную. Это чисто "житейский" подход, что мы отделаем главное от не главного, а код здесь вторичен.


P.S. Я это видел на практике, один объект везде, что-то типа такого:

class Customer: Entity
{ 
   [NoMapper] - что это здесь делает?
   strring property{get;set;}

   DateTime DateTime {get;set;}

   string FomratDateTime
   {
     returt DatetTim.Format - //возвращаем в нужном формате
   }
}
Программа – это мысли спрессованные в код
Отредактировано 29.11.2025 8:10 Qulac . Предыдущая версия .
Re[4]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 09:23
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Еще раз повторю: проекты валятся не из-за того, что в 10 местах переменную переименовать нужно, а из-за того, что в БЛ в в том виде в котором она реализована, становится невозможно вносить изменения, а баги начинают жить вечно. Это вопрос собственно какую ценность мы выбираем: проект или код в котором не нужно менять в трех местах переменную. Это чисто "житейский" подход, что мы отделаем главное от не главного, а код здесь вторичен.


Давай на примерах рассмотрим.

Q>P.S. Я это видел на практике, один объект везде, что-то типа такого:

Q>

Q>class Customer: Entity
Q>{ 
Q>   [NoMapper] - что это здесь делает?
Q>   strring property{get;set;}

Q>   DateTime DateTime {get;set;}

Q>   string FomratDateTime
Q>   {
Q>     returt DatetTim.Format - //возвращаем в нужном формате
Q>   }
Q>}
Q>


Т.е. вам не нравится что в одном классе лишние поля, часть из которых не нужна для конкретного слоя? А что если добавить методы-расширения или mixin, чтобы нужные для конкретного слоя поля были в этом слое?
Re[5]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 09:36
Оценка:
Здравствуйте, Shmj, Вы писали:

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


Q>>Еще раз повторю: проекты валятся не из-за того, что в 10 местах переменную переименовать нужно, а из-за того, что в БЛ в в том виде в котором она реализована, становится невозможно вносить изменения, а баги начинают жить вечно. Это вопрос собственно какую ценность мы выбираем: проект или код в котором не нужно менять в трех местах переменную. Это чисто "житейский" подход, что мы отделаем главное от не главного, а код здесь вторичен.


S>Давай на примерах рассмотрим.


Q>>P.S. Я это видел на практике, один объект везде, что-то типа такого:

Q>>

Q>>class Customer: Entity
Q>>{ 
Q>>   [NoMapper] - что это здесь делает?
Q>>   strring property{get;set;}

Q>>   DateTime DateTime {get;set;}

Q>>   string FomratDateTime
Q>>   {
Q>>     returt DatetTim.Format - //возвращаем в нужном формате
Q>>   }
Q>>}
Q>>


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


А ради чего дрючиться, ради какой такой святой цели? Что бы с "оптимизировать" код который имеет низкую ценность и вообще ни на что не влияет?
А как быть с вот таким ответом из БЛ:

class CustomerCarTuple: ValueObject
{
  public Customer Customer {get;private set}

  public Car Car {get;private set}
}

//метод сервиса
public Ienumerable<CustomerCarTuple> GetCustomerCarReport()
{
  //
  returt ...
}

Программа – это мысли спрессованные в код
Re[6]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 09:43
Оценка:
Здравствуйте, Qulac, Вы писали:

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


А зачем плодить лишние сущности? Вот в чем вопрос. Какой реальный смысл создавать одинаковые классы на каждом уровне и потом еще и маппить один в один?

Ну ОК, если совсем другая структура — то создай. А для всех случаев в чем смысл? Однообразно и безобразно?

Q>А как быть с вот таким ответом из БЛ:


Q>
Q>class CustomerCarTuple: ValueObject
Q>{
Q>  public Customer Customer {get;private set}

Q>  public Car Car {get;private set}
Q>}

Q>//метод сервиса
Q>public Ienumerable<CustomerCarTuple> GetCustomerCarReport()
Q>{
Q>  //
Q>  returt ...
Q>}
Q>

Q>

А в чем вопрос?
Re[7]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 09:46
Оценка:
Здравствуйте, Shmj, Вы писали:

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


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


S>А зачем плодить лишние сущности? Вот в чем вопрос. Какой реальный смысл создавать одинаковые классы на каждом уровне и потом еще и маппить один в один?


S>Ну ОК, если совсем другая структура — то создай. А для всех случаев в чем смысл? Однообразно и безобразно?


Q>>А как быть с вот таким ответом из БЛ:


Q>>
Q>>class CustomerCarTuple: ValueObject
Q>>{
Q>>  public Customer Customer {get;private set}

Q>>  public Car Car {get;private set}
Q>>}

Q>>//метод сервиса
Q>>public Ienumerable<CustomerCarTuple> GetCustomerCarReport()
Q>>{
Q>>  //
Q>>  returt ...
Q>>}
Q>>

Q>>

S>А в чем вопрос?


Здесь в viewModel только маппинг нужен.
Программа – это мысли спрессованные в код
Re: Что если не разделять строго dto, entity, bo...
От: DiPaolo Россия  
Дата: 29.11.25 10:20
Оценка:
S>И у меня сейчас проект, который нужно дорабатывать. Там этой парадигмы разделения не придерживались строго, так что в ui проникают как dto, так и entity. Проект пока не большой, около 25 тыс. строк кода, т.е. за пару-тройку дней можно разделить и добавить мапперы.

Ну может оно и не надо? Тут надо оценить целесообразность и учесть:
— на каком этапе проект
— сколько денег приносит и сколько клиентов имеет
— объем доработок (+ в процентах к текущим LOC)
— единоразовая ли доработка
— как часто проект требует вмешательства в-принципе

Я бы сильно задумался, а стоит ли оно вообще что-то менять вот так кардинально. И учел бы ответы на вопросы выше. ИМХО вот так сходу кажется, что не стоит ничего менять

S>Но на практике вот что. Если что-то нужно добавить в UI — можно использовать расширения/mixin. И что? Никакой сложности не добавляет.


S>Если что-то изменилось в API — то один хрен нужно менять все слои. Но если добавилось новое поле и мы его не используем — то и в текущей схеме ничего не сломается.


S>Если изменилась схема хранения данных, к примеру переименовали поле — то сейчас нужно в двух местах переименовать — в entity и в ui, где этот entity напрямую используется. Если добавим мапперы — легче не станет.


Основная суть даже не в тестировании (хотя и это тоже), а в том, чтобы абстрагировать каждый слой и сделать его независимым от внешних изменений, оставляя нетронутым его интерфейс.

Давай на примерах:
— связка сервис <-> слой БД: ты захотел оптимизировать хранение и теперь хочешь хранить не доллары+центы, а доллары умноженные на 100. Если у тебя один общий объект, ты должен по всему коду в сервисе и в БД поменять 1 поле на два + всю связанную логику. Если два отдельных объекта: поменял только часть на стороне БД и живешь дальше спокойно
— связка REST API <-> сервис: ну тут вообще часто бывают изменения во внутренних сервисах, которые не должны никак затрагивать REST API, оставляя его неизменным. Например, пришла пора порефакторить внутри код и вынести какую-то логику в отдельный сервис. Вот у тебя информация об автомобиле приходила в одном объекте, а теперь есть отдельный сервис для хранения и расчетов по технической части. Тогда тебе надо, чтобы информация также и приходила в одном объекте через АПИ, а потом надо побить его на два объекта: каждый в свой сервис пойдет
— UI <-> REST API: тоже часто бывают изменения, например, когда сущности/элементы UI меняют свое название либо требуют отдельных полей для удобства работы. Ну например, был у тебя один элемент для тех же долларов+центов, ты его там строкой показывал. А теперь понадобилось сделать два отдельных элемента, да чтобы они еще и отдельно каждые могли изменяться пользователем. Сплетешь флоатинг филд, приходящий с РЕСТ АПИ, на два Филда по Инту на каждый и биндишь его к своим двум элементам управления на UI.

В целом, надо всегда думать головой и выбирать, что уместнее в каждом конкретном случае. Где-то и один и тот же объект удобнее таскать А где-то внутренние entity будут всегда жестко связаны с БД и быть один-в-один с таблицами/колонками.
Патриот здравого смысла
Re[7]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 10:32
Оценка:
Здравствуйте, Shmj, Вы писали:

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


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


S>А зачем плодить лишние сущности? Вот в чем вопрос. Какой реальный смысл создавать одинаковые классы на каждом уровне и потом еще и маппить один в один?


Вот опять вопрос понимания. Сущности сидят в БЛ, а тут нет сущностей, тут классы, просто так удобней. Вообще класс — это синтаксическая конструкция языка, а будет он сущностью или нет зависит от того, как мы им пользуемся.
Программа – это мысли спрессованные в код
Re[2]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 12:55
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

Вы сейчас о чем говорите? Самая дорогая часть это UI. Туда обычно тратится больше всего времени аналитиков, дизайнеров, и разработчиков. Это касается и веба, где ui от бизнес-логики отделен http-вызовами, и десктоп приложений, где визуальное представление связано с логикой через viewmodel/presenter.

А на втором месте по объему затрат и кода занимает работа с базой и обеспечение согласованности.

Если вы отделяете работу с базой от БЛ, то что выполняется в БЛ после того как вы вытащили данные из базы и перед тем как отдали в UI?
Re[3]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 13:38
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


Q>>Правильно. Еще БЛ — это центральное место приложения усилий при разработке. Здесь находится самый дорогой код, на него было потрачено сотни часов работы аналитика, здесь самые дорогие и долгоживущие баги.

G>Вы сейчас о чем говорите? Самая дорогая часть это UI. Туда обычно тратится больше всего времени аналитиков, дизайнеров, и разработчиков. Это касается и веба, где ui от бизнес-логики отделен http-вызовами, и десктоп
приложений, где визуальное представление связано с логикой через viewmodel/presenter.

Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

G>А на втором месте по объему затрат и кода занимает работа с базой и обеспечение согласованности.

Это почти все бизнес-логика, как и должно быть.

G>Если вы отделяете работу с базой от БЛ, то что выполняется в БЛ после того как вы вытащили данные из базы и перед тем как отдали в UI?


Преобразование к модели вида, т.е. данные отображения.
Программа – это мысли спрессованные в код
Re[2]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 13:45
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Если для заказчика/стейкхолдера/пользователя, то очевидно никаких. Тому кто платит деньги и конечному пользователю без разницы сколько у вас слоев, дто и мапперов.


Для заказчика важно чтобы скорость разработки и поддержки была приемлемой, будет плохо если один простой баг будут исправлять день а то и несколько дней. И никто на земле не сможет исправить быстрее, ведь там слишком все запутано как узелок с нитками.

И что заказчику делать, если разработчик три дня исправляет простой баг а после исправления создает новый баг? Выгонять?

Ок, выгнал (а скорее тот сам ушел еще до того, как проблема стала очевидной). Берет нового — новый говорит что нужно все переписывать с нуля. Берет другого — тот делает вид что работает, месяц делает вид, два — говорит что еще разбирается в проекте. А потом начинает работать еще медленнее.
Re[4]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 14:57
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.


Q>Преобразование к модели вида, т.е. данные отображения.

То есть то, что делает маппер?
Re[5]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 15:17
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


Q>>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

G>Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.

Если вы используете какую ни будь хорошую библиотеку для ui, то все практические превращается в банальное формошлебство — т.е. соединение одного с другим. Это если правильно делать. Приведу пример из практики как не правильно. Дано: штук 5 справочников к которым нужно приделать новый фронт на реакт + добавить возможность редактирования. Все уже для этого есть и компонеты и дизайн. Казалось бы делай вот так:

1. Получили из апи данные справочника
2. Загрузили из другого апи данные выпадающего списка
3. Отправили на апи результат из диалоговой формы
4. Перешли к другому справочнику

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

Q>>Преобразование к модели вида, т.е. данные отображения.

G>То есть то, что делает маппер?

Нет, маппер к нужным видам приводит, их может быть несколько разных, бл возвращает данные такими какие они есть в бд.
Программа – это мысли спрессованные в код
Отредактировано 29.11.2025 15:17 Qulac . Предыдущая версия .
Re[6]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.11.25 17:09
Оценка:
Здравствуйте, Qulac, Вы писали:

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


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


Q>>>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

G>>Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.

Q>Если вы используете какую ни будь хорошую библиотеку для ui, то все практические превращается в банальное формошлебство — т.е. соединение одного с другим. Это если правильно делать. Приведу пример из практики как не правильно. Дано: штук 5 справочников к которым нужно приделать новый фронт на реакт + добавить возможность редактирования. Все уже для этого есть и компонеты и дизайн. Казалось бы делай вот так:


Q>1. Получили из апи данные справочника

Q>2. Загрузили из другого апи данные выпадающего списка
Q>3. Отправили на апи результат из диалоговой формы
Q>4. Перешли к другому справочнику
То есть предлагаете копипастить кучи кода?

А что делать на нетривиальных формах?
— кода видимость/обязательность одних элементов зависит от значен у других?
— когда используются справочники, в том числе каскадные ?
— когда а одной форме есть mater-detail и логика работающая на всех detail записях?

На стороне бл это простое дерево объектов: получили, обновили из запроса, записали в базу.
А на стороне клиента это тонна логики

Q>На фронтенду захотелось сделать универсальный для таких случаев способ, т.е. что бы один запрос возвращал json который описывает данные, поля, выпадающие списки и прочее что может быть в форме. В результате конечно полезли баги, а как это работает через неделю уже не вспомнишь. Вот на пустом месте сами себе создали проблему и дрючились. И такое где react и vue встречается довольно часто, т.е. люди сами себе усложняют задачу, зачем и ради какой цели — не понятно. И это только один пример у меня было еще хлеще.

То есть вы против dry на клиенте, потому что создание повторно используемого кода это сложно?
Может на сервере делать также? Просто скопипастить код в контроллерах, и поменять запросы?

Q>>>Преобразование к модели вида, т.е. данные отображения.

G>>То есть то, что делает маппер?

Q>Нет, маппер к нужным видам приводит, их может быть несколько разных, бл возвращает данные такими какие они есть в бд.

Ну выглядит так, что именно это маппер и делает. В чем тогда заключается БЛ, если отделяем её от запросов?
Re[7]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 29.11.25 17:21
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


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


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


Q>>>>Если это не про игры или какие ни будь с заказным навороченным дизайном — то это говорит о том, что кто-то как-то не правильно все делает.

G>>>Почему неправильно? Любой ui это много элементов и взаимодействий, а логика гораздо проще, ибо код stateless, а все «состояние» находится вовне.

Q>>Если вы используете какую ни будь хорошую библиотеку для ui, то все практические превращается в банальное формошлебство — т.е. соединение одного с другим. Это если правильно делать. Приведу пример из практики как не правильно. Дано: штук 5 справочников к которым нужно приделать новый фронт на реакт + добавить возможность редактирования. Все уже для этого есть и компонеты и дизайн. Казалось бы делай вот так:


Q>>1. Получили из апи данные справочника

Q>>2. Загрузили из другого апи данные выпадающего списка
Q>>3. Отправили на апи результат из диалоговой формы
Q>>4. Перешли к другому справочнику
G>То есть предлагаете копипастить кучи кода?

Тут в копипастинге нет ни чего плохого, потому что это не приводит к проблемам. В конце концов есть наследование, можно его использовать.

G>А что делать на нетривиальных формах?

G>- кода видимость/обязательность одних элементов зависит от значен у других?
G>- когда используются справочники, в том числе каскадные ?
G>- когда а одной форме есть mater-detail и логика работающая на всех detail записях?

Что делать, писать код.

G>На стороне бл это простое дерево объектов: получили, обновили из запроса, записали в базу.

G>А на стороне клиента это тонна логики

Q>>На фронтенду захотелось сделать универсальный для таких случаев способ, т.е. что бы один запрос возвращал json который описывает данные, поля, выпадающие списки и прочее что может быть в форме. В результате конечно полезли баги, а как это работает через неделю уже не вспомнишь. Вот на пустом месте сами себе создали проблему и дрючились. И такое где react и vue встречается довольно часто, т.е. люди сами себе усложняют задачу, зачем и ради какой цели — не понятно. И это только один пример у меня было еще хлеще.

G>То есть вы против dry на клиенте, потому что создание повторно используемого кода это сложно?

Оно просто не нужно.

G>Может на сервере делать также? Просто скопипастить код в контроллерах, и поменять запросы?


Q>>>>Преобразование к модели вида, т.е. данные отображения.

G>>>То есть то, что делает маппер?

Q>>Нет, маппер к нужным видам приводит, их может быть несколько разных, бл возвращает данные такими какие они есть в бд.

G>Ну выглядит так, что именно это маппер и делает. В чем тогда заключается БЛ, если отделяем её от запросов?

Еще раз, видом у сущности может быть много, не пихать же каждый в бл, поэтому бл должна возвращать данные в каком — то одном виде, а уже потом это будет преобразоваться.
Программа – это мысли спрессованные в код
Re[2]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 29.11.25 18:08
Оценка:
Здравствуйте, DiPaolo, Вы писали:

DP>Давай на примерах:


а давай

DP>- связка сервис <-> слой БД: ты захотел оптимизировать хранение и теперь хочешь хранить не доллары+центы, а доллары умноженные на 100. Если у тебя один общий объект, ты должен по всему коду в сервисе и в БД поменять 1 поле на два + всю связанную логику. Если два отдельных объекта: поменял только часть на стороне БД и живешь дальше спокойно


Ну можно же 1 поле добавить для хранения а то что было ранее — сделать Transient (не хранится в базе) — а сразу вычисляется на основе нового поля, которое хранится в базе. Тогда 1 изменение и все. А вам с вашим разделением строгим — еще в маппере нужно менять, то есть 2 изменения против одного.

Получается код с единственным классом — выигрывает

DP>- связка REST API <-> сервис: ну тут вообще часто бывают изменения во внутренних сервисах, которые не должны никак затрагивать REST API, оставляя его неизменным. Например, пришла пора порефакторить внутри код и вынести какую-то логику в отдельный сервис. Вот у тебя информация об автомобиле приходила в одном объекте, а теперь есть отдельный сервис для хранения и расчетов по технической части. Тогда тебе надо, чтобы информация также и приходила в одном объекте через АПИ, а потом надо побить его на два объекта: каждый в свой сервис пойдет


Ну тут еще вот в чем дело. В этом проекте нет строгости — то есть для части объектов есть маппинг api object -> data enity. Когда это удобно — маппинг есть. Примерно в 40% случаев. Но только когда это имеет смысл.

Я же думаю над тем чтобы не решать имеет смысл или нет — а делать строгое разделение для всех случаев.

И сейчас пытаюсь понять плюсы и минусы.

Похоже что плюсов особо нет.

Т.е. еще раз. В этом проекте нет именно что строгой идеи — что будем делать только так. В одном месте для одного случая разделение объектов добавили — кое-где даже ViewModel есть. А в других случаях разделения нет и api object отображается прямо на форме.

DP>- UI <-> REST API: тоже часто бывают изменения, например, когда сущности/элементы UI меняют свое название либо требуют отдельных полей для удобства работы. Ну например, был у тебя один элемент для тех же долларов+центов, ты его там строкой показывал. А теперь понадобилось сделать два отдельных элемента, да чтобы они еще и отдельно каждые могли изменяться пользователем. Сплетешь флоатинг филд, приходящий с РЕСТ АПИ, на два Филда по Инту на каждый и биндишь его к своим двум элементам управления на UI.


Ну так можно же методы-расширения/mixin добавить для таких редких случаев. Т.е. оставляете тот же объект, но в отдельной папочке пишите extension — и добавляете поверх новые свойства.

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

DP>В целом, надо всегда думать головой и выбирать, что уместнее в каждом конкретном случае. Где-то и один и тот же объект удобнее таскать А где-то внутренние entity будут всегда жестко связаны с БД и быть один-в-один с таблицами/колонками.


Тут же нет запрета — хочешь создавай спец. объект для отдельного слоя.

Вопрос лишь вот в чем: если взять это за обязательное правило — то в чем плюсы?
Re[6]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 30.11.25 06:55
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Это возможно если для реализации требований нужно менять верхние слои, при этом не трогая нижние . Но при разделением как рекомендует domain model или onion/hexagon/clean architecture это невозможно, так как почти каждое значимое изменение требований приведет к изменению не только представления, но и хранимых данных, и, соответственно, всех слове между ними.


Тут вот для чего. Если над каждым слоем работает свой человек — то без создания объектов на каждом уровне — они будут кивать друг на друга. Не могу сделать — слой данных еще не готов.

Когда же строгое разделение — тебе пофиг готов слой данных или не готов — забадяжил свои объекты, инициализировал фейковыми данными — проверил. Потом уже тот кто интегрирует и пишет мапперы протестирует с реальными данными.

А для реализации "не трогать нижние" — в Dart, к примеру, есть extension-свойства и методы.

https://dart.dev/language/extension-methods

И что, эта маленькая фича языка отменяет смысл создания объектов на каждом уровне? Т.е. если на твоем уровне чего-то не хватает — добавь расширения. Если всего хватает — ничего не добавляй.

S>>Других плюсов особо не видно. Т.е. если у вас нет строгого разделения труда — то нет смысла и в строгом разделении объектов. Но когда несколько человек работают над системой одновременно и каждый занимается своим слоем — появляется смысл все-же.

G>На практике удобнее не горизонтальное, а вертикальное деление. Например asp.net identity. Показывает как можно сделать отдельную функциональность, котрая содержит как работу с базой, так и часть представления, при этом достаточно хорошо кастомизируется и интегрируется с другими частями

Но при таком разделении нет смысла для каждого слоя во всех случаях (т.е. не берем отдельные случаи) клепать свои объекты и мапперы Но при этом нет смысла и запрещать — смотреть по ситуации. Иногда это имеет смысл а иногда нет.

S>>А вот строгость в придерживании архитектуры, как то принято писать ViewModel — но ты для отдельных форм это не применяешь (а просто напрямую вызываешь api-методы и базу из обработчика кнопки) — тут есть минус. А именно, код становится сложнее поддерживать, сложнее дорабатывать.


G>Я, честно, не видел современных приложений построенных по такому принципу. За счет того что везде есть data binding проще иметь промежуточный объект, к которому привязывается форма, а внутри него уже дергать методы БЛ. А если мокать бл для объекта, то можно удобно тесты писать


Но что делать если не строго придерживаются этого правила и иногда прямо из обработчика события нажатия кнопки вызывают внешние сервисы

S>>Порядок. Вот в вещах порядок — можно все разложить по коробочкам (особенно поймут электронщики). А можно как бы не заморачиваться и все вывалить в одну большую кучу.

G>Если бы «раскладывание по коробочкам» было бесплатно, то все бы так делали. Но почему-то нет. См тот же asp.net identity

Не бесплатно, коробочки денег стоят, причем иногда дороже чем сами детали. Но это обязательно — иначе будет хаос — в большой куче ничего не найти.

Но нужно подходить с умом — иногда, если в коробочке 1 деталь — то смысла нет.

S>>Когда тебе нужно найти деталь — то по коробочка найдешь сразу (при грамотном структурировании). А кучу нужно перебирать каждый раз с нуля.

G>Мне кажется это миф, все равно надо читать код и делать go to definition. И чем меньше кода и перекладываний объектов, тем проще. По крайней мере я на себе ни разу не замечал улучшение чтения от разделения.

При перекладывании объектов — тут да, смысла особо нет. А в других аспектах, как то строгое разделение на слои — смысл огромный.

S>>Но тогда ты просто перекладываешь проблему разработки и чистоты кода на чужие плечи. А проблема эта никуда не ушла. Лучше разберись сам и научить чистоте кода без привлечения посредников.

G>Далеко не каждый сам способен разобраться

Но речь то о тех, кто хочет маржу забрать себе — т.е. не нанимать команду а сам заняться разработкой. И часто такие люди, которые решили заниматься разработкой — не думают о качестве кода — смотрят только на реально сделанные фичи. Большое заблуждение.
Re[3]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 30.11.25 16:10
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Если вы отделяете работу с базой от БЛ, то что выполняется в БЛ после того как вы вытащили данные из базы и перед тем как отдали в UI?


Сама бл в этом случае и есть то, что между чтением из бд и пулянием в ui
Отредактировано 01.12.2025 7:28 Pauel . Предыдущая версия .
Re[4]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 30.11.25 19:03
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Сама бл в этом случае и есть то, что между чтением и бд и пулянием в ui


Между получением данных из API и DB — есть есть еще кеширование — но это в репозиториях, слой данных.

Логика — это когда есть состояние а разные сценарии, в зависимости от состояния. Т.е. if на неком состоянии.

Вот практически везде есть:

1. Логика авторизации, устаревания и обновления сессии, проверка актуальности ключа и при протухании/деактивации ключа — заново требовать авторизацию. Сюда же смена пользователя и пр.
2. Вызов по таймеру и отметка в базе о последнем успешном обновлении.
3. Логика оффлайн-режима. Т.е. перевести в состояние "оффлай", выдавать только старые данные, паттерн "короткое замыкание".

В общем то и все, обычно.

4. Иногда различного рода калькуляторы, нередко с зависимостью от курсов валют и пр. Но бывает что это на сервере а клиент просто делает запрос.

А так основная логика сейчас на стороне сервера, клиенты в основном только эти 3 пункта логики. Остальное — UI и кеширование.

Часто путают логику со слоем данных — т.е. называют логикой простое получение данных с кешированием.
Отредактировано 30.11.2025 19:06 Shmj . Предыдущая версия .
Re[6]: Что если не разделять строго dto, entity, bo...
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 02.12.25 03:32
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


В чём тогда серебряная пуля? Где граница применимости и как понять когда всё, приехали и "абстракции" давят и наоборот когда код превратился в набор спагетти? Все DDD, CA и т.п. было зря?
Sic luceat lux!
Re[7]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 02.12.25 05:51
Оценка:
Здравствуйте, Kernan, Вы писали:

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


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


K>В чём тогда серебряная пуля? Где граница применимости и как понять когда всё, приехали и "абстракции" давят и наоборот когда код превратился в набор спагетти? Все DDD, CA и т.п. было зря?


Тут нет ни какого другого способа, кроме как работать с моделью. Если ее смог создать у себя бизнес, то собственно и мы можем ее сделать в программной реализации. Для этого ее нужно отделить от обслуживающих ее слоев, что бы нам ни чего не мешало сосредотачиваться на ней. Общий подход, если простыми словами: все есть модель, а остальное — "обслуга" модели. И важно: мы тут еще отделяем проблемную часть, от не проблемной.
Программа – это мысли спрессованные в код
Re[8]: Что если не разделять строго dto, entity, bo...
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 02.12.25 06:35
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Тут нет ни какого другого способа, кроме как работать с моделью. Если ее смог создать у себя бизнес, то собственно и мы можем ее сделать в программной реализации. Для этого ее нужно отделить от обслуживающих ее слоев, что бы нам ни чего не мешало сосредотачиваться на ней. Общий подход, если простыми словами: все есть модель, а остальное — "обслуга" модели. И важно: мы тут еще отделяем проблемную часть, от не проблемной.

Ну кулстори, конечно. Делай хорошо и будет всё замечательно. Я не согласен с этим. Вот по своей практике у меня сложилось мнение, что основные задачи проектирования это снижение сложности и создания архитектуры устойчивой к изменению требований, в разумных пределах конечно же. Если первое можно решать созданием удобных для использования типов данных, ну например, currency и money, то второе сводится к натягиванию предметной области на код в виде абстракций с сложным разграничением ответственности м/д классами и подход к разработке архитектуры через наши любимые принципы, паттерны, СОЛИД, GRASP и т.п. Однако, тезисы Ганджустата как-то говорят о том, на мой взгляд, что домены это хорошо, но пиши как знаешь и проще, всё равно по метрикам на большом проекте это не даёт особого профита. Вот как быть?
Sic luceat lux!
Re[9]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 02.12.25 07:15
Оценка:
Здравствуйте, Kernan, Вы писали:

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


Q>>Тут нет ни какого другого способа, кроме как работать с моделью. Если ее смог создать у себя бизнес, то собственно и мы можем ее сделать в программной реализации. Для этого ее нужно отделить от обслуживающих ее слоев, что бы нам ни чего не мешало сосредотачиваться на ней. Общий подход, если простыми словами: все есть модель, а остальное — "обслуга" модели. И важно: мы тут еще отделяем проблемную часть, от не проблемной.

K>Ну кулстори, конечно. Делай хорошо и будет всё замечательно. Я не согласен с этим. Вот по своей практике у меня сложилось мнение, что основные задачи проектирования это снижение сложности и создания архитектуры устойчивой к изменению требований, в разумных пределах конечно же. Если первое можно решать созданием удобных для использования типов данных, ну например, currency и money, то второе сводится к натягиванию предметной области на код в виде абстракций с сложным разграничением ответственности м/д классами и подход к разработке архитектуры через наши любимые принципы, паттерны, СОЛИД, GRASP и т.п. Однако, тезисы Ганджустата как-то говорят о том, на мой взгляд, что домены это хорошо, но пиши как знаешь и проще, всё равно по метрикам на большом проекте это не даёт особого профита. Вот как быть?

Если он это подтвердит исследованиями, а так это его просто личное мнение.
Программа – это мысли спрессованные в код
Re[10]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 03.12.25 12:47
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Например, у вас сервис работает с несколькими стораджами/провайдерами/итд, у всех разные дто.


Во! Кстати действительно веская причина — если одновременно несколько разных СУБД — тут да, нужны мапперы.
Re[8]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 04.12.25 17:58
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


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


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


K>>В чём тогда серебряная пуля? Где граница применимости и как понять когда всё, приехали и "абстракции" давят и наоборот когда код превратился в набор спагетти? Все DDD, CA и т.п. было зря?



G>Ключевое прекрасно описано вот в этом посте: https://www.teamten.com/lawrence/programming/write-code-top-down.html


G>Процитирую основную мысль:

G>

G>Существует два подхода к проектированию программ и написанию кода: «сверху вниз» и «снизу вверх».

G>При проектировании сверху вниз вы начинаете с представления о программе в целом, возможно, о некоторых её компонентах и о том, как они взаимодействуют друг с другом, но сами компоненты ещё не до конца ясны. Вы реализуете высокоуровневую версию программы, которая вызывает упрощённые версии компонентов (которые могут ничего не делать), и постепенно углубляетесь в детали каждого компонента.

G>При проектировании снизу вверх вы начинаете с компонентов, которые вам хорошо видны, но пока неясно, как они сочетаются друг с другом. Вы пишете компоненты по отдельности, тестируете их, а затем собираете в целую программу.

G>Правильный подход к проектированию и написанию программы — «сверху вниз». Это не вопрос вкуса или предпочтений. Подход «снизу вверх» в корне ошибочен, и его не следует использовать.


G>Если вы со старта проекта начинаете применять архитектурные паттерны, то вы фактически занимаетесь проектированием «снизу вверх».


G>

G>На каждом уровне существует стремление в программировании «снизу вверх». Избегайте этого. Вместо этого начните с верхнего уровня, с main() или его эквивалента, и пишите так, как будто все части уже написаны. Добейтесь правильного вида. Вставьте заглушки или хардкод отдельных частей пока не добьетесь компиляции и запуска. Затем медленно продвигайтесь вниз, стараясь максимально упростить все. Не пишите ни строчки кода, которая не решает проблему, с которой вы столкнулись прямо сейчас. Тогда у вас может появиться шанс написать большую, работоспособную и долговечную программу.


Clean Architecture не мешает разрабатывать в любом направлении. Вот TDD — подход с верху в низ, но работают здесь с моделью.
Программа – это мысли спрессованные в код
Re[9]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 04.12.25 18:24
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Clean Architecture не мешает разрабатывать в любом направлении.

Честно до сих пор не понимаю что такое CA.
Если я написал контроллер из которого вызвал EF и данные в базу записал это уже clean или еще нет?
Если мне для Clean Architecture еще что-то сделать, то это уже программирование «снизу вверх».
Re[10]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 04.12.25 18:39
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


Q>>Clean Architecture не мешает разрабатывать в любом направлении.

G>Честно до сих пор не понимаю что такое CA.
G>Если я написал контроллер из которого вызвал EF и данные в базу записал это уже clean или еще нет?
G>Если мне для Clean Architecture еще что-то сделать, то это уже программирование «снизу вверх».

Нет не CA. Лучше книжку почитать, самому поэкспериментировать.
Программа – это мысли спрессованные в код
Re[8]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.12.25 06:52
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Ключевое прекрасно описано вот в этом посте: https://www.teamten.com/lawrence/programming/write-code-top-down.html


Так себе статья. bottom up нужен в тех случаях, когда вы не знаете куда двигаться, и потому создаёте небольшие кирпичики, которые потом объединяете в компоненты.
В этом случае вы даже не знаете, какая архитектура будет через год.
И это нормально, есть на то причины.

Другое дело, когда вы лепите типовые проекты. Здесь ваши предположения гораздо точнее даже в отсутствие требований. И можно просто заранее заложить нужную архитектуру.

G>Если вы со старта проекта начинаете применять архитектурные паттерны, то вы фактически занимаетесь проектированием «снизу вверх».


Накидывание паттернов к этим двум подходам никак не относится. Например, решили, что "у нас будут микросервисов 100 штук, свяжем через очередь, хз зачем, детали накинем позже"
Вот вам и top down, читаем вместе вашу же ссылку "With top-down design you start with a vision of the whole program, perhaps what some of the components are, and how they fit together, but the components themselves are still fuzzy. "
Re[9]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.12.25 07:31
Оценка:
Здравствуйте, Pauel, Вы писали:

P>В этом случае вы даже не знаете, какая архитектура будет через год.

Никто не знает какая архитектура будет через год. Все кто утверждает обратное — скорее всего просто заблуждаются

P>Другое дело, когда вы лепите типовые проекты. Здесь ваши предположения гораздо точнее даже в отсутствие требований. И можно просто заранее заложить нужную архитектуру.

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

G>>Если вы со старта проекта начинаете применять архитектурные паттерны, то вы фактически занимаетесь проектированием «снизу вверх».

P>Накидывание паттернов к этим двум подходам никак не относится. Например, решили, что "у нас будут микросервисов 100 штук, свяжем через очередь, хз зачем, детали накинем позже"
Как это будет реально выглядеть?

Вот ты сделаешь file->new project... как из этого получится 100 микросервисов, чем они будут заниматься?

P>Вот вам и top down, читаем вместе вашу же ссылку "With top-down design you start with a vision of the whole program, perhaps what some of the components are, and how they fit together, but the components themselves are still fuzzy. "

Так прочитай внимательно что написано — "вы начинаете с представления о всей программе, возможно, о некоторых её компонентах". То есть не надо заранее придумать ВСЕ компоненты. Если ты заранее проектируешь компоненты, а потом из них что-то работающее собрать — это проектирование "снизу вверх"
Re[10]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.12.25 08:22
Оценка:
Здравствуйте, gandjustas, Вы писали:

P>>В этом случае вы даже не знаете, какая архитектура будет через год.

G>Никто не знает какая архитектура будет через год. Все кто утверждает обратное — скорее всего просто заблуждаются

Опаньки! И как же вы будете код сверху вниз писать не зная? Вам придется растить приложение архитектуру эволюционно, добавлять те или иные вещи по мере необходимости.

P>>Другое дело, когда вы лепите типовые проекты. Здесь ваши предположения гораздо точнее даже в отсутствие требований. И можно просто заранее заложить нужную архитектуру.

G>Откуда ты знаешь какая архитектура нужна на любом нетиповом проекте?
G>Понятно если если ты делаешь сайт-визитку, то они все плюс-минус одинаковые, и в принципы готовые решения-фреймворки есть, в рамках которых ты также двигаешься "сверху вниз".

Вы зачем то пересказываете то, что я вам сам же и сказал Вы читаете или только пишете?

P>>Накидывание паттернов к этим двум подходам никак не относится. Например, решили, что "у нас будут микросервисов 100 штук, свяжем через очередь, хз зачем, детали накинем позже"

G>Как это будет реально выглядеть?

G>Вот ты сделаешь file->new project... как из этого получится 100 микросервисов, чем они будут заниматься?


В вашей ссылке на это ответ "the components themselves are still fuzzy". Обычно это так выглядит "вот здесь будет сервис, но что он будет делать, решим потом"

P>>Вот вам и top down, читаем вместе вашу же ссылку "With top-down design you start with a vision of the whole program, perhaps what some of the components are, and how they fit together, but the components themselves are still fuzzy. "

G>Так прочитай внимательно что написано — "вы начинаете с представления о всей программе, возможно, о некоторых её компонентах". То есть не надо заранее придумать ВСЕ компоненты. Если ты заранее проектируешь компоненты, а потом из них что-то работающее собрать — это проектирование "снизу вверх"

Нету никакого проектирования компонентов, есть исключительно представление о всей программе целиком. Ни про один из компонентов нет внятного представления. То есть, ровно то, о чем в вашей ссылке.
Отредактировано 05.12.2025 10:00 Pauel . Предыдущая версия .
Re[8]: Что если не разделять строго dto, entity, bo...
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 05.12.25 08:42
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Ключевое прекрасно описано вот в этом посте: https://www.teamten.com/lawrence/programming/write-code-top-down.html

Ну так в CA про тоже написано.

G>Процитирую основную мысль:

G>

G>При проектировании снизу вверх вы начинаете с компонентов, которые вам хорошо видны, но пока неясно, как они сочетаются друг с другом. Вы пишете компоненты по отдельности, тестируете их, а затем собираете в целую программу.

Не совсем понятно как это работает, если честно.

G>Если вы со старта проекта начинаете применять архитектурные паттерны, то вы фактически занимаетесь проектированием «снизу вверх».

Со старта я начинаю собирать сценарии использования и через них выхожу на модели предметной области, алгоритмы и т.п. и вот там уже при проектировании можно говорить про паттерны если оно очевидно или писать как есть и потом это дело выделять, потом и все SOLID будет понятно где применить. Похоже на практику экстремального программирования.

G>

G>На каждом уровне существует стремление в программировании «снизу вверх». Избегайте этого.

Не совсем понятно как это работает в реальном мире. ibn4: оно не работает.
Sic luceat lux!
Re[12]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.12.25 16:10
Оценка:
Здравствуйте, Pauel, Вы писали:

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


G>>Я говорил что надо уменьшить количество строк.


P>Смотрите сам, что вы пишете "кода с разделением и без и не код с разделением стабильно проигрывал"


Когда код делает +\- одно и то же и может быть написан без архитектурных паттернов, то по формальным метрикам он скорее всего превзойдет код с такими паттернами. Но я не исключаю, что могут быть случаи, когда паттерны реально уменьшают количество кода и\или улучшают потребительские характеристики системы. Но это надо в каждом конкретном случае оценивать, а не принимать как мантру, что DDD\CA\SOLID\GRASP\DICK это хорошо и обязательно надо делать.

G>>Во-первых

G>>Во-вторых
G>>В-третьих
G>>В-четвертых
G>>В-пятых

P>На примере 1 файл 1 main вам вроде бы понятно, какие последствия если отказаться от того самого разделения.

P>А вот с мапперами вам почему то непонятно
Потому что мапперы это не корень проблемы, а следствие. Если вам нужен маппер, то вероятно, что вы сильно ранее свернули не туда.

P>Любой концепт — класс, функция, интерфейс, итд, это то самое разделение.

P>Если бенефитов нет, см ваши "во-первых..." то добавление класса, функции, интерфейса, итд смысла не имеет. Мапперы, паттерны здесь ничего не меняют.
Еще раз:
1) Без разделения скорее всего кода станет больше
2) Иногда разделение необходимо для использования фреймворков и библиотек
3) Разделение нужно чтобы была навигация по коду. если у вас одна сплошная простыня текста на много экранов, то вы много времени тратить будете на навигацию.


P>А кто говорил, что надо заранее? Любое разделение обязанностей, см ваши пункты про main, нужно вводить вовремя. Слишком рано — утяжеляем и замедляем разработку. Слишком поздно — хаос.

Рецепт как вводить изменения вовремя уже многократно дан — ты пишешь максимально простой код чтобы решить ту задачу, которая у тебя есть в данный момент и не пишешь код, который к решению задачи не относится.

P>А если изначально большую писать как маленькую, то есть чудовищно огромный шанс или утопить, или вырастить монстра, или убить весь бюджет на один только рефакторинг.

Вот что-то я такого не видел. Усложнять всегда просто, упрощать — сложно.

G>>Я всегда говорил, что нужно в каждый момент времени писать минимум кода для решения задачи, которая есть в данный момент. ИМХО в таких условиях вероятность появления domain model и DTO стремится вообще к нулю.

P>Ой да ладно. Вы подразумеваете какой то свой набор приложений-проектов. Озвучьте уже его.
Да любые корпоративные многопользовательские приложения.
Re[8]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 05.12.25 19:17
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Процитирую основную мысль:

G>

G>При проектировании сверху вниз вы начинаете с представления о программе в целом, возможно, о некоторых её компонентах и о том, как они взаимодействуют друг с другом, но сами компоненты ещё не до конца ясны. Вы реализуете высокоуровневую версию программы, которая вызывает упрощённые версии компонентов (которые могут ничего не делать), и постепенно углубляетесь в детали каждого компонента.


G>Если вы со старта проекта начинаете применять архитектурные паттерны, то вы фактически занимаетесь проектированием «снизу вверх».


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

То что вы предлагаете — сразу писать реализацию чтобы сразу работало не думая об архитектуре — и есть снизу вверх. Неужели не очевидно?
Re[11]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 05.12.25 19:19
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Я всегда говорил, что нужно в каждый момент времени писать минимум кода для решения задачи, которая есть в данный момент. ИМХО в таких условиях вероятность появления domain model и DTO стремится вообще к нулю.


Тут вопрос — а если не продумали архитектуру и:

1. Можно решить задачу просто добавив 100 строк.
2. Можно убрать 10 тыс. лишних строк и добавить еще 500 строк.

Что выбрать?
Re[12]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.12.25 19:58
Оценка:
Здравствуйте, Shmj, Вы писали:

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


G>>Я всегда говорил, что нужно в каждый момент времени писать минимум кода для решения задачи, которая есть в данный момент. ИМХО в таких условиях вероятность появления domain model и DTO стремится вообще к нулю.


S>Тут вопрос — а если не продумали архитектуру и:


S>1. Можно решить задачу просто добавив 100 строк.

S>2. Можно убрать 10 тыс. лишних строк и добавить еще 500 строк.

S>Что выбрать?


В этом случае конечно второе. Но это уже последствие.
Ведь кто-то изначально написал эти 10к ЛИШНИХ строк, потратив кучу времени и денег.
А если бы с самого начала не занимались этим, то вариант 2 не возник бы никогда.
Re[9]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.12.25 20:14
Оценка:
Здравствуйте, Shmj, Вы писали:

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


G>>Процитирую основную мысль:

G>>

G>>При проектировании сверху вниз вы начинаете с представления о программе в целом, возможно, о некоторых её компонентах и о том, как они взаимодействуют друг с другом, но сами компоненты ещё не до конца ясны. Вы реализуете высокоуровневую версию программы, которая вызывает упрощённые версии компонентов (которые могут ничего не делать), и постепенно углубляетесь в детали каждого компонента.


G>>Если вы со старта проекта начинаете применять архитектурные паттерны, то вы фактически занимаетесь проектированием «снизу вверх».


S>Как раз нет — там же прямо написано "о программе в целом, возможно, о некоторых её компонентах и о том, как они взаимодействуют друг с другом". Т.е. реализации еще нет, а уже есть взаимодействие — это и есть паттерны.

Конечно, если он решают конкретную задачу, которая есть в данный момент. Если такой нет, то и паттерн никакой не нужен.

S>То что вы предлагаете — сразу писать реализацию чтобы сразу работало не думая об архитектуре — и есть снизу вверх. Неужели не очевидно?

Не очевидно почему эт "не думая об архитектуре". Нигде ведь не написано что не надо вообще применять паттерны, структурировать код итд.
Все что написано:
1) Напиши сначала вызывающий код, а потом вызываемый, не наоборот
2) Не пиши код, который не требуется для задачи, которую ты решаешь в данный момент
3) Пиши максимально простой код для решения задачи, например есть если ты можешь написать 10 строк, то не надо писать 100

Если что-то из этого мешает тебе думать об архитектуре?
Может то, что ты называешь архитектурой и есть тот самый bottom-up development, который мешает?
Re[11]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 05.12.25 20:22
Оценка:
Здравствуйте, Kernan, Вы писали:

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


K>>>Со старта я начинаю собирать сценарии использования

G>>Сценарий использования это набор форм и или методов апи — создай эти формы\методы для начала
K>А лучше начать с тестов...
Чем лучше? Я вот сомневаюсь. Запускаемое работающие приложение лучше десятка "зеленых" тестов.
Конечно иногда запустить код сложно, поэтому нужны тесты, но это скорее костыль

G>>Повтори процедуру для других форм и методов. Устрани противоречия. Сделай рефакторинг, вынеси повторяющийся код в отдельные функции\классы. Только тут могут появиться простые паттерны GoF. До DDD и прочих архитектурных излишеств не дойдет если не пытаться решать задачи, которых нет.

K>Не получилось бы так, чтобы всё написанное не пришлось бы переписать полностью после неудачных решений по-месту.
Ну перепиши. Если ты написал 10 строк, то можешь их переписать на написать новые 10.
Это будет проще, че поменять 10 строк в эквивалентном коде на 100 строк со всякими паттернами итд.

Опять таки есть святая вера что если написать заранее больше, то потом придется писать и править меньше. Но нет, количество и сложность изменений прямо пропорциональны объему кода.

G>>Мне кажется программисты слишком заморочены на "модели предметной области", как-будто есть в этом ценность.

K>Проще работать с моделями и метафорами чем с набором примитивных типов.
За счет чего проще? Не является ли этой очередной популярной мантрой?
Если код структурирован, имеет хороший нейминг, высокую согласованность внутри классов и низкую связность между ними, придерживается SOLID, то какая по большому счету разница если нет набора классов, которые вы могли бы назвать "моделью предметной области"
Re[13]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 05.12.25 21:15
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>1. Можно решить задачу просто добавив 100 строк.

S>>2. Можно убрать 10 тыс. лишних строк и добавить еще 500 строк.

S>>Что выбрать?


G>В этом случае конечно второе. Но это уже последствие.


Тут вот в чем дело. Добавить 100 строк — проще, чем удалить 10 тыс. и добавить 500. Верно? Т.е. для бизнеса здесь и сейчас — лучше не перекраивать архитектуру а просто добавить 100 строк.

G>Ведь кто-то изначально написал эти 10к ЛИШНИХ строк, потратив кучу времени и денег.

G>А если бы с самого начала не занимались этим, то вариант 2 не возник бы никогда.

Вот по тому же принципу и было добавлено — проще не делать архитектуру, где будет минимум кода — а добавить очередной костыль побыряку.
Re[10]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 05.12.25 22:05
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Как раз нет — там же прямо написано "о программе в целом, возможно, о некоторых её компонентах и о том, как они взаимодействуют друг с другом". Т.е. реализации еще нет, а уже есть взаимодействие — это и есть паттерны.

G>Конечно, если он решают конкретную задачу, которая есть в данный момент. Если такой нет, то и паттерн никакой не нужен.

А какая может быть задача? Вот есть задача — разработать сервис. Кто-то продумал функционал. Что делать? Сделать кусочек работающего функционала, чтобы хотя бы одна страничка работала — или же сделать скелет, который охватывает все, но при этом ничего полезного не делает?
Re[11]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.12.25 17:33
Оценка:
Здравствуйте, Shmj, Вы писали:

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


S>>>Как раз нет — там же прямо написано "о программе в целом, возможно, о некоторых её компонентах и о том, как они взаимодействуют друг с другом". Т.е. реализации еще нет, а уже есть взаимодействие — это и есть паттерны.

G>>Конечно, если он решают конкретную задачу, которая есть в данный момент. Если такой нет, то и паттерн никакой не нужен.

S>А какая может быть задача? Вот есть задача — разработать сервис. Кто-то продумал функционал. Что делать? Сделать кусочек работающего функционала, чтобы хотя бы одна страничка работала — или же сделать скелет, который охватывает все, но при этом ничего полезного не делает?

Речь всегда идет о решении задачи\проблемы пользователя.
Re[14]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.12.25 17:40
Оценка:
Здравствуйте, Shmj, Вы писали:

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


S>>>1. Можно решить задачу просто добавив 100 строк.

S>>>2. Можно убрать 10 тыс. лишних строк и добавить еще 500 строк.

S>>>Что выбрать?


G>>В этом случае конечно второе. Но это уже последствие.

S>Тут вот в чем дело. Добавить 100 строк — проще, чем удалить 10 тыс. и добавить 500. Верно? Т.е. для бизнеса здесь и сейчас — лучше не перекраивать архитектуру а просто добавить 100 строк.
Проще — да. Совокупный экономический эффект от удаления 9500 строк окажется выше. Возможно даже стоит разделить задачи — сначала удалить лишнее, а потом добавить 100 строк, которые решают задачу пользователя.


G>>Ведь кто-то изначально написал эти 10к ЛИШНИХ строк, потратив кучу времени и денег.

G>>А если бы с самого начала не занимались этим, то вариант 2 не возник бы никогда.

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

Ты сам себе противоречишь.
1) Если когда-то было написано 10000 срок, которые сейчас можно удалить, то это были лишние строки еще в момент написания. Это значит кто-то отклонился от правила писать минимум строк для решения задачи.
2) Если эти сроки не были лишние в момент написания, но просто стали ненужными из-за изменения требований, то удалить их проблемы не представляет и надо это сделать.
3) Если строки нельзя просто удалить, потому что на них завязан другой код, но их удалить НУЖНО, то см п1
Re[12]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 07.12.25 18:20
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>А какая может быть задача? Вот есть задача — разработать сервис. Кто-то продумал функционал. Что делать? Сделать кусочек работающего функционала, чтобы хотя бы одна страничка работала — или же сделать скелет, который охватывает все, но при этом ничего полезного не делает?

G>Речь всегда идет о решении задачи\проблемы пользователя.

Пользователю нужен продукт, а чтобы сделать продукт — нужно решить множество задач.

Еще раз вопрос как вы поставите работу: сделаете 1 минимальную рабочую страницу/экран, который делает уже что-то. Либо же напишите скелет системы, который ничего не делает а просто как бы охватывает все без реализации? Это важный вопрос.
Re[15]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 07.12.25 18:39
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Тут вот в чем дело. Добавить 100 строк — проще, чем удалить 10 тыс. и добавить 500. Верно? Т.е. для бизнеса здесь и сейчас — лучше не перекраивать архитектуру а просто добавить 100 строк.

G>Проще — да. Совокупный экономический эффект от удаления 9500 строк окажется выше. Возможно даже стоит разделить задачи — сначала удалить лишнее, а потом добавить 100 строк, которые решают задачу пользователя.

Кто сказал что выше? Кому мешают лишние строки — ведь удалить — это работа. Оно же все завязано одно на другое — это не значит что просто взял и удалил вчистую.

G>>>Ведь кто-то изначально написал эти 10к ЛИШНИХ строк, потратив кучу времени и денег.

G>>>А если бы с самого начала не занимались этим, то вариант 2 не возник бы никогда.

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

G>Ты сам себе противоречишь.
G>1) Если когда-то было написано 10000 срок, которые сейчас можно удалить, то это были лишние строки еще в момент написания. Это значит кто-то отклонился от правила писать минимум строк для решения задачи.

Давай на примере, причем реальном. Вот, под некий язык нет библиотек для авто-генерации под SOAP. Что делать? Поискали — нету.

Нужно сделать задачу, задействовав несколько SOAP-методов. Проще руками. Раз и написал.

Далее, через год в проекте уже 1.9 Мб и 300+ файлов с ручными SOAP-обертками. Почему? Потому что каждый раз для решения задачи легче было написать несколько оберток вручную, чем выделить время для написания кодогенератора по WSDL.

И тут приходит Вася, пишет кодогенератор на 49 Кб — это значит все эти 1.9 Мб — можно выкинуть. Но кодогенератор имеет немалый код — 49 Кб. — писать не один день а скорее несколько дней, причем код сложнее чем тривиальный код обертки.

Вот и получается — в любой момент времени для решения текущей задачи — было не выгодно писать генератор, всегда было выгоднее написать обертку вручную. И со временем количество вручную написаных оберток как раз и достигло огромного масштаба. Отдельное удовольствие править эти обертки, когда меняются API.

Т.е. нужно не просто быстро решить текущую задачу — а понимать масштабы проекта и видеть на несколько шагов вперед.

G>2) Если эти сроки не были лишние в момент написания, но просто стали ненужными из-за изменения требований, то удалить их проблемы не представляет и надо это сделать.


Представляет проблему — т.к. вручную написанные обертки отличаются от тех, что будут сгенерены автоматом — там свои именования (чуть другие), свои методы для enum и т.д. Т.е. огромный кусок работы — пока решено оставить как есть, хотя генератор все генерит за секунду и писать не нужно.

G>3) Если строки нельзя просто удалить, потому что на них завязан другой код, но их удалить НУЖНО, то см п1


Но бизнесу это не даст бонусов, т.к. написанное вручную уже более-менее работает.
Re[15]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 07.12.25 19:48
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Если хорошо натренировать всегда выдавать максимально простой код, то это будет сильно быстрее, чем то, что фигачат DDD-программисты и всякие ИИ. Потому что есть предел количества строк отлаженного продуктивного кода, который может выдавать программист в единицу времени. И он почти не зависит ни от языка, ни от архитектуры.


Тут вот в чем проблема. На начальном этапе проще код написанный в лоб. Когда проект уже вырос — получается что первоначальная стратегия уже не годится, что лучше подойти с умом.
Re[16]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 08.12.25 07:26
Оценка:
Здравствуйте, Shmj, Вы писали:

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


S>>>Тут вот в чем дело. Добавить 100 строк — проще, чем удалить 10 тыс. и добавить 500. Верно? Т.е. для бизнеса здесь и сейчас — лучше не перекраивать архитектуру а просто добавить 100 строк.

G>>Проще — да. Совокупный экономический эффект от удаления 9500 строк окажется выше. Возможно даже стоит разделить задачи — сначала удалить лишнее, а потом добавить 100 строк, которые решают задачу пользователя.

S>Кто сказал что выше? Кому мешают лишние строки — ведь удалить — это работа. Оно же все завязано одно на другое — это не значит что просто взял и удалил вчистую.

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

G>>>>Ведь кто-то изначально написал эти 10к ЛИШНИХ строк, потратив кучу времени и денег.

G>>>>А если бы с самого начала не занимались этим, то вариант 2 не возник бы никогда.

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

S>Нужно сделать задачу, задействовав несколько SOAP-методов. Проще руками. Раз и написал.
Допустим. У тебя как минимум появится код, который делает сериализацию-десериализацию в SOAP, который может быть обобщен, так как не зависит от сервисов. Для первой обертки это конечно не имеет смысла.

S>Далее, через год в проекте уже 1.9 Мб и 300+ файлов с ручными SOAP-обертками. Почему? Потому что каждый раз для решения задачи легче было написать несколько оберток вручную, чем выделить время для написания кодогенератора по WSDL.

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


S>И тут приходит Вася, пишет кодогенератор на 49 Кб — это значит все эти 1.9 Мб — можно выкинуть. Но кодогенератор имеет немалый код — 49 Кб. — писать не один день а скорее несколько дней, причем код сложнее чем тривиальный код обертки.

Допустим это не вася, а просто нашли готовую реализацию генератора. Значит весь старый код не нужен. Просто все обертки надо удалить, а потом в местах вызовов этих оберток поправить код на использование сгенерированных. Ведь мест вызовов гораздо меньше чем мегабайт.
Это как раз случай, который описан в п2.

И естественно оно все никак не связно с задачей добавления нового функционала.

S>Т.е. нужно не просто быстро решить текущую задачу — а понимать масштабы проекта и видеть на несколько шагов вперед.

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

G>>2) Если эти сроки не были лишние в момент написания, но просто стали ненужными из-за изменения требований, то удалить их проблемы не представляет и надо это сделать.

S>Представляет проблему — т.к. вручную написанные обертки отличаются от тех, что будут сгенерены автоматом — там свои именования (чуть другие), свои методы для enum и т.д. Т.е. огромный кусок работы — пока решено оставить как есть, хотя генератор все генерит за секунду и писать не нужно.
Если у вас генератор не поддерживает мэппинг на существующие классы, то вы с высокой вероятностью не откажетесь от самописных оберток.
Но суть проблемы это не меняет. Ваши мегабайты говнокода появились именно потому, что программисты не следовали правилу создавать максимально простое решение в каждый момент времени.

G>>3) Если строки нельзя просто удалить, потому что на них завязан другой код, но их удалить НУЖНО, то см п1

S>Но бизнесу это не даст бонусов, т.к. написанное вручную уже более-менее работает.
Поэтому в реальности такой замены не будет, видел это несколько раз. Замена будет тогда, когда SOAP сменится на какой-нибудь rest и править мегабайты самописных оберток станет невозможно, тогда просто выкинут старое и возьмут генератор.
Re[16]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 08.12.25 07:29
Оценка:
Здравствуйте, Shmj, Вы писали:

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


G>>Если хорошо натренировать всегда выдавать максимально простой код, то это будет сильно быстрее, чем то, что фигачат DDD-программисты и всякие ИИ. Потому что есть предел количества строк отлаженного продуктивного кода, который может выдавать программист в единицу времени. И он почти не зависит ни от языка, ни от архитектуры.


S>Тут вот в чем проблема.

В чем?

S>На начальном этапе проще код написанный в лоб.

Никто не спорит.

S>Когда проект уже вырос — получается что первоначальная стратегия уже не годится, что лучше подойти с умом.

Звучит как-будто вы вчера писали все в одном файле в main, а сегодня у вас 100500 сервисов\проектов\классов\файлов.
Это может случится если вайб-кодить, но если писать руками, то развитие идет постепенно. На второй или максимум третьей однотипной задаче код получится легче если провести небольшой рефакторинг и вынести общие куски.
Re[17]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 08.12.25 18:32
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


Вот в том то и проблема — никто не знает заранее как приложение получится проще. А когда уже написано — то на текущий момент нет времени переписывать — т.к. нужен ежедневный результат и текучка задач от бизнеса — на рефакторинг и приведение в порядок уже нет времени обычно.

G>Допустим это не вася, а просто нашли готовую реализацию генератора. Значит весь старый код не нужен.


Не нашли. Кто-то понял что так будет проще и взял и написал, вместо того чтобы ждать пока до других это дойдет.
Re[17]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 08.12.25 18:33
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Когда проект уже вырос — получается что первоначальная стратегия уже не годится, что лучше подойти с умом.

G>Звучит как-будто вы вчера писали все в одном файле в main, а сегодня у вас 100500 сервисов\проектов\классов\файлов.
G>Это может случится если вайб-кодить, но если писать руками, то развитие идет постепенно. На второй или максимум третьей однотипной задаче код получится легче если провести небольшой рефакторинг и вынести общие куски.

К сожалению так не работает. Архитектура должна быть изначально — иначе потом переделывать под другую архитектуру будет слишком дорого и не будет времени.
Re[17]: Что если не разделять строго dto, entity, bo...
От: Shmj Ниоткуда  
Дата: 09.12.25 07:42
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>И тут приходит Вася, пишет кодогенератор на 49 Кб — это значит все эти 1.9 Мб — можно выкинуть. Но кодогенератор имеет немалый код — 49 Кб. — писать не один день а скорее несколько дней, причем код сложнее чем тривиальный код обертки.

G>Допустим это не вася, а просто нашли готовую реализацию генератора.

Вот на этом примере и открывается главная ваша проблема.

Вы не смотрите в будущее.

Вот нашли — это настоящий момент, цена равна нулю — ничего вкладывать и рисковать не нужно — халява.

А если нет халявы и нужно принять решение? Нужно написать генератор кода по WSDL, который охватит все API используемые (по стандарту не требуется — пусть работает только для наших API + возможность доработки, кода чего-то не хватает) — кто будет оценивать сколько строк кода и насколько сложно это написать??? Кто будет оценивать стоит ли игра свеч???

Вот это и есть самое сложное — и никто точно не может сказать как лучше, как проще
Re[13]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.12.25 14:10
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Что выбрать?


G>В этом случае конечно второе. Но это уже последствие.

G>Ведь кто-то изначально написал эти 10к ЛИШНИХ строк, потратив кучу времени и денег.
G>А если бы с самого начала не занимались этим, то вариант 2 не возник бы никогда.

Сомнительно. Если предположить, что разработчик был добросовестным, то 10к лишних строк появились по простой причине
1 появились требования
2 появилось решение с учетом всех целей и приоритетов того времени
3 требования поменялись, возможно, несколько раз
4 "инвентаризацию" отложили на потом т.к. были другие приоритеты

Это ведь только у джуна одна единственная цель "что бы работало". Обычно же есть множество сопутствующих целей. И решение должно достигать все актуальные цели. Потому и кода получается больше, чем просто "что бы работало"

Например, можно точечно поправить условие, это приведет к тому, что следующие N фиксов у других разработчиков будут заканчиваться неудачами. Так мины обычно и закладываются — находишь однострочник, а потом по всему коду попытки купировать, то тут, то там.
Re[13]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 29.12.25 10:18
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>В этом случае конечно второе. Но это уже последствие.

G>Ведь кто-то изначально написал эти 10к ЛИШНИХ строк, потратив кучу времени и денег.
G>А если бы с самого начала не занимались этим, то вариант 2 не возник бы никогда.

Почему обязательно лишних, и потратив кучу времени и денег? Может оказаться что всё ровно наоборот.

Например, на момент написания эти 10к строк решали конкретные требования которые со временем отжили своё. Или, например, срочность изменений в требованиях была настолько высокой, что другого варианта, кроме как строчить и копипастить, вообще не было.

То есть, чаще всего вот эти "лишние" строки становятся такими только со временем. Это если отказаться от варианта "все дураки"

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

Например, реанимировать проект краткосрочными интервенциями "главное сделать" не получится. Скорее всего, он именно и зашел в тупик благодаря "главное сделать".
Re[10]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 29.12.25 11:36
Оценка:
Здравствуйте, gandjustas, Вы писали:

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

G>Мне кажется программисты слишком заморочены на "модели предметной области", как-будто есть в этом ценность.

Внезапно программисты получают деньги не за то, что они есть, а за то, что решают бизнес проблемы заказчика.
И вот, чтобы как можно легче, проще и быстрее решать эти проблемы и появились всякие модели предметной области и DDD.
Кодом людям нужно помогать!
Re[12]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 29.12.25 12:01
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>За счет чего проще? Не является ли этой очередной популярной мантрой?

G>Если код структурирован, имеет хороший нейминг, высокую согласованность внутри классов и низкую связность между ними, придерживается SOLID, то какая по большому счету разница если нет набора классов, которые вы могли бы назвать "моделью предметной области"

Считается, что первое достигается при помощи второго.
Кодом людям нужно помогать!
Re[15]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 29.12.25 12:15
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Если хорошо натренировать всегда выдавать максимально простой код, то это будет сильно быстрее, чем то, что фигачат DDD-программисты и всякие ИИ. Потому что есть предел количества строк отлаженного продуктивного кода, который может выдавать программист в единицу времени. И он почти не зависит ни от языка, ни от архитектуры.


Я ни разу не апологет DDD, ни одной (пока) книги не прочитал, хотя тему изучал. Так вот, люди его не зря ценят, начиная от определенного объема
сложности, если архитектура спроектирована с учетом DDD, банально проще и быстрее расширять, вносить изменения и т.п. Но это дает свои плоды
при определенных объемах задачи\предметной области, т.е. много человеколет.
Кодом людям нужно помогать!
Re[11]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.12.25 13:24
Оценка:
Здравствуйте, Sharov, Вы писали:

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


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

G>>Мне кажется программисты слишком заморочены на "модели предметной области", как-будто есть в этом ценность.

S>Внезапно программисты получают деньги не за то, что они есть, а за то, что решают бизнес проблемы заказчика.

И? как это связано с "моделью предметной области"? Я не улавливаю.

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

Слишком мало примеров когда они что-то упрощают и слишком много примеров, когда они что-то усложняют.
Re[13]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.12.25 13:26
Оценка:
Здравствуйте, Sharov, Вы писали:

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


G>>За счет чего проще? Не является ли этой очередной популярной мантрой?

G>>Если код структурирован, имеет хороший нейминг, высокую согласованность внутри классов и низкую связность между ними, придерживается SOLID, то какая по большому счету разница если нет набора классов, которые вы могли бы назвать "моделью предметной области"

S>Считается, что первое достигается при помощи второго.

Не понимаю логики:
1) считается что без "модели предметной области" не бывает хорошей структуры кода? Это мягко говоря неправда
2) считается что наличие "модели предметной области" всегда приводит к хорошей структуре? Это еще большая неправда
Re[12]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 29.12.25 14:03
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Внезапно программисты получают деньги не за то, что они есть, а за то, что решают бизнес проблемы заказчика.

G>И? как это связано с "моделью предметной области"? Я не улавливаю.

Без понимания и выработки соотв. абстракций решать проблемы будет крайне затруднительно.

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

G>Слишком мало примеров когда они что-то упрощают и слишком много примеров, когда они что-то усложняют.

Это факт. Это, кмк, нужно для больших, типа банковских и т.п., сервисов и приложений. Но по отдельности и некоторые компоненты DDD можно
использовать -- ubitiquos language, bounded context и т.п. Но тут тогда уж проще следовать методологии целиком, а не по кускам выдергивать.
Мож не взлетает именно из-за кусочничества .
Кодом людям нужно помогать!
Re[14]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 29.12.25 14:04
Оценка:
Здравствуйте, gandjustas, Вы писали:


S>>Считается, что первое достигается при помощи второго.

G>Не понимаю логики:
G>1) считается что без "модели предметной области" не бывает хорошей структуры кода? Это мягко говоря неправда
G>2) считается что наличие "модели предметной области" всегда приводит к хорошей структуре? Это еще большая неправда

Понимание модели предметной области помогает достигать качественного кода -- все по папочка и т.п., а не в одном большом
методе main.
Кодом людям нужно помогать!
Re[15]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 29.12.25 14:16
Оценка:
Здравствуйте, gandjustas, Вы писали:

P>>То есть, чаще всего вот эти "лишние" строки становятся такими только со временем. Это если отказаться от варианта "все дураки"

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

Как вы это представляете, каждая строка сама напишет в Slack "репозиторий-путь-файл-номер, можно удалять?"

Мертвый код сначаоа нужно идентифицировать. Чаще всего он просто выглядт, как живой код.

G>Проблема удаления кода возникает когда он используется, на него много зазвано.


Необязательно. Куда чаще мертвый код просто выглядит как живой и работающий, хотя нигде не вызывается или же его вызовы заканчиваются сразу на старте if (disabled) return;

G>То есть сначала делаем "главное чтобы заработало", потом устраняем ошибки в corner cases, очевидные code smells, вписываем в сущствующую архитектуру, делаем оптимальным.


Это всё крайне растяжимое. У каждого своё видение, насколько глубоко это всё надо делать.

G>Главное фокусироваться на одной задаче, а не заниматься проектированием системы. То есть не трогать ничего, что напрямую не касается данной задачи.


Это общие слова. Одна единственная задача это только краткосрочная перспектива. Пример — думали хватит чисто эндпоинта таскать из ui в базу и обратно, а после первого релиза вылезло такое...

P>>Например, реанимировать проект краткосрочными интервенциями "главное сделать" не получится. Скорее всего, он именно и зашел в тупик благодаря "главное сделать".

G>Как раз наоборот, в тупик заходят проекты, "проектируют наперед". Потому что если ты каждый раз делаешь минимум кода для решения задачи, то по какой причине у тебя появится тонна ненужного, но используемого кода?

Я вам уже привел пример Хорошее проектирование это не только здесь и сейчас, за что вы топите, но прежде всего и адеватный горизонт планирования.

На одном проекте горизонт это день, на другом — год. В первом случае вам абы результат показать, а во втором у вас наверняка появятся всевозможные особенности maintainability. И если вы попутаете кейсы, и во втором проекте начнете струячить, как на первом, хаос будет бежать впереди вас.
Re[13]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.12.25 15:32
Оценка:
Здравствуйте, Sharov, Вы писали:

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


S>>>Внезапно программисты получают деньги не за то, что они есть, а за то, что решают бизнес проблемы заказчика.

G>>И? как это связано с "моделью предметной области"? Я не улавливаю.

S>Без понимания и выработки соотв. абстракций решать проблемы будет крайне затруднительно.

Честно не понимаю о чем речь. Давайте возьмём например разработку форума. Какие абстракции для этого нужно создать? Того что предлагает .NET FW недостаточно?


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

G>>Слишком мало примеров когда они что-то упрощают и слишком много примеров, когда они что-то усложняют.

S>Это факт. Это, кмк, нужно для больших, типа банковских и т.п., сервисов и приложений. Но по отдельности и некоторые компоненты DDD можно

S>использовать -- ubitiquos language, bounded context и т.п. Но тут тогда уж проще следовать методологии целиком, а не по кускам выдергивать.
S>Мож не взлетает именно из-за кусочничества .
Тем не менее не видел примеров где БОЛЬШЕ ДДД делает код лучше, чем когда МЕНЬШЕ ДДД.
Может это какие-то слишком простые примеры были, но где взять сложные, чтобы можно было сравнивать подходы?
Re[16]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.12.25 15:46
Оценка:
Здравствуйте, Pauel, Вы писали:

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


P>>>То есть, чаще всего вот эти "лишние" строки становятся такими только со временем. Это если отказаться от варианта "все дураки"

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

P>Как вы это представляете, каждая строка сама напишет в Slack "репозиторий-путь-файл-номер, можно удалять?"

P>Мертвый код сначаоа нужно идентифицировать. Чаще всего он просто выглядт, как живой код.
Давайте считать что мертвый код уже был идентифицирован, ибо если нет, то о чем разговор?

G>>Проблема удаления кода возникает когда он используется, на него много зазвано.

P>Необязательно. Куда чаще мертвый код просто выглядит как живой и работающий, хотя нигде не вызывается или же его вызовы заканчиваются сразу на старте if (disabled) return;
Обычно мертвый код выглядит как классы которые нигде не создаются, находятся тремя-четырьмя кликами в студии.
Мы же говорим о тысячах строк такого кода, вряд ли это будет в таких ифах.

G>>То есть сначала делаем "главное чтобы заработало", потом устраняем ошибки в corner cases, очевидные code smells, вписываем в сущствующую архитектуру, делаем оптимальным.

P>Это всё крайне растяжимое. У каждого своё видение, насколько глубоко это всё надо делать.
Рамки задачи всегда можно сохранить. Просто задавай себе вопрос: "как это влияет на ту задачу, которую мне сейчас необходимо решить?". Если никак, то не надо этого делать.
Кроме того, я изначально писал что нужно заниматься проектированием и программированием "сверху вниз", тогда контролировать скоуп несложно.

G>>Главное фокусироваться на одной задаче, а не заниматься проектированием системы. То есть не трогать ничего, что напрямую не касается данной задачи.

P>Это общие слова.
Вполне конкретные.

P>Одна единственная задача это только краткосрочная перспектива.

Это именно краткосрочная.

P>Пример — думали хватит чисто эндпоинта таскать из ui в базу и обратно, а после первого релиза вылезло такое...

Ну так после первого релиза и поправьте. Никто ведь заранее не знал, что вылезет после релиза, а если бы пытались угадать, то вероятнее всего не угадали бы.


P>>>Например, реанимировать проект краткосрочными интервенциями "главное сделать" не получится. Скорее всего, он именно и зашел в тупик благодаря "главное сделать".

G>>Как раз наоборот, в тупик заходят проекты, "проектируют наперед". Потому что если ты каждый раз делаешь минимум кода для решения задачи, то по какой причине у тебя появится тонна ненужного, но используемого кода?

P>Я вам уже привел пример Хорошее проектирование это не только здесь и сейчас, за что вы топите, но прежде всего и адеватный горизонт планирования.

Практика показывает что занимаясь проектированием "только здесь и сейчас" почти всегда получается компактный код, который легко поддерживать. Как только пытаешься проектировать "наперед" появляется херня которая потом тянет назад, или просто зря тратишь время.
Особенно плохо если "каркас" приложения пишет "архитектор", а рядовые разрабы пытаются впихнуть в эти рамки свою логику, не имея возможности поменять неудобные места.
Re[14]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 30.12.25 08:53
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Без понимания и выработки соотв. абстракций решать проблемы будет крайне затруднительно.

G>Честно не понимаю о чем речь. Давайте возьмём например разработку форума. Какие абстракции для этого нужно создать? Того что предлагает .NET FW недостаточно?

Ну, например, абстракция "Запись" или "Пользователь". Когда какой-то пользователь создает где-то "Запись". У абстракции "Запись"
может быть ряд своих атрибутов тип содержимого, когда создан, можно ли редактировать, показывать данную запись всем или только
зарегистрированным пользователем. У "Пользователя" есть свои атрибуты. Форум -- это группа записей объединенных по какому-либо
критерию, скажем подфорум. Ну в общем, продолжая в том же духе можно еще прикинуть какие-нибудь важные доменные объекты или
абстракции. Что такого предлагает .NET FW кроме инструментов для работы с абстракциями(доменными сущностями)?

S>>Это факт. Это, кмк, нужно для больших, типа банковских и т.п., сервисов и приложений. Но по отдельности и некоторые компоненты DDD можно

S>>использовать -- ubitiquos language, bounded context и т.п. Но тут тогда уж проще следовать методологии целиком, а не по кускам выдергивать.
S>>Мож не взлетает именно из-за кусочничества .
G>Тем не менее не видел примеров где БОЛЬШЕ ДДД делает код лучше, чем когда МЕНЬШЕ ДДД.
G>Может это какие-то слишком простые примеры были, но где взять сложные, чтобы можно было сравнивать подходы?

Ну вот я работал в компании, где монолит распили на микросервисы по ДДД. Вроде работало. Но опять же, от ДДД там только
разбивка на микросервисы с помощью Bounded Context + Ubiquitous Language. Короче, в основном стратегические паттерны.
Кодом людям нужно помогать!
Re[16]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 30.12.25 09:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Вы сейчас пытаетесь сказать, что не бывает хорошего структурированного кода без "модели предметной области"? Я еще раз повторю что это неправда, предлагаю перестать об этом говорить.


А какую проблему решает хороший код, если он даже не пытается моделировать предметную область, т.е. не оперирует необходимыми абстракциями?
По-моему, даже на не ООП языках типа С люди стараются оперировать абстракциями в коде.

G>Могу показать примеры хорошего структурированного кода, где нет ничего, что можно было было назвать "моделью предметной области". Опять-таки можно сказать что это простые примеры, но я не видел сложных примеров с ДДД, где везде хороший структурированный код.


Давайте, а то мне кажется мы говорим о разном, подразумевая "модель предметной области".
Кодом людям нужно помогать!
Re[15]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.12.25 10:12
Оценка:
Здравствуйте, Sharov, Вы писали:

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


S>>>Без понимания и выработки соотв. абстракций решать проблемы будет крайне затруднительно.

G>>Честно не понимаю о чем речь. Давайте возьмём например разработку форума. Какие абстракции для этого нужно создать? Того что предлагает .NET FW недостаточно?

S>Ну, например, абстракция "Запись" или "Пользователь". Когда какой-то пользователь создает где-то "Запись". У абстракции "Запись"

S>может быть ряд своих атрибутов тип содержимого, когда создан, можно ли редактировать, показывать данную запись всем или только
S>зарегистрированным пользователем. У "Пользователя" есть свои атрибуты. Форум -- это группа записей объединенных по какому-либо
S>критерию, скажем подфорум. Ну в общем, продолжая в том же духе можно еще прикинуть какие-нибудь важные доменные объекты или
S>абстракции.

Из этой речи я понял, что "абстракции" это описания типов хранимых данных, чтобы делать запросы и получать данные типизировано?
Если так, то слово "абстракция" тут неуместно.

S>Что такого предлагает .NET FW кроме инструментов для работы с абстракциями(доменными сущностями)?

Например ASP.NET Core Identity. Он как раз представляет из себя абстракцию (определяет операции, позволяющие потребителю не зависеть от их реализации) для работы с пользователями в любой системе.
Вы можете по образу и подобию сделать свою абстракцию для работы с темами и сообщениями в форуме. Но она имеет смысл только тогда, кода к этой абстракции будет обращаться кто-то еще.
Для решения конкретной задачи — создания форума — нужны такие абстракции как "обработчик веб-запроса" (контроллеры), доступ к данным Entity Framework Core, фоновые задачи — backgroundservice, инструменты для работы с конфигурацией — Configuration и Options/
Вы на них собираете нужную вам функциональность.

Какие абстракции еще нужны? Или все "абстракции" сводятся к описаниям типов хранимых и передаваемых данных?
Re: Что если не разделять строго dto, entity, bo...
От: elmal  
Дата: 30.12.25 17:32
Оценка:
Здравствуйте, Shmj, Вы писали:

S>По этому как бы, получается, есть вера что нужно разделять — но нет реального смысла.

Смысл появляется с ростом проекта и с изменениями в проекте. На этапе прототипа и всяких MVP можно не разделять. Основное — выкатить что хоть как то работающее как можно быстрее. А вот далее пойдет развитие, доработки и т.д. И тут рано или поздно появится именно необходимость уже все разделять. Но в теории может и не понадобиться, если по быстрому написали и далее изменений не требуется почти. Но далее наверняка будут миграции всякие, смены базы данных, смена библиотек, возможно даже смена языка программирования, плюс все будет переписываться частями, потребуются хитрые интеграции со сторонними сервисами, зачастую еще разных версий — вот тут уже будут и разные DTO и чего только не будет. И это все будет очень оправдано, так как это тупо сэкономит до хрена времени на разработку и поиск и исправление багов. А пока проект детский, большой необходимости в разделении на Entity, DTO и бизнес объекты по большому счету нет. При развитии это все можно достаточно быстро все выносить, сложности то в преобразовании никакой. Но ключевое — хоть и сами объекты могут и выполнять на начальном этапе разные роли, крайне важно даже на этапе прототипа MVP не смешивать логику ввода-вывода, UI и бизнес логику. Иначе проблемы будут даже на детских проектах и будет баг на баге.
Re[18]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 31.12.25 00:13
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>А какую проблему решает хороший код, если он даже не пытается моделировать предметную область, т.е. не оперирует необходимыми абстракциями?

G>1) Уменьшает дублирование кода
G>2) Уменьшает количество связей и сайд-эффектов
G>3) Уменьшает цепочку вызовов и количество промежуточных слоев между вызовов и действием
G>4) Увеличивает быстродействие
G>5) Уменьшает неявную передачу данных и изменение стояния
G>Это все вещи связанные, но в некоторых местах могут противоречить друг другу, поэтому хороший код это баланс.

Ну т.е. код ради кода, понятно. Ну вот есть хороший код, который плохо решает поставленную задачу, поскольку автор
толком не разобрался в предметной области. Ну и какой прок от этой программы кроме эстетики кода?
Ну и самый главный вопрос, а как всему вышеперечисленному мешает оперирование объектами доменной модели?


S>>По-моему, даже на не ООП языках типа С люди стараются оперировать абстракциями в коде.

G>Вы как-то слишком широко применяете слово "абстракция". Когда вы создаете класс с набором свойств это не абстракция. Реализация интерфейса это тоже не абстракция. Абстракция это то, что использует такие классы или интерфейсы. А писать такой код нет необходимости. Большинство полезных абстракций уже есть в библиотеках, зачастую стандартных.

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

G>>>Могу показать примеры хорошего структурированного кода, где нет ничего, что можно было было назвать "моделью предметной области". Опять-таки можно сказать что это простые примеры, но я не видел сложных примеров с ДДД, где везде хороший структурированный код.

S>>Давайте, а то мне кажется мы говорим о разном, подразумевая "модель предметной области".
G>Начнем с простого, позже смогу вырезать кусок из реального проекта.
G>Недавно делал пример для статьи на Хабре https://github.com/gandjustas/habr-post-stock-api, АПИшка для резервации заказов, работает с базой, содержит очень важную для бизнеса логику. Это как маленький кусок большого приложения

Ну мы ведем речь про явно более крупные приложения, а не про crud на 3 операции.

G>Там даже есть абстракция — очередь запросов (она не шибко полезная в целом)


Зачем, лукавое это? А что стандартная библиотека, кстати, не помогла?

G>Что там является "моделью предметной области", в чем её ценность, и как она влияет на остальные части кода?


Ну как минимум https://github.com/gandjustas/habr-post-stock-api/blob/main/Model.cs
Кодом людям нужно помогать!
Re[17]: Что если не разделять строго dto, entity, bo...
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 31.12.25 13:16
Оценка:
Здравствуйте, gandjustas, Вы писали:

P>>Мертвый код сначаоа нужно идентифицировать. Чаще всего он просто выглядт, как живой код.

G>Давайте считать что мертвый код уже был идентифицирован, ибо если нет, то о чем разговор?

Ага, давайте считать, что проблемы нет, а строчки сами будут говорить надо ли их удалять.

G>Обычно мертвый код выглядит как классы которые нигде не создаются, находятся тремя-четырьмя кликами в студии.


Необязательно. Чаще всего они могут создаться, вызываться итд по недостижимым путям. У вас нет абсолютно точного синтаксического анализатора, который выдаст всё на блюдечке — проблема останова мешает.

P>>Это всё крайне растяжимое. У каждого своё видение, насколько глубоко это всё надо делать.

G>Рамки задачи всегда можно сохранить. Просто задавай себе вопрос: "как это влияет на ту задачу, которую мне сейчас необходимо решить?". Если никак, то не надо этого делать.

Вы в слова играете. У каждого своё видение, что именно относится к задаче. Например, один меняет метод, и все точки вызова проверит и поправит. А другой решит,что такая чистка к его задаче не относится, и даже тикет не создаст.

G>Кроме того, я изначально писал что нужно заниматься проектированием и программированием "сверху вниз", тогда контролировать скоуп несложно.


Это общие слова.

P>>Одна единственная задача это только краткосрочная перспектива.

G>Это именно краткосрочная.

О чем я вам говорю, и это — проблема, т.к. все среднесрочные и долгосрочные цели вне фокуса.

P>>Пример — думали хватит чисто эндпоинта таскать из ui в базу и обратно, а после первого релиза вылезло такое...

G>Ну так после первого релиза и поправьте. Никто ведь заранее не знал, что вылезет после релиза, а если бы пытались угадать, то вероятнее всего не угадали бы.

В этом и есть проектирование — выяснить, какие у вас цели, абы сделать, или глянуть чуть дальше, те самые среднесрочные-долгосрочные цели.

P>>Я вам уже привел пример Хорошее проектирование это не только здесь и сейчас, за что вы топите, но прежде всего и адеватный горизонт планирования.

G>Практика показывает что занимаясь проектированием "только здесь и сейчас" почти всегда получается компактный код, который легко поддерживать.

Вам что бы обратную совместимость заложить в какое апи уже надо отойти от здесь и сейчас, а рассмотреть а что же вообще может или не может появиться.
Или вы предлагаете сначала сломать, а потом, если у когото утекут миллионы, завести тикет и начать фиксить?
Re[19]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 02.01.26 01:22
Оценка:
Здравствуйте, Sharov, Вы писали:

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


G>>Что там является "моделью предметной области", в чем её ценность, и как она влияет на остальные части кода?

S>Ну как минимум https://github.com/gandjustas/habr-post-stock-api/blob/main/Model.cs
То есть "модель предметной области" это типизированное описание схемы БД, так?
Апологеты DDD как раз с этим спорят.




S>>>А какую проблему решает хороший код, если он даже не пытается моделировать предметную область, т.е. не оперирует необходимыми абстракциями?

G>>1) Уменьшает дублирование кода
G>>2) Уменьшает количество связей и сайд-эффектов
G>>3) Уменьшает цепочку вызовов и количество промежуточных слоев между вызовов и действием
G>>4) Увеличивает быстродействие
G>>5) Уменьшает неявную передачу данных и изменение стояния
G>>Это все вещи связанные, но в некоторых местах могут противоречить друг другу, поэтому хороший код это баланс.

S>Ну т.е. код ради кода, понятно. Ну вот есть хороший код, который плохо решает поставленную задачу, поскольку автор толком не разобрался в предметной области. Ну и какой прок от этой программы кроме эстетики кода?

А кто сказал что отсутствие "объектов доменной модели" автоматически приводит к плохому решению задачи?
И кто сказал что наличие "объектов доменной модели" автоматически приводит к хорошему решению задачи?


S>Ну и самый главный вопрос, а как всему вышеперечисленному мешает оперирование объектами доменной модели?

Никак не мешает и никак не помогает. Хотя зависит от того, что входит в понятие "оперирование объектами доменной модели", так как это может давать ограничения
Например код вида
ctx.Stock.Where(s => s.Wharehouse == id).ExecuteUpdate(x => x.SetProperty(s => s.Quantity, s => s.Quantity - s.Reserved).x.SetProperty(s => s.Reserved, 0))

Является "оперированием объектами доменной модели"?

S>>>По-моему, даже на не ООП языках типа С люди стараются оперировать абстракциями в коде.

G>>Вы как-то слишком широко применяете слово "абстракция". Когда вы создаете класс с набором свойств это не абстракция. Реализация интерфейса это тоже не абстракция. Абстракция это то, что использует такие классы или интерфейсы. А писать такой код нет необходимости. Большинство полезных абстракций уже есть в библиотеках, зачастую стандартных.

S>Делаю какой-нибудь реалистичны автотренажер или игру для машин, есть в стандартной библиотеке класс автомобиль, мотор и т.п.?

Мы тут вроде как корпоративные приложения рассматриваем, которые оперируют данными в бд в многпользовательском режиме.
Думаю если бы мы рассматривали однопользовательскую 3д игру (видимо под ней понимается автотренажер), то там были бы объекты движка, которые представляют из себя "объекты на сцене", с "геомертрией", "текстурами" итд
Нужно ли из них делать классы вроде "автомобиль", "мотор" — я не уверен.

G>>>>Могу показать примеры хорошего структурированного кода, где нет ничего, что можно было было назвать "моделью предметной области". Опять-таки можно сказать что это простые примеры, но я не видел сложных примеров с ДДД, где везде хороший структурированный код.

S>>>Давайте, а то мне кажется мы говорим о разном, подразумевая "модель предметной области".
G>>Начнем с простого, позже смогу вырезать кусок из реального проекта.
G>>Недавно делал пример для статьи на Хабре https://github.com/gandjustas/habr-post-stock-api, АПИшка для резервации заказов, работает с базой, содержит очень важную для бизнеса логику. Это как маленький кусок большого приложения

S>Ну мы ведем речь про явно более крупные приложения, а не про crud на 3 операции.

Вспоминаем закон Галла

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

Вот простая система есть, мы начнем дополнять функциями, а модель БД — сущностями\таблицами
Если функции пухнут — делаем Extract Method.
Если несколько методов имеют один и тот же набор параметров, то делаем класс с этими параметрами в конструкторе и переносим вызовы внутрь него.

Сколько нам нужно функций, чтобы DDD с его паттернами стало давать какой-то профит?


G>>Там даже есть абстракция — очередь запросов (она не шибко полезная в целом)

S>Зачем, лукавое это?
Да, в посте написано, что так делать не надо в подавляющем большинстве случаев.

S>А что стандартная библиотека, кстати, не помогла?

Помогла
Отредактировано 02.01.2026 1:38 gandjustas . Предыдущая версия .
Re[20]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 03.01.26 15:57
Оценка:
Здравствуйте, gandjustas, Вы писали:


G>>>Что там является "моделью предметной области", в чем её ценность, и как она влияет на остальные части кода?

S>>Ну как минимум https://github.com/gandjustas/habr-post-stock-api/blob/main/Model.cs
G>То есть "модель предметной области" это типизированное описание схемы БД, так?
G>Апологеты DDD как раз с этим спорят.

1)Сразу оговорюсь, я не апологет DDD. Я ни одно книжки по DDD не прочитал, и много знаю по касательной.
Я просто не считаю правильным отмахивать от DDD, как о бесполезной штуке. Оно большое, и люди частями или
целиком его вполне успешно применяют.
2)

То есть "модель предметной области" это типизированное описание схемы БД,

Что в этом плохого и кто с этим спорит? В DDD есть паттерн Repository, как раз и отвечает за сохранение главных
доменных сущностей, наверное и таблицы соотв. должны были быть.

S>>Ну т.е. код ради кода, понятно. Ну вот есть хороший код, который плохо решает поставленную задачу, поскольку автор толком не разобрался в предметной области. Ну и какой прок от этой программы кроме эстетики кода?

G>А кто сказал что отсутствие "объектов доменной модели" автоматически приводит к плохому решению задачи?

Никто не сказал, просто это, кхм, странно. Задача софта эмулировать соотв. процессы. Как можно эмулировать что-то без
соотв. сущностей?

G>И кто сказал что наличие "объектов доменной модели" автоматически приводит к хорошему решению задачи?


Никто не сказал. Но вот вопрос -- что лучше, плохо написанная программа, которая прилично решает соотв. проблему предметной
области, или хорошо написанная программа, которая плохо решает заявленную проблему? Вы лично за какую бы программу заплатили бы
деньги?

Я вообще не вижу противоречия между хорошим кодом и объектами доменной модели. Это прям какая-то странная дихотомия.

S>>Ну и самый главный вопрос, а как всему вышеперечисленному мешает оперирование объектами доменной модели?

G>Никак не мешает и никак не помогает. Хотя зависит от того, что входит в понятие "оперирование объектами доменной модели", так как это может давать ограничения
G>Например код вида
G>
G>ctx.Stock.Where(s => s.Wharehouse == id).ExecuteUpdate(x => x.SetProperty(s => s.Quantity, s => s.Quantity - s.Reserved).x.SetProperty(s => s.Reserved, 0))
G>

G>Является "оперированием объектами доменной модели"?

Скорее оперирование представлением в бд.

S>>>>По-моему, даже на не ООП языках типа С люди стараются оперировать абстракциями в коде.

G>>>Вы как-то слишком широко применяете слово "абстракция". Когда вы создаете класс с набором свойств это не абстракция. Реализация интерфейса это тоже не абстракция. Абстракция это то, что использует такие классы или интерфейсы. А писать такой код нет необходимости. Большинство полезных абстракций уже есть в библиотеках, зачастую стандартных.

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

S>>Делаю какой-нибудь реалистичны автотренажер или игру для машин, есть в стандартной библиотеке класс автомобиль, мотор и т.п.?

G>Мы тут вроде как корпоративные приложения рассматриваем, которые оперируют данными в бд в многпользовательском режиме.

Какая разница, софт есть софт.

G>Думаю если бы мы рассматривали однопользовательскую 3д игру (видимо под ней понимается автотренажер), то там были бы объекты движка, которые представляют из себя "объекты на сцене", с "геомертрией", "текстурами" итд

G>Нужно ли из них делать классы вроде "автомобиль", "мотор" — я не уверен.

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


S>>Ну мы ведем речь про явно более крупные приложения, а не про crud на 3 операции.

G>Вспоминаем закон Галла
G>

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

G>Вот простая система есть, мы начнем дополнять функциями, а модель БД — сущностями\таблицами
G>Если функции пухнут — делаем Extract Method.
G>Если несколько методов имеют один и тот же набор параметров, то делаем класс с этими параметрами в конструкторе и переносим вызовы внутрь него.

Вот цитата Б. Мейера отсюда -- https://bertrandmeyer.com/2012/11/27/why-so-many-features/

It is easy to complain about software bloat, and examples of needlessly complex system abound. But your bloat may be my lifeline, and what I dismiss as superfluous may for you be essential. To paraphrase a comment by Ichbiah, the designer of Ada, small systems solve small problems. Outside of academic prototypes it is inevitable that a successful software system will grow in complexity if it is to address the variety of users’ needs and circumstances. What matters is not size but consistency: maintaining a well-defined architecture that can sustain that growth without imperiling the system’s fundamental solidity and elegance.


Апологет DDD какай-то такой целью и задавались. На сколько вышло -- Народ использует, конференции ежегодные проводят, значит
кому-то заходит.

G>Сколько нам нужно функций, чтобы DDD с его паттернами стало давать какой-то профит?


Какой-то дурацкий вопрос, если честно. Типа сколько нужно людей, чтобы лампочку вкрутить. Вы какую-то цифру ждете?
Она, скорее всего, у каждого будет своя.

S>>А что стандартная библиотека, кстати, не помогла?

G>Помогла

Само собой, но ее одной не достаточно.
Кодом людям нужно помогать!
Re[22]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 07.01.26 15:27
Оценка:
Здравствуйте, gandjustas, Вы писали:


G>Я не утрирую, с 2002 по 2017 год было всего два визионера про DDD, и одна достойная книга про DDD, не на Java, и Фаулер, который активно это все пиарил в своем блоге.


А сколько визионеров надо, что технология взлетела? У ООП много было визионеров, тоже 2-3 человека.
По DDD уже много лет конференции проводят -- https://www.youtube.com/@ddd_eu

G>Поэтому я, возможно, чуть лучше разбираюсь в DDD. Кстати Фаулера я прочитал в 2008, а Эванса в 2009, и еще тогда многие подходы мне показались сомнительными.


Я же не спорю с этим.

S>>Я просто не считаю правильным отмахивать от DDD, как о бесполезной штуке. Оно большое, и люди частями или целиком его вполне успешно применяют.

G>А чем измеряется успех? В том что программа работает? В том что заказчик платит денег? Может это успех вопреки? Может без DDD денег было бы больше, а программа правильнее?

Ну какая-то статистика и выборка же есть, этим не одна компания занимается. Метрики такие, например, что сложный софт развивается.
Т.е. заказчик деньги платит не зря.

G>Без сравнения в равных условиях мы не узнаем.


Ну такой себе странный аргумент. Лишних денег ни у кого нету. Разве что у крупняка типа ibm, которые могут себе позволить несколько назависимых отделов
для решения одной проблемы.


S>>Что в этом плохого и кто с этим спорит? В DDD есть паттерн Repository, как раз и отвечает за сохранение главных

S>>доменных сущностей, наверное и таблицы соотв. должны были быть.
G>Ты не на тот вопрос отвечаешь. Вопрос такой: является ли набор классов без логики, с которыми работает ORM, "моделью предметной области" в понимании ДДД (по книгам)? Я могу однозначно сказать что нет.

Без логики не является, и? ORM это не тот уровень, на котором стоит обсуждать DDD. Он там спрятан за паnтерном Repository.

G>>>А кто сказал что отсутствие "объектов доменной модели" автоматически приводит к плохому решению задачи?

S>>Никто не сказал, просто это, кхм, странно. Задача софта эмулировать соотв. процессы. Как можно эмулировать что-то без соотв. сущностей?
G>Еще раз. DDD как набор паттернов, говорит нам:
G>- Domain Model это набор классов с данными поведением, которые соответствуют существительным в едином языке, выработанным между бизнесом и командой разработки
G>- Вся бизнес-логика (Core Domain) должна быть описана как взаимодействие этих объектов

Там вроде, все строится вокруг взаимодействия AggregateRoot'ов, которые несколько больше чем просто "набор классов с данными поведением".

G>Я сейчас не буду говорить о том, насколько корректно так проектировать программы, но без этого DDD не будет считаться DDD.


Я пока понять не могу, что в этом плохого?

G>>>И кто сказал что наличие "объектов доменной модели" автоматически приводит к хорошему решению задачи?


S>>Никто не сказал. Но вот вопрос -- что лучше, плохо написанная программа, которая прилично решает соотв. проблему предметной

S>>области, или хорошо написанная программа, которая плохо решает заявленную проблему? Вы лично за какую бы программу заплатили бы
S>>деньги?
G>Я не очень понимаю критериев оценки "хорошо или плохо". Программа может проблему решать или не решать. Мне как пользователю совершенно без разницы есть там "модель предметной области" или нет. Если две программы одинаково решают мою (не какой-то абстрактной предметной области) проблему, то выберу ту, которая дешевле по совокупной стоимости владения.

Это уход от ответа на конкретный вопрос. Речь не про одинаково. Программа написана хорошо, но не покрывает большую часть use-case'ов или
делает это криво. У другой все наоборот. Какой программист больше заработает денег?

S>>Я вообще не вижу противоречия между хорошим кодом и объектами доменной модели. Это прям какая-то странная дихотомия.

G>Я тоже не вижу. Качество программы и наличие в ней domain model — вещи ортогональные, то есть независимые друг от друга.

Ну т.е. можно использовать excel в качестве бд, написан хорошо, данные хранить может. Или все же возьмем что-то другое для
данной задачи?


G>>>Является "оперированием объектами доменной модели"?

S>>Скорее оперирование представлением в бд.
G>То есть не соответствует DDD никак, да еще и ужасную вещь делает с точки зрения Clean Architecture — прибивает бизнес-логику к инфраструктуре.
G>Причем этот код решает задачу "сделать отгрузку товаров со склада X", которую крайне сложно описать в DDD, особенно чтобы была изоляция. Внезапно еще и "отгрузка" никак не фигурирует в моделях БД.

Этот код может и ракету в космос запустить, дальше что?


S>>Какая разница, софт есть софт.

G>У Эрика Липперта — он написал гораздо больше и полезнее, чем Фаулер, Эванс и Вернон вместе взятые и вообще крутой программист и инженер — есть потрясающая серия статей Wizards and Warriors, которую я даже перевел на хабре
G>В пятой части он сформулировал тезис:
G>

G>Программа должна поддерживать согласованное состояние перед лицом попыток пользователя (клиента) изменить это состояние

G>Когда у нас программа работает на компьютере пользователя, в одном процессе (адресном пространстве) и её состояние существует столько, сколько существует процесс, то требования будут одни. Если состояние программы хранится во внешнем хранилище, к которому надо обращаться по ненадежной сети, причем обращаться могут несколько пользователей из разных экземпляров программы, то требования получатся совершенно другие. И подходы к проектированию и реализации программы будут разные.

Инвариант класса называется, которое Б. Мейер лет 40 назад ввел в обиход. При чем здесь бд или сеть?


S>>Вот цитата Б. Мейера отсюда -- https://bertrandmeyer.com/2012/11/27/why-so-many-features/

S>>

S>>It is easy to complain about software bloat, and examples of needlessly complex system abound. But your bloat may be my lifeline, and what I dismiss as superfluous may for you be essential. To paraphrase a comment by Ichbiah, the designer of Ada, small systems solve small problems. Outside of academic prototypes it is inevitable that a successful software system will grow in complexity if it is to address the variety of users’ needs and circumstances. What matters is not size but consistency: maintaining a well-defined architecture that can sustain that growth without imperiling the system’s fundamental solidity and elegance.

S>>Апологет DDD какай-то такой целью и задавались. На сколько вышло --
G>Очень сложно проверить насколько им удалось придумать архитектуру, которая сохраняет целостность и элегантность длительное время.

S>>Народ использует, конференции ежегодные проводят, значит кому-то заходит.

G>Это вообще не показатель. Я пережил столько хайпов в ИТ уже, и после каждого еще долго оставались толпы фанатов "кому заходит".
G>Тем более есть проблема: кроме Clean Architecture и DDD в медийном поле вообще не существует других подходов. У альтернативы ДДД даже названия собственного нет, она состоит из применения принципов YAGNI, KISS, DRY, top-down подхода к проектированию и разработке, частично SOLID.
G>Многое кстати было описано в книге Pragmatic Programmer Ханта и Томаса (2000 год), то есть за пар лет до фаулера-эванса и там нет такой категоричной упоротости на ООП. Несмотря на то, что части сведений в книге устарели я, с вашего позволения, буду называть подход — Прагматичным Программированием или Прагматичным Проектированием, сокрушённо ПП



G>>>Сколько нам нужно функций, чтобы DDD с его паттернами стало давать какой-то профит?

S>>Какой-то дурацкий вопрос, если честно. Типа сколько нужно людей, чтобы лампочку вкрутить. Вы какую-то цифру ждете?
S>>Она, скорее всего, у каждого будет своя.
G>Любую теорию, например теорию о полезности DDD, можно считать научной если существует хотя бы один эксперимент, который может теорию опровергнуть, даже если он еще не проведен. Это называется критерий фальсифицируемости поппера.
G>А если такого эксперимента не существует, то это уже не теория, а вера.

Я не понимаю о чем идет речь и к чему эти странные вопросы и ответы с отсылками на Поппера. Возьмите какой-нибудь проект по DDD
и подсчитай в нем ф-ии.

Если так подходить, то сколько надо строк кода, чтобы ООП давал выхлоп? Может < писать на Си или ФЯ? Но почему-то для простейших задачи
на сотни строк кода все равно используют ООП. Странно, правда?

G>Я посмотрел историю избранных другими моих сообщений. Я холиварю против DDD с 2009 года (видимо сразу после того как книгу прочитал), с тех пор НИ ОДНОГО ПРИМЕРА, демонстрирующего превосходства DDD над ПП в рамках этого форума. Я даже для прикола брал ndddsample и переписывал на код без DDD — получалось компактнее при том же функционале. Жалко код уже утерян.


Ну нету здесь таких, ищите на хабре, например или на SO.
Кодом людям нужно помогать!
Re[24]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 09.01.26 00:27
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>А сколько визионеров надо, что технология взлетела? У ООП много было визионеров, тоже 2-3 человека.

G>Считаем:
G>1) Создатели языка Simula, где впервые появилось слово class — Оле-Йохан Даль и Кристен Нюгор, оба профессора
G>2) Алан Кей, который придумал сам термин ООП и язык Smalltalk, который под воздействием Simula получил понятия "класс" и "объект"
G>3) Бьёрн Страуструп, который идею классов и объектов натянул на С++, дав начало большей части современных ОО-яызыков
G>Каждый из них в отдельности имеет больше достижений, написал больше статей и больше создал кода, чем все авторы по DDDвместе взятые.


Все это так, но речь не об этом. Все это ученые и компиляторо писатели. А Эрик Эванс вроде разрабатывал бизнес приложения,
и вроде (но не точно) работал в ibm. Мой вопрос был про кол-во людей, что много людей для того, чтобы технология взлетела
и не требуется. Сравнивать их не имеет смысл. У DDD роль гораздо меньше.

S>>По DDD уже много лет конференции проводят -- https://www.youtube.com/@ddd_eu

G>Это вообще не показатель. Люди астрологией и гомеопатией занимаются, гораздо больше лет конференции проводят. Программисты тоже подвержены влиянию всяких лженаук.

Ну не скажите, там иногда читают очень достойные доклады. Вот например:
https://www.youtube.com/watch?v=KTy4rqgPOjg

S>>Ну какая-то статистика и выборка же есть, этим не одна компания занимается. Метрики такие, например, что сложный софт развивается.

S>>Т.е. заказчик деньги платит не зря.
G>Повторить аргумент про лженауки?

В чем проблема найти компании и продукты у которых работает DDD? Спросите нейронку какую-нибудь. Наверняка что-то есть из докладов
по ссылке выше.

S>>Ну такой себе странный аргумент. Лишних денег ни у кого нету. Разве что у крупняка типа ibm, которые могут себе позволить несколько назависимых отделов

S>>для решения одной проблемы.
G>То есть просто вера, что DDD помогает? Верить не мешает. Но для участия в научном споре одной веры недостаточно.

А в ООП тоже верят? Ведь есть проекты для которых он избыточен, но все равно будет написано с 95% на каком-нибудь ООП языке.


S>>Без логики не является, и? ORM это не тот уровень, на котором стоит обсуждать DDD.

G>Почему? Меня интересует только подход к проектированию и написанию кода. Если DDD не про это, то я не понимаю о чем говорить.

Он не про ORM и таблицы в бд.

S>>Он там спрятан за паnтерном Repository.

G>И какой интерфейс выставляет этот Repository?

Можно нагуглить.

G>>>- Вся бизнес-логика (Core Domain) должна быть описана как взаимодействие этих объектов

S>>Там вроде, все строится вокруг взаимодействия AggregateRoot'ов, которые несколько больше чем просто "набор классов с данными поведением".
G>Если для реализации поведения вам нужны Order, Line и Product, то они попадут в один агрегат.

Вероятно и у приложения будет один Bounded Context и один микросервис. Что не так?

S>>Я пока понять не могу, что в этом плохого?

G>Если программа НЕ будет соответствовать паттернам DDD она будет лучше, чем если будет им соответствовать.

Зависит от сложности. Ну найдите людей у которых все по DDD и поговорите с ними. Писать калькулятор по DDD странно, но какой-нибудь
банковский софт, где требования регулярно меняются вполне может быть ок. Как обычно -- it depends.

S>>Какой программист больше заработает денег?

G>Зависит от разницы в цене и насколько пользователь готов пожертвовать решением за эту разницу

Едва ли будет ценовая разница, край несколько 10$. Можно считать, что цена одинакова.


S>>Инвариант класса называется, которое Б. Мейер лет 40 назад ввел в обиход. При чем здесь бд или сеть?

G>Инвариантность класса не помогает обеспечить целостность состояния во внешнем хранилище.

Если сохранять класс, когда у него все ок с инвариантами, то почему нет? Для пользователя класса у него всегда должны
быть инварианты, пользователь затем может этот класс сохранить.

S>>Я не понимаю о чем идет речь и к чему эти странные вопросы и ответы с отсылками на Поппера. Возьмите какой-нибудь проект по DDD и подсчитай в нем ф-ии.

G>И как это поможет доказать что DDD имеет какие-то преимущества?

А как это может доказать обратное? Зачем вообще что-либо подсчитывать?

S>>Если так подходить, то сколько надо строк кода, чтобы ООП давал выхлоп?


G>вот минимальный пример:

G>
G>abstract class CollectionBase<T>
G>{
G>    public int Count { get; private set; }

G>    protected virtual void AddCore(T item)
G>    public void Add(T item) 
G>    {
G>         AddCore(item);
G>         Count+=1;
G>    }

G>    protected virtual T GetCore(int index);
G>    public T Get(int index)
G>    {
G>       ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, Count);
G>       ArgumentOutOfRangeException.ThrowIfNegative(index);
G>       return GetCore(index);  
G>    }
G>}
G>

G>Тут и наследование, и инкапсуляция, и полиморфизм, и OCP, и LSP.
G>Попытка получить от кода те же свойства без наследования, инкапсуляции и полиморфизма ни к чему хорошему не приведут.

А как люди с коллекциями на Си работали и работают?


S>>Может < писать на Си или ФЯ? Но почему-то для простейших задачи на сотни строк кода все равно используют ООП. Странно, правда?

G>Мне кажется что осмысленно говорить, что кто-то использует ООП, только когда есть наследование, инкапсуляция и полиморфизм.
G>Я видел много кода на C#, который с точностью до синтаксиса и названия библиотек\неймспейсово\классов\методов можно переписать на Rust. Использует ли такой код на C# ООП? Я считаю что нет.

Тем не менее пишут же зачем-то на C#.
Кодом людям нужно помогать!
Re[26]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 13.01.26 23:28
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Все это так, но речь не об этом. Все это ученые и компиляторо писатели. А Эрик Эванс вроде разрабатывал бизнес приложения, и вроде (но не точно) работал в ibm.

G>Честно говоря я вообще не знаю чем ванс занимался до написания книги и есть и значимые проекты в его истории. После он начал заниматься консалтингом.

Я тоже не знаю. Но он как и Фаулер или дядя Боб -- что-то поделали в самом начале, потом решили лопаты продавать книги писать.

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

G>Вроде ты сам пытался сравнить DDD и ООП.

Неправда. Я сравнивал кол-во апологетов ООП и ДДД. Намек был на то, что и там и там их было немного. Более того, сравнивать их лично не имеет
никакого смысла -- одни делали новую технологию, другие -- методологию.

S>>Ну не скажите, там иногда читают очень достойные доклады. Вот например:

S>>https://www.youtube.com/watch?v=KTy4rqgPOjg
G>Не понял что в этом докладе интересного. Целый час только ради одного слайда с одной мыслью
G>

G>Pain = Strength * Volatility * Distance.
G>Reduce one of them to 0 to minimize the pain of necessary coupling.


Мне понравился, добавил в избранное на пересмотреть. Там много вещей проговаривает помимо этой формулы.


S>>В чем проблема найти компании и продукты у которых работает DDD? Спросите нейронку какую-нибудь. Наверняка что-то есть из докладов по ссылке выше.

G>Еще раз повторить аргумент про лженауки? У кого-то и астрология "работает".
G>Единственный способ доказать что что-то работает — провести эксперимент. Для ДДД это простой эксперимент — берем любой код с DDD, делаем эквивалентный без DDD и сравниваем объективные показатели — объем кода, количество связей между классами итд.
G>Важно взять именно работающий код, решающий задачу от начала до конца.

Мне это не интересно. Вам интересно, вы и делайте. Я хочу донести мысль, что огульно выкидывать ДДД не стоит -- для кого-то на каких-то проектов
он работает. Я работал в компании, которая распиливала монолит на микросервисы по ДДД. Использовали стратегические паттерны. Оправдано или нет -- не знаю, но вроде как-то работало. Опять же ДДД был не в полный рост, а что-то заимствовалось.


S>>А в ООП тоже верят? Ведь есть проекты для которых он избыточен, но все равно будет написано с 95% на каком-нибудь ООП языке.

G>Некоторые не верят, но что это меняет? Современные языки используют ОО-парадигму и часто базовые библиотеки реализованы как библиотеки классов. То есть ты любом случае будешь использовать ООП, даже если сам не придерживаешься ОО-парадигмы.

Некоторые не верят в ДДД, но что это меняет.

S>>Он не про ORM и таблицы в бд.

G>А про что?

101 раз говорю, что там все эти детали скрыты за паттерном Репозиторий. ДДД, кажется, не об этом.

G>Меня интересует подход к проектированию от начала до конца, а не просто в какой-то части, делая вид что других не существует.


Это подход к проектировании на основе проблем бизнеса, а не про орм или таблицы.

S>>Вероятно и у приложения будет один Bounded Context и один микросервис. Что не так?

G>Если order, line и product в одном агрегате, где root это order, то как получить список "лидеры продаж" с топ 30 товаров за месяц.

Какой-то метод добавить в репозиторий, наверное.

S>>Зависит от сложности. Ну найдите людей у которых все по DDD и поговорите с ними. Писать калькулятор по DDD странно, но какой-нибудь банковский софт, где требования регулярно меняются вполне может быть ок. Как обычно -- it depends.

G>См выше про эксперимент. Мнение интересует в последнюю очередь.

Сдается мне, на ООП языках вы стали писать без всяких экспериментов. На основе чьего-то мнения, скорее всего. И, наверное, до сих пор
полет нормальный.

S>>Если сохранять класс, когда у него все ок с инвариантами, то почему нет?

G>Потому что в рамках одного класса нельзя сделать контроль остатков.

Почему?

S>>Для пользователя класса у него всегда должны быть инварианты, пользователь затем может этот класс сохранить.

G>Как описать инвариант: остаток товаров на складе должен быть не меньше суммы зарезервированных?

Вычитать соотв. поля из бд, взяв соотв. лок предварительно, посчитать и в зависимости от, продолжить работу.

S>>А как это может доказать обратное? Зачем вообще что-либо подсчитывать?

G>Затем что нужны объективные измеримые показатели преимуществ того или иного подхода: объем, цикломатическая сложность, вложенность вызовов. Иначе это вера, а не инженерный подход.

См. выше про ООП -- что такое проделывали?

Еще раз -- я не агитирую за ДДД, я против огульного откидывания подходов, мол "не нравится", "не встречал" и т.п. Это субъективщина.
Наверняка можно найти человека с обратным опытом.
Кодом людям нужно помогать!
Re[28]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 14.01.26 23:07
Оценка:
Здравствуйте, gandjustas, Вы писали:


S>>Я тоже не знаю. Но он как и Фаулер или дядя Боб -- что-то поделали в самом начале, потом решили лопаты продавать книги писать.

G>Товарищ Мартин свой опыт описывает во множестве книг, например он участвовал в разработке Rational Rose в IBM, где видимо и упорролся в "компонентность", что легло в основу его книги clean architecture. Фаулер не был выдающимся инженером, но он был "computer scientist" — изучал существующие методики, и придумывал новые, о чем очень много писал статей в доинтернетную эпоху. Он стоял у истоков Agile вместе с Беком и фактически ввел в обиход термин "рефакторинг".

Чем DDD хуже истоков agile и термина рефакторинг?

G>А что касается Эванса — я вообще не нашел историю чем он занимался до книги и каких-то достижений после публикации тоже нет. Других книг он не выпускал.

G>Мне кажется что товарищ эванс вообще является подставным лицом, и DDD придумал Фаулер, но по причине неполного содержания книги, несвойственного Фаулеру, выпустил не под своим именем, а нашел соавтора.

Мне не кажется, что Эванс чем-то хуже Фаулера. Оба губошлепы.

S>>Мне это не интересно. Вам интересно, вы и делайте.

S>>Я хочу донести мысль, что огульно выкидывать ДДД не стоит -- для кого-то на каких-то проектов он работает.
G>Это опять слепая вера. Если хотите сказать что DDD работает лучше чем нажимать рандомные кнопки на клавиатуре, то конечно работает. Как и любая методика проектирования и любые паттерны. Если мы говорим о применении конкретных паттернов, то появляются вопросы эффективности, но которые уже 20 лет нет ответа.


S>>Я работал в компании, которая распиливала монолит на микросервисы по ДДД. Использовали стратегические паттерны.

G>Какие паттерны?

https://habr.com/ru/articles/787460/

S>>101 раз говорю, что там все эти детали скрыты за паттерном Репозиторий. ДДД, кажется, не об этом.

G>А о чем тогда? Ну это смешно: как только в обсуждении DDD доходит до деталей, то "DDD не об этом". Что DDD в любой программе касается 10% не самого важного кода. Поэтому чтобы такие спекуляции исключить я и предлагаю взять пример, который от начала до конца работает.

Ну поищите пример программы в гугле, в чем проблема?

S>>Это подход к проектировании на основе проблем бизнеса, а не про орм или таблицы.

G>В результате ведь получается код, который рабоает с таблицами в БД и, вероятнее всего, с помощью ORM. Или нет?

Какие-то технологии будет использоваться, но при чем здесь DDD? DDD это методология, а не технология.

S>>Какой-то метод добавить в репозиторий, наверное.

G>Это тот самый репозитрий, который скрывает детали? То есть важнейшее требования — это "детали", которые надо "скрывать"?

Детали реализации -- да, скрывает. Добавьте соотв. метод в соотв. интерфейс и всех делов.

G>И кто вызывать будет этот репозиторий?


Тот, кому нужен соотв. функционал.

S>>Сдается мне, на ООП языках вы стали писать без всяких экспериментов. На основе чьего-то мнения, скорее всего. И, наверное, до сих пор полет нормальный.

G>Я писать на ОО языках начал потому что выбора не было. Сейчас сложно найти мейнстримный язык без ООП, а когда я начинал таких вообще не было.

Помилуйте, были Си (процедурный язык), Lisp\Ocaml (фп языки), prolog (лп). Языков тьма. Тот же Erlang был. Но вот почему-то был выбран один
из ООП языков. Почему?

S>>Почему?

G>По факту. Работа с объектами в памяти не обеспечивает изоляцию транзакций, когда есть более одного экземпляра процесса.

Проверка инварианта делегируются бд, а класс получает результат этой проверки. В бд можно делать еще lock, если что.

S>>Вычитать соотв. поля из бд, взяв соотв. лок предварительно, посчитать и в зависимости от, продолжить работу.

G>Два пользователя параллельно пытаются зарезервировать товар.
G>Один процесс считает данные из базы и считает предварительно. У него ок.
G>Второй процесс (на другом сервере) параллельно также считывает данные из базы и у него тоже ок.
G>Оба процесса создают резрвы товаров и сумма резервов получается больше остатка.

Ну так переделайте на read-write, а не просто read. И используйте соотв. уровень изоляции, например read commited.

S>>См. выше про ООП -- что такое проделывали?

G>Конечно, я даже пример минимальный скидывал, который иллюстрирует преимущества. Любые подходы без ООП увеличивают объемы дублирующегося кода кода, при той же функцинальности.

Не серьезно -- вы приложили опереточный пример, а в случае DDD речь может идти о 10 или 100 тыс. строк кода минимум.
Не одно и то же. Одно дело сравнить алгоритм сортировки на Си vs С#, другое дело какое-нибудь годами разрабатываемое десятками людей ПО.


G>Так давайте найдем, пусть пример покажет. Мы же не только что прочитали про DDD, напомню что я уже 16ый год участвую в эти дискуссиях и пока НИ РАЗУ не увидел примера приложения, сделанного 100% по DDD, чтобы оно не содержало дублирования, множества лишних связей, проблем быстродействия и ошибок несогласованности данных.


Попросите у чатбота какого-нибудь пример приложения, написанного по DDD.
Кодом людям нужно помогать!
Re[28]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 15.01.26 12:25
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Еще раз -- я не агитирую за ДДД, я против огульного откидывания подходов, мол "не нравится", "не встречал" и т.п. Это субъективщина.

S>>Наверняка можно найти человека с обратным опытом.
G>Так давайте найдем, пусть пример покажет. Мы же не только что прочитали про DDD, напомню что я уже 16ый год участвую в эти дискуссиях и пока НИ РАЗУ не увидел примера приложения, сделанного 100% по DDD, чтобы оно не содержало дублирования, множества лишних связей, проблем быстродействия и ошибок несогласованности данных.

Вот видео про то, как использовали DDD в Яндекс 360
https://www.youtube.com/watch?v=N-ro_8te98A

В комментариях нашел ссылку на тг канал по DDD
https://t.me/iDDDqd
Вот тут можно, наверное, с людьми про их проекты поговорить и похоливарить.
Кодом людям нужно помогать!
Re[29]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.01.26 12:36
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Чем DDD хуже истоков agile и термина рефакторинг?

Тем что рефакторинг и agile имеет доказанную пользу, а DDD — нет.

S>Мне не кажется, что Эванс чем-то хуже Фаулера. Оба губошлепы.

Эванс вообще ноунейм, у Фаулера есть полезные вещи.

S>>>Мне это не интересно. Вам интересно, вы и делайте.

S>>>Я хочу донести мысль, что огульно выкидывать ДДД не стоит -- для кого-то на каких-то проектов он работает.
G>>Это опять слепая вера. Если хотите сказать что DDD работает лучше чем нажимать рандомные кнопки на клавиатуре, то конечно работает. Как и любая методика проектирования и любые паттерны. Если мы говорим о применении конкретных паттернов, то появляются вопросы эффективности, но которые уже 20 лет нет ответа.


S>>>Я работал в компании, которая распиливала монолит на микросервисы по ДДД. Использовали стратегические паттерны.

G>>Какие паттерны?
S>https://habr.com/ru/articles/787460/
Это не про код, а про какую-то философию, тут вообще сложно что-либо оценивать. Меня именно код интересует.
Ну вот мы сделали два разных класса Employee. У меня сразу вопрос: это одна таблица в системе или нет? Если
Как быть если ЗА начинает зависеть от skills (они в разных моделях)?
И вообще calculateWageWithoutTax в employee выглядит крайне сомнительно, для расчета ЗП и налогов нужно такое количество данных подтянуть из всей системы, из-за которых сама система и делает, что прокинуть это все в один Employee выглядит неразумным.


S>>>101 раз говорю, что там все эти детали скрыты за паттерном Репозиторий. ДДД, кажется, не об этом.

G>>А о чем тогда? Ну это смешно: как только в обсуждении DDD доходит до деталей, то "DDD не об этом". Что DDD в любой программе касается 10% не самого важного кода. Поэтому чтобы такие спекуляции исключить я и предлагаю взять пример, который от начала до конца работает.
S>Ну поищите пример программы в гугле, в чем проблема?
Нет ни одного, который не вызывает вопросов целесообразности применения тех или иных паттернов.
Вот даже "стратегические паттерны" из статьи выше вопросы вызывают, это даже до кода не дошли.

S>>>Это подход к проектировании на основе проблем бизнеса, а не про орм или таблицы.

G>>В результате ведь получается код, который рабоает с таблицами в БД и, вероятнее всего, с помощью ORM. Или нет?
S>Какие-то технологии будет использоваться, но при чем здесь DDD? DDD это методология, а не технология.
DDD это набор паттернов, которые вроде как должны хорошо работать в каких-то сценарияхх, но на проверку они все плохо работают.
В любой книге про DDD 80% это паттерны и 20% это какие-то философские вещи.

S>>>Какой-то метод добавить в репозиторий, наверное.

G>>Это тот самый репозитрий, который скрывает детали? То есть важнейшее требования — это "детали", которые надо "скрывать"?
S>Детали реализации -- да, скрывает. Добавьте соотв. метод в соотв. интерфейс и всех делов.
Еще зар: проверка остатков это важнейшая часть бизнес-логики, ради которой система и создается. Это стало "деталями" которые надо скрывать.

G>>И кто вызывать будет этот репозиторий?

S>Тот, кому нужен соотв. функционал.
Функционал нужен пользователю. Пользователь нажимает кнопки, кнопки вызывают хэндлеры. Вызывать репозиторий из хэндлера? А где тогда DDD?


S>>>Сдается мне, на ООП языках вы стали писать без всяких экспериментов. На основе чьего-то мнения, скорее всего. И, наверное, до сих пор полет нормальный.

G>>Я писать на ОО языках начал потому что выбора не было. Сейчас сложно найти мейнстримный язык без ООП, а когда я начинал таких вообще не было.

S>Помилуйте, были Си (процедурный язык), Lisp\Ocaml (фп языки), prolog (лп). Языков тьма. Тот же Erlang был. Но вот почему-то был выбран один из ООП языков. Почему?

Потому что в середине двухтысячных были современные языки: C#, Java, Delphi (еще живой был, но только десктоп)), С++ (который был в глубочайшем кризисе)
Для веба был еще PHP, но он даже на фоне Delphi выглядел как наколеночная поделка.
Так как я знал делфи и хотел развиваться в сторону веба, то выбор был C# или Java — оба ОО-языки.

S>>>Почему?

G>>По факту. Работа с объектами в памяти не обеспечивает изоляцию транзакций, когда есть более одного экземпляра процесса.
S>Проверка инварианта делегируются бд, а класс получает результат этой проверки. В бд можно делать еще lock, если что.
Покажешь пример кода, как это сделать?

S>>>Вычитать соотв. поля из бд, взяв соотв. лок предварительно, посчитать и в зависимости от, продолжить работу.

G>>Два пользователя параллельно пытаются зарезервировать товар.
G>>Один процесс считает данные из базы и считает предварительно. У него ок.
G>>Второй процесс (на другом сервере) параллельно также считывает данные из базы и у него тоже ок.
G>>Оба процесса создают резрвы товаров и сумма резервов получается больше остатка.
S>Ну так переделайте на read-write, а не просто read. И используйте соотв. уровень изоляции, например read commited.
На read commited это и происходит.
Можно for update локи вешать в начале, если меняется та же запись, но на практике есть остаток на складе и список реезрвов, там уже serializable надо.
Но мы уже ушли от работы с объектами в памяти. Что собственно и демонстрирует что в таком режиме самые важные инварианты реализовать нельзя. Надо с базой работать.

S>>>См. выше про ООП -- что такое проделывали?

G>>Конечно, я даже пример минимальный скидывал, который иллюстрирует преимущества. Любые подходы без ООП увеличивают объемы дублирующегося кода кода, при той же функцинальности.

S>Не серьезно -- вы приложили опереточный пример, а в случае DDD речь может идти о 10 или 100 тыс. строк кода минимум.

Это опять вера, что на каком-то количестве строк DDD обязательно сработает. Но примеров нет.
Почему-то все работающие методики работают даже на очень малых примерах.

S>Не одно и то же. Одно дело сравнить алгоритм сортировки на Си vs С#, другое дело какое-нибудь годами разрабатываемое десятками людей ПО.

Любое ПО декомпозируется на отдельные компоненты, о чем говорят все методики и DDD в том числе. если в рамках одного простого компонента нет преимуществ, то почему кто-то думает, что на большом масштабе преимущества появятся?

G>>Так давайте найдем, пусть пример покажет. Мы же не только что прочитали про DDD, напомню что я уже 16ый год участвую в эти дискуссиях и пока НИ РАЗУ не увидел примера приложения, сделанного 100% по DDD, чтобы оно не содержало дублирования, множества лишних связей, проблем быстродействия и ошибок несогласованности данных.

S>Попросите у чатбота какого-нибудь пример приложения, написанного по DDD.
Я спрашивал, все примеры содержат очень сомнительные решения, которые без паттернов DDD были бы проще и надежнее.
Re[29]: Как внедряли DDD в Яндекс 360.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.01.26 20:24
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Вот видео про то, как использовали DDD в Яндекс 360

S>https://www.youtube.com/watch?v=N-ro_8te98A
Многовато болтологии. Про eventstorming я идею не выкупил, как оно соотносится со сложными моделями. например упомянутым ранее расчетом ЗП, отпускных, налогов и прочих выплат итд. По большому счету яндекс 360 это набор независимых сервисов, каждый из которых имеет простую относительно предметную область. Сложнее всего интеграции выглядят интеграции между сервисами, тут и правда может помочь eventstorming, но это не про запутанность, а не неочевидность "модели".

Много пиарят книжу Хононова, она и правда хороша, в одно месте описывает современные паттерны микросервисной архитектуры, но это уже позднее переосмысление

Про недостатки очень верно сказал.
1) DDD это сложно, а сложность должна окупатся хоть както, и вот из разговора я так и не понял за счет чего окупается, на чем в итоге экономят.
2) Имеет проблемы с быстродействием. Соответственно для нагруженной системы я бы не выбирал DDD, странно что в яндекс 360 используют такой подход. Может быть они его используют в ненагруженных частях?

S>В комментариях нашел ссылку на тг канал по DDD

S>https://t.me/iDDDqd
Всего 1000 участников...
В чатике только по дотнету 8,5к, по 1С десятки тысяч.

S>Вот тут можно, наверное, с людьми про их проекты поговорить и похоливарить.

Они там сами справляются, на любое негативное мнение по поводу ДДД говорят что автор не понимает бизнес.
Re[30]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 16.01.26 12:19
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Много пиарят книжу Хононова, она и правда хороша, в одно месте описывает современные паттерны микросервисной архитектуры, но это уже позднее переосмысление


G>Про недостатки очень верно сказал.

G>1) DDD это сложно, а сложность должна окупатся хоть както, и вот из разговора я так и не понял за счет чего окупается, на чем в итоге экономят.

Блин, ну он же говорит, что работал в мамбе где было 1млн loc на пхп. И там, например, анкета могла быть в 50 разных контекстах. И если бы
не ДДД, то по его мнению, было бы очень и очень плохо. Т.е. окупается поддерживаемостью.

G>2) Имеет проблемы с быстродействием. Соответственно для нагруженной системы я бы не выбирал DDD, странно что в яндекс 360 используют такой подход. Может быть они его используют в ненагруженных частях?


Не знаю. Но в целом может быть, т.к. абстракций там накручивают не мало.

S>>В комментариях нашел ссылку на тг канал по DDD

S>>https://t.me/iDDDqd
G>Всего 1000 участников...
G>В чатике только по дотнету 8,5к, по 1С десятки тысяч.

И? Вы еще с общим чатиком по программированию сравните. дотнет -- технология, ддд -- одна из возможных методологий для разработки ПО
на той же дотнет. Все, кмк, естественно.

S>>Вот тут можно, наверное, с людьми про их проекты поговорить и похоливарить.

G>Они там сами справляются, на любое негативное мнение по поводу ДДД говорят что автор не понимает бизнес.

Вы хотели с кем-то пообщаться за 16 лет, вот пожалуйста. Это в любом сообществе так. Идите в группу дотнет и начните рассказывать
про преимущества ручной сборки мусора.
Кодом людям нужно помогать!
Re[30]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 16.01.26 12:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Чем DDD хуже истоков agile и термина рефакторинг?

G>Тем что рефакторинг и agile имеет доказанную пользу, а DDD — нет.

Для разработчика из видео выше это будет не так -- у него ДДД имеет доказанную пользу. Короче, это субъективщина.


S>>>>Я работал в компании, которая распиливала монолит на микросервисы по ДДД. Использовали стратегические паттерны.

G>>>Какие паттерны?
S>>https://habr.com/ru/articles/787460/
G>Это не про код, а про какую-то философию, тут вообще сложно что-либо оценивать. Меня именно код интересует.
G>Ну вот мы сделали два разных класса Employee. У меня сразу вопрос: это одна таблица в системе или нет? Если

Это можно решить в самый последний момент, согласно ДДД. Это детали.

G>Как быть если ЗА начинает зависеть от skills (они в разных моделях)?

G>И вообще calculateWageWithoutTax в employee выглядит крайне сомнительно, для расчета ЗП и налогов нужно такое количество данных подтянуть из всей системы, из-за которых сама система и делает, что прокинуть это все в один Employee выглядит неразумным.

Значит нужен какой-то другой agg root.

G>DDD это набор паттернов, которые вроде как должны хорошо работать в каких-то сценарияхх, но на проверку они все плохо работают.

G>В любой книге про DDD 80% это паттерны и 20% это какие-то философские вещи.

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

G>Функционал нужен пользователю. Пользователь нажимает кнопки, кнопки вызывают хэндлеры. Вызывать репозиторий из хэндлера? А где тогда DDD?


Значит тут и репозиторий особо не нужен, обычный DAL.

S>>Помилуйте, были Си (процедурный язык), Lisp\Ocaml (фп языки), prolog (лп). Языков тьма. Тот же Erlang был. Но вот почему-то был выбран один из ООП языков. Почему?

G>Потому что в середине двухтысячных были современные языки: C#, Java, Delphi (еще живой был, но только десктоп)), С++ (который был в глубочайшем кризисе)
G>Для веба был еще PHP, но он даже на фоне Delphi выглядел как наколеночная поделка.
G>Так как я знал делфи и хотел развиваться в сторону веба, то выбор был C# или Java — оба ОО-языки.

Но опять же, никаких разумных сравнений произведено не было -- loc, сложность поддержки и т.п. Чисто умозрительные вывод. Вот для кого-то
и ДДД выглядит интересно.

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

G>Покажешь пример кода, как это сделать?

В транзакции что-то посчитать? Закиньте соотв. промт в чатбот.


S>>Ну так переделайте на read-write, а не просто read. И используйте соотв. уровень изоляции, например read commited.

G>На read commited это и происходит.
G>Можно for update локи вешать в начале, если меняется та же запись, но на практике есть остаток на складе и список реезрвов, там уже serializable надо.
G>Но мы уже ушли от работы с объектами в памяти. Что собственно и демонстрирует что в таком режиме самые важные инварианты реализовать нельзя. Надо с базой работать.

А бд не с объектами в памяти работает? Ну если у нас данные лежат в бд, то естественно что их надо забрать оттуда.


S>>Не серьезно -- вы приложили опереточный пример, а в случае DDD речь может идти о 10 или 100 тыс. строк кода минимум.

G>Это опять вера, что на каком-то количестве строк DDD обязательно сработает. Но примеров нет.
G>Почему-то все работающие методики работают даже на очень малых примерах.

Кто-то считает, что 1 млн лок на пхп без ДДД это уже вилка. Ну вот можно от этой цифры отталкиваться. Хотя сколько людей, столько мнений.

S>>Не одно и то же. Одно дело сравнить алгоритм сортировки на Си vs С#, другое дело какое-нибудь годами разрабатываемое десятками людей ПО.

G>Любое ПО декомпозируется на отдельные компоненты, о чем говорят все методики и DDD в том числе. если в рамках одного простого компонента нет преимуществ, то почему кто-то думает, что на большом масштабе преимущества появятся?

https://ru.wikipedia.org/wiki/%D0%AD%D0%BC%D0%B5%D1%80%D0%B4%D0%B6%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D1%81%D1%82%D1%8C


S>>Попросите у чатбота какого-нибудь пример приложения, написанного по DDD.

G>Я спрашивал, все примеры содержат очень сомнительные решения, которые без паттернов DDD были бы проще и надежнее.

Возможно. 101 раз повторю -- это вкусовщина. У разработчика из Я. по ссылке выше на этот счет может быть другое мнение. И это нормально.
Кодом людям нужно помогать!
Re[31]: Как внедряли DDD в Яндекс 360.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 16.01.26 22:04
Оценка:
Здравствуйте, Sharov, Вы писали:

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


G>>Много пиарят книжу Хононова, она и правда хороша, в одно месте описывает современные паттерны микросервисной архитектуры, но это уже позднее переосмысление


G>>Про недостатки очень верно сказал.

G>>1) DDD это сложно, а сложность должна окупатся хоть както, и вот из разговора я так и не понял за счет чего окупается, на чем в итоге экономят.

S>Блин, ну он же говорит, что работал в мамбе где было 1млн loc на пхп. И там, например, анкета могла быть в 50 разных контекстах. И если бы не ДДД, то по его мнению, было бы очень и очень плохо. Т.е. окупается поддерживаемостью.

Опять предлагаете довериться мнению третьего человека, не смотря в код?


S>>>В комментариях нашел ссылку на тг канал по DDD

S>>>https://t.me/iDDDqd
G>>Всего 1000 участников...
G>>В чатике только по дотнету 8,5к, по 1С десятки тысяч.

S>И? Вы еще с общим чатиком по программированию сравните. дотнет -- технология, ддд -- одна из возможных методологий для разработки ПО на той же дотнет. Все, кмк, естественно.

Методологии должны же быть шире технологий, не?

S>>>Вот тут можно, наверное, с людьми про их проекты поговорить и похоливарить.

G>>Они там сами справляются, на любое негативное мнение по поводу ДДД говорят что автор не понимает бизнес.

S>Вы хотели с кем-то пообщаться за 16 лет, вот пожалуйста. Это в любом сообществе так.

Я почитал что там пишут, примеров тоже нет, куча скепсиса, кризис идентичности.

S>Идите в группу дотнет и начните рассказывать про преимущества ручной сборки мусора.

Таких преимуществ в природе не существует.
Re[32]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 17.01.26 00:27
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Блин, ну он же говорит, что работал в мамбе где было 1млн loc на пхп. И там, например, анкета могла быть в 50 разных контекстах. И если бы не ДДД, то по его мнению, было бы очень и очень плохо. Т.е. окупается поддерживаемостью.

G>Опять предлагаете довериться мнению третьего человека, не смотря в код?

Вашему же я должен довериться, что ДДД не нужен. А его почему-то нет.

S>>И? Вы еще с общим чатиком по программированию сравните. дотнет -- технология, ддд -- одна из возможных методологий для разработки ПО на той же дотнет. Все, кмк, естественно.

G>Методологии должны же быть шире технологий, не?

Не факт, книжка по какой-нибудь СУБД или ЯП может в разы оказаться больше чем та же ДДД.

S>>Вы хотели с кем-то пообщаться за 16 лет, вот пожалуйста. Это в любом сообществе так.

G>Я почитал что там пишут, примеров тоже нет, куча скепсиса, кризис идентичности.

Вы вопрос задайте, возможно там накидают примеры кода по ДДД, где без оного было бы хуже.
Кодом людям нужно помогать!
Re[33]: Как внедряли DDD в Яндекс 360.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 17.01.26 12:12
Оценка:
Здравствуйте, Sharov, Вы писали:

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


S>>>Блин, ну он же говорит, что работал в мамбе где было 1млн loc на пхп. И там, например, анкета могла быть в 50 разных контекстах. И если бы не ДДД, то по его мнению, было бы очень и очень плохо. Т.е. окупается поддерживаемостью.

G>>Опять предлагаете довериться мнению третьего человека, не смотря в код?

S>Вашему же я должен довериться, что ДДД не нужен. А его почему-то нет.

Я не призываю моему мнению довериться, я призываю провести эксперимент.


S>>>И? Вы еще с общим чатиком по программированию сравните. дотнет -- технология, ддд -- одна из возможных методологий для разработки ПО на той же дотнет. Все, кмк, естественно.

G>>Методологии должны же быть шире технологий, не?

S>Не факт, книжка по какой-нибудь СУБД или ЯП может в разы оказаться больше чем та же ДДД.

А при чем тут книжка если мы про охват аудитории?

S>>>Вы хотели с кем-то пообщаться за 16 лет, вот пожалуйста. Это в любом сообществе так.

G>>Я почитал что там пишут, примеров тоже нет, куча скепсиса, кризис идентичности.
S>Вы вопрос задайте, возможно там накидают примеры кода по ДДД, где без оного было бы хуже.
Так я тебе задаю, ты же утверждаешь что DDD обладает преимуществами при некоторых условиях. Вот я и хочу прмиер.
Re[34]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 17.01.26 22:44
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Вашему же я должен довериться, что ДДД не нужен. А его почему-то нет.

G>Я не призываю моему мнению довериться, я призываю провести эксперимент.

Мне этот эксперимент не интересен. Это долго, и самое главное, дорого. Написать дважды одно и тоже, причем софт должен быть крупный, типа
1млн пхп кода, как прозвучало в видео. И опять же, экспериментов должно быть несколько, вообще говоря много, чтобы что-то утверждать --
1 раз без ДДД лучше, другой -- хуже, ну и какой вывод? Т.е. я не считаю, что это возможно. Ну т.е. возможно, но для компаний типа ibm и проч.
крупняк

S>>Не факт, книжка по какой-нибудь СУБД или ЯП может в разы оказаться больше чем та же ДДД.

G>А при чем тут книжка если мы про охват аудитории?

Да, неправ, согласен. Забираю свою аргументацию назад -- очевидно, что по ДДД можно и на пхп писать, на фп, да хоть на Си.
Т.е. я не знаю ответ на свой вопрос -- технология vs методология -- но очевидно, что моя аргументация не верна.
Ну да, ДДД особой популярностью не пользуется. И ладно, я вовсе за него не топлю. Есть что-то полезное, есть что-то не очень.

S>>Вы вопрос задайте, возможно там накидают примеры кода по ДДД, где без оного было бы хуже.

G>Так я тебе задаю, ты же утверждаешь что DDD обладает преимуществами при некоторых условиях. Вот я и хочу прмиер.

Я 101 раз говорю, что я не апологет и я не знаю. Выше дал ссылку на практика ДДД, где он озвучивал некоторые условия -- много
кода на пхп, например. Ну поговорите с гпт каким-нибудь. Лично мне подход моделирования бизнеса, выработки общего словаря,
определения доменных границ нравится. Похоже на правду, скажем так. Видел работающий пример разбивки монолита на мс по ДДД.
Другого опыта нету.
Кодом людям нужно помогать!
Re[32]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 17.01.26 23:10
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Для разработчика из видео выше это будет не так -- у него ДДД имеет доказанную пользу. Короче, это субъективщина.

G>Мне кажется ты не понимаешь суть слова "доказанную"...

Доказанную в кавычках, согласен. Типа работает. Применил ДДД -- получилось.

S>>Это можно решить в самый последний момент, согласно ДДД. Это детали.

G>Так вот мы пришли к этому моменту. Это одна таблица или нет?

Ну какая разница-то для данного обсуждения?

G>Какой? Почему в этом примере именно Employee? Что этот пример должен был нам сказать?

G>Может нам наоборот стоит нарезать задачу контексты по другому? напрмиер на расчет зряплаты, грейдирование, итд. В каждом будут свои "root", а Employee как раз получится один для всех, так как он по сути просто справочник, который точно хранится в одной таблице.
G>Я тут не фантазирую, конфигурация 1С ЗУП так устроена. В 1С кстати заложена архитектура Event Sourcing и оптимизации темпоральных запросов (даже проверка остатков прекрасно решается), но в ней нет Domain Model (вернее эта модель полностью соответствует таблицам в БД) и Bounded Context (одна баз — один bounded context).

Ничего не могу сказать по поводу 1С ЗУП, сделали как считали правильным.

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

G>Пробелма в том, что без "тактических паттернов" методология DDD настолько очевидна, что смысла нет в отдельном названии.
G>Она сводится к трем вещам:
G>1) Универсальный язык для общения с заказчиком. По сути это раздел "термины и определения" из ТЗ по любому стандарту
G>2) Разделение проблемы на области — то что везде называние "модулями" (термин из структурного программирования) или "подсистемами" (термин из системной инженерии). В книге вернона и последующих даже упоминается иерархния (вложенность) областей, также как модули и подсистемы могут иметь вложенность.
G>3) Ограниченные контексты — единицы разработки и\или единицы деплоя.
G>Еще недавно появился EventStorming — по сути обычные брейнштормы, если отвязать их от event sourcing.

Да, вполне согласен. Не исключаю, что все эти моменты под одну крышуметодологию запихнули и все. Как-то так оно и есть.
Потом решили развивать идею дальше, и появились тактические паттерны и тп.


G>Фактически ничего нового DDD не дает. Мы все это видели например в UML — диграммы компонентов это предметные области, а диаграммы развертывания, диаграммы юзкейсов, процессов и логической структуры.


Ну тактические все-таки что-то новое, все эти agg root, transaction script, entity, values. А так да, взяли отовсюду понемногу.

S>>Значит тут и репозиторий особо не нужен, обычный DAL.

G>Так это в любой программе так.

Какой сервис в компании не беру, везде есть Repository. Это уже ~Dal по сути.

S>>Но опять же, никаких разумных сравнений произведено не было -- loc, сложность поддержки и т.п. Чисто умозрительные вывод.

G>Серьезно? Только что описал почему фактически не было никаких языков кроме ОО, которые имело смысл изучать. Это сейчас есть не(до)-ОО языки, такие как Go, Rust и Kotlin

Вкусовщина, типа нраится\ не нраится. Могли бы perl для веба взять. Никаких экспериментов по написанию веб приложения на пхп, а потом на C# не было
же?

S>>Вот для кого-то и ДДД выглядит интересно.

G>Кстати регулярно в чатике дотнета вижу как приходит новичок, который хочет DDD изучать и его всем чатом начинают отговаривать.

102 заявляю, что я не апологет ДДД. Но вещь интересная и откидывать ее с порога не стоит, там говорят дельный, но возможно,
кому-то очевидные вещи. Но да, новичку изучать ДДД такое себе. Я как бы сам толком его не изучал -- посмотрел некоторое кол-во видео,
почитал хабр и проч. статьи и все. Никаких классиков не читал и не планирую.

G>Какой промпт? Напиши кодом то, что ты словами хочешь объяснить.

G>Всего-то надо по-ДДДному сделать проверку остатков.

1) Каким боком это к дискуссии?
2) Речь же шла про инвариант класса, а не ДДДшное исполнение чего-то. Инвариант класса и ДДД противоречат где-то?

S>>А бд не с объектами в памяти работает?

G>нет конечно, она с данными на диске работает.

Она(бд) эти данные потом в память себе загоняет и работает с ними. Так что в памяти и работает.

S>>Ну если у нас данные лежат в бд, то естественно что их надо забрать оттуда.

G>нет конечно, проверка остатков делается без поднятия в память данных.

Как?

S>>Кто-то считает, что 1 млн лок на пхп без ДДД это уже вилка. Ну вот можно от этой цифры отталкиваться. Хотя сколько людей, столько мнений.

G>Очередное мнение, которое подкреплено примерно ничем?

Чем хуже вашего мнения?

S>>https://ru.wikipedia.org/wiki/%D0%AD%D0%BC%D0%B5%D1%80%D0%B4%D0%B6%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D1%81%D1%82%D1%8C

G>А почему такое же свойство не может проявиться у достаточно большой системы без DDD? В чем особенность именно DDD?

ДДД утв. что если вы правильно поняли бизнес и модель предметной области, то все должно взлететь. Делайте так и все получится.
При этом никто не увт., что если делать иначе, то не получится.

S>>Возможно. 101 раз повторю -- это вкусовщина. У разработчика из Я. по ссылке выше на этот счет может быть другое мнение. И это нормально.

G>Поэтому и не надо отсылать к мнению и чату ГПТ. Приведи просто пример, хоть свой, хоть из интернета, кода с DDD, который по твоему демонстрирует преимущества и я его перепишу без ДДД и сравним по любым формальным (не зависящим от мнения) характеристикам

Ну ведь фигней занимаетесь, не будете переписывать огромный софт под 1млн. без ДДД. Ну к чему эта бравада?
Какое-то детсадовское взятие на слабо. Не серьезно.

G>Пока выглядит так, что ДДД хорош только потому что он кому-то нравится.

G>Меня интересует более научный подход, когда результат можно как-то измерить.

Я говорил, что он не плох, если кому-то не нравится. Ровно в этом моя позиция. Научный подход в ИТ вещь такая себе -- почему написали на C#, когда
можно было на С++ или вообще на Си? Это бред и демагогия, не нравится, не пользуйтесь. Я вот избирательно что-то для себя в ДДД подчеркнул и мне
хорош, никакого научного подхода не надо.

Блин, ну какой научный подход у agile, рефакторинга и solid?
Кодом людям нужно помогать!
Re[22]: Что если не разделять строго dto, entity, bo...
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.01.26 07:11
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Тем более есть проблема: кроме Clean Architecture и DDD в медийном поле вообще не существует других подходов. У альтернативы ДДД даже названия собственного нет, она состоит из применения принципов YAGNI, KISS, DRY, top-down подхода к проектированию и разработке, частично SOLID.

Эмм, частично антиподом является anemic model. Термин введён, афаир, как ругательство апологетами DDD, но вполне отражает как минимум часть подхода.

З.Ы. Полностью согласен со всем вашим постом.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[29]: Что если не разделять строго dto, entity, bo...
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.01.26 07:34
Оценка:
Здравствуйте, Sharov, Вы писали:


S>Детали реализации -- да, скрывает. Добавьте соотв. метод в соотв. интерфейс и всех делов.

Не получится.
S>Проверка инварианта делегируются бд, а класс получает результат этой проверки. В бд можно делать еще lock, если что.
Нет, это так не работает. Из-за этого примерно все образцы DDD либо не работают вообще, либо чудовищно неэффективны.

S>>>Вычитать соотв. поля из бд, взяв соотв. лок предварительно, посчитать и в зависимости от, продолжить работу.

Ну, то есть то, что СУБД обеспечивала из коробки, мы превращаем в закат солнца вручную.

S>Ну так переделайте на read-write, а не просто read. И используйте соотв. уровень изоляции, например read commited.

С этим всё очень и очень плохо. Сделать эффективным взаимодействие между ООП и RDBMS таким образом ещё никому не удалось.

S>>>См. выше про ООП -- что такое проделывали?

G>>Конечно, я даже пример минимальный скидывал, который иллюстрирует преимущества. Любые подходы без ООП увеличивают объемы дублирующегося кода кода, при той же функцинальности.

S>Не серьезно -- вы приложили опереточный пример, а в случае DDD речь может идти о 10 или 100 тыс. строк кода минимум.

Вот как раз в опереточных примерах DDD хоть как-то работает. Когда речь будет идти о десятках тысяч строк, DDD станет гирей на шее пловца.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 28.01.26 08:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

G>>Тем более есть проблема: кроме Clean Architecture и DDD в медийном поле вообще не существует других подходов. У альтернативы ДДД даже названия собственного нет, она состоит из применения принципов YAGNI, KISS, DRY, top-down подхода к проектированию и разработке, частично SOLID.

S>Эмм, частично антиподом является anemic model. Термин введён, афаир, как ругательство апологетами DDD, но вполне отражает как минимум часть подхода.

Anemic model антипод Rich model, и ничто не мешает ее использовать в DDD. У DDD проблема такая же как и у ООП, все про него рассказывают, но действительно понимают границы применения единицы. Как раз поэтому бездумное следование принципам DDD можно противопоставить принципам YAGNI, KISS.
Re: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 28.01.26 09:00
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Вопрос такой.


S>Вот, обычно делают слои и на уровне каждого слоя свои объект — для строгого разделения. А потом мапперы между слоями.


Попадалась такая библиотека https://github.com/Tim-Maes/Facet, кодогенерация dto и мапперов из других dto. Но еще не нашел проекта, где можно было бы опробовать
Re[24]: Что если не разделять строго dto, entity, bo...
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.01.26 12:07
Оценка:
Здравствуйте, amironov79, Вы писали:

A>Anemic model антипод Rich model,

тут согласен.
A>и ничто не мешает ее использовать в DDD
Тут — спорно. По Фаулеру, она — антипаттерн.
Рич модель является стандартом DDD; многие вообще считают, что без неё никакого DDD нет.
A>У DDD проблема такая же как и у ООП, все про него рассказывают, но действительно понимают границы применения единицы. Как раз поэтому бездумное следование принципам DDD можно противопоставить принципам YAGNI, KISS.
Было бы неплохо показать какой-нибудь авторитетный источник, который бы объяснял, где проходят эти границы применимости.
Как тут верно заметил коллега gangustas, за последние 16 лет не появилось ни одного убедительного примера, который бы показал преимущества DDD при полном его использовании (а не когда мы от него оставляем какой-то несущественный фрагмент).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.01.26 13:13
Оценка:
Здравствуйте, 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>>>https://ru.wikipedia.org/wiki/%D0%AD%D0%BC%D0%B5%D1%80%D0%B4%D0%B6%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D1%81%D1%82%D1%8C

G>>А почему такое же свойство не может проявиться у достаточно большой системы без DDD? В чем особенность именно DDD?

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

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



S>>>Возможно. 101 раз повторю -- это вкусовщина. У разработчика из Я. по ссылке выше на этот счет может быть другое мнение. И это нормально.

G>>Поэтому и не надо отсылать к мнению и чату ГПТ. Приведи просто пример, хоть свой, хоть из интернета, кода с DDD, который по твоему демонстрирует преимущества и я его перепишу без ДДД и сравним по любым формальным (не зависящим от мнения) характеристикам
S>Ну ведь фигней занимаетесь, не будете переписывать огромный софт под 1млн. без ДДД. Ну к чему эта бравада?
S>Какое-то детсадовское взятие на слабо. Не серьезно.
Как тогда доказать что-то про ДДД?

G>>Пока выглядит так, что ДДД хорош только потому что он кому-то нравится.

G>>Меня интересует более научный подход, когда результат можно как-то измерить.

S>Я говорил, что он не плох, если кому-то не нравится. Ровно в этом моя позиция. Научный подход в ИТ вещь такая себе -- почему написали на C#, когда можно было на С++ или вообще на Си? Это бред и демагогия, не нравится, не пользуйтесь. Я вот избирательно что-то для себя в ДДД подчеркнул и мне

хорош, никакого научного подхода не надо.
Звучит как вера. Вам верить никто не мешает, но нести свою веру другим в целом противопоказано.

S>Блин, ну какой научный подход у agile, рефакторинга и solid?

Есть конечно, исследования всякие.
Насчет solid не знаю, про agile и рефакторинг находил.
Re[25]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 28.01.26 15:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

A>>и ничто не мешает ее использовать в DDD

S>Тут — спорно. По Фаулеру, она — антипаттерн.
S>Рич модель является стандартом DDD; многие вообще считают, что без неё никакого DDD нет.

Мне наоборот казалось, что сейчас большинство склоняются к anemic.

S>Было бы неплохо показать какой-нибудь авторитетный источник, который бы объяснял, где проходят эти границы применимости.

S>Как тут верно заметил коллега gangustas, за последние 16 лет не появилось ни одного убедительного примера, который бы показал преимущества DDD при полном его использовании (а не когда мы от него оставляем какой-то несущественный фрагмент).

Нет их, сам всех про такой спрашиваю Я как раз писал о частичной применимости.
Re[25]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 28.01.26 15:50
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Насколько я знаю основной паттернов DDD является aggregate root — сущность, которая поднимается из бд и все изменения вызываются из нее. То есть мы взываем Root.DoSmth(...), а рут в свою очередь вызывает методы дочерних объектов. Именно рут отвечает за целостность операции

G>За все затягивание и сохранение отвечает репозиторий (это второй по важности паттерн в DDD), а вызывающий код работает с объектами.

Это всё детали реализации. Что мешает реализовать aggregate root как сервис и dto?

G>ООП люди понимают и применяют, посмотри на любой UI фреймворк на ОО-языке — WPF или, прости господи, WinForms.

G>А еще можешь посмотреть базовые библиотеки дотнета или жабы, они тоже полны достаточно качественного ООП (со своими особенностями каждая).

А если взять корпоративные приложения, для которых DDD в первую очередь и предназначен, много там качественного ООП именно в бизнес домене?
Re[34]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 28.01.26 16:01
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>>>Значит тут и репозиторий особо не нужен, обычный DAL.

G>>>Так это в любой программе так.
S>>Какой сервис в компании не беру, везде есть Repository. Это уже ~Dal по сути.
G>Мода — она такая, везде ропозитарии, хотя они не нужны.

Репозиторий как DAL конечно не нужен, здесь ORM нормально справляется. Если же репозиторий как сервис, работающий с внешними данными, и который является частью домена, то почему нет.
Re[32]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 28.01.26 18:52
Оценка:
Здравствуйте, 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>Это всё нерелевантно. Плоскоземельщиков тоже великие толпы. Идти к ним проповедовать — а зачем? Вопрос как раз в том, есть ли чему научиться полезному у плоскоземельщиков.

Ну а как узнать, если не пытаться заговорить, а ходить вокруг да около?
Кодом людям нужно помогать!
Re[34]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 28.01.26 18:58
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>Вашему же я должен довериться, что ДДД не нужен. А его почему-то нет.

S>Не, тут работает презумпция ненужности. Каждый раз, когда вам предлагают какую-нибудь новую практику — хоть уринотерапию, хоть методику или парадигму разработки — по умолчанию ответ "обойдёмся".
S>Это задача предлагающего доказать, что с ним будет лучше.
S>У DDD фундаментальная проблема — многие вопросы в нём неразрешимы совсем. Другие — создают трудности, которых нет в других подходах.

Какие, например?
Кодом людям нужно помогать!
Re[30]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 28.01.26 19:11
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>Детали реализации -- да, скрывает. Добавьте соотв. метод в соотв. интерфейс и всех делов.

S>Не получится.

Почему, как репозиторий зависит от физического хранилища?

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

S>Нет, это так не работает. Из-за этого примерно все образцы DDD либо не работают вообще, либо чудовищно неэффективны.

А при чем здесь DDD? Здесь побочный разговор на тему проверки инвариантов в случае, когда данные хранятся в бд.
Я так понимал суть вопроса.

S>>>>Вычитать соотв. поля из бд, взяв соотв. лок предварительно, посчитать и в зависимости от, продолжить работу.

S>Ну, то есть то, что СУБД обеспечивала из коробки, мы превращаем в закат солнца вручную.

Речь про транзакции? Я не знаю как обеспечивать инваринат класса (домена), если все данные хранятся в бд.
Кроме как неэффективно все лочить ничего придумать не могу, а если использовать бд для этого, то это уже
не инвариант класса получается.
Кодом людям нужно помогать!
Re[34]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 28.01.26 19:28
Оценка:
Здравствуйте, 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...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.01.26 21:06
Оценка:
Здравствуйте, 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...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 28.01.26 21:09
Оценка:
Здравствуйте, amironov79, Вы писали:

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


S>>>>>Значит тут и репозиторий особо не нужен, обычный DAL.

G>>>>Так это в любой программе так.
S>>>Какой сервис в компании не беру, везде есть Repository. Это уже ~Dal по сути.
G>>Мода — она такая, везде ропозитарии, хотя они не нужны.

A>Репозиторий как DAL конечно не нужен, здесь ORM нормально справляется. Если же репозиторий как сервис, работающий с внешними данными, и который является частью домена, то почему нет.

Почему для внешних данных нужен репозиторий? Зачастую внешний сервис, это именно сервис. Ты ему запросы, он тебе ответы. Все. Никакого ооп не надо. И заботиться о целостности внешних данных не надо. На то они и внешние.
Re[35]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.01.26 03:02
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Какие, например?

Банальные вопросы вроде "зарезервировать товары заказа на складе".
Потому что в домене есть складские остатки, есть товары, есть заказы. Ни в кого из них запихать метод "зарезервируй" не получается без того, чтобы втащить внутрь этого метода не-доменную логику.
А делать специальный AggregationRoot, который типа и должен всё это делать, противоречит самой идее Ubuquitous Language, т.к. этого рута в "домене" не существует.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[36]: Как внедряли DDD в Яндекс 360.
От: Miroff Россия  
Дата: 29.01.26 04:04
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Банальные вопросы вроде "зарезервировать товары заказа на складе".

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

Как правило, такие вопросы свидетельствуют о некорректном разделении домена на сущности. К тому же, доменным сущностям не запрещено иметь проекции друг на друга. Скажем, в проекции SKU на склад вполне найдется место для метода "зарезервировать", а в проекции резерва на контрагента найдется место для отгрузочной накладной.
Re[37]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.01.26 04:18
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Как правило, такие вопросы свидетельствуют о некорректном разделении домена на сущности.

Хм. Покажите корректное разделение домена на сущности.
Для взаимопонимания: в качестве домена мы понимаем ER-модель. Она хороша тем, что не отвлекается на детали реализации, вроде иерархии классов или там структуры таблиц. Чисто концептуальная модель предметной области.
Вот у нас есть Товар, есть Склад, есть Заказ.
Есть связь Заказ-Товар (многие-ко-многим, с атрибутом "количество").
Есть связь Товар-Склад (многие-ко-многим, с атрибутами "доступно" и "зарезервировано").

Что здесь сделано некорректно, и как мы поймём, что ошибка есть?

M>К тому же, доменным сущностям не запрещено иметь проекции друг на друга. Скажем, в проекции SKU на склад вполне найдется место для метода "зарезервировать", а в проекции резерва на контрагента найдется место для отгрузочной накладной.

Что такое "проекции друг на друга"? Расскажите подробнее.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[27]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 29.01.26 04:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

A>>Это всё детали реализации. Что мешает реализовать aggregate root как сервис и dto?

G>А есть пример такой архитектуры. Я правда не понимаю как это должно выглядеть.

https://medium.com/@inzuael/anemic-domain-model-vs-rich-domain-model-78752b46098f

A>>А если взять корпоративные приложения, для которых DDD в первую очередь и предназначен, много там качественного ООП именно в бизнес домене?

G>Примерно ничего. ООП плох для моделирования связей и ограничений в предметной области.

Поэтому и непонятно, почему anemic model называют антипаттерном
Re[36]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 29.01.26 04:35
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>Мода — она такая, везде ропозитарии, хотя они не нужны.

A>>Репозиторий как DAL конечно не нужен, здесь ORM нормально справляется. Если же репозиторий как сервис, работающий с внешними данными, и который является частью домена, то почему нет.
G>Почему для внешних данных нужен репозиторий? Зачастую внешний сервис, это именно сервис. Ты ему запросы, он тебе ответы. Все. Никакого ооп не надо. И заботиться о целостности внешних данных не надо. На то они и внешние.

Он нужен, если стоит задача в домене абстрагироваться от способа получения данных. Если такой задачи не стоит, то можно и DbContext из сервиса дёргать, а то и прямо из контроллера
Re[37]: Что если не разделять строго dto, entity, bo...
От: TG  
Дата: 29.01.26 05:20
Оценка:
Здравствуйте, amironov79, Вы писали:

A>>>Репозиторий как DAL конечно не нужен, здесь ORM нормально справляется. Если же репозиторий как сервис, работающий с внешними данными, и который является частью домена, то почему нет.

G>>Почему для внешних данных нужен репозиторий? Зачастую внешний сервис, это именно сервис. Ты ему запросы, он тебе ответы. Все. Никакого ооп не надо. И заботиться о целостности внешних данных не надо. На то они и внешние.
A>Он нужен, если стоит задача в домене абстрагироваться от способа получения данных.

А в каких случаях надо абстрагироваться от способа получения данных? И зачем?
Re[39]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.01.26 14:27
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Дизайн строится не от данных, а от от операций.

Это интересно. Давайте построим дизайн от операций.
M>Если у тебя не получается логично присунуть метод, значит ты что-то сделал не так.



M>Давай разберем что. В ДДД принято идти от предметной области, а в предметной области нет никаких ER, а есть единица товара, у которой есть SKU, физическая локация (на главном склад, у перевозчика, у покупателя и т.п.) и обязательства (вернуть постащику, сжечь, поставить покупателю и т.п.) И когда ты такую модель строишь у тебя логичным образом возникает поединичный учет и резервирование товара логично превращается в метод sku_item.createObligation(Supplybbligation(Order))


M>ER модель при этом будет выглядеть так


M>СКУ, Единица товара, Склад, обязательство, заказ


M>Связи:

M>СКУ — единица товара (один-ко-многим)
M>обязательство — единица товара (один-ко-многим)
M>заказ — обязательство (один-ко-многим)
M>СКУ — склад (многие-к-одному)

Непонятно. Какие атрибуты будут у этих сущностей? Как устроен метод sku_item.createObligation(Supplybbligation(Order))?
Почему метод вы написали так, а не SupplyObligation.create(sku_item, Order), и не Order.createSupplyObligation(sku_item)?
Как мне гарантировать атомарность резервирования товаров в заказе — либо весь заказ, либо ничего?

M>При этом логичным образом решаются и другие задачи, вроде "посчитать себестоимость хранения товара на складе" или "посчитать ущерб от уничтоженного товара находившегося на сгоревшем складе"

Давайте пока с простым разберемся. А потом попробуем придумать, к какому из классов приделать упомянутые вами методы.

S>>Что такое "проекции друг на друга"? Расскажите подробнее.


M>Это из функционального программирование пришло. В данном случае это обратимое преобразование F(Товар, Склад, Заказ) -> (Товар, Остаток, Резерв)

По-прежнему ничего не понятно. Кто тут на кого проецируется? Я в функциональном программировании термина "проекция" не встречал. Если он общепринятый — киньте ссылку на первоисточник, если ваш — распишите подробнее.
M>Ты можешь рассматривать проекции как DB view только не с точки зрения БД, а с точки зрения классов.
Непонятно. В DB View не ограничены проекциями (в терминах реляционной алгебры).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[40]: Как внедряли DDD в Яндекс 360.
От: Miroff Россия  
Дата: 30.01.26 04:53
Оценка:
Здравствуйте, Sinclair, Вы писали:

M>>Давай разберем что. В ДДД принято идти от предметной области, а в предметной области нет никаких ER, а есть единица товара, у которой есть SKU, физическая локация (на главном склад, у перевозчика, у покупателя и т.п.) и обязательства (вернуть постащику, сжечь, поставить покупателю и т.п.) И когда ты такую модель строишь у тебя логичным образом возникает поединичный учет и резервирование товара логично превращается в метод sku_item.createObligation(Supplybbligation(Order))


M>>ER модель при этом будет выглядеть так


M>>СКУ, Единица товара, Склад, обязательство, заказ


M>>Связи:

M>>СКУ — единица товара (один-ко-многим)
M>>обязательство — единица товара (один-ко-многим)
M>>заказ — обязательство (один-ко-многим)
M>>СКУ — склад (многие-к-одному)

S>Непонятно. Какие атрибуты будут у этих сущностей?


Релевантных для задачи никаких.

S>Как устроен метод sku_item.createObligation(Supplybbligation(Order))?


Как реализуешь, так и будет устроен. Может он записи в БД создает, может API вызывает, может в файл складывает.

S>Почему метод вы написали так, а не SupplyObligation.create(sku_item, Order), и не Order.createSupplyObligation(sku_item)?


Потому что логика предметной области требует писать именно так. Обязательство это свойство единицы товара, а не самостоятельная сущность и тем более не свойство заказа. Вся идея ДДД состоит в том, что архитектура должна проистекать из домена, а не из представления архитектора о прекрасном.

S>Как мне гарантировать атомарность резервирования товаров в заказе — либо весь заказ, либо ничего?


Как тебе угодно: транзакциями, блокировами, многофазными коммитами, вручную, автоматически или через аспекты. Физическая реализация ортогональна дизайну.

Что важно, это задуматься действительно ли атомарность нужна по предметной области или это очередная выдуманная хотелка потому что все так делают? В предметной области такого требования может вообще не существовать. Допустим, ты покупаешь пакетный тур и туроператор бронирует для тебя перелет, отель и дайвинг курс. В реальности, на любом этапе ЖЦ заказа может произойти факап: рейс отменят, отель сгорит, дайв-центр потеряет аккредитацию PADI и в заказ придется вносить изменения. В том числе и порождающие финансовые транзакции в произвольном направлении.

S>По-прежнему ничего не понятно. Кто тут на кого проецируется? Я в функциональном программировании термина "проекция" не встречал. Если он общепринятый — киньте ссылку на первоисточник, если ваш — распишите подробнее.


Представь, что у тебя есть вьюха из нескольких таблиц. В классических СУБД она доступна только для чтения. А теперь представь, что ты можешь делать в нее INSERT или UPDATE и эта команда автоматически приведет к изменению исходных таблиц. Дальше представь, что это вьюха маппится на какую-то entity в коде и эта entity ведет себя неотличима от всех остальных маппингов. Вот это и есть проекция. Детали реализации могут быть совершенно любыми, от вьюх и хранимых процедур на уровне БД, до полной иммутабельности на эффектах и соответствующих монадах.
Re[41]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.01.26 07:17
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Релевантных для задачи никаких.

Это понятно, просто их описание лучше помогло бы мне понять, какая у них семантика.

S>>Как устроен метод sku_item.createObligation(Supplybbligation(Order))?

M>Как реализуешь, так и будет устроен. Может он записи в БД создает, может API вызывает, может в файл складывает.
Это не ответ, а уход от ответа. Очень многие "архитектуры" спотыкаются ровно на том, что при реализации получается чушь, хотя картинка исходно была красивая.

S>>Почему метод вы написали так, а не SupplyObligation.create(sku_item, Order), и не Order.createSupplyObligation(sku_item)?

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

M>Вся идея ДДД состоит в том, что архитектура должна проистекать из домена, а не из представления архитектора о прекрасном.

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

S>>Как мне гарантировать атомарность резервирования товаров в заказе — либо весь заказ, либо ничего?

M>Как тебе угодно: транзакциями, блокировами, многофазными коммитами, вручную, автоматически или через аспекты. Физическая реализация ортогональна дизайну.
Так не бывает. Дизайн очень сильно влияет на реализацию, ни о какой ортогональности речь идти не может.

M>Что важно, это задуматься действительно ли атомарность нужна по предметной области или это очередная выдуманная хотелка потому что все так делают?

Можно и задуматься, хотя в контексте этого разговора это оффтоп. Оффтоп потому, что предметная область существует объективно. Да, на этапе анализа иКмеет смысл уточнять требования — совершенно необязательно автоматизировать неэффективный процесс, можно сначала его перепроектировать, а уже потом воплощать в коде.
Но рано или поздно мы приходим к тому, что есть некоторые требования. Реализация не должна диктовать требования архитектуре, а архитектура — бизнесу.
Нам нужна такая методология, которая позволяет проектировать архитектуру так, чтобы она одновременно удовлетворяла бизнес-требованиям и позволяла эффективную реализацию.
А не так, что мы делаем архитектуру для "а давайте мы изменим постановку задачи", и потом "наша ортогональная реализация работает за O(N^3), хотя у конкурентов O(logN)".


M>Представь, что у тебя есть вьюха из нескольких таблиц. В классических СУБД она доступна только для чтения. А теперь представь, что ты можешь делать в нее INSERT или UPDATE и эта команда автоматически приведет к изменению исходных таблиц. Дальше представь, что это вьюха маппится на какую-то entity в коде и эта entity ведет себя неотличима от всех остальных маппингов. Вот это и есть проекция. Детали реализации могут быть совершенно любыми, от вьюх и хранимых процедур на уровне БД, до полной иммутабельности на эффектах и соответствующих монадах.

Нет, это не проекция. То, что вы описываете — это REST-идеология, когда все сценарии выражаются в терминах CRUD-операций. Но она сама по себе работает только тогда, когда у нас нет никакого "поведения" за пределами этих модификаций. Вот я взял и добавил связь между сотрудником и департаментом — и это привело к определённому результату, независимо от того, оформил ли я это через department.Employees += e или через e.Deparment = department. А может, так вообще нельзя, и нужно создать экземпляр EmployeeContractAddendum, который после подписания обеими сторонами автоматически отразит изменения штатного расписания департамента и должности у сотрудника.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 30.01.2026 7:18 Sinclair . Предыдущая версия .
Re[39]: Что если не разделять строго dto, entity, bo...
От: TG  
Дата: 30.01.26 08:04
Оценка:
Здравствуйте, amironov79, Вы писали:

TG>>А в каких случаях надо абстрагироваться от способа получения данных? И зачем?

A>Когда работаешь с несколькими источниками однотипных данных, которые могут отличаться как по протоколу, так и по схеме данных. Интерфейс у репозитория описывается в терминах домена, реализация для каждого источника своя.

Так полного абстрагирования не получится.
Детали реализации доступа к источнику все равно понадобятся для реагирования на ошибки, например.
И невозможно будет делать транзакционно некоторые группы операций.
Re[40]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 30.01.26 14:14
Оценка:
Здравствуйте, TG, Вы писали:

TG>Так полного абстрагирования не получится.

TG>Детали реализации доступа к источнику все равно понадобятся для реагирования на ошибки, например.
TG>И невозможно будет делать транзакционно некоторые группы операций.

Транслируй ошибки в ошибки домена, если очень надо. Репозиторий это просто адаптер в терминах паттернов. С транзакциями да, придется поплясать.
Re[39]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.01.26 17:27
Оценка:
Здравствуйте, amironov79, Вы писали:

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


TG>>А в каких случаях надо абстрагироваться от способа получения данных? И зачем?


A>Когда работаешь с несколькими источниками однотипных данных, которые могут отличаться как по протоколу, так и по схеме данных. Интерфейс у репозитория описывается в терминах домена, реализация для каждого источника своя.


Сколько раз у тебя такое было на практике? Я за всю жизнь встретил примерно ноль таких кейсов.
Re[41]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.01.26 17:34
Оценка:
Здравствуйте, amironov79, Вы писали:

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


TG>>Так полного абстрагирования не получится.

TG>>Детали реализации доступа к источнику все равно понадобятся для реагирования на ошибки, например.
TG>>И невозможно будет делать транзакционно некоторые группы операций.

A>Транслируй ошибки в ошибки домена, если очень надо. Репозиторий это просто адаптер в терминах паттернов. С транзакциями да, придется поплясать.


Да бог с ними, с транзакциями.
По СУБД можно искать произвольным запросом, а по условному веб-сервису не всегда.
Если ты в своей программе ориентируешься на метод например GetOrdersByUser, а веб-сервис возвращает только по id, то ты никогда не заменишь базу на веб-сервис.
Re[40]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 31.01.26 07:29
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Сколько раз у тебя такое было на практике? Я за всю жизнь встретил примерно ноль таких кейсов.


Пару раз было. Но появлялось не сразу, а в результате рефакторинга.
Re[42]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 31.01.26 07:29
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>По СУБД можно искать произвольным запросом, а по условному веб-сервису не всегда.

G>Если ты в своей программе ориентируешься на метод например GetOrdersByUser, а веб-сервис возвращает только по id, то ты никогда не заменишь базу на веб-сервис.

А как задача GetOrdersByUser для такого веб-сервиса будет решаться без репозитория?
Re[43]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 31.01.26 07:50
Оценка:
Здравствуйте, amironov79, Вы писали:

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


G>>По СУБД можно искать произвольным запросом, а по условному веб-сервису не всегда.

G>>Если ты в своей программе ориентируешься на метод например GetOrdersByUser, а веб-сервис возвращает только по id, то ты никогда не заменишь базу на веб-сервис.

A>А как задача GetOrdersByUser для такого веб-сервиса будет решаться без репозитория?

Она вообще никак решаться не будет, в этом и проблема. Если ты для реализации требований опирался на такую операцию, то ты никогда ни на какие внешние сервисы не переедешь.
Чтобы была возможность такого переезда у тебя должны быть или очень простые задачи по работе с состоянием, которые сводятся к взять\положить по ключу, или внешний сервис не такой уж внешний, а дорабатывается по вашим требованиям и фактически в него протекают части логики.
Re[41]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 31.01.26 07:51
Оценка:
Здравствуйте, amironov79, Вы писали:

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


G>>Сколько раз у тебя такое было на практике? Я за всю жизнь встретил примерно ноль таких кейсов.


A>Пару раз было. Но появлялось не сразу, а в результате рефакторинга.


Можно подробнее по конкретный кейс, какие запросы к базе были и на что переехали в итоге?
Re[25]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 31.01.26 08:22
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


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


G>Других хорошим применений ООП немного и попытка натянуть на ООП состояние приложения в основном ущербна. На эту тму у товарища Лиипперта есть потрясающая серия статей Wizards and Warriors, которую я даже перевел на хабре


автор меняет условия для модели хочет что было как в прошлый раз: игроку можно присвоить оружие. А с чего он решил что в новых условиях эта операция вообще должна быть, просто потому что ему так захотелось? Его нет потому что ее нет в реальности, которую он моделирует.
Программа – это мысли спрессованные в код
Re[26]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 31.01.26 14:20
Оценка:
Здравствуйте, Qulac, Вы писали:

G>>Других хорошим применений ООП немного и попытка натянуть на ООП состояние приложения в основном ущербна. На эту тму у товарища Лиипперта есть потрясающая серия статей Wizards and Warriors, которую я даже перевел на хабре


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


А ваше предложение какое? Как в ООП моделировать то, что он описал?
На каждое требование переделывать классы домена? Ну допустим, приведите ваш вариант как праавильно.
А в реальности ДДД мы разве не прибиваем домен к "общему языку" и фактически не можем менять произвольно модель?
Re[27]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 31.01.26 14:45
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


G>>>Других хорошим применений ООП немного и попытка натянуть на ООП состояние приложения в основном ущербна. На эту тму у товарища Лиипперта есть потрясающая серия статей Wizards and Warriors, которую я даже перевел на хабре


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


G>А ваше предложение какое? Как в ООП моделировать то, что он описал?

G>На каждое требование переделывать классы домена? Ну допустим, приведите ваш вариант как праавильно.

Мы имеем то что имеем, хоть с ооп хоть без ооп. Я бы выбрал приведеный пример с дженериками.

G>А в реальности ДДД мы разве не прибиваем домен к "общему языку" и фактически не можем менять произвольно модель?


Фраза:"Игроку дали оружие" не имеет смысла в не контекста. Кто дает? Если про игру то это возможно какой другой игровой персонаж. Тогда проблема решается перегрузкой методов или шаблоном "визитер"
Программа – это мысли спрессованные в код
Re[28]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 31.01.26 15:03
Оценка:
Здравствуйте, Qulac, Вы писали:

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


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


G>>>>Других хорошим применений ООП немного и попытка натянуть на ООП состояние приложения в основном ущербна. На эту тму у товарища Лиипперта есть потрясающая серия статей Wizards and Warriors, которую я даже перевел на хабре


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


G>>А ваше предложение какое? Как в ООП моделировать то, что он описал?

G>>На каждое требование переделывать классы домена? Ну допустим, приведите ваш вариант как праавильно.
Q>Мы имеем то что имеем, хоть с ооп хоть без ооп. Я бы выбрал приведеный пример с дженериками.
Он же в итоге не полностью описывает ограничения предметной области.
Это по твоему "достаточно хорошо"?

G>>А в реальности ДДД мы разве не прибиваем домен к "общему языку" и фактически не можем менять произвольно модель?

Q>Фраза:"Игроку дали оружие" не имеет смысла в не контекста. Кто дает? Если про игру то это возможно какой другой игровой персонаж. Тогда проблема решается перегрузкой методов или шаблоном "визитер"
А ты дальше второй части читал? Там есть и перегрузка и визитер.
Re[29]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 31.01.26 15:05
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


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


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


G>>>>>Других хорошим применений ООП немного и попытка натянуть на ООП состояние приложения в основном ущербна. На эту тму у товарища Лиипперта есть потрясающая серия статей Wizards and Warriors, которую я даже перевел на хабре


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


G>>>А ваше предложение какое? Как в ООП моделировать то, что он описал?

G>>>На каждое требование переделывать классы домена? Ну допустим, приведите ваш вариант как праавильно.
Q>>Мы имеем то что имеем, хоть с ооп хоть без ооп. Я бы выбрал приведеный пример с дженериками.
G>Он же в итоге не полностью описывает ограничения предметной области.

Где не полностью?
G>Это по твоему "достаточно хорошо"?

G>>>А в реальности ДДД мы разве не прибиваем домен к "общему языку" и фактически не можем менять произвольно модель?

Q>>Фраза:"Игроку дали оружие" не имеет смысла в не контекста. Кто дает? Если про игру то это возможно какой другой игровой персонаж. Тогда проблема решается перегрузкой методов или шаблоном "визитер"
G>А ты дальше второй части читал? Там есть и перегрузка и визитер.

Ну и хорошо.
Программа – это мысли спрессованные в код
Re[31]: Что если не разделять строго dto, entity, bo...
От: Qulac Россия  
Дата: 31.01.26 16:42
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


Q>>>>Мы имеем то что имеем, хоть с ооп хоть без ооп. Я бы выбрал приведеный пример с дженериками.

G>>>Он же в итоге не полностью описывает ограничения предметной области.
Q>>Где не полностью?

G>
G>abstract class Player<TWeapon>  where TWeapon : Weapon
G>{
G>  TWeapon Weapon { get; set; }
G>}
G>sealed class Wizard : Player<Staff> { }
G>sealed class Warrior : Player<Sword> { }
G>

G>Ты про этот пример:
G>Любой метод, который принимал Player теперь не сможет принять Wizard или Warrior.
G>Это не будет масштабироваться. Если добавить требования «игрок может носить доспехи, а волшебник может носить только мантию», и «игрок может читать книги, а воин может читать только немагические книги», то все быстро развалится.


G>>>>>А в реальности ДДД мы разве не прибиваем домен к "общему языку" и фактически не можем менять произвольно модель?

Q>>>>Фраза:"Игроку дали оружие" не имеет смысла в не контекста. Кто дает? Если про игру то это возможно какой другой игровой персонаж. Тогда проблема решается перегрузкой методов или шаблоном "визитер"
G>>>А ты дальше второй части читал? Там есть и перегрузка и визитер.
Q>>Ну и хорошо.
G>Ничего хорошего в итоге не получилось. Куча кода и dynamic dispatch в рантайме, никакого контроля оишбков на уровне системы типов, то есть того, ради чего система типов и затевалась.

все ясно продолжать не имеет смысла.
Программа – это мысли спрессованные в код
Re[36]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 31.01.26 20:55
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>>>Ну тактические все-таки что-то новое, все эти agg root, transaction script, entity, values. А так да, взяли отовсюду понемногу.

G>Абсолютно не связанные между собой вещи. Микросервисы ничего не говорят об архитектуре внутри сервиса.

Тактические и стратегические да, не связаны. Зачем-то их убрали под один зонтик ДДД. На счет арх-ры
микросервисов -- ну приставка микро должна говорить о том, что все-таки желательно иметь что-то простое.
Т.е. в идеале микросервис должен говорить об очень простой архитектуре.

S>>Ну а Эванс добавил стратегические паттерны и превратил все это методологию. Что называется стоял на плечах гигантов.

G>Как я и написал ниже он добавил философию.

1)Это, кстати, важно. Кроме шуток. Философия вещь важая и нужная.
2)Все-таки он превратил все это дело в методологию.

S>>Соглашусь. Ну, кстати, и ООП тоже своего рода мода.

G>На ооп мода была в середине девяностых — середине нулевых. Мода прям адская, все что не ООП — было "фу". На волне этой моды ДДД и появилось.
G>Потом микрософт нанял Эрика Мейера, который до этого Хаскелем занимался и он всех покусал функциональщиной, а в 2011 вышел стандарт с++11, в ктором вся стандартная библиотека была функциональной.
G>На той волне даже JS голову поднял, в нем давно было то, что в мире ФП ценилось.

Да, помню эти времена и по срачам в жж и тут. Машинное обучение все это снесло или сделало мало релевантным.
Народ перенес свой фокус туда.

S>>Странно, учитывая что он на 20 лет появился раньше. А на питон почему не смотрели, вроде для него уже были фреймоврки для веба?

G>Возраст языка не показатель популярности. в 2005 на полках книг по C# и Java было одинаково, даже по C++ было меньше, хотя он старше. А по перлу если одна попадалась на полке, то лежала там несколько лет.

В библио-глобусе до фига была книг по любой технологии, бывал там в 2005-2010 очень и очень часто.
Но это в Москве. Хотя думаю, и в любом крупном областном центре были свои хорошие книжные.

S>>При чем здеьс обеспечение инварианта и ДДД?

G>Видимо это никак не связанные вещи

Видимо.

S>>Объектами самой бд, типа строки\колонки\талбицы и т.п.

G>У слова "объект" в программировании есть вполне конкретное значение. строки\колонки\талбицы не являются объектами с точки зрения работы с БД.

С тз реализации вполне являются.


S>>Я пытаюсь настоять на его полезности хотя бы в рамках распила монолита на микросервисы.

G>Ок, давай примеры чем именно ДДД помогает. А еще было бы неплохо описать "механизм действия", а то может ДДД не при чем.
G>Или нам поверить что помогает потому что кто-то сказал?

Берете монолит, находите в нем домены, в доменах BC и по этим BC микросервисы и нарезаете. Желательно чтобы
1 BC — 1 agg. root. Но это, кажется, не обязательно.

G>>>Бремя доказательство обычно возлагается на того кто утверждает, пока он не представил объективные аргументы.

S>>У меня их нету
G>Ок, значит просто вера

Как и в эффективность ООП, получается.

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

G>Допустим разрабатывается система, аля трекер. Заказчик хочет возможность ограничить количество задач для пользователя.
G>Будут две сущности: Issue и User, связанные много-к-одному.
G>У Issue есть метод AssignTo, которому надо передать User или его Id, чтобы связать. И надо как-то гарантировать что выполняется условие, что для одного User назначено не более трех Issue/

G>Какую реализацию нам диктует прагматичный подход (ПП):

G>Прямо в контроллере, в одной транзакции (!) сделать два запроса:
G>
G>update issues set user_id = @userid where id = @id;
G>select count(*)from issues where user_id = @userid
G>

G>Для PG и других баз с оптимистичными блокировками нужен уровень изоляции serializable и повтор запросов при ошибке, а для SQL Server без RCS и MySQL (и других блокировочников) достаточно read committed

G>Реализация на C# для postgres может выглядеть так:

G>
G>var db = ctx.Database;
G>await db.CreateExecutionStrategy().ExecuteAsync(async ct =>
G>{
G>    await using var t = await db.BeginTransactionAsync(System.Data.IsolationLevel.Serializable, ct);
G>    await ctx.Issues.Where(i => i.Id == id).ExecuteUpdateAsync(s => s.SetProperty(x => x.UserId, userId), ct); 
G>    if (await ctx.Issues.CountAsync(x => x.UserId == userId, ct) > 3) throw new Exception("Auchtung");
G>}, ct);
G>


Для MVP сойдет, а для какого-нибудь аналога джиры такое себе.

G>С этой же задачей я пошел в рекомендованный тобой чат, попросил показать пример DDD. три дня срачей, рассказов что я не умею требования анализировать, что задача вообще нереальная и не надо её решать итд.

G>Самое лучшее что один из участников написал пайтоне
G>
G>class User(DomainEntity[UserId]):
G>    def __init__(self, entity_id: UserId, issue_count: int) -> None:
G>        super().__init__(entity_id)
G>        self._issue_count = issue_count

G>    def take_issue(self) -> None:
G>        MAX_ISSUE_COUNT = 3
G>        self._issue_count += 1
G>        if self._issue_count > MAX_ISSUE_COUNT:
G>            raise TooManyIssues


G>class Issue(DomainEntity[IssueId]):
G>    def __init__(self, entity_id: IssueId, metadata: str, user_id: UserId | None):
G>        super().__init__(entity_id)
G>        self._metadata = metadata
G>        self._user_id = user_id

G>    def assign_to(self, user: User) -> None:
G>        if self._user_id:
G>            raise IssueIsAlreadyAssigned

G>        user.take_issue()
G>        self._user_id = user.entity_id

G>


G>То есть прделагают два агрегата. User хранит счетчик issue. Причем в реальности такая логика будет размазана по разным файлам.

G>1) Во первых код тупо не полный, так как кроме увеличения при назначении надо еще уменьшать при переназначении.
G>2) Как будет обеспечиваться изоляция транзакций непонятно, этого кода также нет.


G>А теперь представим что программа у нас развивается и требования чуть усложнились: теперь надо считать не все Issue, а только в нужном статусе.

G>В варианте на C# добавить фильтр и код проверки вызывать как в методе назначения задачи, так и при смене статуса на нужный.
G>Что делать в варианте на пайтоне — даже боюсь представить.

G>Получается что сделали по ДДД максимально хорошо насколько люди поняли ДДД, а получилось раздутое нерасширяемое и скорее всего ненадежное говно.


Нерасширяемое оно получилось как раз на С# -- начните получать певрые пожелания и доработки от заказчиков, а играться
со статусами и привет. На питоне как-то солиднее решение, да делать дольше и сложнее, но надолгосрок будет проще.


S>>Блин, ну как тогда любая технология взлетает, если в нее по сути по началу верять пару человек, если вообще не один? При таком подходе никакого ООП бы не было.

G>Серьезно считаешь что ООП родилось из веры?
G>ООП родилось из решения частных задач, а именно моделирования поведения в агентной системе. Внезапно первый ОО-язык это была в первую очередь агентная система.
G>Авторы ООП никуда ООП не продвигали. Последователи сами захотели включить его в свои языки, причем сильно по разному.
G>От появления ООП до первых популярных языков прошло почти 20 лет.
G>Больше всех ООП популяризировал C++, потому что он по сути добавлял новые фичи в адски популярный тогда С. Возможно если бы не Страуструп то такого хайпа и не случилось бы.
G>Популярность ООП это скорее череда совпадений и неплохой изначальной идем, которую специально никто не форсил.

А откуда была уверенность в неплохой изначальной идеи? Т.е. это был прагматичный расчет? А куда девать тогда
череду совпадений?

G>А с DDD ровно обратная картина.


Блин, кучу всего объединил под один зонтик (см. выше) и попытались приделать какую-то методологию.
Что там обратного -- не понятно.


G>>>Насчет solid не знаю, про agile и рефакторинг находил.

S>>Ну вот про научно доказанную пользу agile я бы почитал.
G>Да там банальное исследование было: опрос какие практики применяют и считали корреляцию с "успешностью" проектов. Как успешность считали уже не помню.

Я так и думал -- correlation doesn't imply causation. (с) Т.е. никакого научного обоснования, а такая же веря как с ДДД.
Кодом людям нужно помогать!
Re[36]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 31.01.26 20:58
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>Какие, например?

S>Банальные вопросы вроде "зарезервировать товары заказа на складе".
S>Потому что в домене есть складские остатки, есть товары, есть заказы. Ни в кого из них запихать метод "зарезервируй" не получается без того, чтобы втащить внутрь этого метода не-доменную логику.
S>А делать специальный AggregationRoot, который типа и должен всё это делать, противоречит самой идее Ubuquitous Language, т.к. этого рута в "домене" не существует.

Это странно, почему так нельзя делать? А как тогда машину описать, ведь ее не существует, а существуют колеса,
кузов, двигателя, трансмиссия, ходовая часть и т.п. Но очевидно в соотв. домене будет что-то типа Car или Automobile и т.п.
именования.
Кодом людям нужно помогать!
Re[38]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 31.01.26 22:29
Оценка:
Здравствуйте, gandjustas, Вы писали:


S>>Я так и думал -- correlation doesn't imply causation. (с) Т.е. никакого научного обоснования, а такая же веря как с ДДД.

G>Это называется "когортные исследования". В пирамиде медицинских доказательств они например занимают третье место. Второе за рандомизированными плацебо-контролируемыми исследованиями, а первое — мета-анализы. Когда провести рандомизированный эксперимент невозможно, то когортные исследования признаются достаточно хрошим источником доказательств.
G>Напомню что про DDD вообще нет ни одного исследования, которое хоть какие-то измеримые результаты дает. Там все "доказательства" это просто мнения людей. Причем изначально довольно небольшой группы. Сейчас люди часто приводят пример из книги Эванса (которой уже 20+лет), а когда доходит до примеров реалистичных и актуальных — уже не так хорошо даже на них ДДД работает.

Согласен, но все равно это так себе исследования. Будем тут честны.

G>Так что вера ДДД гораздо сильнее, чем вера в ООП или agile.


Спорить не буду.
Кодом людям нужно помогать!
Re[39]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 01.02.26 00:12
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Также напомню читателям, что моделировать модель предметную область гораздо лучше, чем обновлять соотв. строки в бд.

Для этого утверждения нет никаких доказательств.
Re[37]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.02.26 02:12
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Это странно, почему так нельзя делать? А как тогда машину описать, ведь ее не существует, а существуют колеса,

S>кузов, двигателя, трансмиссия, ходовая часть и т.п. Но очевидно в соотв. домене будет что-то типа Car или Automobile и т.п.
S>именования.
Вот такие примеры — вредны. Они не решают реальную проблему, и иллюстрируют удобство написания кода, который вообще не надо писать.
Точно так же, как примеры про наследование фигур. Я уже неоднократно говорил — ни в одной системе вам не потребуется наследовать фигуры друг от друга; скорее всего, единственная фигура, которая вам потребуется — это PolyLine. А наследования с полиморфизмами появятся там, где вы будете этот Polyline обрабатывать — ну там, растеризовать, или превращать в SVG, или в метафайл.
Так и с автомобилем — скорее всего, у вас не будет полиморфного объекта "Car" с объектами, из которых она состоит.
Будет, скорее всего, какой-то объект типа ComplexAssembly, с умением "состоять из".
При этом никакого поведения, кроме "состоять из", у него не будет. Всё остальное будет делать какая-то внешняя по отношению к нему логика — собирать, учитывать, регистрировать, отгружать заказчику и т.п.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[39]: Что если не разделять строго dto, entity, bo...
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.02.26 02:25
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Речь про долгосрок, про подстелить себе салому, а не дурака валять с ООП. Все-таки на долгий срок

S>если выбирать, то питон решение выглядит солиднее, чем sql скрипт + обвязка на C#. Во втором случае скорее
S>всего во что-то упретесь и придется переписывать с нуля, а в первом добавить немного кода.

Скорее всего наоборот: в питоновом решении упрётость наступит примерно сразу, и придётся переписывать всё это нагромождение паттернов друг на друга.
А в С# кода мало, даже если его придётся целиком переписать — не жалко. Да и переписывать-то скорее всего не придётся — учёт статусов и чего угодно делается добавлением предикатов к запросу.
Как только предикаты становятся сложными и начинают использоваться в нескольких местах — код уезжает из каждого конкретного запроса в функцию, которой пользуются все:
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.СountUserIssues(userId, ct) > await ctx.GetMaxUserIssues(userId)) throw new Exception("Auchtung");
}, ct);


S>Также напомню читателям, что моделировать модель предметную область гораздо лучше, чем обновлять соотв. строки в бд.

Вопрос не в том, моделировать ли. Вопрос — в том, как моделировать.
Тот самый Липперт же не предлагает отказаться от программирования D&D. Он предлагает другую модель, которая, в отличие от наивного подхода с new Warrior(), работает.
S>Да, дольше и сложнее, но на долгосрок самое то.
Нет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 01.02.2026 4:49 Sinclair . Предыдущая версия .
Re[42]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 01.02.26 06:31
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Можно подробнее по конкретный кейс, какие запросы к базе были и на что переехали в итоге?


Была задача получать и обрабатывать документы из Postgres. Сделали ее максимально просто: никаких репозиториев, в сервисный слой сразу инжектировался DbContext. Потом приходит задача, что нужно обрабатывать аналогичные документы из Oracle, в котором совершенно другая схема. То есть меняется только способ получения данных, поэтому вполне нормально в такой ситуации выделить из сервисного слоя отдельный сервис для работы с данными и назвать его DocumentsRepository, разделить его на интерфейс, который будет использоваться в сервисном слое, и две реализации, которые будут согласовывать внешние данные с данными приложения. В итоге приложение работает с IDoсumentsRepository, в котором методы GetActualDocuments, GetDocumentsForSign, GetDocumentStreamById и т.д., а все зависимости от конкретных провайдеров и схем лежат в отдельных подпроектах и в бизнес коде никак не участвуют.
Re[44]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 01.02.26 06:31
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>По СУБД можно искать произвольным запросом, а по условному веб-сервису не всегда.

G>>>Если ты в своей программе ориентируешься на метод например GetOrdersByUser, а веб-сервис возвращает только по id, то ты никогда не заменишь базу на веб-сервис.

A>>А как задача GetOrdersByUser для такого веб-сервиса будет решаться без репозитория?

G>Она вообще никак решаться не будет, в этом и проблема. Если ты для реализации требований опирался на такую операцию, то ты никогда ни на какие внешние сервисы не переедешь.
G>Чтобы была возможность такого переезда у тебя должны быть или очень простые задачи по работе с состоянием, которые сводятся к взять\положить по ключу, или внешний сервис не такой уж внешний, а дорабатывается по вашим требованиям и фактически в него протекают части логики.

Тогда о чем разговор? Задача нерешаема, что с репозиторием, что без.
Re[43]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 01.02.26 10:24
Оценка:
Здравствуйте, amironov79, Вы писали:

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


G>>Можно подробнее по конкретный кейс, какие запросы к базе были и на что переехали в итоге?


A>Была задача получать и обрабатывать документы из Postgres. Сделали ее максимально просто: никаких репозиториев, в сервисный слой сразу инжектировался DbContext. Потом приходит задача, что нужно обрабатывать аналогичные документы из Oracle, в котором совершенно другая схема.

Вы же говорили что использовали внешний сервис, который вообще не РСУБД. Или я что-то не понял?



A>То есть меняется только способ получения данных, поэтому вполне нормально в такой ситуации выделить из сервисного слоя отдельный сервис для работы с данными и назвать его DocumentsRepository, разделить его на интерфейс, который будет использоваться в сервисном слое, и две реализации, которые будут согласовывать внешние данные с данными приложения. В итоге приложение работает с IDoсumentsRepository, в котором методы GetActualDocuments, GetDocumentsForSign, GetDocumentStreamById и т.д., а все зависимости от конкретных провайдеров и схем лежат в отдельных подпроектах и в бизнес коде никак не участвуют.


Использование двух баз с разными схемами и провайдерами в рамках EF решается просто, даже без класса репозитария
Простой способ:
1) Делаете один базовый абстрактный класс контекста со всеми свойствами и классами сущностей и два наследника, в каждом свою модель пилите под свой провайдер
2) Делаете ОДИН класс контекста, в котором модель переключаете так: https://learn.microsoft.com/en-us/ef/core/modeling/dynamic-model, и используете KeyedService для подстановки, но если вы заходите миграции, то придется еще отдельный код для этого написать.
Re[45]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 01.02.26 10:25
Оценка:
Здравствуйте, amironov79, Вы писали:

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


G>>>>По СУБД можно искать произвольным запросом, а по условному веб-сервису не всегда.

G>>>>Если ты в своей программе ориентируешься на метод например GetOrdersByUser, а веб-сервис возвращает только по id, то ты никогда не заменишь базу на веб-сервис.

A>>>А как задача GetOrdersByUser для такого веб-сервиса будет решаться без репозитория?

G>>Она вообще никак решаться не будет, в этом и проблема. Если ты для реализации требований опирался на такую операцию, то ты никогда ни на какие внешние сервисы не переедешь.
G>>Чтобы была возможность такого переезда у тебя должны быть или очень простые задачи по работе с состоянием, которые сводятся к взять\положить по ключу, или внешний сервис не такой уж внешний, а дорабатывается по вашим требованиям и фактически в него протекают части логики.

A>Тогда о чем разговор? Задача нерешаема, что с репозиторием, что без.

Именно. Поэтому использование репозитария может "помочь" только при смене одной РСУБД на другую, а это прекрасно делается и без репозитария.
Re[44]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 01.02.26 15:41
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Вы же говорили что использовали внешний сервис, который вообще не РСУБД. Или я что-то не понял?


Я говорил, что не не РСУБД, а в том числе и не РСУБД.

G>Использование двух баз с разными схемами и провайдерами в рамках EF решается просто, даже без класса репозитария

G>Простой способ:
G>1) Делаете один базовый абстрактный класс контекста со всеми свойствами и классами сущностей и два наследника, в каждом свою модель пилите под свой провайдер
G>2) Делаете ОДИН класс контекста, в котором модель переключаете так: https://learn.microsoft.com/en-us/ef/core/modeling/dynamic-model, и используете KeyedService для подстановки, но если вы заходите миграции, то придется еще отдельный код для этого написать.

Каша какая-то. Проще 2 отдельных контекста сделать.
Re[38]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 01.02.26 17:56
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>Это странно, почему так нельзя делать? А как тогда машину описать, ведь ее не существует, а существуют колеса,

S>>кузов, двигателя, трансмиссия, ходовая часть и т.п. Но очевидно в соотв. домене будет что-то типа Car или Automobile и т.п.
S>>именования.
S>Вот такие примеры — вредны. Они не решают реальную проблему, и иллюстрируют удобство написания кода, который вообще не надо писать.
S>Точно так же, как примеры про наследование фигур. Я уже неоднократно говорил — ни в одной системе вам не потребуется наследовать фигуры друг от друга; скорее всего, единственная фигура, которая вам потребуется — это PolyLine. А наследования с полиморфизмами появятся там, где вы будете этот Polyline обрабатывать — ну там, растеризовать, или превращать в SVG, или в метафайл.
S>Так и с автомобилем — скорее всего, у вас не будет полиморфного объекта "Car" с объектами, из которых она состоит.
S>Будет, скорее всего, какой-то объект типа ComplexAssembly, с умением "состоять из".
S>При этом никакого поведения, кроме "состоять из", у него не будет. Всё остальное будет делать какая-то внешняя по отношению к нему логика — собирать, учитывать, регистрировать, отгружать заказчику и т.п.

А что значит никакого поведения, если он состоит из мн-ва сложных объектов со сложным поведением?
Как поведение "состоять из" поможет в поведении поехать прямо? Нам же не только нужно что-то перечеслять,
но и взаимодействовать и управлять этим надо. Вот абстаркция Car по заветам ООП все это дело, всю эту сложность,
прячет под, каламбур, капот. Кому-то и "состоять из" понадобиться, кому-то ехать вперед и рулить.
Кодом людям нужно помогать!
Re[39]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.02.26 03:40
Оценка:
Здравствуйте, Sharov, Вы писали:

S>А что значит никакого поведения, если он состоит из мн-ва сложных объектов со сложным поведением?

S>Как поведение "состоять из" поможет в поведении поехать прямо? Нам же не только нужно что-то перечеслять,
S>но и взаимодействовать и управлять этим надо. Вот абстаркция Car по заветам ООП все это дело, всю эту сложность,
S>прячет под, каламбур, капот. Кому-то и "состоять из" понадобиться, кому-то ехать вперед и рулить.
Это — опасное заблуждение. Во-первых, задача "ехать прямо" или там "рулить" не имеет никакого отношения к деятельности, к примеру, автосалона.
Из того, что он продает авмтомобили, вовсе не следует, что надо бежать и реализовывать класс "автомобиль", экземпляры которого будут сложным образом взаимодействовать с запчастями этого автомобиля.
Во-вторых, даже если у вас действительно есть задача автоматизации управления автомобилем, инкапсуляция физики внутрь иерархии объектов очень вряд ли будет конструктивным способом решения этой задачи.
Поэтому перед тем, как рассуждать о поведении, нужно сначала озаботиться постановкой задачи. А не бежать слепо моделировать реальный мир при помощи иерархий классов и взаимодействия объектов.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[46]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 02.02.26 04:39
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>Вы же говорили что использовали внешний сервис, который вообще не РСУБД. Или я что-то не понял?

A>>Я говорил, что не не РСУБД, а в том числе и не РСУБД.
G>Я спрашивал про не РСУБД. Было такое на практике?

Пока еще нет, но... Безопасники постоянно грозятся закрыть прямой доступ в "чужие" БД, поэтому вероятность, что ходить за данными придется через HttpClient ненулевая, и когда все запросы локализованы в конкретном месте, такой переход будет достаточно прост.

G>>>Использование двух баз с разными схемами и провайдерами в рамках EF решается просто, даже без класса репозитария

G>>>Простой способ:
G>>>1) Делаете один базовый абстрактный класс контекста со всеми свойствами и классами сущностей и два наследника, в каждом свою модель пилите под свой провайдер
G>>>2) Делаете ОДИН класс контекста, в котором модель переключаете так: https://learn.microsoft.com/en-us/ef/core/modeling/dynamic-model, и используете KeyedService для подстановки, но если вы заходите миграции, то придется еще отдельный код для этого написать.

A>>Каша какая-то.

G>Это разные способы

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

G>2)Проще 2 отдельных контекста сделать.

G>Это п1

G>В обоих случаях вызывающий код будет прост ссылку на класс наследник DbContext принимать ссылку и работать с ним.


То есть ты предлагаешь сделать общую модель для DbContext и в конфигурации натягивать на нее существующие схемы БД? Так это ничем не лучше пункта 2. Модель контекста должна максимально отражать реальную схему БД с минимумом маппингов, адаптировать данные для приложения надо в другом месте, и репозиторий на роль такого адаптера очень даже подходит.
Re[47]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 02.02.26 10:38
Оценка:
Здравствуйте, amironov79, Вы писали:

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


G>>>>Вы же говорили что использовали внешний сервис, который вообще не РСУБД. Или я что-то не понял?

A>>>Я говорил, что не не РСУБД, а в том числе и не РСУБД.
G>>Я спрашивал про не РСУБД. Было такое на практике?
A>Пока еще нет, но... Безопасники постоянно грозятся закрыть прямой доступ в "чужие" БД, поэтому вероятность, что ходить за данными придется через HttpClient ненулевая, и когда все запросы локализованы в конкретном месте, такой переход будет достаточно прост.
Ну вот когда сделаете, тогда и поговорим о смене РСУБД на веб-сервис, а пока смысла в репозитории исчезающе мало.

G>>В обоих случаях вызывающий код будет прост ссылку на класс наследник DbContext принимать ссылку и работать с ним.

A>Модель контекста должна максимально отражать реальную схему БД с минимумом маппингов, адаптировать данные для приложения надо в другом месте, и репозиторий на роль такого адаптера очень даже подходит.
Так ты определись — тебе скрывать надо смену провайдера и бд или наоборот модель должна соответствовать.
Если у тебя вызывающий код работает с сущностями A,B,C, то ты можешь мэпинг на них настроить в EfCore, а не делать в EfCore C,D,E и мапить вручную.
Re[48]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 02.02.26 13:26
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Ну вот когда сделаете, тогда и поговорим о смене РСУБД на веб-сервис, а пока смысла в репозитории исчезающе мало.


А что здесь говорить? Всё зависит от задачи, в некоторых можно и DbContext из контроллера дёргать

A>>Модель контекста должна максимально отражать реальную схему БД с минимумом маппингов, адаптировать данные для приложения надо в другом месте, и репозиторий на роль такого адаптера очень даже подходит.

G>Так ты определись — тебе скрывать надо смену провайдера и бд или наоборот модель должна соответствовать.
G>Если у тебя вызывающий код работает с сущностями A,B,C, то ты можешь мэпинг на них настроить в EfCore, а не делать в EfCore C,D,E и мапить вручную.

Модель еf core -- это модель конкретной БД, пытаться изобразить на ef core модель домена, если она отличается, -- плохая затея.
Re[40]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 02.02.26 21:22
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


S>>А что значит никакого поведения, если он состоит из мн-ва сложных объектов со сложным поведением?

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

Ну вот так оно в реальном мире работает -- делали для автосалоно, а по итогу надо, чтобы ездило, да еще вчера должно
быть сделано. И вот как "состоять из" тут поможет? Обходить все узлы и что-то с ними делать для\при движении? Или
просто вызывать высоуровневые методы "ехать (прямо\влево...)"?

S>Во-вторых, даже если у вас действительно есть задача автоматизации управления автомобилем, инкапсуляция физики внутрь иерархии объектов очень вряд ли будет конструктивным способом решения этой задачи.


Проще для CarAssemly с api "состоять из" -- да, для тех, кому нужно ехать -- едва ли.

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


Нужно было CarAssemly, а, внезапно, появился заказчик, которому нужно еще и ехать (а может и вовсе только ехать, нужен гоночный автомобиль, а не выставочный, куча денег на кону). Оно так чаще всего и бывает.
Кодом людям нужно помогать!
Re[40]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 02.02.26 21:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Также напомню читателям, что моделировать модель предметную область гораздо лучше, чем обновлять соотв. строки в бд.

G>Для этого утверждения нет никаких доказательств.

Был неточен -- не обновлят строки в бд, а править BL vs правки, по сути, sql скрипта.
Кодом людям нужно помогать!
Re[32]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 02.02.26 22:01
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>>Почему, как репозиторий зависит от физического хранилища?

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

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

S>Внезапно оказывается, что хранить всю модель домена в JSON-файле, или в RDBMS, или во внешнем REST-сервисе — это три большие разницы.

S>В первую очередь потому, что эти три вида хранилищ обеспечивают крайне разную асимптотику при выполнении одинаковых запросов. И то, что в одной реализации делалось за O(logN), в другой может упереться в O(N2).

Все так.

S>>А при чем здесь DDD? Здесь побочный разговор на тему проверки инвариантов в случае, когда данные хранятся в бд.

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

А почему на стороне бд это не сделать эффективно и получит только необходимые цифры по итогу?

S>>Речь про транзакции?

S>Речь про запросы. В БД я могу проверить подобные предикаты, не поднимая в память сервера приложений вообще никаких данных. Часть предикатов я вообще могу проверять декларативно.
S>Более того — если окажется, что проверка поднимает слишком много данных в память СУБД, то у меня есть богатый набор инструментов по борьбе с этим не нарушая семантики — например, создание индексов, партиционирование таблиц и прочая DBA-магия. В DDD мы тащим всё это туда, где обработка будет иметь максимальную стоимость.

См. выше вопрос.
Кодом людям нужно помогать!
Re[41]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.02.26 05:27
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Ну вот так оно в реальном мире работает -- делали для автосалоно, а по итогу надо, чтобы ездило, да еще вчера должно

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

S>просто вызывать высоуровневые методы "ехать (прямо\влево...)"?

Отлично. И как эти методы будут устроены? Будут рекурсивно вызывать аналогичные методы у всех компонентов?
И вот у нас уже двигатель должен уметь выполнять команду "ехать влево". Чувствуете, как быстро наступает абсурд?

S>>Во-вторых, даже если у вас действительно есть задача автоматизации управления автомобилем, инкапсуляция физики внутрь иерархии объектов очень вряд ли будет конструктивным способом решения этой задачи.

S>Проще для CarAssemly с api "состоять из" -- да, для тех, кому нужно ехать -- едва ли.
А там нет никакого API. "Состоять из" вообще не относится к автомобилю. В какой-нибудь инверсной кинематике есть модель системы, в которой нет ни наследования, ни инкапсуляции, ни полиморфизма.
Есть только шарниры и сочленения, с очень узким, заранее известным набором типов и характеристик.
Чтобы описать поведение автомобиля с прицепом, не нужно делать никаких "классов" — нужно просто записать модель автомобиля в кинематических терминах, и всё.

S>Нужно было CarAssemly, а, внезапно, появился заказчик, которому нужно еще и ехать (а может и вовсе только ехать, нужен гоночный автомобиль, а не выставочный, куча денег на кону). Оно так чаще всего и бывает.

И в таком подходе нужно чётко понимать, что рич-DDD-модель вообще никак не помогает решить эту задачу. Скорее наоборот — затрудняет.
Поэтому добавить в CAD-систему сопромат — нетрудно, если в её основе лежит анемик-модель, которая просто агрегирует точки/линии/грани/тела.
И практически невозможно, если в основе лежит рич-модель, в которой параллелепипед отнаследован от куба.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: Что если не разделять строго dto, entity, bo...
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.02.26 05:34
Оценка:
Здравствуйте, Sharov, Вы писали:


S>А почему на стороне бд это не сделать эффективно и получит только необходимые цифры по итогу?

Потому что тогда у вас нет никаких гарантий про семантику. Кто-то пошёл и поменял java-код вычисления бонусов сотрудникам. На страничке профиля сотрудника цифры новые, а в отчёте, который был наговнокожен "мимо" рич-модели — старые.

S>См. выше вопрос.

См. выше ответ. В СУБД встроены всякие клёвые гарантии — вроде того, что запрос при исполнении через индекс даст тот же результат, что и при исполнении через table scan. Только быстрее.
А когда я пишу два разных алгоритма, один из которых императивно обходит граф объектов, строя результат, а другой срезает какие-то углы, то у меня нет примерно никакого способа гарантировать совпадение результатов.

Это всё было ещё на заре времён — модель CODASYL появилась до реляционной; и выкинули её ровно по этой причине — нет надёжной механики алгебраических трансформаций, сохраняющих инварианты.
В итоге анемик как раз и даёт способ отделить схему "данных" от "трансформаций", и оптимизировать эти трансформации с гарантией сохранения семантики.
И при этом он не ограничен убогими выразительными способностями SQL, в котором почти ничего нельзя повторно использовать.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[49]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 03.02.26 10:49
Оценка:
Здравствуйте, amironov79, Вы писали:

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


A>А что здесь говорить? Всё зависит от задачи, в некоторых можно и DbContext из контроллера дёргать

А в каких нельзя?

A>Модель еf core -- это модель конкретной БД, пытаться изобразить на ef core модель домена, если она отличается, -- плохая затея.

У самого ef такого ограничения нет. Это у вас в голове.
Re[41]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 03.02.26 10:51
Оценка:
Здравствуйте, Sharov, Вы писали:

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


S>>>Также напомню читателям, что моделировать модель предметную область гораздо лучше, чем обновлять соотв. строки в бд.

G>>Для этого утверждения нет никаких доказательств.
S>Был неточен -- не обновлят строки в бд, а править BL vs правки, по сути, sql скрипта.
Но и этому тоже нет никаких доказательств.
Re[50]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 03.02.26 18:47
Оценка:
Здравствуйте, gandjustas, Вы писали:

A>>Модель еf core -- это модель конкретной БД, пытаться изобразить на ef core модель домена, если она отличается, -- плохая затея.

G>У самого ef такого ограничения нет. Это у вас в голове.

Да, у меня нет никакого желания вешать эту функциональность на orm. Мне проще в репозитории сделать несколько явных linq запросов и собрать модель для домена, чем колдовать с конфигурацией ef core и в итоге получить кучу "магии".
Re[51]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 04.02.26 12:27
Оценка:
Здравствуйте, amironov79, Вы писали:

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


A>>>Модель еf core -- это модель конкретной БД, пытаться изобразить на ef core модель домена, если она отличается, -- плохая затея.

G>>У самого ef такого ограничения нет. Это у вас в голове.

A>Да, у меня нет никакого желания вешать эту функциональность на orm. Мне проще в репозитории сделать несколько явных linq запросов и собрать модель для домена, чем колдовать с конфигурацией ef core и в итоге получить кучу "магии".

То есть ты хочешь сказать что у тебя:
1) Два разных DbContext с разными моделями
2) Одна общая "модель предметной области"
3) Один общий репозиторий, в котором ты пишешь все мэпинги между 1 и 2?

Это точно проще, чем сделать мэпинги уровне ORM?
Re[52]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 04.02.26 17:35
Оценка:
Здравствуйте, gandjustas, Вы писали:

A>>Да, у меня нет никакого желания вешать эту функциональность на orm. Мне проще в репозитории сделать несколько явных linq запросов и собрать модель для домена, чем колдовать с конфигурацией ef core и в итоге получить кучу "магии".

G>То есть ты хочешь сказать что у тебя:
G>1) Два разных DbContext с разными моделями
G>2) Одна общая "модель предметной области"
G>3) Один общий репозиторий, в котором ты пишешь все мэпинги между 1 и 2?

Общий только интерфейс, реализация для каждой БД своя.

G>Это точно проще, чем сделать мэпинги уровне ORM?


Точно.
Re[42]: Что если не разделять строго dto, entity, bo...
От: Sharov Россия  
Дата: 04.02.26 22:05
Оценка:
Здравствуйте, gandjustas, Вы писали:


G>>>Для этого утверждения нет никаких доказательств.

S>>Был неточен -- не обновлят строки в бд, а править BL vs правки, по сути, sql скрипта.
G>Но и этому тоже нет никаких доказательств.

Вы и дальше будете писать bl на sql? Пока вся логика на стороне бд. Вроде от этого давно ушли.
Кодом людям нужно помогать!
Re[53]: Что если не разделять строго dto, entity, bo...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.02.26 22:21
Оценка:
Здравствуйте, amironov79, Вы писали:

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


A>>>Да, у меня нет никакого желания вешать эту функциональность на orm. Мне проще в репозитории сделать несколько явных linq запросов и собрать модель для домена, чем колдовать с конфигурацией ef core и в итоге получить кучу "магии".

G>>То есть ты хочешь сказать что у тебя:
G>>1) Два разных DbContext с разными моделями
G>>2) Одна общая "модель предметной области"
G>>3) Один общий репозиторий, в котором ты пишешь все мэпинги между 1 и 2?
A>Общий только интерфейс, реализация для каждой БД своя.
Тогда это не репозиторий

Если что репозиторий это то, что достает из хранилища твою "модель", а у тебя этим занимается непосредственно EF. Далее уже ты берешь разные модели и в какой-то функции мапишь их на одни и те же структуры.
Re[54]: Что если не разделять строго dto, entity, bo...
От: amironov79  
Дата: 07.02.26 15:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Тогда это не репозиторий


У репозитория не может быть нескольких реализаций? Так он только для того и нужен, чтобы можно было между этими реализациями переключаться.

G>Если что репозиторий это то, что достает из хранилища твою "модель", а у тебя этим занимается непосредственно EF. Далее уже ты берешь разные модели и в какой-то функции мапишь их на одни и те же структуры.


Что значит "мою" модель? "Моя" модель определена в домене, orm мне отдает модель БД, а репозиторий как раз и нужен, чтобы смапить одно на другое.
Re[42]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 07.02.26 21:24
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


S>>Ну вот так оно в реальном мире работает -- делали для автосалоно, а по итогу надо, чтобы ездило, да еще вчера должно

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



S>>просто вызывать высоуровневые методы "ехать (прямо\влево...)"?

S>Отлично. И как эти методы будут устроены? Будут рекурсивно вызывать аналогичные методы у всех компонентов?
S>И вот у нас уже двигатель должен уметь выполнять команду "ехать влево". Чувствуете, как быстро наступает абсурд?

Нет, конечно. Мы же не будем рекурсивно обходить все эл-ты для езды влево, это необходимо только рулю как минимум. Факт в том, что
все это скрыто внутри.

S>>>Во-вторых, даже если у вас действительно есть задача автоматизации управления автомобилем, инкапсуляция физики внутрь иерархии объектов очень вряд ли будет конструктивным способом решения этой задачи.

S>>Проще для CarAssemly с api "состоять из" -- да, для тех, кому нужно ехать -- едва ли.
S>А там нет никакого API. "Состоять из" вообще не относится к автомобилю. В какой-нибудь инверсной кинематике есть модель системы, в которой нет ни наследования, ни инкапсуляции, ни полиморфизма.
S>Есть только шарниры и сочленения, с очень узким, заранее известным набором типов и характеристик.
S>Чтобы описать поведение автомобиля с прицепом, не нужно делать никаких "классов" — нужно просто записать модель автомобиля в кинематических терминах, и всё.

Хорошо, но где это запись должна быть, во вне или внутри автомобиля? Как минимум необходимые цифры(коэф.) хранятся у соотв. деталей, т.е. внутри.
С другой стороны, передать их во вне для езды не должно составлять проблем. Ну т.е. может быть внешний модуль, который отвечает за езду и которому
как параметр передается автомобиль. Можно и так. Сложность переедет в какой-то другой модуль.

S>>Нужно было CarAssemly, а, внезапно, появился заказчик, которому нужно еще и ехать (а может и вовсе только ехать, нужен гоночный автомобиль, а не выставочный, куча денег на кону). Оно так чаще всего и бывает.

S>И в таком подходе нужно чётко понимать, что рич-DDD-модель вообще никак не помогает решить эту задачу. Скорее наоборот — затрудняет.
S>Поэтому добавить в CAD-систему сопромат — нетрудно, если в её основе лежит анемик-модель, которая просто агрегирует точки/линии/грани/тела.
S>И практически невозможно, если в основе лежит рич-модель, в которой параллелепипед отнаследован от куба.

Ну почему, появиться еще один домен для езды, например.
Кодом людям нужно помогать!
Re[43]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.02.26 08:37
Оценка:
Здравствуйте, Sharov, Вы писали:

S>>>просто вызывать высоуровневые методы "ехать (прямо\влево...)"?

S>>Отлично. И как эти методы будут устроены? Будут рекурсивно вызывать аналогичные методы у всех компонентов?
S>>И вот у нас уже двигатель должен уметь выполнять команду "ехать влево". Чувствуете, как быстро наступает абсурд?

S>Нет, конечно. Мы же не будем рекурсивно обходить все эл-ты для езды влево, это необходимо только рулю как минимум. Факт в том, что

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

S>Хорошо, но где это запись должна быть, во вне или внутри автомобиля? Как минимум необходимые цифры(коэф.) хранятся у соотв. деталей, т.е. внутри.

Для этого нам не нужно 25000 классов для 25000 видов деталей автомобиля. Оказывается, будет в пределах десятка абстрактных типов данных, из которых собирается любой автомобиль, трактор, вагон метро и так далее.
Не будет никаких глубоких иерархий в этих типах данных.
А что будет — так это, быть может, иерархия решателей систем кинематических уравнений. Вот там — да, ООП и модульность: отделение интерфейса от реализации, что позволяет для одной и той же задачи использовать численные методы, символьные вычисления, аппроксимации и прочее. И любые их комбинации по мере необходимости.
Так и в ентерпрайзе — не надо закладывать никакую "доменную логику" в объекты-факты, вроде "накладной на отгрузку". Накладная — она и в африке накладная, а вот какой метод учёта использовать — LIFO, FIFO, средневзвешенный, и т.п. решает вовсе не накладная.

S>Ну почему, появиться еще один домен для езды, например.

Вот именно. И примерно ничем из вашего исходного домена воспользоваться не удастся.
Потому что в одном домене вопрос "может ли автомобиль выехать из гаража" решается датчиками уровня бензина в бензобаке, в другом — наличием подписанного договора купли-продажи, в третьем — системой управления парковочным шлагбаумом.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[44]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 10.02.26 17:54
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


S>>>>просто вызывать высоуровневые методы "ехать (прямо\влево...)"?

S>>>Отлично. И как эти методы будут устроены? Будут рекурсивно вызывать аналогичные методы у всех компонентов?
S>>>И вот у нас уже двигатель должен уметь выполнять команду "ехать влево". Чувствуете, как быстро наступает абсурд?

S>>Нет, конечно. Мы же не будем рекурсивно обходить все эл-ты для езды влево, это необходимо только рулю как минимум. Факт в том, что

S>>все это скрыто внутри.
S>Как это оно скрыто внутри? Внутри чего? Если у нас есть класс "автомобиль", который из себя представляет aggregation root, то у него и есть метод "Ехать влево".
S>Дальше вы начинаете вызывать методы "Ехать влево" у составляющих агрегат элементов. Вот вы заложились на то, что у руля этот метод нужно вызывать, а у колёс и двигателя — нет.

А откуда следует, что методы "Ехать влево" должны быть у всех? Это детали реализации, сокрытые внутри абстаркции.

S>Завтра к вам приходит заказчик и рассказывает, что в его модели автомобиля задние колёса умеют подруливать, поэтому им тоже нужно "знать" о повороте всего автомобиля влевою

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

В каком-то из. А в чем проблема?

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

S>Не получается получить никакое преимущество от ООП — изоляцию состояний друг от друга.

Я не могу понять, откуда следует, что при поступлении требования менять надо прямо все. Поступило требование для задних колес, менять надо руль.
Из чего это следует? Я же не паттерном Visitor буду обходить все детали и что-то с ними делать, а соотв. класс, который всей этой механикой и занимаетя.
Но этот класс живет где-то внутри модуля Car, он internal.

S>>Хорошо, но где это запись должна быть, во вне или внутри автомобиля? Как минимум необходимые цифры(коэф.) хранятся у соотв. деталей, т.е. внутри.

S>Для этого нам не нужно 25000 классов для 25000 видов деталей автомобиля. Оказывается, будет в пределах десятка абстрактных типов данных, из которых собирается любой автомобиль, трактор, вагон метро и так далее.
S>Не будет никаких глубоких иерархий в этих типах данных.

Пожалуйста, это детали реализации. Я вовсе не против.



S>>Ну почему, появиться еще один домен для езды, например.

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

Ну так с тз какого-нибудь ДДД, это отдельные домены с соотв. агг рутами. Почему при этом автомобиль не может ехать, и как ему мешает наличие договора купли-продажи мне
по-прежнему не ясно.
Кодом людям нужно помогать!
Re[45]: Как внедряли DDD в Яндекс 360.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.02.26 21:30
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Ну так с тз какого-нибудь ДДД, это отдельные домены с соотв. агг рутами. Почему при этом автомобиль не может ехать, и как ему мешает наличие договора купли-продажи мне по-прежнему не ясно.


Мне вот тоже интересно.

Делаем ERP для конгломерата автопарков. Множество площадок по стране, тысячи машин, все обмазали датчиками.
Есть отдельные домены:
1) Юридический — учет и контроль документов на право управлять автомобилем и использовать его для перевозок — договоры, путевые листы, регистрация.
2) Технический — сбор данных с датчиков автомбиля, контроль состояния.
3) Интеграционный — загрузка маршрутов в автономную систему навигации, взаимодействие с автоматическими шлагбаумами, контролирующими вьезд-выезд автомобилей на территории автопарков.

Все вроде отдельные домены. У каждого свои руты. Но везде так или иначе будет сущность "автомобиль".
И вот нам надо реализовать операцию "выпустить автомобиль на маршрут",для корректной работ нужны данные из всех трех доменов.
Это будет отдельный домен и рут? Это будут разные сущности или одна? Разные таблицы в базе или одна?
Re[45]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.26 05:04
Оценка:
Здравствуйте, Sharov, Вы писали:


S>А откуда следует, что методы "Ехать влево" должны быть у всех? Это детали реализации, сокрытые внутри абстаркции.

Я же написал, откуда следует. Вы заранее не знаете, у кого они должны быть, а у кого — нет.
Получается, что ваша "абстракция" зависит от подробностей "реализации".

S>В каком-то из. А в чем проблема?

В том, что её придётся перекладывать из класса в класс по четыре раза в неделю. Я же вам привёл примеры.

S>Я не могу понять, откуда следует, что при поступлении требования менять надо прямо все. Поступило требование для задних колес, менять надо руль.

S>Из чего это следует? Я же не паттерном Visitor буду обходить все детали и что-то с ними делать, а соотв. класс, который всей этой механикой и занимаетя.
S>Но этот класс живет где-то внутри модуля Car, он internal.
Я же вам показал примеры. Что именно в них непонятно?

S>Пожалуйста, это детали реализации. Я вовсе не против.

Это не "деталь реализации", это архитектура системы. Контракты абстракций.

S>Ну так с тз какого-нибудь ДДД, это отдельные домены с соотв. агг рутами. Почему при этом автомобиль не может ехать, и как ему мешает наличие договора купли-продажи мне

S>по-прежнему не ясно.
Очень просто: непонятно, кто из этих рутов будет принимать окончательное решение по поводу "ехать".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[46]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 11.02.26 08:40
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>>А откуда следует, что методы "Ехать влево" должны быть у всех? Это детали реализации, сокрытые внутри абстаркции.

S>Я же написал, откуда следует. Вы заранее не знаете, у кого они должны быть, а у кого — нет.

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

S>Получается, что ваша "абстракция" зависит от подробностей "реализации".


Каким образом?

S>>В каком-то из. А в чем проблема?

S>В том, что её придётся перекладывать из класса в класс по четыре раза в неделю. Я же вам привёл примеры.

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

S>>Я не могу понять, откуда следует, что при поступлении требования менять надо прямо все. Поступило требование для задних колес, менять надо руль.

S>>Из чего это следует? Я же не паттерном Visitor буду обходить все детали и что-то с ними делать, а соотв. класс, который всей этой механикой и занимаетя.
S>>Но этот класс живет где-то внутри модуля Car, он internal.
S>Я же вам показал примеры. Что именно в них непонятно?

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

S>>Пожалуйста, это детали реализации. Я вовсе не против.

S>Это не "деталь реализации", это архитектура системы. Контракты абстракций.

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

S>>Ну так с тз какого-нибудь ДДД, это отдельные домены с соотв. агг рутами. Почему при этом автомобиль не может ехать, и как ему мешает наличие договора купли-продажи мне

S>>по-прежнему не ясно.
S>Очень просто: непонятно, кто из этих рутов будет принимать окончательное решение по поводу "ехать".

Техническое за Car, может бензина нет или другая поломка. Во всех остальных случаях -- зависит от контекста. Может документов каких нету?
Кодом людям нужно помогать!
Re[47]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.26 09:46
Оценка:
Здравствуйте, Sharov, Вы писали:


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

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

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

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

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

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

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


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

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

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

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

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

Непонятно. Сущность не может быть свойством другой сущности.

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

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

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

Это не означает, что я обязан держать где-то столько строчек, сколько есть экземпляров однотипных товаров у меня на складе.
Вот например, я продаю кому-то 0.435 кг изюма. Что такое "обязательство"? Что тут будет "предметом, выделяемым из кучи однотипных"? 1380 изюминок?

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

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

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

Чего это вдруг? Запросто перемещу. Для этого мне достаточно оформить накладную на списание. И какое там "поведение" у этого товара мне наплевать — процесс списания регламентируется приказом по компании, и сегодня он один, завтра другой, а послезавтра он зависит от цвета шляпы. Бежать внедрять код логики списания внутрь класса, объектом которого является "красная шляпа" — это последнее, что стоит делать. Именно по этой причине.

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



M>К тому же, в современных системах не принято при выполнении доменной операции сразу бежать и что-то менять в хранилищах. Вместо этого операции накапливаются, а потом материализуются пачкой. Это могут транзакции в БД, CQRS,

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


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

Всё верно. Это означает, что подход, в котором "цена" является свойством "товара", непригоден. Даже если мы это свойство делаем вычисляемым. Сам товар не может знать, почём его продают — потому что ценообразование динамическое, и оно зависит и от товара, и от наличия этого товара на складе сейчас, и от покупателя и его предыстории, и от соседних товаров в том же заказе.
Никакая из этих "доменных сущностей" не подходит для размещения логики определения цены. Только какой-то внешний по отношению к этому домену "динамический ценообразователь", который, как правило, стейтлесс.
Вот он скорее всего будет построен по принципам ООП — там тебе и наследование, и полиморфизм, и агрегация, и паттерны Policy, и Factory Method и все лучшие наработки. А вот в "доменных сущностях" (в терминологии ER-модели) никакой логики не будет.

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


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


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


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

То, что вы используете общепринятые термины в необщепринятом смысле, только затрудняет коммуникацию.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[43]: Как внедряли DDD в Яндекс 360.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 12.02.26 00:29
Оценка:
Здравствуйте, Miroff, Вы писали:

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


Никогда не видел столько заблуждений в одной фразе.
Это же насколько надо не разбираться в:
— архитектуре ПО
— финансах
— маркетинге
— человеческой психологии
чтобы толкать такую чушь...
Re[44]: Как внедряли DDD в Яндекс 360.
От: Miroff Россия  
Дата: 12.02.26 01:54
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Никогда не видел столько заблуждений в одной фразе.

G>Это же насколько надо не разбираться в:
G>- архитектуре ПО
G>- финансах
G>- маркетинге
G>- человеческой психологии
G>чтобы толкать такую чушь...

Самшено слышать это от человека, у которого корзина обновляется транзакционно со складом
Re[44]: Как внедряли DDD в Яндекс 360.
От: Miroff Россия  
Дата: 12.02.26 03:25
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Непонятно. Сущность не может быть свойством другой сущности.


С чего бы? Колеса это свойство автомобиля в значении part of.

S>Этот объект совершенно точно не может быть отдельным. Потому что без сотрудника он невозможен, как и без отдела. Можно усложнять доменную модель, которую я предложил — например, так, как предложили вы.


Роль может существовать и без сотрудника и без отдела. Например, ТКРФ определяет роль "представитель профсоюза" необходимую для решения трудовых конфликтов. У тебя в компании может не быть ни профсоюза, ни сотрудников, но роль такая есть в силу закона. А из твоего утверждения следует, что раз в компании нет профсоюза, то и представителей профсоюза не бывает.

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


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


Именно это и означает. Вам даже государство прямым текстом говорит через честный знак: ребята, надо переходить на поединичный учет. Пора уже, ну сколько можно?

S>Вот например, я продаю кому-то 0.435 кг изюма. Что такое "обязательство"? Что тут будет "предметом, выделяемым из кучи однотипных"? 1380 изюминок?


Это на самом деле операция производства: из единицы хранения ящик изюма ты выделяешь 435г в упаковку и эта упаковка становится новой товарной единицей.

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

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

Именно! Если мы пересматриваем модель ценообразования, нам нужно глубоко анализировать домен, в котором эта цена вычисляется. Нас буквально ЗАСТАВЛЯЮТ отвечать на "неудобные" вопросы, вроде: из чего складывается цена? Каким образом она складывается? Различимы ли с точки зрения цены красная шляпа один, красная шляпа два и черная шляпа три? Должна ли история продаж лапсердаков влиять на цену красных шляп? Сама архитектура провоцирует глубокую аналитику и ресерч, а не просто копировать одни и те же таблички из проекта в проект.

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


Очень трудно говорить с человеком, который ментально застрял где-то в 2006 году)

Я рекомендую тебе попробовать сделать какой-нибудь проект на принципиально новом для тебя стеке, например на Scala c CATS/ZIO. Там у тебя будут нормальные функциональные монады, множественное наследование, частичное наследование, богатая система типов, частичные вычисления и богата система типов. Такой опыт сильно расширит твой архитектурный кругозор пониманием, что вовсе не обязательно ограничиваться двумя отношениями is_a и part_of.

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

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

2. Выделение сервисов происходит либо строго по границам доменных сущностей, что эквивалентно рич модели с точностью до положения методов. Либо сервисы выделяются произвольным образом безотносительно реального мира. Индикатором этого служат затруднения разработчиков в именовании сервисов случающиеся у разработчиков. Это как в философии, если ты не можешь что-то поименовать, то этого не существует. И даже если ты выделил сервис по акторам реального мира то со временем в эти сервисы просочатся нехарактерные для этих акторов методы просто потому что так удобнее. И в силу размытости ответственности сервисов из п1. разработчики легко натянут аргументацию почем именно этот метод должен быть именно в этом сервисе. Потому что на самом деле в какой из MiscService класть метод вообще не важно.

3. В силу п.2, иерархии сервисов не коррелируют с иерархиями доменной модели. Это приводит к тому, что сервисы изобилуют проверками сущностей, с которыми они взаимодействуют. Это еще один источник багов, прямо по Аллену. К тому же, это даже не ООП, а откат к процедурному программированию.
Re[45]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.02.26 06:55
Оценка:
Здравствуйте, Miroff, Вы писали:

M>С чего бы? Колеса это свойство автомобиля в значении part of.

По определению. Сущность — концепт предметной области, обладающий идентичностью и с независимым от других сущностей жизненным циклом.
В вашей метафоре колеса существуют совершенно отдельно от автомобиля — например, лежат на складе.
А когда мы их монтируем в автомобиль, то между автомобилем и колесом возникает связь "to be part of" / "to consist of".

M>Роль может существовать и без сотрудника и без отдела. Например, ТКРФ определяет роль "представитель профсоюза" необходимую для решения трудовых конфликтов.

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

M>Именно это и означает. Вам даже государство прямым текстом говорит через честный знак: ребята, надо переходить на поединичный учет. Пора уже, ну сколько можно?

Вы уже начали поединичный учёт зерён гречки и изюминок? Нет? Пора уже, ну сколько можно!

M>Это на самом деле операция производства: из единицы хранения ящик изюма ты выделяешь 435г в упаковку и эта упаковка становится новой товарной единицей.

Нет никакой упаковки, и никакой новой товарной единицы.
И чем "ящик изюма" так принципиально отличается от "ящика шляп" или "склада с цементом"?

M>Именно! Если мы пересматриваем модель ценообразования, нам нужно глубоко анализировать домен, в котором эта цена вычисляется. Нас буквально ЗАСТАВЛЯЮТ отвечать на "неудобные" вопросы, вроде: из чего складывается цена? Каким образом она складывается? Различимы ли с точки зрения цены красная шляпа один, красная шляпа два и черная шляпа три? Должна ли история продаж лапсердаков влиять на цену красных шляп? Сама архитектура провоцирует глубокую аналитику и ресерч, а не просто копировать одни и те же таблички из проекта в проект.

Всё верно. При этом DDD нам тут только мешает, т.к. требует вносить эту логику манипулирования сущностями внутрь самих этих сущностей.

M>Очень трудно говорить с человеком, который ментально застрял где-то в 2006 году)

Я с радостью выйду из 2006 года, если вы мне дадите ссылку на какую-нибудь литературу, которая систематически излагает "более новую" модель, которой вы оперируете.

M>Я рекомендую тебе попробовать сделать какой-нибудь проект на принципиально новом для тебя стеке, например на Scala c CATS/ZIO. Там у тебя будут нормальные функциональные монады, множественное наследование, частичное наследование, богатая система типов, частичные вычисления и богата система типов. Такой опыт сильно расширит твой архитектурный кругозор пониманием, что вовсе не обязательно ограничиваться двумя отношениями is_a и part_of.

Я придерживаюсь той точки зрения, что стек — вторичен. Первична именно архитектура. Не имеет никакого смысла изучать особенности какого-то конкретного фреймворка, не понимая первооснов.
Например, модель Чена, придуманная ажно в 1975 году, популярна как раз в силу своей агностики по отношению к выбранной технологии. Поэтому можно брать её за основу, а уже потом переходить от концептуальной модели к какой-нибудь логической — например, к реляционной, или объектной, или функциональной.
Кстати, функциональная модель обычно навязывает гораздо более качественную архитектуру, чем лобовое DDD. Потому что в ней манипуляции (функции) отделены от состояния (данных).
Когда мы применяем этот подход к проектированию бизнес-софта с использованием ООП, возникает т.н. "анемик модель", в которой объекты делятся на две несимметричные группы: "сущности", у которых нет поведения, и "обработчики", у которых нет состояния.

M>Я понимаю твою позицию, давайте сделаем анемичную модель и распихаем логику по сервисам. На практике это едва ли не худший подход, который можно себе представить Сервисная архитектура довольно быстро вырождается в уродливого неподдерживаемого монстра по нескольким причинам.

Причины хорошие, но они остаются, скажем так, абстрактными рассуждениями без реального кода.
Вот вы предложили скалу с каким-то фреймворком — ок, давайте рассмотрим, как выглядит в ней решение какой-нибудь типовой задачи. Да хоть с теми же заказами, товарами, покупателями, оплатами и отгрузками.
Эта задача хороша тем, что она подробно задокументирована, например — в спецификации тестов TPC-C.
Решение в стиле 90х для неё есть — там где адский SQL с его хранимками.
Как будет выглядеть её решение в каноническом DDD на Java мы тоже знаем (и понимаем, почему оно превращается в неподдерживаемого монстра, который работает в 100 раз медленнее, чем решение на устаревших технологиях).
Как будет выглядеть модное решение? Ну, хотя бы его фрагмент?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[45]: Как внедряли DDD в Яндекс 360.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 12.02.26 08:03
Оценка:
Здравствуйте, Miroff, Вы писали:

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


G>>Никогда не видел столько заблуждений в одной фразе.

G>>Это же насколько надо не разбираться в:
G>>- архитектуре ПО
G>>- финансах
G>>- маркетинге
G>>- человеческой психологии
G>>чтобы толкать такую чушь...

M>Самшено слышать это от человека, у которого корзина обновляется транзакционно со складом

А вы тоже можете (нет) привести пример кода как это сделать лучше?
Re[48]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 15.02.26 13:57
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

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

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


Почему всю-то сразу, добавляем новую реализацию соотв. интерфейса. Автомобиль грубо можно поделить на 3 части -- кузов, двигатель и шасси(ходовая).
Каждый является в свою очередь модулем, состоящим из более мелких деталей. Соотв. изменения будут только в этом соотв. модуле, могут
быть несколько реализаций колес, например. По отдельности собираем каждый модуль и передаем все в конструктор машины. Расширения будут,
но всегда локализовано.

Короче, если я вас правильно понял, то вы хотите, чтобы абстракция Car была максимально простой и буквально реализовывала метод "consist of",
а вся сложность за отдельные "виды деятельности" переехала бы в соотв. классы (кинематическая модель и т.п.), верно? Т.е. некоторые
абстракции, которые бы на вход получали только Car. Если так, то мне не нравится этот подход размазыванием логики по нескольким модулям.
Это, кмк, очень на процедурный стиль похоже. Я бы все-таки все эти детали прятал бы под абстракцией Car и добавлял бы в соотв. интерфейс
только необходимые высокоуровневые методы, типа move\drive. Да, была бы большая и сложная абстракция Car, зато все как-то локализовано и похоже
на моделируемый внешний мир.

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

S>Нет конечно. Нет такой абстракции "Car". Она тут совершенно не нужна. Есть "кинематическая схема", и она никакая не абстрактная, а совершенно конкретная. У неё нет никакого "поведения" в смысле ООП.

Ну как нет-то, если в реальном мире есть "Car", а в модели почему-то не нужен?

S>Если вам завтра надо будет решать задачу управления катером, а не автомобилем — вы что, будете с нуля писать новую абстракцию Boat?

S>А зачем? Чем эта абстракция будет отличаться от абстракции Car? Ладно, пусть там будет не Car/Boat, а абстракция Vehicle. Нужны ли будут для кинематики катера и автомобиля классы Boat:Vehicle и Car:Vehicle?

Средой движения будет отличаться, как минимум физикой движения и соотв. законами и параметрами. Общее, вроде двигателей, тоже будет.
Но как-то полиморфно работать и с машиной и с катером... ну такое.

S>Если да, то зачем?


Не глядя на код этой кинематики, трудно представить, чтобы она единообразно отвечала за движения и автомобиля и катера. Уж больно
они разные. Т.е. что-то такое можно сделать, но это будет нечто высокоуровневое и простое, а вся сложность уедет в соотв. реализацию
Vehicle. Собственно, я за такой подход и ратую. А нужно тогда будет отдельная кинематическая модель, если вся сложность будет
инкапсулирована в Vehicle, может в интерфейс Vehicle добавить методов и все?


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

S>Это не ответ. Сможем ли мы повторно использовать "абстракцию Car" во всех трёх доменах, или придётся всякий раз писать её заново?
S>Сможем ли мы реализовать в одном конкретном "классе SpecificCar" все три абстракции?

На сколько я понимаю ДДД + здравый смысл мне говорит, что нет, для каждого домена должны быть своя особенная Car. Для Car, которая умеет двигаться,
зачем ей уметь работать со всякими регистрациями и т.п.? Там сильно своя специфика. Т.е. должны быть 3 разных Car, но их инстансы должны шарить\иметь
какой-то общий id, чтобы можно было понять, что речь идет об одном и том же автомобиле, но в разных доменах.
Кодом людям нужно помогать!
Re[49]: Как внедряли DDD в Яндекс 360.
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.02.26 01:45
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Почему всю-то сразу, добавляем новую реализацию соотв. интерфейса.

Потому что в соотв. интерфейсе у вас исходно не было метода "ехать влево". Вы же полагали, что он нужен только рулю.

S>Автомобиль грубо можно поделить на 3 части -- кузов, двигатель и шасси(ходовая).

S>Каждый является в свою очередь модулем, состоящим из более мелких деталей. Соотв. изменения будут только в этом соотв. модуле, могут
S>быть несколько реализаций колес, например. По отдельности собираем каждый модуль и передаем все в конструктор машины. Расширения будут,
S>но всегда локализовано.
Смотрите, дело не в изменениях реализаций. Дело в том, что приходится вносить изменения в интерфейс, т.к. поведение не локализовано.
В итоге вы заканчиваете тем, что кузов, двигатель, и шасси реализуют ровно один и тот же интерфейс, в котором реализован полный набор всех методов, которые умеет делать автомобиль.

S>Короче, если я вас правильно понял, то вы хотите, чтобы абстракция Car была максимально простой и буквально реализовывала метод "consist of",

S>а вся сложность за отдельные "виды деятельности" переехала бы в соотв. классы (кинематическая модель и т.п.), верно?
Это не я хочу, это вам придётся так сделать. И в итоге продуктивнее окажется вообще отказаться от абстракции Car, потому что она ничем-ничем не отличается от абстракции Helicopter.
Более того, абстракция "Шасси" в вашем Car тоже реализует ровно тот же интерфейс, что и абстракции Helicopter и Car. Это интерфейс CompositeModel.

S>Т.е. некоторые абстракции, которые бы на вход получали только Car. Если так, то мне не нравится этот подход размазыванием логики по нескольким модулям.

Это у вас пока не наработана архитектурная интуиция. Не "размазывание", а концентрация. Tight cohesion, low coupling. Кинематическая логика сосредоточена в модуле кинематики, который никак не завязан на автомобильность.
Логика ценообразования — в модуле ценообразования, который опять никак не завязан на торговлю именно автомобилями.
При этом у нас нет смешивания логики кинематики (которая описывает физический мир, и потому неизменна) с логикой ценообразования (которая может меняться ежеквартально).

S>Это, кмк, очень на процедурный стиль похоже. Я бы все-таки все эти детали прятал бы под абстракцией Car и добавлял бы в соотв. интерфейс

S>только необходимые высокоуровневые методы, типа move\drive. Да, была бы большая и сложная абстракция Car, зато все как-то локализовано и похоже
S>на моделируемый внешний мир.
Ну потому что вас так воспитали дурацкие книжки. Вы усердно хотите написать большой, сложный, плохо поддерживаемый код, под тем предлогом, что он чем-то там похож на реальный мир.
Нет, в реальном мире всё работает не так, как в ООП.

S>Ну как нет-то, если в реальном мире есть "Car", а в модели почему-то не нужен?

Это иллюзия, а не Car. В реальном мире есть какое-нибудь "основное средство", в котором от автомобиля нет примерно никаких особенностей. Более того, поведение основных средств зависит не от этих средств, а от учётной политики.

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

S>они разные. Т.е. что-то такое можно сделать, но это будет нечто высокоуровневое и простое, а вся сложность уедет в соотв. реализацию
S>Vehicle. Собственно, я за такой подход и ратую. А нужно тогда будет отдельная кинематическая модель, если вся сложность будет
S>инкапсулирована в Vehicle, может в интерфейс Vehicle добавить методов и все?
Нет. Вся сложность будет реализована в движке расчёта физики. Потому что физика — она одна на всех.

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

S>зачем ей уметь работать со всякими регистрациями и т.п.? Там сильно своя специфика. Т.е. должны быть 3 разных Car, но их инстансы должны шарить\иметь
S>какой-то общий id, чтобы можно было понять, что речь идет об одном и том же автомобиле, но в разных доменах.
А то. И общее устройство — потому что если в одном из этих Car смонтирован двигатель, то и в двух других тот же двигатель.
Так мы и приходим к абстракции Car как plain data object.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[50]: Как внедряли DDD в Яндекс 360.
От: Sharov Россия  
Дата: 17.02.26 23:32
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>>Автомобиль грубо можно поделить на 3 части -- кузов, двигатель и шасси(ходовая).

S>>Каждый является в свою очередь модулем, состоящим из более мелких деталей. Соотв. изменения будут только в этом соотв. модуле, могут
S>>быть несколько реализаций колес, например. По отдельности собираем каждый модуль и передаем все в конструктор машины. Расширения будут,
S>>но всегда локализовано.
S>Смотрите, дело не в изменениях реализаций. Дело в том, что приходится вносить изменения в интерфейс, т.к. поведение не локализовано.
S>В итоге вы заканчиваете тем, что кузов, двигатель, и шасси реализуют ровно один и тот же интерфейс, в котором реализован полный набор всех методов, которые умеет делать автомобиль.

Почему? У меня три независимых модуля, которые взаимодействуют определенным образом. Да, надо добавить метод "ехать влево", но добавлен он будет
только верхнеуровневой абстракции (Car) и модулю ходовой. Кузов и двигатель тут не при делах. Все-таки какая-то функциональная изоляция должна быть.
Автомобиль "ехать влево" будет дергать только у ходовой.

S>>Короче, если я вас правильно понял, то вы хотите, чтобы абстракция Car была максимально простой и буквально реализовывала метод "consist of",

S>>а вся сложность за отдельные "виды деятельности" переехала бы в соотв. классы (кинематическая модель и т.п.), верно?
S>Это не я хочу, это вам придётся так сделать. И в итоге продуктивнее окажется вообще отказаться от абстракции Car, потому что она ничем-ничем не отличается от абстракции Helicopter.
S>Более того, абстракция "Шасси" в вашем Car тоже реализует ровно тот же интерфейс, что и абстракции Helicopter и Car. Это интерфейс CompositeModel.

У меня совершенно не было идеи использовать паттерн композит, хотя понятно, откуда откуда у двигателя может появиться метод "ехать влево".
Совершенно обычная агрегация автомобилем других классов, типа:
class Car
{
class carcase;
class engine;
class chassis
}

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


S>>Т.е. некоторые абстракции, которые бы на вход получали только Car. Если так, то мне не нравится этот подход размазыванием логики по нескольким модулям.

S>Это у вас пока не наработана архитектурная интуиция. Не "размазывание", а концентрация. Tight cohesion, low coupling. Кинематическая логика сосредоточена в модуле кинематики, который никак не завязан на автомобильность.

Это очень спорный факт, что на автомобильность не завязано. Потому как мне кажется, тут будет ровно наоборот -- low cohesion, high coupling.
Вместо того, чтобы все что связано с автомобилем максимально убрать в автомобиль, в том числе соотв. физ. модели. Это и будет high cohesion, low coupling.

S>Логика ценообразования — в модуле ценообразования, который опять никак не завязан на торговлю именно автомобилями.

S>При этом у нас нет смешивания логики кинематики (которая описывает физический мир, и потому неизменна) с логикой ценообразования (которая может меняться ежеквартально).

Ну да, а я и не предлагал тащить в ценообразование Car, туда надо тащить CarProxy какой-то.

S>>Это, кмк, очень на процедурный стиль похоже. Я бы все-таки все эти детали прятал бы под абстракцией Car и добавлял бы в соотв. интерфейс

S>>только необходимые высокоуровневые методы, типа move\drive. Да, была бы большая и сложная абстракция Car, зато все как-то локализовано и похоже
S>>на моделируемый внешний мир.
S>Ну потому что вас так воспитали дурацкие книжки. Вы усердно хотите написать большой, сложный, плохо поддерживаемый код, под тем предлогом, что он чем-то там похож на реальный мир.

Я хочу именно, как выше верно добавлено в дискуссию, "high cohesion, low coupling". Вот именно это. Надо было раньше об этом написать.

S>Нет, в реальном мире всё работает не так, как в ООП.


Мы решаем проблемы реального мира или ООП?

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

S>>они разные. Т.е. что-то такое можно сделать, но это будет нечто высокоуровневое и простое, а вся сложность уедет в соотв. реализацию
S>>Vehicle. Собственно, я за такой подход и ратую. А нужно тогда будет отдельная кинематическая модель, если вся сложность будет
S>>инкапсулирована в Vehicle, может в интерфейс Vehicle добавить методов и все?
S>Нет. Вся сложность будет реализована в движке расчёта физики. Потому что физика — она одна на всех.

Ну не верю я, что физика не будет учитывать особенности движения и строения вертолета и машины или лодки. Это совершенно разные физ. области(домены).

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

S>>зачем ей уметь работать со всякими регистрациями и т.п.? Там сильно своя специфика. Т.е. должны быть 3 разных Car, но их инстансы должны шарить\иметь
S>>какой-то общий id, чтобы можно было понять, что речь идет об одном и том же автомобиле, но в разных доменах.
S>А то. И общее устройство — потому что если в одном из этих Car смонтирован двигатель, то и в двух других тот же двигатель.
S>Так мы и приходим к абстракции Car как plain data object.

Я не согласен. У нас есть модель физ. автомобиля и его прокси для соотв. доменов. Они шарят что-то общее, чтобы понять, что речь о конкретном автомобиле,
но не более.
Кодом людям нужно помогать!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.