2013-09-27 4 views
0
public class ProjectType : Entity 
{ 
    public ProjectType(Guid id,string name) 
    { 
    Id=id; 
    Name=name; 
    } 

    public virtual string Id {get;private set;} 
    public virtual string Name {get;private set;} 
} 

public class Project : Entity 
{ 
    public Project(Guid id, ProjectType projectType) 
    { 
    Id = id; 
    ProjectType = projectType; 
    } 

    private IList<Task> _tasks = new List<Task>(); 
    public ProjectType {get;private set;} 
    public IEnumerable<Task> Tasks 
    { 
    get{ 
     return _tasks; 
    } 
    } 

    public void AddTask(Task task) 
    { 
    // some business logic for this.ProjectType 
    task.SetProject(this); 
    _tasks.Add(task); 
    } 

    public void RemoveTask(Task task) 
    { 
    _tasks.Remove(task); 
    } 
} 

public class Task : Entity 
{ 
    public Task(Guid taskId,Project project) 
    { 
    Id = taskId, 
    Project = project; 
    } 

    public Project Project {get;private set;} 
    public Task ParentTask {get;private set;} 

    private IList<Task> _subTasks = new List<Task>(); 

    public IEnumerable<Task> SubTasks 
    { 
    get{ 
     return _subTasks; 
    } 
    } 

    public void AddSubTask(Task task) 
    { 
    // some business logic for Project.ProjectType 
    task.SetProject(this.Project); 
    task.ParentTask = this; 
    _subTasks.Add(task); 
    } 

    public void RemoveSubTask(Task task) 
    { 
    _subTasks.Remove(task); 
    } 

    internal void SetProject(Project project) 
    { 
    Project = project; 
    } 
} 

내 질문 :DDD, 집계 루트 디자인

  1. 이 프로젝트 집계 루트인가?
  2. 작업 집계 루트입니까?
  3. AddTask, RemoveTask를 프로젝트에 포함해야합니까?
  4. AddSubTask, RemoveSubTask가 작업에 속해야합니까?

답변

2

답은 사용자 (실제로 도메인 전문가)가 보호하고자하는 불변량에 따라 달라집니다.

프로젝트가 addTask 일 때 작업이 집계이고 작업이 로컬 엔터티이고 하나의 트랜잭션에서 일부 불변량 (예 : "this.ProjectType"에 대한 귀하의 의견 "// 일부 비즈니스 로직")을 보호하려는 경우 (즉,이 제약 조건은 언제든지 깨진). 따라서 addTask/removeTask 및 심지어 addSubTask/removeSubTask가 Project에 추가되어야합니다. 프로젝트 관리자와 같은 사용자가 한 명만있는 경우에는 문제가되지 않지만 할당 된 사용자와 같은 많은 사용자가 자신의 작업을 수정하려는 경우 빈번한 동시 오류가 발생하여 응용 프로그램을 사용할 수 없게 될 수 있습니다.

Vernon‘s famous article about aggregate에 관심이있을 수 있습니다. 그가 사용한 예는 그나저나 당신의 경우와 아주 유사합니다.

UPDATE는

나는 큰 집계 unneccesary 동시 고장의 원인이됩니다 것을 의미한다. Project가 집계이고 Task가 로컬 엔터티라고 가정하면 Project를 통해서만 추가/제거 및 수정 작업을 수행 할 수 있습니다. Project1의 Task1의 담당자이고 Project1의 Task2에 대한 assgine이라고 가정 해 봅시다. Project1 (하나는 성공하고 다른 하나는 동시성 실패에 실패했습니다)에 대한 작업 설명을 동시에 업데이트 할 수 없습니다. 큰 프로젝트와 많은 작업 (따라서 잠재적으로 많은 할당 된 사용자)이있는 경우이 문제는 더 심각합니다. 반면에 응용 프로그램이 프로젝트 관리자 용으로 만 설계된 경우 큰 집계는 문제가되지 않습니다. 두 명의 프로젝트 관리자가 동시에 한 프로젝트를 수정하는 경우는 거의 없기 때문입니다. UPDATE2

당신은 더러운 업데이트를 방지 할 수 있습니다 전략을 잠금 언급 한 바와 같이. 그러나 문제는 자물쇠의 정밀도입니다.

작업이 집계 인 경우 다른 사용자가 편집하려고 할 때 Task1 만 잠겨 있습니다. 잠재적 인 경쟁이 낮습니다 (sametime의 누군가가 Task2를 편집하려고합니다. 괜찮습니다. 그냥 수행하십시오. 동시성 문제 없음).

프로젝트가 집계 인 경우 누구나 Project1을 잠글 필요가 있으므로 다른 사람이 Task2 (Project를 잠글 필요가 있음)를 편집하려는 경우 동시성 오류가 발생하거나 기다려야합니다. 이 이 유용성 문제가 될 수 있으므로 은 종종이 관련없는 문제 (사용자 관점에서 볼 때 왜 다른 사람이 Task1을 편집 할 때 Task2를 편집 할 수 없습니까?)에 실패하면 짜증이납니다.

Vernon의 글에서 설명한 솔루션은 더 작은 집계를 사용하는 것입니다. 처리량과 확장 성을 향상 시키지만 복잡성을 추가합니다. (프로젝트에 의해 보호되는 불변 변수는 트랜잭션 일관성있게 보호되어야합니다. 즉, 언제든지 보호되지 않아야합니다.)나는 당신이 신중하게 불변의 것을 고려해 보라고 제안한다. (그들은 정말로 필요하다.) "더 작은 집계가 더 좋다"와 같은 선입견이 아니라 실제 생각과 확장성에 기초한 당신의 결정을 내릴 것을 제안한다. 건배.

+0

나는이 라인을 이해하지 못한다 : "프로젝트 관리자와 같은 한 명의 사용자 만 있다면 이것은 괜찮은 일이다.하지만 많은 사용자 (예 : 할당 된 사람)가 자신의 작업을 수정하려고 할 때 이것은 자주 발생하는 동시 발생을 야기 할 수있다. 응용 프로그램을 사용할 수 없게 만듭니다. " – oguzh4n

+0

@ oguzh4n 죄송합니다, 저의 가난한 영어 :(내 업데이 트를 보시고 Vernon의 기사에서 작은 집계 장을 가져올 수 있습니다. (링크 참조) – Hippoom

+0

감사합니다. 동시에 많은 사용자와 함께 작업을 편집 할 수 있습니다. 힌트 : 낙관적 인 동시성을 사용하지만 "동시성 (concurrency)"이란 말은 동시성 문제를 어떻게 해결할 수 있습니까? – oguzh4n

1

1 + 2. 프로젝트를 다른 엔터티에 의존하지 않고도 소유 할 수 있습니까? 자체 라이프 사이클이 있습니까? 예. 그것은 집합입니다. 작업이 다른 종속성 없이도 살 수 있습니까? 그것 자체에 승무원 과제가있는 것이 당연한가요? 그것은 그렇지 않은 것 같습니다. 집계가 아닙니다 (루트). 프로젝트 만 독립적 인 라이프 사이클을 가지며, 태스크는 그렇지 않습니다.

3 + 4. 작업은 프로젝트에 따라 다르므로 프로젝트에 CRUD 작업을 추가/제거하는 것만으로도 충분합니다.

부모가 아닌 루트 태스크의 상황을 커버하지 않기 때문에 서브 태스크 방법은 조금 어렵다. 물론 null을 사용할 수 있지만이 특수한 종류의 작업 (예 : RootTask)을 표현하면 많은 문제를 해결할 수 있으며 머리에 낀 것은 의심 할 여지가 있습니다. 프로젝트는 루트 작업 만 포함하고 이러한 작업은 하위 작업을 허용 할 수 있습니다. (단순한) 과제 자체와 프로젝트 사이에는 직접적인 관계가 없다.