DDD - 实体状态转换

Chr*_*ris 8 .net c# java design-patterns domain-driven-design

考虑以下简化示例:

public class Ticket
{
   public int Id;
   public TicketState State;

   public Ticket()
   {
      // from where do I get the "New" state entity here? with its id and name
      State = State.New;
   }

   public void Finished()
   {
      // from where do I get the "Finished" state entity here? with its id and name          
      State = State.Finished;
   }
}

public class TicketState
{
   public int Id;
   public string Name;
}
Run Code Online (Sandbox Code Playgroud)

类状态直接在域对象票证中使用.在故障单生命周期的后期可能会设置其他状态.

故障单将持久保存到故障单表以及TicketState中.因此,在数据库中,票证将具有票证状态表的外键.

在我的实体中设置适当的状态时,如何从数据库加载状态实例?我是否必须将存储库注入实体?在这种情况下,我是否需要使用像城堡这样的框架?或者有更好的解决方案,可能从外面传递状态?

public class Ticket
{
   //...
   public ITicketStateRepository stateRep; //<-- inject

   public Ticket()
   {
      State = stateRep.GetById(NEW_STATE_ID);
   }
   //...
}
Run Code Online (Sandbox Code Playgroud)

有没有最好的做法?到目前为止,我没有使用任何依赖注入框架或任何东西,并保持任何持久性的东西超出我的域..

另一个问题:

public class Ticket
{
   //...

   public Ticket(NewTicketState newTicketState)
   {
      State = newTicketState;
   }
   public void Finished(FinishedTicketState finishedTicketState)
   {
      State = finishedTicketState;
   }
   //...
}
Run Code Online (Sandbox Code Playgroud)

duf*_*ymo 4

票证不会引用存储库。它与 TicketState 具有一对一的关系,TicketRepository 将简单地进行 JOIN 并将值映射到 Ticket 中。

当我创建模型对象时,我通常不会让它们知道它们是否是持久的,因此它们不会注入存储库。存储库处理所有 CRUD 操作。

有些人对此表示反对,认为这会导致领域模型贫血;也许你就是其中之一。如果是这种情况,请将存储库注入到您的 Ticket 对象中,但简单地要求它执行 JOIN 并返回一个已填充状态的 Ticket。当您插入或更新时,您必须将两个表作为一个工作单元进行修改,因此请务必打开事务。

我喜欢在域模型对象之外进行 CRUD 操作的原因是,它通常不是参与用例或事务的唯一域对象。例如,也许您的简单“买票”用例将有一个 Ticket 对象,但可能还必须有一些其他对象来处理预订、座位、总账、行李库存以及各种其他事情。您确实希望将多个模型对象保留为一个工作单元。只有服务层才能知道模型对象何时独立运行以及何时作为更大、更宏大的计划的一部分。

更新:

我不喜欢用 DAO 注入模型对象以使其能够处理持久性职责的另一个原因是层的浪费和它引入的循环依赖。如果您保持模型不包含任何对持久性类的引用,您就可以使用它们而无需调用其他层。这是一种单向依赖;持久化知道模型,但模型不知道持久化。

将持久性注入模型中,它们循环相互依赖。您永远无法在没有另一个的情况下使用或测试其中之一。没有分层,没有关注点分离。