如何通过聚合根控制不变量

Any*_*are 5 c# architecture ienumerable domain-driven-design aggregateroot

如果我有两个类[Shift,ShiftDetails],那[Shift]就是聚合根.基于特定字段我想约束实例的数量ShiftDetails.


我创建一个ShiftDetailsView类,然后在Shift聚合根中创建两个方法来控制不变量:

  • public IEnumerable ConstructShift(); //基于NumberOfSuccessions字段

此方法应ShiftDetailsView根据该字段创建初始化的数量,然后将它们添加到列表中,并将结果作为IEnumerable返回给用户(开发人员).

然后用户应该CompleteShift在填充从前一个方法返回的初始IEnumerable后调用:

  • public List CompleteShift(IEnumerable shiftDetailsViews)

我做了两个单独的步骤来控制通过聚合根的子数量,我认为有更好的方法来保证整个事物的(ACID).


根据评论,这个问题需要更多的澄清,因为我试图简化问题,我犯了一个错误并改变了真正的问题.因为当我们处理域问题时,我们必须准确并澄清确切的问题.所以我会尝试更详细地解释它.

我有以下两个聚合:

1. First Aggregate

1-WorkingSystem :(聚合根)

    private readonly ICollection<WorkingTime> _assignedWorkingTimes;

    public string Name { get; private set; }
    public short NumberOfSuccessions { get; private set; }
    public Week WeekStart { get; private set; }
    public bool IsActive { get; private set; }
    public bool IsDefault { get; private set; }
    public short NumberOfWeekends { get; private set; }
    public virtual ICollection<WorkingTime> AssignedWorkingTimes { get => _assignedWorkingTimes; }
Run Code Online (Sandbox Code Playgroud)

例:

 Id |Name     | NumberOfSuccessions|WeekStart|IsActive|NumberOfWeekends 
  1 |Employees|       2            |Sunday   |  1     |   2
  2 |Lecturers|       1            |Saturday |  1     |   1
Run Code Online (Sandbox Code Playgroud)

2 WorkingTime:

public string Name { get; set; }
public short NumberOfHours { get; set; }
public int WorkingSystemId { get; private set; }
Run Code Online (Sandbox Code Playgroud)

例:

Id|Name   |  NumberOfWorkingHours  | WorkingSystemId 
 1|Summer |  8                     | 1
 2|Winter |  6                     | 1
 3|General|  8                     | 2
Run Code Online (Sandbox Code Playgroud)

2.第二集合

3-Shift(聚合根).

private readonly List<ShiftDetail> _assignedShiftDetails;
public string Name { get; set; }
public ShiftType ShiftType { get; set; }
public int WorkingSystemId { get; set; }
public virtual WorkingSystem WorkingSystem { get; set; }
public virtual IEnumerable<ShiftDetail> AssignedShiftDetails { get => _assignedShiftDetails; }
Run Code Online (Sandbox Code Playgroud)

例:

Id|Name            |ShiftType | WorkingSystemId 
1 |restaurant-shift|Morning   |  1
Run Code Online (Sandbox Code Playgroud)

4- ShiftDetails:

public Guid ShiftId { get; private set; }
public int WorkingTimeId { get; set; }
public DateTimeRange ShiftTimeRange { get; set; }
public virtual WorkingTime WorkingTime { get; set; }
Run Code Online (Sandbox Code Playgroud)

例:

 ShiftId = 1|WorkingTimeId = 1|ShiftStart = 8:00|ShiftEnd = 16:00
 ShiftId = 1|WorkingTimeId = 2|ShiftStart = 9:00|ShiftEnd = 15:00
Run Code Online (Sandbox Code Playgroud)

现在我想根据NumberOfSuccessions每个WorkingSystem 约束细节数量!并且因为我可以访问WorkingSystemId我的聚合根,Shift然后我可以访问此信息.

你能帮我根据聚合根中的字段控制实例数吗?

Voi*_*son 4

您能帮我根据聚合根中的字段控制实例数量吗?

这两种方法仅在创建新班次时使用。因为我是 DDD 的新手,所以我认为我没有以正确的方式约束不变量

哦,我明白了——您特别担心创建聚合的事务中会发生什么。

Eric Evans(第 6 章)描述的通常模式是,域模型将公开一个工厂,该工厂知道如何从应用程序获取数据并返回一个新的聚合实例。

在该工厂中,您将创建构成聚合初始状态的所有值。这些值了解它们自己的约束(“我是 an Amount,所以我需要一个大于或等于零的整数”;“我是 a Money,所以我需要一个非 nullAmount和一个非 null CurrencyCode)。

工厂接受来自应用程序的数据,构造值图,最后调用具有当前状态的聚合的构造函数。

模型中的值负责验证已传入的数据,并且可以包括验证其他两个值是否一致的值,这是完全正常的事情。

因此,例如,您的工厂可能会采用 aNumberOfDetails和 a List<ShiftDetails>,并从中生成一个VerifiedDetails类型,最终将根据该类型构造聚合。

关于这种方法的一本很好的读物是Scott Wlaschin 的《Domain Modeling Made Function》