簡體   English   中英

具有嵌套實體的 DDD 根聚合

[英]DDD Root Aggregate with nested entities

設想

| 警告:我省略了部分代碼以提高可讀性(即公共/私有設置器等)

我有:


class Configuration : RootAggregate
{
     public string code;

     // other fields

     public List<Group> Groups;
}

class Group : Entity
{
     public string: code;
     
     // other fields

     public List<Characteristic> Characteristics;
}

class Characteristic : Entity
{
     public string: code;
     
     // other fields

     public List<Value> Values;
}

class Value : ValueObject
{
     public string code;
     public string value;
}

所以我有一個帶有嵌套實體的 RootAggregate。

配置一
__ 最多10人
______ 特性高達 150
__________ 值高達 50

我做了什么:

第一個解決方案

一起將實體作為參數傳遞給方法(而不是原語)

我不喜歡的是:要更新單個特性的值,我必須首先加載所有組和相關特性,並擔心性能和復雜性,同樣在存儲庫上,我必須有方法用相關實體更新整個配置,對於單個特性的值我必須查詢所有,然后更新特性,然后在所有實體中堅持配置循環並與數據庫協調

class Configuration : RootAggregate
{
     public string code;

     // other fields

     public List<Group> Groups;

     public void AddGroup(Group group)

     public void UpdateGroup(Group group)

     public void RemoveGroup(string code)
}

class Group : Entity
{
     public string: code;
     
     // other fields

     public List<Characteristic> Characteristics;

     public void AddCharacteristic(Characteristic characteristic)

     public void UpdateCharacteristic(Characteristic characteristic)

     public void RemoveCharacteristic(string code)
}

class Characteristic : Entity
{
     public string: code;
     
     // other fields

     public List<Value> Values;

     public void CreateValue(string code, string value)

     public void UpdateValue(string code, string value)

     public void RemoveValue(string code)
}

第二種解決方案

從組中拆分配置(或配置-> 組並拆分特性-> 值)

我不喜歡的是:-> 這違反了 DDD 原則,因為我必須在添加到配置之前驗證組(對於雙重代碼)。



class Configuration : RootAggregate
{
     public string code;

     // other fields


}

class Group : RootAggregate
{
     public string ConfigurationId;

     public string: code;
     
     // other fields

     public List<Characteristic> Characteristics;

     public void CreateCharacteristic (string code, <other fields>, IEnumerable<Value> values)

     public void UpdateCharacteristic (string code, <other fields>, IEnumerable<Value> values)

     public void DeleteCharacteristic (string code)
}

class Characteristic : Entity
{
     public string: code;
     
     // other fields

     public List<Value> Values;

     public SetValues(List<Value> values);
}

class Value : ValueObject
{
     public string code;
     public string value;
}

注意我已經讀過這個類似的問題,但我認為不適用於這種情況。

具有根聚合和 N 嵌套實體級別的 DDD 模式的方法是什么?

在這個特定場景中最好的解決方案是什么?

保存所選解決方案的IRepository結構是什么?

為了告訴您什么是正確的聚合,我想知道業務需求,而不是您的結構。 在第一個解決方案中對您造成傷害的實際上被稱為 DDD 中的最佳實踐(為了保持一致性,您有義務急切地加載聚合根及其所有嵌套實體)。

我從您的代碼中推斷出,里面有以下業務規則:
Configuration不應有重復的Codes

如果您想將其建模為聚合根,那么我將僅在Configuration中保留該數據,這確實是保持不變量一致所必需的 - 因此它可能僅保留沒有值的codes 因此,使用改進模型的示例代碼:

public void addCode(ConfigurationId configurationId, string code, string value){
   Configuration configuration = configRepo.Fetch(configurationId);
   configuration.AddCode(code);
   Value value = new Value(code, value);
   configRepo.Save(configuration);
   valueRepo.Save(value);
}

然后你可以操縱值而不必擔心樂觀鎖定和不變量以這種方式被破壞:

public void updateValue(string code, string newValue){
   Value value = valueRepo.fetch(code);
   value.innerValue = newValue;
   valueRepo.save(value);
}

但是,這只是猜測,因為我不知道您的確切不變量。 如果您提供它們,那么我將能夠改進上述代碼。

實現域模型時,深層次結構並不理想。 從概念上講,存在層次結構,但這並不意味着您不能將其拆分為域模型中的不同聚合。

對於事物的讀取方面,您的表示層很可能仍然將層次結構可視化為似乎是單一的事物。

我肯定會采用您的第二種方法。

任何需要具有一致性的東西,例如您的非重復組代碼不變性,您都可以放入適當的聚合中。 您可以在包含聚合中使用標識符或值對象來表示它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM