DDD以及Entity和Value对象之间的区别。选择聚合根

时间:2010-03-21 16:51:48

标签: domain-driven-design aggregate

我是设计和EMR。我已确定域的中心对象是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(); }
    }
}

1 个答案:

答案 0 :(得分:1)

我不完全确定您的实际问题。缺少问号使得有点难以理解 - 不过我会尝试回答看似问题的问题。

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

但是,这些实体不会相互聚合。医生可以在没有医疗记录的情况下存在,患者也可以。遗憾的是,医疗记录需要患者医生,因此他们无法通过任何一个进行汇总。因此,他们成为了一个实体。

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

  

我仍然用自己的密钥

识别数据库中的生命值

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

  

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

对于医生或患者来说,“遭遇”肯定不是一个总体根源:这又是一个m:n关系,这次是医生和患者之间的关系,所以很明显每位患者和每位医生会遇到很多次。如果其中一次遭遇被删除(例如,因为它们不正确),这将不会删除患者或医生。此外,Encounter不是处方的聚合根:例如,X射线本身就是完全合理的。但是,您可能希望保留引用。同样,将来删除Encounter将不会还原X射线。

遭遇者不拥有医生或患者。医生自己的遭遇也没有。

另请注意,遇到可能导致药物被处方,或者可能不会导致任何事情。

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