Сервисов может быть 100500 и у сервиса по 100500 методов. Если каждый позволяет себе писать в свойства объекта, то инварианты придется собирать по всей системе, а также будет тяжело гарантировать их сохранность.
Если сервис А пишет в свойства X и Y, а сервис B в свойства Y и Z, то если существует правило для свойств X и Z, вы рискуете его нарушить. На практике ещё хуже, сначала правила нет, а потом вдруг нарисовывается. Заниматься поиском всех мест, где оно вовлечено, занятие неблагодарное.
Иными словами, свойства сущности сильно связанные штуки, и потому дистанция до кода, их меняющего, должна быть минимальна.
Глагол to link используют продакты. Ограничение в виде одноразовости проистекает из описания процесса. В требованиях нет кейсов на изменение или сброс ссылки. Если такие требования появятся, будет и соответствующее изменение в коде.
Так никто ж не предлагает вообще все в класс тащить. Для этого и существуют доменные события, доменные сервисы и сервисы уровня приложения.
Я скорее про случаи когда бизнес объект вырождается в DTO с кучей мутабельных свойств типа int или string. И совершенно неочевидно, как эти свойства эволюционируют и взаимодействуют меж собой.
Чисто из недавнего пример:
Нужно сохранить номер заказа во внешней системе, разработчик влепил:
public string? OrderReference {get; set;}
Но можно чуть иначе:
public string? OrderReference {get; private set;}
public Result LinkOnceToOrder(string orderReference)
{
if (OrderReference is not null && orderReference != OrderReference)
{
return Failure();
}
...
}
Кода больше, факт, но и ясности, на мой взгляд, добавляется. Свойство напрямую поменять нельзя. Линкануть можно единожды, анлинкануть вообще нельзя.
В принципе, можно и для OrderReference, при необходимости, свой тип определить или, если поведение сущности меняется, разбить тип самой сущности на два: Xyz и LinkedXyz (имена условные).
Сложность же не только в требованиях, но и в и том, где они находятся. Event storming обычно проводят для формирования целостного представления о системе путем выковыривания священного знания из людских голов.
Если код не является хорошей моделью релевантных бизнес понятий и процессов, то часто приходится разбираться к кому идти с вопросами, а потом организовывать общение по теме. Vernon это называет tacit knowledge.
Отношусь к DDD как к методу обменять бизнесовую сложность на техническую.
Предпочту отразить в коде и сделать более явными бизнес-требования, даже если код становится чуть сложнее для привыкших к процедурному стилю с анемичными моделями. На практике это практически всегда себя оправдывает, потому как при эволюции системы первое на порядки важнее. Глядеть в "простой" код, зная, что он делает, без понимания "почему" и каковы ограничения — боль.
Самый сложный тактический паттерн — агрегат. Выбрать правильные границы с первого захода очень непросто. Да и ORM'ы, к сожалению, далеко не всегда способны в маппинг по-настоящему, когда объекты не являются копиями плоских таблиц в памяти.
А почему нет? Jit может очень агрессивно оптимизировать, а с nTier ещё и с использованием эвристик. Аллокация памяти тоже быстрее, чем в С++, а если memory traffic per request маленький и во 2е поколение мало что попадает, то даже накладные расходы на GC могут быть не ужас-ужас. В общем допускаю, что можно подобрать сценарий, когда будет быстрее.
Вот как раз хотел сказать, что если смотреть исключительно на американские компании с офисами в Амстердаме, то такая медиана может нарисоваться, но вообще они априори сильно выше рынка дают.
https://stackoverflow.com/a/78050832/921054
Разница лишь в warning'ах
Самая большая сложность "продать" подход бизнесу. :'-(
Забыли упомянуть важный момент: subdomain discovery (problem space) vs bounded context design (solution space).
Сервисов может быть 100500 и у сервиса по 100500 методов. Если каждый позволяет себе писать в свойства объекта, то инварианты придется собирать по всей системе, а также будет тяжело гарантировать их сохранность.
Если сервис А пишет в свойства X и Y, а сервис B в свойства Y и Z, то если существует правило для свойств X и Z, вы рискуете его нарушить. На практике ещё хуже, сначала правила нет, а потом вдруг нарисовывается. Заниматься поиском всех мест, где оно вовлечено, занятие неблагодарное.
Иными словами, свойства сущности сильно связанные штуки, и потому дистанция до кода, их меняющего, должна быть минимальна.
Глагол to link используют продакты. Ограничение в виде одноразовости проистекает из описания процесса. В требованиях нет кейсов на изменение или сброс ссылки. Если такие требования появятся, будет и соответствующее изменение в коде.
Так никто ж не предлагает вообще все в класс тащить. Для этого и существуют доменные события, доменные сервисы и сервисы уровня приложения.
Я скорее про случаи когда бизнес объект вырождается в DTO с кучей мутабельных свойств типа int или string. И совершенно неочевидно, как эти свойства эволюционируют и взаимодействуют меж собой.
Чисто из недавнего пример:
Нужно сохранить номер заказа во внешней системе, разработчик влепил:
Но можно чуть иначе:
Кода больше, факт, но и ясности, на мой взгляд, добавляется. Свойство напрямую поменять нельзя. Линкануть можно единожды, анлинкануть вообще нельзя.
В принципе, можно и для OrderReference, при необходимости, свой тип определить или, если поведение сущности меняется, разбить тип самой сущности на два: Xyz и LinkedXyz (имена условные).
Сложность же не только в требованиях, но и в и том, где они находятся. Event storming обычно проводят для формирования целостного представления о системе путем выковыривания священного знания из людских голов.
Если код не является хорошей моделью релевантных бизнес понятий и процессов, то часто приходится разбираться к кому идти с вопросами, а потом организовывать общение по теме. Vernon это называет tacit knowledge.
FP нормально обходится без rich объектов, но там обычно получше с системами типов. https://pragprog.com/titles/swdddf/domain-modeling-made-functional/
Отношусь к DDD как к методу обменять бизнесовую сложность на техническую.
Предпочту отразить в коде и сделать более явными бизнес-требования, даже если код становится чуть сложнее для привыкших к процедурному стилю с анемичными моделями. На практике это практически всегда себя оправдывает, потому как при эволюции системы первое на порядки важнее. Глядеть в "простой" код, зная, что он делает, без понимания "почему" и каковы ограничения — боль.
Самый сложный тактический паттерн — агрегат. Выбрать правильные границы с первого захода очень непросто. Да и ORM'ы, к сожалению, далеко не всегда способны в маппинг по-настоящему, когда объекты не являются копиями плоских таблиц в памяти.
При чем тут F#, если претензия была к AOT в .NET
Почему, он же развернуто объяснил, чем не подошёл .NET в их случае.
Можно добавить ещё вариант HTTP1.1+protobuf formatter
А почему нет? Jit может очень агрессивно оптимизировать, а с nTier ещё и с использованием эвристик. Аллокация памяти тоже быстрее, чем в С++, а если memory traffic per request маленький и во 2е поколение мало что попадает, то даже накладные расходы на GC могут быть не ужас-ужас. В общем допускаю, что можно подобрать сценарий, когда будет быстрее.
Вот как раз хотел сказать, что если смотреть исключительно на американские компании с офисами в Амстердаме, то такая медиана может нарисоваться, но вообще они априори сильно выше рынка дают.
Это в Нидерландах-то 108к медиана?! А что за источник таких цифр у вас?