Domain driven design 领域驱动设计——我发现很难为这种业务逻辑找到解决方案 介绍

Domain driven design 领域驱动设计——我发现很难为这种业务逻辑找到解决方案 介绍,domain-driven-design,domain-model,Domain Driven Design,Domain Model,假设我有三个域对象: Proposition Phase Task 一个命题可以有一个或多个阶段。阶段可以有一个或多个任务 如果我在最后一个阶段完成了最后一个任务,则命题必须设置为“已关闭” 在代码中,我创建了类似这样的东西来完成阶段的最后一个任务 //My Business Layer does this: -------------------------------------- pseudo: var phase = _phaseRepository.GetById(id); phas

假设我有三个域对象:

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 2a)在业务层 2b)在业务层,可能有更好的方式: 3) 让一切都过去: 因为命题不需要加载,如果它没有加载,我们会得到一个异常

选项2a有问题,因为在执行phase.LastTask.SetComplete()后,命题的状态不正确。在代码中任何可以访问Phase的地方,“Phase.LastTask.SetComplete()”都可以执行,而无需对命题执行相关操作

选项2b的问题与2a相同

选项3赋予命题类太多的责任


你们有什么建议吗?

我猜命题是聚合根。任务最终是命题的一部分,我认为Tssk应该通知完成了,我会尝试这种方法(基本上选项3有点修改)

公共类命题()
{
公共任务GetTask(int taskId)
{
//查找并返回任务
} 
}
//在业务层
var p=_repository.GetProposition(id);
p、 GetTask(taskId.SetComplete();
公开课任务
{
公共活动行动完成;
公共void SetComplete()
{
如果(已完成!=null)已完成(此);
}
该阶段应处理任务的已完成事件,在触发时,检查是否是最后一个任务,并通知比例师自行关闭。现在,使用事件可能不是最好的实现方式,可能观察者模式更好,但主要思想是:

  • 您通过命题方法获得任务(因为命题是AR)
  • 任务在阶段完成时通知阶段
  • 阶段在最后一个任务完成时通知命题
  • 提案应检查是否有任何阶段正在进行,并自行关闭
  • 在存储库中保存命题

想一想,这基本上就是域事件模式。

好的,这是一个明确的答案。问题:为什么你必须通过命题来获得任务?我如何确保业务层不能通过阶段访问任务。任务?我知道我可以使阶段。任务是私有的或内部的,但实际上它可能需要是公共的,对吗?命题是一个聚合根,任务是它的子项,在DDD中,您应该只通过AR处理AR子项,因为它们是在一起的,而不是作为单独的部分:)您公开阶段。只有在需要时才使用TAK,如果不隐藏它们的话。另一种方法是通过接口,使阶段实现特定的接口,并且只使用它们在业务层。也就是说,BL将只与有意义的抽象一起工作,这些抽象将隐藏任何不必要的功能。
public class Task()
{
   public Phase Phase { get; set; }

   public void SetComplete()
   {
      Phase.IsFinished = true;
      Phase.Proposition.IsClosed = true;
   }
}
var phase = _phaseRepository.GetById(id);
phase.LastTask.SetComplete();

var proposition = _propositionRepository.GetById(phase.PropositionId);
proposition.IsClosed = true;
var phase = _phaseRepository.GetByIdIncludingProposition(id);
phase.LastTask.SetComplete();
phase.proposition.SetClosed();
//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;
   }
}
Phase.Proposition.IsClosed = true;
public class Proposition()
{
  public Task GetTask(int taskId)
  {
      //find and return task
  } 
}

//in business layer 
var p= _repository.GetProposition(id);
p.GetTask(taskId).SetComplete();

public class Task
{
  public event Action<Task> Completed;       


   public void SetComplete()
   {
        if (Completed!=null) Completed(this);
    }