2011-08-17 5 views
2

클라이언트 코드는 루트가 아닌 집계 내의 엔터티를 참조 할 수 있습니까? 나는 Story (루트), Team (엔티티) 및 TeamMember (엔티티)이 있습니다. AddTeamMember 메서드가 Team 또는 Story에 속하는지 결정하려고합니다.기본 집계 질문

제가보기에 다소 잘못 이해 한 것 같습니다. 내 진짜 질문은 집계 내의 클라이언트 코드 참조 비 루트 엔터티 수 있습니다?

답변

1

제 생각에는 - 그렇게해서는 안됩니다. 특정 집계에 속한 엔티티에 대한 참조가 있으면 전체 집계 컨텍스트없이 해당 엔티티의 메소드를 호출 할 수 있다는 것을 의미하며이를 허용하면 전체 집계가 유효하고 일관성 있는지 여부를 확신 할 수 없습니다.

간단한 예 : 당신이 볼 수 있듯이 구축하고 우리는 두 유효성 검사 규칙이 선택이 집계 루트를 통해 MyEntity를 검색하는 동안

public class MyAggregateRoot 
    { 
     protected MyEntity entity; 

     public void BuildUpAggregate() 
     { 
      ValidateSomeRule(); 
      LoadEntityFromDatabase(); 
     } 

     public MyEntity MyEntity 
     { 
      get 
      { 
       VerifySomeOtherRule(); 
       return entity; 
      } 
     } 
    } 

, - 직접 MyEntity를 참조하는 클라이언트를 허용 할 경우 집계에서 변경 될 수 있습니다 클라이언트가 엔터티를 검색하고 작업을 수행 할 때까지의 시간이므로 더 이상 유효하지 않게되지만이 사실을 알지 못합니다. 즉, 집계가 일관성이없고 잠재적으로 유효하지 않을 수 있습니다.

일반적으로 DDD에는 집계의 엔티티에 대한 모든 액세스가 집계 루트에서 트래버스하여 수행되어야한다는 강력한 규칙이 있습니다.이 규칙은 집계의 일관성을 위해서입니다.

즉, 클라이언트가 참조 할 수있는 것은 엔티티의 투영입니다. 이는 현재 상황에서 특정 작업을 사용할 수 있는지 여부를 표시하고 결정하는 데 필요한 데이터 만 포함하는 읽기 전용 복사본입니다. 더 나아가서 엔티티 세트의 데이터를 단일 프로젝션으로 집계하고 약간 조정하여 UI의 요구 사항에 맞게 조정할 수 있습니다. 이 기술은 비즈니스 도메인을 모델링하는 방법을 UI에서 결정할 수 없기 때문에 매우 유용했습니다.

+0

+1 모든 비 집합 루트 엔티티를 C# 'internal'과 같은 것으로 숨김으로써 이것을 시행하는 것이 합리적이라고 생각하십니까? – Dmitry

+0

@Dmitry : @Dmitry : 이러한 제한 사항의 이점을 볼 수는 있지만 개념적 차원에서이를 시행하려고합니다. 제가 주로하는 일은 집계 루트에 대한 리포지토리를 만들고 리포지토리를 통해서만 엔티티를 검색 할 수있는 규칙을 도입하는 것입니다. '내부'에 숨어있는 것은 테스트를 좀 더 어렵게 만들고 프로젝트의 물리적 구조를 강화한다는 것입니다. AssemblyInfo에서 내부 클래스의 가시성을 설정할 수 있지만, 그럴 경우 솔루션으로 생각할 수 있습니다. 프록시 또는 모의 객체를 만드는 것이 더 어렵습니다. 물론 접근 방식은 팀의 성숙도에 달려 있습니다. – kstaruch

0

아키텍처가 어떻게 작동해야하는지 알지 못하면 Story 대신 Team을 입력해야하는 것처럼 들립니다. 그것은 Team에서 Team Member까지 1 대 다수를 가정하고 그 Team MemberTeam 개체의 자식이며 Story이 아니라고 가정합니다.

+0

'팀'에 1 명 이상의 '팀원'이 있다고 가정합니다. – Tejs

+0

당신은 아이를 말했고, 나는 어떻게 든 하위 클래스를 읽었습니다. 절대로 내 말을 신경 쓰지 마 :) –

0

'루트'또는 '집계'규칙에 대해 확실하지 않지만 스토리가 팀 구성원 자격을 관리하는 방법에 대해 알고 있어야한다고 생각하지 않습니다.

+0

글쎄 팀은 이야기가 없으면 존재하지 않는다. – Marco

0

팀 구성원과 팀 관계가 있어야합니다. 이야기와 팀 구성원은 서로 직접 관련이 없습니다.

클래스가 보일 것 같은 :

class team 
{ 
list<TeamMember> teamMembers; 
void AddTeamMember(TeamMember member){} 
} 

다음 명시 적으로 구성원을 추가 할 팀을 언급해야하는 방법은 이야기의 일부인 경우 팀, 팀 멤버 메소드를 추가해야합니다 또 다른 이유.

addteamMember(Team T, TeamMember member); 

루트는 루트가 아닌 요소 (중첩의 첫 번째 수준)에 액세스하기위한 적절한 방법을 제공해야합니다. 귀하의 경우에는 팀이 addTeamMember 메소드를 가져야하며 스토리에는 지정된 팀의 addTeamMember 메소드를 호출하는 메소드 (AddMemberToTeam (팀 t, 팀 멤버 m))가 있어야합니다.

+0

위의 수정 사항을 참조하십시오. 나의 예가 조금 어지럽 혔다. – Marco

+0

마르코를 얻었습니다. 루트는 루트가 아닌 요소 (중첩의 첫 번째 레벨)에 액세스하기위한 적절한 메소드를 제공해야합니다. 귀하의 경우에는 팀이 addTeamMember 메소드를 가져야하며 스토리에는 지정된 팀의 addTeamMember 메소드를 호출하는 메소드 (AddMemberToTeam (팀 t, 팀 멤버 m))가 있어야합니다. – Tarang

+1

있어. 그래서 클라이언트 코드가 특정 팀 구성원을 요구한다면, 나는 실제 엔티티를 리턴해서는 안되지만, 본질적으로 엔티티의 스냅 샷 인 다른 불변 오브젝트를 리턴해야할까요? – Marco