У меня есть агрегат с корневым объектом (Документация) и VO (Документ). Документы связаны с файлами (pdf, изображения, офисные документы и т. д.), поэтому мне приходится сохранять совокупность в базе данных и файлы на ftp-сервере (файлы не могут быть сохранены в базе данных, поскольку объем файлов слишком велик). Мой класс репозитория db реализует интерфейс с такими методами, как FindXXX, AddDocument, RemoveDocument и другими. Как я могу реализовать постоянство ftp? Должен ли мой репозиторий db подключаться к ftp setver в AddDocument и RemoveDocument? Или я должен создать класс репозитория ftp, который реализует интерфейс. Если это так, то методы вроде FindXXX не имеют смысла. Насколько я знаю о DDD, у каждого агрегата есть только один репозиторий интерфейса, который представляет, как можно сохранять. Он может иметь несколько «режимов сохранения» (в базе данных, ftp, файле и т. д.), но интерфейс должен быть одинаковым.
Различные репозитории сохраняемости для агрегата в DDD
Ответы (2)
Насколько я знаю о DDD, у каждого агрегата есть только один репозиторий интерфейса, который представляет, как можно сохранять.
В основном это правда; люди обычно предполагают, что весь агрегат будет храниться в одном месте. Когда вы распределяете состояние агрегата по нескольким единицам хранения, режимы отказа требуют особого внимания.
Итак, нужно учитывать, являются ли отдельно хранящиеся документы чем-то, что является частью агрегата, или чем-то, на что агрегат ссылается.
Если агрегат ссылается на них, то вы рассматриваете их как любую другую ссылку на другой агрегат. Агрегат документации хранит идентификатор/ссылку/подсказку для документа и использует службу домена для доступа к документу, если он ему нужен.
Если они являются частью совокупности, то обычным ответом будет то, что "репозиторий" будет фасадом перед сложной инфраструктурой, которая маскирует тот факт, что документация и документ(ы) хранятся отдельно.
Другими словами, уровень инфраструктуры будет пытаться организовать операции загрузки и сохранения, а остальной части системы не нужно знать подробности.
Поздний ответ. Но, проще говоря, у вас должно быть два сервиса. В моем понимании DDD репозитории часто рассматриваются как службы инфраструктуры. В этом случае у вас есть два:
- Репозиторий/интерфейс для хранения и базового поиска идентификаторов документов, метаданных и ссылок.
- Репозиторий/интерфейс для хранения и базового поиска больших двоичных объектов данных.
Иногда имеет смысл иметь несколько агрегатов и репозиториев. Фактически, некоторые примеры Вона Вернона в ограниченных контекстах (https://github.com/VaughnVernon/IDDD_Samples) включать агрегаты, содержащие ссылки на другие агрегаты. Я бы сказал, что вы должны делать то, что имеет смысл и кажется уместным.
Действительно, если вы управляете центром сбора почтовых отправлений, скорее всего, у вас будет способ 1. хранить посылки от маленьких до больших и 2. составлять указатель того, где в центре находятся все посылки от маленьких до больших, чтобы вы может получить его.
Мой класс репозитория db реализует интерфейс с такими методами, как FindXXX, AddDocument, RemoveDocument и другими. Как я могу реализовать постоянство ftp? Должен ли мой репозиторий db подключаться к ftp setver в AddDocument и RemoveDocument? Или я должен создать класс репозитория ftp, который реализует интерфейс.
Если ваш репозиторий базы данных подключается к FTP в дополнение к какому-либо другому хранилищу данных, возможно, вы возлагаете слишком много логики и ответственности на одну область. Тем не менее, в этом тоже нет ничего плохого.
Если это так, то методы вроде FindXXX не имеют смысла. Насколько я знаю о DDD, у каждого агрегата есть только один репозиторий интерфейса, который представляет, как можно сохранять.
Для этой конкретной проблемы большинство практиков DDD порекомендуют вам иметь отдельную службу/модель представления. Он может создавать материализованный/представленный DTO для репозиториев или сервисов.
По сути, должно быть легко тестировать отдельные части и заменять базовые реализации. Если вы однажды решили переключиться (или даже включить поддержку) с FTP на Google Cloud Storage / AWS S3, то может потребоваться дополнительная работа и изменения в тестовых примерах.