1

我想知道我的表示层的结构是否可以引导我设计聚合根。

让我们有一个实体 ProjectEntity 及其相关实体 ProjectMemberEntity (1:M)

页面结构如下:

页面顶部是 ProjectEntity 的表单

表单下方是一个显示 ProjectMemberEntity 列表的网格。

如果要添加新的 ProjectMember,用户必须转到此页面并单击位于网格标题中的“添加新成员”按钮。编辑和删除具有相同的类比。

我想知道这种行为/“页面结构”是否可能是聚合根(项目实体)的提示

4

2 回答 2

1

这肯定是一个暗示。但没有了。

澄清实体关系的更好方法是询问领域专家:

  • 没有项目,项目成员是否有意义?
  • 会员可以参与多个项目吗?

如果这些回答是肯定的,那么您很可能应该将项目成员建模为聚合根本身。否则 - 将其降级为无法使用 oa 项目的实体。


这里有一些代码可能会给你一些想法:

public class Project:Root{
 private List _members;
 public IEnumerable<Member> Members{get {return _members;}}
 public string Name{get;private set;}
 public bool IsFinished{get;private set;}
 public bool FinishedOn{get;private set;}
 public Project(string projectName){
  _members=new List<Member>();
  Name=projectName;
 }
 public Member AssignMember(string memberName){
  var member=new Member(memberName);
  _members.Add(member);
  return member;
 }
 public void UnassignMember(string memberName){
  var member=_members.First(m=>m.Name==memberName);
  if(!member.HasCompletedAllTasks())
   throw new Exception
    ("Cannot unassign member with incompleted tasks!");
  _members.Remove(member);
 }
 public void AssignTaskToMember(string taskName, string memberName){
  var member=_members.First(m=>m.Name==memberName);
  member.AssignTask(taskName);
 }
 public void MemberHasCompletedTask(Member member, Task task){
  EnsureListContains(_members,member);
  EnsureListContains(member.Tasks,task);
  task.MarkAsCompleted();
 }    
 public void FinishProject(){
  if(_members.Any(m=>!m.HasCompletedAllTasks()))
   throw new Exception
    ("Can't finish project before members have completed all their tasks.");
  IsFinished=true;
  FinishedOn=DateTime.Now;
 }
 private void EnsureListContains<T>(IList<T> lst, T itm){
  if(!lst.Contains(itm)) throw new Exception();
 }
}

public class Member:Entity{
 public string Name{get;private set;}
 private List<Task> _tasks;
 public IEnumerable<Task> Tasks{get{return _tasks;}}
 internal Member(string memberName){
  Name=name;
  _tasks=new List<Task>();
 }
 internal void AssignTask(string taskName){
  _tasks.Add(new Task(taskName));
 }
 public bool HasCompletedAllTasks(){
  return _tasks.All(t=>t.IsCompleted);
 }
 public Task GetNextAssignedTask(){
  return _tasks.Where(t=>!t.IsCompleted)
    .OrderBy(t=>t.AssignedOn).First();
 }
}

public class Task:Entity{
 public string Name{get; private set;}
 public bool IsCompleted{get; private set;}
 public DateTime CompletedOn{get; private set;}    
 public DateTime AssignedOn{get; private set;}
 internal Task(string name){
  Name=name;
  AssignedOn=DateTime.Now;
 }
 internal void MarkAsCompleted(){
  if(IsCompleted) throw new Exception
   ("Task is already completed!");
  IsCompleted=true;
  CompletedOn=DateTime.Now;
 }
}

public class App{
 public static void Main(){
  var project=new Project
    ("Question: Aggregate root design and presentation layer");
  var me=project.AssignMember("Arnis Lapsa");
  project.AssignTaskToMember("Try to help user137348","Lapsa");
  var currentTask=me.GetNextAssignedTask();
  //SpamStackOverflow();
  project.MemberHasCompletedTask(me,currentTask);
  if(me.HasCompletedAllTasks()) project.Finish();
  else throw new Exception("Enough for today...");
 }
}

请记住,我对您的业务内容知之甚少。这只是一个即兴创作。:)

于 2011-01-06T13:58:44.597 回答
0

对于 DDD,请确保在尝试设计域和聚合时不会出现分析瘫痪。它发生在我身上。我的项目实际上已经停止了整整一个月,因为我无法直接获得我的聚合。我说的是一个简单的 3 个数据库表的情况。用户、地址和用户配置文件。

DDD 的问题是没有像 DONE THE RIGHT WAY 这样的事情。如果您在此处每隔 3 个月发布相同的问题,您将始终得到“专家”在每个问题上为您提供完全不同的答案。Amis L. 很友好地给了你一个简单的例子。大多数人会从埃里克的书中复制和粘贴。

做任何让你的船漂浮的事情。归根结底,无论您的域名如何手工制作,它都永远不适合社区。放松并享受编码。

于 2012-12-17T00:09:18.003 回答