Как вы моделируете операцию сохранения изображения с использованием DDD? - PullRequest
0 голосов
/ 05 июня 2018

По сути, пользователь хочет изменить изображение своего профиля.Веб-сервер получает опубликованное изображение со значением /user/35435/profile/picture, поэтому данные должны быть сохранены, а свойство LastModification объекта профиля обновлено.

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

В настоящий момент каждая операция представлена ​​либо командой, либо запросом.Команды выполняются в окружающей транзакции (например, транзакция SQL).Операция загрузки изображения не является транзакционной, но в случае ошибки может быть выполнено компенсирующее действие (т. Е. Удаление изображения в случае сбоя операции БД).

В простой реализации - команда, содержащая как текущую дату, так иданные изображения созданы.Обработчик команды выполняется, он загружает агрегат ProfileAggregate, и ProfileAggregate.updateProfilePicture(imageUploader, image, currentDate) выполняется, передавая службу домена imageUploader в качестве параметра.Внутри метода изображение загружается, а профиль обновляется.Обработчик команд сохраняет изменения в БД и возвращает.

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

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

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Главный вопрос, который поможет вам, - что делать системе, когда изображение не может быть загружено.Я думаю, что ответ заключается в том, что вы хотите, чтобы пользователь получил сообщение об ошибке, и система (профиль) должна остаться без изменений.

С точки зрения домена, фактический процесс загрузки / сохранения изображения не имеет значения.Это действие фактически является частью инфраструктуры и должно быть организовано прикладным уровнем до того, как команда будет отправлена ​​на уровень домена (в агрегат профиля).Таким образом, если загрузка не удалась по какой-либо причине, команда не будет отправлена.

Загрузка изображения может выполняться синхронно или асинхронно;это зависит от вашей платформы / языка программирования / и т.д., и это не имеет значения.Дело в том, что вы отправляете команду в агрегат только после успешной загрузки изображения.Команда должна включать ImageStorageId и, возможно, некоторые метаданные (например, имя файла, размер файла, размер изображения и т. Д.).

0 голосов
/ 05 июня 2018

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

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

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

Здесь я предлагаю следующий подход:

  • Агрегат Профиль должен отвечать за принятие изображения.Таким образом, его операция updateProfilePicture будет просто оценивать метаданные изображения (возможно, у вас есть правило, что изображение должно иметь определенный размер или проверяться по какому-либо алгоритму, чтобы попытаться найти обнаженное тело, такого рода вещи) ивнутреннее состояние целевого объекта Профиль , чтобы разрешить выполнение действия и обновить его внутреннее состояние с помощью свойства lastUpdated или чего-либо еще.

  • The ImageUploadService предоставит вам автономную функциональность для получения изображения и его хранения соответствующим образом.

  • Обе эти операции будут выполняться независимо и в конечном итоге будут согласованы посредством обмена сообщениями.

Таким образом, ваш обработчик команд будет:

  • Загрузить Профиль Сводный
  • Вызвать updateProfilePicture (который будет прерван при достижении недопустимого состояния).Здесь вы можете оставить агрегат Profile в состоянии PendingUpload (если вы хотите использовать пессимистический подход к загрузке) или просто предположить, что загрузка обычно завершится успешно (с оптимистическим подходом) и получить компенсациюизмеряет, когда происходит сбой.
  • Вызывает ImageUploadService напрямую и асинхронно (запускать и забывать)
  • Фиксация изменений в Профиль после загрузкиway

Когда ImageUploadService завершит получение изображения, оно отправит сообщение в домен профиля, сообщающее об успешном / неудачном завершении загрузки.Тогда:

  • Если бы вы выбрали пессимистический подход, Успех вывел бы агрегат Профиль из состояния ожидания.
  • Если вы выбрали оптимистический подход,В случае успеха обработка не требуется.
  • В любом случае сбой загрузки должен быть обработан путем отката агрегата Profile до состояния обновления изображения до обновления.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...