领域驱动设计 - 我发现很难为这种业务逻辑提出解决方案
简介
假设我有三个领域对象:
Proposition
Phase
Task
一个命题可以有一个或多个阶段。一个阶段可以有一个或多个任务。
如果我完成了最后一个阶段的最后一个任务,则该提案必须设置为“已关闭”。
在代码中,我创建了类似的东西来完成阶段
//My Business Layer does this:
--------------------------------------
pseudo:
var phase = _phaseRepository.GetById(id);
phase.LastTask.SetComplete();
// My Domain Entities look like this:
------------------------
public class phase()
{
public Task LastTask { get; set; } // not real code of course
}
public class Task()
{
public Phase Phase { get; set; }
public void SetComplete()
{
Phase.IsFinished = true;
}
}
问题
的最后一个任务我在哪里放置代码以将提案设置为“已关闭”?
选项
我认为有几个选项:
1)在域实体中:Task.SetComplete
public class Task()
{
public Phase Phase { get; set; }
public void SetComplete()
{
Phase.IsFinished = true;
Phase.Proposition.IsClosed = true;
}
}
2a)在业务层中
var phase = _phaseRepository.GetById(id);
phase.LastTask.SetComplete();
var proposition = _propositionRepository.GetById(phase.PropositionId);
proposition.IsClosed = true;
2b)在业务层中,也许更好一点的方式:
var phase = _phaseRepository.GetByIdIncludingProposition(id);
phase.LastTask.SetComplete();
phase.proposition.SetClosed();
3)让一切都通过命题:
//My Business Layer:
var proposition = _propositionRepository.GetById(id);
proposition.CompleteTask(taskId);
// Domain Object:
public class Proposition()
{
public List<Phase> Phases { get; set; }
public void CompleteTask(long taskId)
{
var task = // psuedo: select relevant task from Phases.Tasks, using taskid
task.SetComplete();
task.Phase.SetFinished();
//psuedo: if task.Phase is last phase in proposition
Phase.Proposition.IsClosed = true;
}
}
关于选项
选项 1 是有问题的,
Phase.Proposition.IsClosed = true;
因为 Proposition 不需要加载,如果它没有加载,我们会得到一个异常。
选项 2a 是有问题的,因为在执行 Phase.LastTask.SetComplete() 后,命题未处于正确的状态。在任何可以访问 Phase 的代码中,都可以执行“phase.LastTask.SetComplete()”,而无需对 Proposition 执行相关操作。
选项 2b 与 2a 存在相同的问题。
选项 3 赋予 Proposition 类太多的责任。
你们有什么建议吗?
Introduction
Let's say I have three Domain Objects:
Proposition
Phase
Task
A Proposition can have one or more Phases. A Phases can have one or more Tasks.
If I completed the last Task in the last Phase, the Proposition must be set to 'Closed'.
In code I've created something like this to complete the last Task of a Phase
//My Business Layer does this:
--------------------------------------
pseudo:
var phase = _phaseRepository.GetById(id);
phase.LastTask.SetComplete();
// My Domain Entities look like this:
------------------------
public class phase()
{
public Task LastTask { get; set; } // not real code of course
}
public class Task()
{
public Phase Phase { get; set; }
public void SetComplete()
{
Phase.IsFinished = true;
}
}
Question
Where do I put the code to set the Proposition to 'Closed'?
Options
I think have a few options:
1) In the Domain Entity: Task.SetComplete
public class Task()
{
public Phase Phase { get; set; }
public void SetComplete()
{
Phase.IsFinished = true;
Phase.Proposition.IsClosed = true;
}
}
2a) In the Business Layer
var phase = _phaseRepository.GetById(id);
phase.LastTask.SetComplete();
var proposition = _propositionRepository.GetById(phase.PropositionId);
proposition.IsClosed = true;
2b) In the Business Layer, maybe a bit nicer way:
var phase = _phaseRepository.GetByIdIncludingProposition(id);
phase.LastTask.SetComplete();
phase.proposition.SetClosed();
3) Let everything pass thru Proposition:
//My Business Layer:
var proposition = _propositionRepository.GetById(id);
proposition.CompleteTask(taskId);
// Domain Object:
public class Proposition()
{
public List<Phase> Phases { get; set; }
public void CompleteTask(long taskId)
{
var task = // psuedo: select relevant task from Phases.Tasks, using taskid
task.SetComplete();
task.Phase.SetFinished();
//psuedo: if task.Phase is last phase in proposition
Phase.Proposition.IsClosed = true;
}
}
About the options
Option 1 is problematic on the line
Phase.Proposition.IsClosed = true;
because Proposition doesn't have to be loaded, and if it's not loaded we get an exception.
Option 2a is problematic because after phase.LastTask.SetComplete() is executed the proposition is not in the correct state. And everywhere in code where one has access to Phase, "phase.LastTask.SetComplete()" can be executed without doing the relevant operations on Proposition.
Option 2b has the same problem as 2a.
Option 3 gives the Proposition class too much responsibilities.
Do you guys have any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我猜测命题是聚合根。任务最终是命题的一部分,我认为 Tssk 应该通知已完成我会尝试这种方法(基本上选项 3 稍作修改)
阶段应该处理Task 的完成事件,触发时检查是否是最后一个任务,并通知 Proprisiton 关闭。现在,也许使用事件并不是最好的实现,可能观察者模式更好,但主要思想是:
想想看,这基本上是领域事件模式。
I'm guessing that Proposition is the aggregate root.A task is part of a proposition in the end and I think that the Tssk should notify that is completed i'd try this approach (basically option 3 a bit modified)
The Phase should handle the completed event of Task and when it is triggerd, chek if it's the last task and notify the proporisiton to closeitself. NOw maybe using events is not the best implemetnation, probably the Observer pattern is better, but the main ideas are:
Come to think of it, this is basically the domain event pattern.