我想知道我的表示层是如何构建的,可能会导致设计我的聚合根。
让我们有一个实体ProjectEntity及其相关实体ProjectMemberEntity(1:M)
页面结构如下:
页面顶部是ProjectEntity的表单
表单下方是一个显示ProjectMemberEntity列表的网格。
如果要添加新的ProjectMember,用户必须转到此页面并单击位于网格标题中的“添加新成员”按钮。编辑和删除也具有相同的类比。
我想知道这种行为/'页面结构'是否可以作为聚合根的提示(projectentity)
答案 0 :(得分:1)
这是一个肯定的暗示。但不多了。
澄清实体关系类型的更好方法是询问领域专家:
如果积极回答这些问题,那么您很可能应该将项目成员建模为聚合根本身。否则 - 将其降级为无法与项目共存的实体。
以下是一些可能为您提供一些想法的代码:
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...");
}
}
请记住,我对您的业务知之甚少。这只是即兴创作。 :)
答案 1 :(得分:0)
对于DDD,请确保在尝试设计域和聚合时不会出现分析瘫痪。它发生在我身上。我的项目在整整一个月内完全停止了,因为我无法直接获得我的聚合。而我正在谈论一个简单的3数据库表情况。用户,地址和用户配置文件。
DDD的东西是没有像DONE THE RIGHT WAY这样的东西。如果你在这里发布相同的问题,彼此间隔3个月,你将始终让“专家”在每个问题中给出完全不同的答案。 Amis L.非常友好地给你一个简单的例子。大多数人都会从埃里克的书中复制和粘贴。
做任何漂浮你的船。在一天结束时,无论您的域名如何手工制作,它都不会对社区产生影响。只是冷静下来,享受编码。