Я понимаю, что мы не должны напрямую изменять дочерние элементы агрегатного корня, но вместо этого они должны выполняться с помощью методов в агрегированном корне. . order.SetOrderLineQty(product, qty);
Доступ к субъектам с подклассами
Но что, если дети совокупного корня являются чем-то абстрактным? Представьте, что у вас есть корень агрегата автомобиля, который содержит список IWheel как часть совокупности. Как бы вы добавили/изменили свойства колеса через его совокупный корень (который ничего не знает о том, каков конкретный тип колеса, которым они могли бы быть)?
Более реальный пример мира: Врач может создать MedicalRerport (aggregate-root), который содержит список IMedicalNote (как часть агрегата MedicalReport). IMedicalNote - это базовый класс/интерфейс, который подклассифицирован в несколько конкретных подклассов, например. BloodCheckNote, TemperatureNote, MineralConcentrationNote и т. Д.
Каждый подкласс имеет разные свойства, и все они доступны для редактирования. Агрегат MedicalReport может содержать одну или несколько из этих заметок. (Каждый подкласс примечаний имеет конкретное пользовательское управление для пользователя, чтобы вводить/обновлять детали, отображаемые в виде панелей/вкладок под большим экраном MedicalReport)
Мой вопрос в том, как добавить/отредактировать свойства этих Примечания строго через его совокупный корень (MedicalReport)? Так как я не разрешается изменять эти заметки свойства непосредственно, один уродливый вариант, подвергая все возможные свойства ноты на агрегированном корня (MedicalReport), то есть:
report.SetWhiteBloodCellCount(cellCount);
report.SetBloodCheckComment(comment);
report.SetTemperature(bodyPart, temperature);
report.AddMineral(mineral, concentration);
Каждый из этих методов будет обновляться (или создать новый) обратите внимание на элементы внутренней коллекции детей. У нас есть две очевидные проблемы:
- Мы должны определить все доступные свойства всех возможных подклассов IMedicalNote в агрегированном корне. Это неприемлемо, так как количество подклассов гарантировано растет, зависит от типа медицинских данных, которые мы хотим захватить, что является целым наследованием на первом месте.
- В списке может быть несколько экземпляров одного и того же типа заметок. Этот API не удастся, так как мы не можем просто сказать
report.SetBloodCheckComment(comment)
и ожидать, что он обновит элемент BloodCheckNote в списке, потому что мы разрешаем использовать более одного объекта BloodCheckNote в списке.
Я все еще хочу, чтобы сохранить все взаимодействия в эти заметки через его совокупный корень, так как он должен контролировать, является ли быть сохранена вся совокупность MedicalReport, будь то агрегат не изменяемый, крупнозернистый optimistic- проверка параллелизма и т. д. Но как я могу это сделать?
Я понимаю, что вы можете получить внутренний объект (IMedicalNote), но только для цели только для чтения. Вы не должны делать никаких изменений. Все изменения должны быть сделаны через корень, чтобы он мог контролировать целостность. Кроме того, что вы подразумеваете, передавая его обратно в корень? Как только мы модифицируем свойство дочернего элемента извне, то это все, оно изменено (по ссылке), минуя корень, не так ли? Что делает «переход к корню» точно? – Sheepy
Извинения, ответ несколько неоднозначный. Корень передает обратно копии объектов, которые клиент затем обновляет и передает обратно root. Корень затем отвечает за проверку инвариантов и установление отношений. Обеспечивает разумное разделение ответственности: корень знает о связях и ограничениях между агрегированными объектами, но не нуждается в подробностях всех подтипов. Клиенты могут работать по определенным подтипам по мере необходимости. Примечание. Корневой элемент, возможно, должен знать некоторые сведения о подтипе (например, если он должен содержать только один «BloodCheckNote», но может иметь много «TemperatureNote's»). – sfinnie
Вы хотите создать механизм клонирования, чтобы корень всегда возвращал клон каждой дочерней заметки при доступе через публичный getter root? И затем способ скопировать эти значения обратно в его фактический объект, как только клиент вернет эти дети обратно в корень. Просто хотел прояснить, понимал ли это то, что вы имели в виду, потому что это звучит довольно много. Cheers – Sheepy