【问题标题】:Enforcing a business rule involving multiple items执行涉及多个项目的业务规则
【发布时间】:2012-04-26 03:24:45
【问题描述】:

假设我有一个简单的 todolist:

interface ITodoList
{
  ITodoItem Create(title);
  IEnumerable<ITodoItem> Items {get;}
}
interface ITodoITem
{
    void StartTrackTime();
    void StopTrackTime();
}

现在我想强制执行,以便一次只跟踪一项(每个用户)的时间。

我是否应该创建像ItemTimeTrackingStarted 这样StartTrackTime 生成的域事件。该事件将由ITodoService 获取,该ITodoService 检查当前用户是否有任何其他时间跟踪项目(并停止它们)。还是有更好的办法?

【问题讨论】:

  • IMO,ITodoService 将被命名为 ITodoPolicy,因为它正在尝试执行规则而不是执行事务。如果跟踪的 TodoItem 是 TodoList 中的第一个,那么您正在使用 FIFO 集合,对吗?
  • 你是不是错过了 TodoList.AssignItemTo(User user) 或 UserTimeTracking.StartTrackingTimeFor(TodoItem item) 之类的东西?

标签: c# architecture domain-driven-design


【解决方案1】:

如果项目之间存在依赖关系,在这种情况下是检查,我的建议是将 track 方法移到待办事项列表对象中,并远离项目。

因此,您请求对包含所有待办事项的对象进行更改,然后您也可以在其中找到检查。

【讨论】:

  • 是不是有点不合逻辑?因为它不是要跟踪时间的列表?
  • 我同意马丁的做法。 TodoList 是聚合。它应该强制执行不变量。
  • 请添加一个示例,展示您如何构建实体。
  • TrackTime方法放在User上不是更好吗?
  • 对我来说,在哪个对象上添加一些数字并不重要,关键是在最适合的地方实现代码,对我来说就是列表。它就像一个门面。
【解决方案2】:

IMO 我会这样做,我不知道上下文的所有细节,但是对于这个特定的功能来说,它是这样的

 public interface ITrackTime
 {

    void StartTrackTime();
    void StopTrackTime();
 }
 public interface ITodoItem
 {
    int Id {get;}  
    //other stuff
 }

 public TodoItem:ITodoITem, ITrackTime {}

 public class TodoList:ITodoList,ITrackItem
 {
    ITodoItem Create(title)
    { 
       //create item and add it to collection 
     }
      TodoItem _currentlyTracking;

     void StartTrackTime(int itemId)
     {

        if (_currentlyTracking == null)
        {
           // getItem and call method for item ..
          item.StartTrackTime();
          _currentlyTracking=item;
         }
        else{
           //get item and check to see if it is the same id
           //throw exception if it is not, ignore it if it is
          }
      }
 }

 var list = new TodoList();
 ITodoItem item= list.Create("titel");
 list.StartTrackingTime(item.Id);
 list.StartTrackingTime(otherId); //should throw or whatever handling

一切都包含在 AR (TodoList) 中。再说一次,这是一个粗略的草稿,因为我并不完全了解上下文和领域。

【讨论】:

    【解决方案3】:

    如上所述,ToDoList 应该强制执行约束,因为约束是在 ToDoList 级别定义的。 (除非它是在用户级别定义的,如您所指出的,在这种情况下,责任将转移到那里)。您可以将方法保留在项目上,但它可以引用父待办事项列表。代码可能如下所示:

    public class ToDoList
    {
      public IList<ToDoListItem> Items { get; private set; }
    
      // factory method creates items as required by ToDoList
      public ToDoListItem Create(string title)
      {
        var item = new ToDoListItem(this, title);
        this.Items.Add(item);
        return item;
      }
    
      ToDoListItem currentItem;
    
      public void StartTrackTimeFor(ToDoListItem item) 
      {
        if (this.currentItem != null)
          throw new Exception();
        // could also throw different exception if specified item is current item being tracked
        // start time tracking logic.
        this.currentItem = item;
      }
    
      public void StopTrackTimeFor(ToDoListItem item)
      {
        if (this.currentItem != item)
          throw new Exception();
        // stop time tracking logic.    
        this.currentItem = null;
      }
    }
    
    public class ToDoListItem
    {
      public ToDoListItem(ToDoList list, string title) 
      {
        this.ToDoList = list;
        this.Title = title;
      }
    
      public ToDoList ToDoList { get; private set; }
    
      public string Title { get; private set; }
    
      public void StartTrackTime()
      {
        this.ToDoList.StartTrackTimeFor(this);
      } 
    
      public void StopTrackTime()
      {
        this.ToDoList.StopTrackTimeFor(this);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-18
      • 2018-12-15
      • 2018-10-28
      • 2021-12-22
      • 2011-07-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多