实施涉及多个项目的业务规则

时间:2012-04-20 10:23:43

标签: c# architecture domain-driven-design

让我说我有一个简单的todolist:

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

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

我应该创建ItemTimeTrackingStarted生成的StartTrackTime之类的域事件。该事件将由ITodoService选取,该{{1}}检查当前用户是否有任何其他时间跟踪的项目(并停止它们)。或者有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

如果你在项目之间存在依赖关系(在这种情况下是检查),我的建议是将track方法移动到todo列表对象,并远离item。

因此,您要求保存包含所有待办事项的对象的更改,并在那里找到检查。

答案 1 :(得分:1)

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)中。再一次,这是一个粗略的草案,因为我不完全了解背景和领域。

答案 2 :(得分:0)

如上所述,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);
  }
}