-
21-12-2019 - |
题
我试图找到一个清晰而简单的例子来说明贫血领域的真正含义。有很多理论,也有很多很好回答的问题。尽管如此,我还是无法清楚地了解“贫血领域”的含义到底有多大。因此,我相信看到贫血领域设计的虚拟实际示例,然后问您如何将其演变成领域驱动的设计,会更简单......
所以,假设我们有一个类型的数据实体 任务数据:
public class TaskData
{
public Guid InternalId { get; set; }
public string Title { get; set; }
public string Details { get; set; }
public TaskState ExplicitState { get; set; }
public IEnumerable<TaskData> InnerTasks { get; set; }
}
并且需要一个名为“的附加属性”实际状态”,这是一个计算状态:如果任务有内部子任务,则该值严格取决于子任务,否则,“实际状态“等于”显式状态"
如果我把这个逻辑写在一个单独的 服务 类(我称它们为“引擎“) 我们有:
internal class TaskStateCalculator
{
public TaskState GetState(TaskData taskData)
{
if (taskData.InnerTasks.Any())
{
if (taskData.InnerTasks.All(x => this.GetState(x) == TaskState.Done))
{
return TaskState.Done;
}
if (taskData.InnerTasks.Any(x => this.GetState(x) == TaskState.InProgress))
{
return TaskState.InProgress;
}
return TaskState.Default;
}
return taskData.ExplicitState;
}
}
这 第一个问题 是:
上面的代码是否反映了贫乏的领域设计,即使 任务状态计算器 服务/引擎是我的域层的一部分?如果是,为了避免它,我们需要将逻辑移到 任务数据 类(并重命名 任务数据 到 任务)。我对吗?
这 第二个问题 是(实际上是它们的链):
如果我们遇到更困难的情况怎么办?假设需要一个名为 计算一些东西 里面 任务 实体,这个属性的逻辑需要访问整个Task的 存储库. 。在这种情况下, 任务 类将依赖于 任务库. 。这样可以吗?EF 将如何构造此类的实例?还有什么选择呢?
解决方案
我试图找到一个清晰简单的例子来说明贫血领域的真正含义
事实上,从贫乏的领域模型转变为丰富的领域模型非常容易。
- 将所有属性设置器设置为
private
如果您想更改模型的状态,然后添加方法。 - 评估全部 德墨忒耳定律 违规并在适当的地方添加方法。
最终你将得到一个正确的模型。
在你的情况下,我会将该逻辑封装在里面 TaskData
因为您的 TaskStateCalculator 违反了德米特法则
public class TaskData
{
public Guid InternalId { get; private set; }
public string Title { get; private set; }
public string Details { get; private set; }
public TaskState ExplicitState { get; private set; }
public IEnumerable<TaskData> InnerTasks { get; private set; }
public TaskState GetState()
{
if (!InnerTasks.Any())
return ExplicitState;
if (InnerTasks.All(x => this.GetState(x) == TaskState.Done))
{
return TaskState.Done;
}
if (InnerTasks.Any(x => this.GetState(x) == TaskState.InProgress))
{
return TaskState.InProgress;
}
return TaskState.Default;
}
}
另一件事是,我可能根本不会向外界公开 InnerTasks 集合(只是将其作为成员字段)。但很难说,因为我不知道该类在其他场景中如何使用。
为什么选择私人设置者
每当您必须更改多个属性时,通常最好使用一种方法来描述行为,因为这样就不可能忘记更改所有必需的属性。与更改一组属性相比,方法还可以更好地描述您正在尝试执行的操作。
即使您只更改单个属性,该属性也可能会将类设置为无效状态,因为更改可能与类中的其余信息不兼容。不要忘记封装是 OOP 的核心原则之一