Pull to refresh
18
0
Андрей @chizh_andrey

Технический директор

Send message

Я не слышал, что есть такой тренд, подскажите, что они перевели.

Действительно есть сходство с MediatR и CQRS, но, на мой взгляд, есть и ряд значимых отличия.

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

Что если можно сделать по другому. Что если можно сделать функцию-объект-сервис "ВыкопатьЗемлюмыЭкскаватором(ЭксковаторИД, ЗемляИД)" и это функция гарантированно изменит состояние всех агрегатов валидно.

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

Зачем нам вообще нужно это ООП для этой задачи?

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

Если выражаться вашими словами, то я действительно говорю об антииООП.

Вы считаете что инстанцирование классов как-то заметно сказывается на потребление ресурсов?

Расскажите пожалуйста, когда синглтон это отличное решение.

Вы правы, отсюда огромная путаница между DDD и ООП, как будто одно должно быть выражено в другом. Я делаю скидку автору, книга была выпущенна в 2007 года, уже почти 20 лет прошло, а писалась наверное еще раньше. В те года "клиенты" были толстые, БД медленные(из за дисков), о stateless подходе мало кто говорил, а парадигма ООП казалась ответом на все вопросы, поэтому автор так много уделил ей внимание.

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

Наверное уже пораньше, 15 лет назад, был очередной виток споров между функциональщиками и инперативщиками. Процедурщики и ООПки, наверное, спорили 30 лет назад, в 80х ) когда C++ вынужден был делать zero cost of abstraction.

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

Наследование вообще спорная вещь, все меньше вижу ему применение(речь не про интерфейсы как контракты). Тем более, когда мы все ближе к миру с discriminated union и exhaustive pattern matching, где у наследования еще меньше причин.

Что такое настоящий динамический объект?

Мы эту папочку с функциями-классами упаковываем в сервис, и только этот сервис знает пароль от БД где лежит состояние агрегатов этого домена. Считаем что все методы этого сервиса(api) обязаны менять состояние агрегата валидно и должны быть затестированы - ~100% покрытие тестами.

Пока только такие способы нашил.

Кстати! Невозможность передавать в MVC контроллер зависимости явно - это боль. Навязанный DI, какая-то жуткая ошибка. Я вот тут поразмышлял об этом https://habr.com/ru/company/retailrocket/blog/512222/

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

Плюсы которые я могу выделить в моем подходе:

1) Для тестирование отдельного метода, не требуется создавать сложный объект со всеми зависимостями;

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

Я вот на этот тезис из книги опираюсь.

Мне кажется, что в тезисе "Одним из посылов[ООП(я добавил)] было соблюдение инвариантов класса." и кроется наше с вами различие взглядов, мне кажется, это ошибочный тезис, тем более если речь идет об сущностях из DDD. ООП, похоже, было про алгебраические типы, вроде int, double, которые между собой независимы и состояние у них крайне ограниченно, если это вообще моно назвать состоянием.

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

"Строить систему на триггерах и хранимках" -- мне казалось, подход, который я предлагаю, прямо противоположный. Все методы изменения состояния явно описаны в коде, независимы друг от друга, да еще и отделены от слоя доступа к данным(data layer). Требуется явный и прямой вызов "функции" изменения состояния, который не удасться скрыть.

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

Подскажите, а как у вас проверяется инвариант.

Статьей я хотел намекнуть, что у DogsService просматриваются проблемы с SRP т.к. сервис имеет все зависимости, которые требуются для поддержания инварианта по всем методам изменения состояния собаки. Везде где разработчики взаимодействуют с "собакой", даже по самым простым методам вроде получения года рождения, будет необходимо знать о всей сложности такого сервиса -- о всех зависимостях. Явно это проблема заметна в тестах, где для проверки простого кейса, вроде вычисления возраста собаки, придется инициализировать объект-сервис непропорциональной кейсу сложности.

Ниже в комментариях так же описали еще две проблемы таких сервисов как DogService:

1) со временем сервисы склонным превращаться в god-object
2) если есть задача в одной транзакции и собаку в будку прописать и кол-во жильцов в будке увеличить, то в каком сервисе(сервис собаки или будки) должен лежать такой метод прописки собаки?

В статье я предлагаю распилить сервис на отдельные функции, сложить их в папку с именем DogsService и там где требуется использовать конкретную "функцию-класс". А те функции, которые меняют состояние двух агрегатов вынести отдельно в папку "Services".

Подскажите, где вам кажется нарушается принцип DRY?

Я могу прислать скан страницы из книги, если вы не верите мне на слово. Нам удается в большом проекте успешно применять DDD, на большом кол-ве сущностей.

Думаю что проблема не в книге Эванса, а в том что "мы"(программисты) пишем "Земля.Копайся()" в книге он не настаивает(не призывает) на к такому подходу, а явно говорит, что его книга не про тактику реализации на конкретной парадигме, а про подход проектирования.

Мне было бы интересно, если бы вы сказали решает ли подход, описанный в коментарии выше, проблемы которые вы упомянули.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity