0

我正在尝试遵循 DDD,但我对建模此示例情况有疑问:

我有一个实体员工:

public class Employee{
   public Int32 Id {get;set;}
   public String Name {get;set;}
   public Decimal Salary {get;set;}
   public List<Retirement> Retirements {get;set;}
}

是不是所有员工都通用,一个名字,一个薪水。但有些人可能会因健康状况不佳而退休。每个退休都与一个员工相关联,所以我有这个实体:

public Retirement {
   public Int32 Id {get;set;}
   public DateTime Begining {get;set;}
   public DateTime End {get;set;}
   public Employee Employee {get;set;}
}

我的疑问是:

  • Employee 实体真的需要 Retirement 列表吗?

(员工存在不带退休,但退休不存在不带员工)

  • 如果我必须获取今天退休的所有员工,那么搜索 Employee 或 Retirement 是否更“合乎逻辑”?
  • 当我雇用一名员工时,我不希望他退休。这不是一个共同的特点。它会改变员工的行为吗?
4

3 回答 3

2

当然,这是一个数据模型,而不是模型。

要开始使用 DDD,您应该阅读蓝皮书几次。

以下是您发布的代码的一些问题:

  1. 实体应该由共享标识符而不是 Int32 来标识。
  2. 实体的身份不能改变:它可以公开只读属性,但不能公开可变属性
  3. 实体应该被正确封装:它们的状态应该只作为commands的影响而改变,但是您通过属性将其公开
  4. 限界上下文是 DDD 中的关键概念:您应该与领域专家一起思考是否Employees属于Retirements同一个上下文。
  5. 如果 EmployeesRetirements属于同一个有界上下文,您应该通过标识符将它们关联起来,而不是直接对象引用。
  6. 每个实体应该只持有严格要求执行其不变量的状态(那些在上下文边界内相关的)。

所以,回答你的问题:

  • Employee 实体真的需要 Retirement 列表吗?

,它可能需要公开一组不可变的退休(例如和IEnumerable<Retirement>),如果它有类似的命令void Retire(DateTime from, DateTime to)(显然有适当的例外)。但是,如果这种情况下,Retirement 将是一个值对象,而不是一个实体;就像是:

public sealed Retirement {
   public Retirement (DateTime begining, DateTime end)
   {
       Begining = begining;
       End = end;
   }
   public DateTime Begining {get; private set;}
   public DateTime End {get; private set;}
}
  • 如果我必须获取今天退休的所有员工,那么搜索 Employee 或 Retirement 是否更“合乎逻辑”?

或许,您应该只有一个员工存储库,即使对于那些已经退休的员工也是如此。

通常,在 OO 语言中,为每种类型的实体创建一个存储库是最佳选择。

  • 当我雇用一名员工时,我不希望他退休。这不是一个共同的特点。它会改变员工的行为吗?

您应该使用异常建模不变量的违规行为。如果员工不能在被雇用的同一天退休,您应该抛出Retire命令中记录的特定异常。

于 2013-08-20T10:21:28.003 回答
1

首先,您的问题根本不清楚。

我看到的第二个问题是退休班有结束日期吗?那个有什么用途?

我会采用以下设计:

class Employee{

   public Int32 Id {get;set;}
   public String Name {get;set;}
   public Decimal Salary {get;set;}
   public bool IsRetired {set;get;}
   public virtual Retirement Retirement{set;get;} 

}

我会得到今天的退休员工如下:

employees.Where(x=>x.Retirement.Beginning < Datetime.Today);

如果您有退休历史,您可以进行如下设计:

class Employee{

   public Int32 Id {get;set;}
   public String Name {get;set;}
   public Decimal Salary {get;set;}
   public bool IsRetired {set;get;}
   public virtual IEnumerable<Retirement> Retirements{set;get;} 
}
于 2013-08-19T19:13:49.017 回答
0

同意@DarthVader。现在最好是这样(Employee --> Collection< Retirement >),因为知道的进一步要求很少。

也许让员工退休可能有点奇怪,但这向员工的客户隐藏了细节(例如,员工什么时候退休,他/她是否已经退休)。

于 2013-08-20T01:21:05.147 回答