实体关系设计:互斥的Has-A关系
Entity Relationship Design: Mutually Exclusive Has-A Relationship
我正在为一个可以与不同类型的其他对象建立关系的对象确定最佳设计方法。但一次只能属于一种类型。互斥的一对多关系是我能想到的描述这种情况的最佳短语。
示例:
我有项目和程序。每个可以包含多个任务。一个任务可以属于一个项目或一个过程,但不能同时属于一个以上。任务可以从项目移动到过程,反之亦然。
因此,在任何时候,Task 都与 Project 具有一对多关系,或者与 Procedure 具有一对多关系。
目前,我正在考虑这样的任务:
class Task(id, name, project_id, procedure_id):
if project_id and procedure_id:
throw Exception("A Task can not be assigned to a Project and a Procedure at the same time")
self.id = id
self.name = name
self.project_id = project_id
self.procedure_id = procedure_id
def move_to_project(project_id):
self.procedure_id = None
self.project_id = project_id
...
任务将保护它只能属于单个项目或过程的不变量。 Project 和 Procedure 上的工厂方法可以创建具有相关关系 ID 的任务。
A Task 与两者都不在同一个聚合中,因此我想通过身份对关系建模。
在我看来,保护这个不变量的唯一方法就是以这种方式对 Task 进行建模。否则我最终会得到一个巨大的 Procedures/Projects/Tasks 集合。
这看起来是一种明智的方法吗?或者有人对可能值得探索的替代设计方法有任何建议吗?
如果一个任务不能同时关联到一个项目和一个过程,我就不会有一个具有两个 ID 的构造函数。我会有一个用于项目 ID,另一个用于过程 ID。我会使用根据 UL 命名的工厂方法来完成。这样您就可以构造一个与项目或过程相关联的任务,但不能同时与两者相关联。
您应该在 TaskService 应用层上有 TaskService.AssignToProject() 和 TaskService.AssigneToProcedure() 方法。如果 Task 是一个单独的聚合,则意味着它可以在没有 Procedure 或 Project 的情况下过自己的生活。它们可以在一段时间内为空。当调用 TaskService.AssignToProject() 或 TaskService.AssigneToProcedure() 时,应分配 ProcedureId 或 ProjectId。因此,在您的 TaskService.AssignToProject() 中,您从数据库中获取任务和项目,然后调用 task.AssignTo(project)。然后验证 ProcedureId 是否为 null 并执行所需操作(抛出异常或 UnassignFromProcedure())。分配完成后,您引发 TaskAssignedToProject 域事件,捕获它并在另一个事务中调用 ProjectService.CommitTask()。那谁会将该任务添加到 Project 聚合的 CommittedTasks 内部集合中。
我正在为一个可以与不同类型的其他对象建立关系的对象确定最佳设计方法。但一次只能属于一种类型。互斥的一对多关系是我能想到的描述这种情况的最佳短语。
示例:
我有项目和程序。每个可以包含多个任务。一个任务可以属于一个项目或一个过程,但不能同时属于一个以上。任务可以从项目移动到过程,反之亦然。
因此,在任何时候,Task 都与 Project 具有一对多关系,或者与 Procedure 具有一对多关系。
目前,我正在考虑这样的任务:
class Task(id, name, project_id, procedure_id):
if project_id and procedure_id:
throw Exception("A Task can not be assigned to a Project and a Procedure at the same time")
self.id = id
self.name = name
self.project_id = project_id
self.procedure_id = procedure_id
def move_to_project(project_id):
self.procedure_id = None
self.project_id = project_id
...
任务将保护它只能属于单个项目或过程的不变量。 Project 和 Procedure 上的工厂方法可以创建具有相关关系 ID 的任务。
A Task 与两者都不在同一个聚合中,因此我想通过身份对关系建模。
在我看来,保护这个不变量的唯一方法就是以这种方式对 Task 进行建模。否则我最终会得到一个巨大的 Procedures/Projects/Tasks 集合。
这看起来是一种明智的方法吗?或者有人对可能值得探索的替代设计方法有任何建议吗?
如果一个任务不能同时关联到一个项目和一个过程,我就不会有一个具有两个 ID 的构造函数。我会有一个用于项目 ID,另一个用于过程 ID。我会使用根据 UL 命名的工厂方法来完成。这样您就可以构造一个与项目或过程相关联的任务,但不能同时与两者相关联。
您应该在 TaskService 应用层上有 TaskService.AssignToProject() 和 TaskService.AssigneToProcedure() 方法。如果 Task 是一个单独的聚合,则意味着它可以在没有 Procedure 或 Project 的情况下过自己的生活。它们可以在一段时间内为空。当调用 TaskService.AssignToProject() 或 TaskService.AssigneToProcedure() 时,应分配 ProcedureId 或 ProjectId。因此,在您的 TaskService.AssignToProject() 中,您从数据库中获取任务和项目,然后调用 task.AssignTo(project)。然后验证 ProcedureId 是否为 null 并执行所需操作(抛出异常或 UnassignFromProcedure())。分配完成后,您引发 TaskAssignedToProject 域事件,捕获它并在另一个事务中调用 ProjectService.CommitTask()。那谁会将该任务添加到 Project 聚合的 CommittedTasks 内部集合中。