【问题标题】:DDD and distinction between Entity and Value object. Choosing the aggregate rootDDD与Entity和Value对象的区别。选择聚合根
【发布时间】:2010-03-21 16:51:47
【问题描述】:

我是设计和电子病历。我已经确定域的中心对象是Patient。患者必须有以下Doctor 和医疗记录。医疗记录是一个分组术语,指的是遭遇、实验室、X 射线、处方......

我是 DDD 的新手,我在一些概念和我对 DDD 的理解方面遇到了问题。下面是显示Encounter 类的代码示例。 Encounter 包含几个属性,它还引用了另一个类 Vitals

VitalsPatient 之外没有任何意义。我仍然使用自己的密钥识别数据库中的生命体征。我不确定这是否使Vitals 成为一个实体。目前我有Vitals 作为值对象。

其次,我的模型构建方式,我将Encounter 定义为Aggregate 根。通过Encounter,医生可以订购实验室、X 光片和开药。基本上Encounter 记录了订购此类物品的原因。

存在一个问题,即我还需要在Encounter 的上下文之外检索这些项目,因此这是否意味着Encounter 不是聚合根。 Vitals 之类的项目只是一个值对象。

这是我的代码...

public class Encounter {
    String ChiefComplaint {get; set;}
    string Plan {get; set;}
    string Assessment {get; set;}
    Vital PatientVital {get; set;}
}

public class Vital {
    public float Temperature { get; private set; }
    public BloodPressure BP { get; private set; }
    public int Pulse { get; private set; }
    public int Respiratory { get; private set; }

    internal Vital(float temperature, int systolic, int diastolic, int pulse, int respiratory) {
        this.Temperature = temperature;
        BloodPressure bp = new BloodPressure();
        bp.Systolic = systolic;
        bp.Diastolic = diastolic;
        this.Respiratory = respiratory;
        this.BP = bp;
    }

    public void AddBP(int systolic, int diastolic) {
        BloodPressure bp = new BloodPressure();
        bp.Systolic = systolic;
        bp.Diastolic = diastolic;
        this.BP = bp;
    }
}

public struct BloodPressure {
    public BloodPressure(int systolic, int diastolic){
        Systolic = systolic;
        Diastolic = diastolic;
    }

    public int Systolic { get; private set; }
    public int Diastolic { get; private set; }

    public string bloodPressure {
        get { return this.Systolic.ToString() + "/" + this.Diastolic.ToString(); }
    }
}

【问题讨论】:

    标签: domain-driven-design aggregate


    【解决方案1】:

    我不完全确定您的实际问题。没有问号让人有点难以理解——不过,我会尝试回答看似问题的问题。

    病历、医生和患者都是关于某事的潜在聚合根:它们都存在于现实世界中,您甚至可以触摸它们,并且它们中的每一个都“聚合”了其他对象或信息片段。但是,您可能不需要将对象建模到它们实际成为聚合根的程度 - 这取决于您的应用程序的确切要求。

    但是,这些实体不会相互聚合。医生可以在没有病历的情况下存在,病人也可以。遗憾的是,病历需要患者医生,因此不能由任一方汇总。因此,他们成为一个实体。

    前面提到的每个人都必须有自己的身份。请注意,即使它们的关联项目不存在,这些对象也会继续存在。最明显的是,即使患者没有,医生也会保留在系统中,但更重要的是,文档也会继续存在(并且可能会阻止患者和医生被删除,但这是另一个问题)。

    我仍然使用自己的密钥识别数据库中的生命体征

    毕竟,您需要为每位患者存储一份 Vitals 列表。由于您可能正在使用 SQL,因此您可能希望使用链接器表对这种 m:n 关系建模,因此您必须分配一个键。那没问题。这是持久层的缺点,而不是模型的缺点,但您应该确保永远不要将此密钥用于内部应用程序之外的任何用途。

    因此这是否意味着 Encounter 不是聚合根

    “遭遇”当然不是关于医生或患者的聚合根:这又是一种 m:n 关系,这次是医生和患者之间的关系,因此显然每位患者和每位医生都会遇到很多次。如果其中一个遭遇被删除(例如,因为它们不正确),这不会删除患者或医生。此外,Encounter 不是处方的聚合根:例如,X 射线本身就是完全有意义的东西。但是,您可能希望保留参考。同样,将来删除 Encounter 不会恢复 X-Ray。

    遭遇并不拥有医生或患者。医生也不会“自己”遭遇。

    另请注意,遭遇可能会导致开药,也可能不会导致任何结果。

    注意您的方法AddBP() 将有效地删除旧值,因此不应将其命名为“添加”。更重要的是,这种方法使Vital 类可变,因此更加复杂。我会摆脱这种方法。

    【讨论】:

    • 对于没有明确的问题,我深表歉意。我知道患者和医生将是聚合根。确实,医生会为给定的患者创建医疗记录,因此这是否意味着在患者环境之外检索医疗记录是没有意义的。同样在处方的情况下,如果存在一个业务规则,即对于每个处方都必须有一个有效的遭遇,那么遭遇只是成为处方的属性
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    相关资源
    最近更新 更多