Я понимаю, что мы не должны напрямую изменять дочерние узлы агрегатного корня, но вместо этого они должны выполняться с помощью методов в агрегатном корне.Например, order.SetOrderLineQty(product, qty);
Но что, если дочерние элементы совокупного корня являются чем-то абстрактным?Представьте, что у вас есть корень агрегата Car, который содержит список IWheel как части агрегата.Как бы вы добавили / изменили свойства колеса через его агрегатный корень (кто ничего не знает о том, каким конкретным типом колеса они могут быть)?
Более реальный пример этого: врач может создатьMedicalRerport (агрегатный корень), который содержит список IMedicalNote (как часть агрегата MedicalReport).IMedicalNote - это базовый класс / интерфейс, который подразделяется на несколько конкретных подклассов, например BloodCheckNote, TemperatureNote, MineralConcentrationNote и т. Д. И т. Д.
Каждый подкласс имеет разные свойства, и все они доступны для редактирования.Агрегат MedicalReport может содержать одну или несколько таких заметок.(У каждого подкласса примечаний есть определенный пользовательский элемент управления, позволяющий пользователю вводить / обновлять детали, отображаемые в виде панелей / вкладок под большим экраном MedicalReport)
У меня вопрос, как я могу добавлять / редактировать свойстваэти примечания строго через его совокупный корень (MedicalReport)?Поскольку мне не разрешено изменять эти свойства заметок напрямую, уродливым вариантом является раскрытие всех возможных свойств заметок в совокупном корне (MedicalReport), а именно:
report.SetWhiteBloodCellCount(cellCount);
report.SetBloodCheckComment(comment);
report.SetTemperature(bodyPart, temperature);
report.AddMineral(mineral, concentration);
Каждый из этих методов будет обновляться (или создаватьnew) отметить элементы в своей внутренней дочерней коллекции.С этим есть 2 очевидные проблемы:
- Мы должны заранее определить все доступные свойства всех возможных подклассов IMedicalNote в агрегатном корне.Это неприемлемо, так как количество подклассов гарантированно возрастет, зависит от типа медицинских данных, которые мы хотим получить, что является главной точкой наследования.
- Может быть несколько экземпляровтого же типа заметки в списке.Этот API не будет работать, так как мы не можем просто сказать
report.SetBloodCheckComment(comment)
и ожидать, что он обновит элемент BloodCheckNote в списке, потому что мы разрешаем более одного элемента BloodCheckNote в списке.
Я все ещехотите поддерживать все взаимодействия с этими заметками через свой агрегатный корень, так как он должен контролировать, является ли совокупный агрегат MedicalReport действительным для сохранения, является ли агрегат не поддающимся изменению, грубой проверкой оптимистического параллелизма и т. д. Но как это сделать?Я так делаю?