Обновить
4

Пользователь

0,1
Рейтинг
Отправить сообщение

А откуда в данном процессе возьмётся агрегат User, если User ещё не создан?

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

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

Почему же ваш услужливый оператор работает сразу в двух агрегатах ("создаёт учётную запись" и "отмечает номер учётной записи в своей табличке с приглашениями")? Кто такой этот "оператор" в программном коде?

Ну и в чём тогда выигрыш. Вот мы разложили всё по "сервисам" - переиспользуемую бизнес-логику и "use-case'ы" - конкретные бизнес-сценарий. У нас система развивается и "конкретный бизнес-сценарий" превратился в "переиспользуемую бизнес-логику". Так что границы между этими понятиями, которые мы для себя нарисовали, оказались весьма условны.

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

Ну и как сохранять то, без ChangeTracker? Хочу услышать ответ. Написать свой ChangeTracker вместо ORM?

Так очевидно же. Как выглядит типичный код с применением DDD?

var request = repository.GetRequest(requestId);
request.Approve(userId);
repository.SaveChanges();

Ну и как вы в данном случае реализуете репозиторий без ORM? ChangeTracker в рукопашку забабахаете?

Ну и сами "доменные модели". Я застал ещё время, когда вся эта доменка представляла собой набор свойств с {get; set}и конструктором по умолчанию. Потому что EF (без Core) ничего сложнее мапить не умел. Сейчас EF многому научился, но уши персистентности из моделей всё равно там и тут торчат. Вот и получается, что проектирование _моделей_, самого сердца DDD, прочно связано с возможностями ORM.

Подпишусь под многим. Правда, тут не в ASP.NET и не в EF дело. И даже не в DDD, а в IT-евангелизме как таковом.

Все озвученные вами проблемы - они и на других платформах и с другими инструментами будут проявляться при внедрении хардкорного тру-DDD подхода. А вот если без хардкора, а просто взять без фанатизма предлагаемый DDD способ _переиспользования_кода_ (через модели), то и с DDD можно жить.

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

Вот у меня есть сценарий - принятие пользователем приглашения о присоединении к системе.

Пользователь проходит по ссылке-приглашению, в результате запись из таблички invitations удаляется, а запись в табличку users добавляется. Кто тут кому root aggregate и как через DDD должны быть организованы события, чтобы всё это дело не рассыпалось? Как это сделать без DDD я и так знаю.

>Мне казалось, что DDD без ORM не живут.

Вот это интересный момент, конечно. Один мой коллега-дотнетчик, когда его отправили учить жизни php-шников, в разговоре с их начальником проронил такую фразу: "ну, я не знаю, есть у вас ORM или нет". От этого по его мнению зависело, можно на их проекте внедрить DDD или нельзя.

И тут корень противоречия. DDD на "философском уровне" про "Tackling Complexity in the Heart of Software" и про полное абстрагирование от способов хранения. А на практике - "если у вас нет ORM, то нет DDD". И ведь действительно очень сложно реализовать стандартные DDD-паттерны проектирования без ORM, если у вас не документоориентированная база данных.

1. Вот был у меня UseCase - создание приглашения о присоединении к системе для пользователя (в табличку запись добавляется, пользователю письмо улетает).
Потом появился новый сценарий - принятие запроса на временное присоединение к пространству пользователя специалиста поддержки, в который так же входит отправка приглашения пользователю (в табличку запись добавляется, пользователю письмо улетает). Теперь мой первый UseCase - уже не UseCase, если это часть другого UseCase? Что мне делать с "последовательностью управляющих конструкций"? Продублировать в двух UseCase'ах? Вынести код из первого UseCase в разделяемый сервис/модель? Вызвать один UseCase из другого?

2. Если сервисы делать маленькими, то это уже UseCase'ы?

Мне из статьи больше идея фича-лида понравилась. Один человек должен прорабатывать требования к фиче, нарезать задачи и принимать MR'ы. Когда во всей команде занимается этим один человек (тим-лид), то на него приходится очень большая нагрузка. Когда фичей никто выделенно не занимается, тогда и планирование превращается в лотерею, и "чужие" MR воспринимаются просто как внешний раздражающий фактор. Да и код-ревью задачи, в которую ты не погружён, вырождается в "скобочки не так расставил".

>По факту ребятам нужно было время, чтобы вникнуть в задачу и понять, как её реализовать, а потом уже разрабатывать.

Но, как обычно, на планировании все видят задачу первый раз, в постановке никто не разбирался, поэтому метают кости играя в "покер"?

Ну, хэш очевидный воркэраунд, если забыть о коллизиях.
Коллизии, кстати, более вероятны, если использовать в качестве ключа блокировки int id из какого-нибудь последовательно растущего sequence. Можно договариваться о диапазонах, конечно (используя первый параметр int, например), но всё это... неудобно.

С pg_advisory_lock для меня основное ограничение в том, что она только bigint принимает (8 байт). Произвольную строку в качестве ключа тут использовать не получится, guid использовать не получится... RedLock поэтому оказывается удобней.

Сергея Теплякова в списке категорически приветствую. Со своим самым долгоиграющим багом я когда-то справился благодаря тому, что вспомнил когда-то написанную им статью.

The danger of TaskCompletionSource
https://devblogs.microsoft.com/premier-developer/the-danger-of-taskcompletionsourcet-class/

Я бы тоже для начинающего посоветовал Албахари, а не любимого Рихтера.

Плюсанусь. Для Getting started может и пойдёт, но Osherove для меня сейчас книга про то, как не надо писать тесты, а Хориков - про то, как надо. Это у Osherove, кажется, был совет делать все методы класса виртуальными, чтобы их всегда можно было замокать.

Без тестов - завернуть, а с хорошими тестами можно попробовать. В библиотечном коде такие вещи более оправданы.

Информация

В рейтинге
4 738-й
Зарегистрирован
Активность