2014-11-21 6 views
7

내 도메인에 대한 간략한 설명은 다음과 같습니다.DDD/CQRS/EventSourced 프로젝트에서 투표/유사 시스템을 모델링하는 방법은 무엇입니까?

나는 어떤 기사 (제목, 요약 및 본문)와 기본적으로 비슷한 기사입니다.

내 기사에 투표를 허용해야하며, 익명 사용자가 투표를 할 수 있습니다 (등록은 필요 없지만 세션은 투표를 저장할 것이므로 여기에 집중하지 마십시오).

이 도메인에서 아티클은 내 통합 루트입니다.

나는 다음과 같은 요구 사항을 내 투표를 모델링하는 방법을 찾을 수 없습니다 :

는 응답이 중 내가 좋아하는 수 있습니다 또는 나는 그것을 변경할 수 있어야한다, 좋아하지 않는다

를 (이 시간이 지남에 따라 변경 될 수 있습니다 또는 심지어 취소됨)

관련 세션이있는 게스트 사용자는 기사당 1 표만 출연 할 수 있습니다.

그럼 투표를 자체적으로 집계해야합니까?

뭔가 내가 유니시티를 확인하는 방법

Class Vote { public function cast(ArticleId id, GuestSessionToken token, VoteValue value); }

그러나이 경우

같은? 최종 일관성 사용 (드물기 때문에 복제본이 없기 때문에 괜찮습니다.)

제 기사 집계에 투표 방법을 추가하면 각 투표에 대한 기록을 재생해야합니다. 이는 각 기사당 100,000 표를 가질 수 있다는 사실을 감안할 때 상당히 느리게 들립니다.

DDD 방식을 설계 할 때 성능 및 최적화를 고려해서는 안되지만 여기서는 구현하기 전에 해결해야 할 특정 문제입니다.

이전에 비슷한 경험을 한 사람이 있습니까?

+0

나는 비슷한 질문을 여기에 대답 : http://stackoverflow.com/a/38259448/225022 – Bishoy

답변

-1

저는 Vote 객체와 VoteCast 객체를 분리 할 것입니다.

VoteCast는 이벤트이며 Up, Down 또는 Cancel 값을 가질 수 있습니다. VoteCast에서 업데이트 된 Vote 객체도 있습니다.

투표 수를 계산할 때 투표 수를 계산하지 않고 투표 수만 계산하면됩니다. Votes를 Article (Up, Down)의 콜렉션에 넣고 콜렉션 수를 반환하면됩니다. VoteCast는 Votes가 포함 된 콜렉션을 수정합니다.

+0

심지어 당신은 "recount"투표에 VoteCasts를 다시 적용 할 수 있습니다 :-) –

7

투표는 자체적으로 집계 된 루트입니다. "하나의 기사에 다수의 표가있는"협회에 관해 생각해 보면 관계형 접근 방식을 적용하고 있으므로 DDD 커뮤니티에서 합의한 비평 방식의 큰 총체 접근 방식으로 기울어지게됩니다. 대신 우리는 행동에 초점을 맞추고 싶습니다. 우리는 이미 기사가 표결을지지 않을 것이라는 것을 알고 있습니다. 투표는 자체 라이프 사이클이 필요할 것이므로 자체 정체성과 자체 저장소를 갖게됩니다. 기사는 사용자가 투표, 우리의 도메인 모델 그래서 우리는

anArticle.votedBy(aReader); 

는 사용자가을한다는 것을 기억하라 "기사는 사용자가 선정되어"말할 수 도메인 전문가의 의미와 재생에 의미를 줄 수있는 좋은 방법입니다 이 한정된 맥락에서 독자의 역할 votedBy 메소드는 투표를 작성하는 위치에있는 팩토리 메소드입니다.그것의 구현은 다음과 같습니다

Article.votedBy(aReader) { 
    return new Vote(this, aReader); 
} 

항상 연결이 끊긴 모델을 홍보하는 대신 다른 집계 뿌리 실제 참조를 들고 투표는 기사와 독자의 개념 식별자를해야합니다 마지막에 그 기억. 따라서 도메인 서비스는 독자가 될 것입니다. 데이터베이스 수준에서 구성 고유 제한 조건을 배치하여 (반드시 사용자가 한 번만 기사를 투표하기) 고유의 휴식 인터페이스

RestInterface.voteArticle(articleId) { 
    reader = new Reader(articleRepository); 
    reader.vote(articleId); 
} 

Reader.vote(anArticleId) { 
    article = articleRepository.get(anArticleId); 
    vote = article.votedBy(this); 
    voteRepository.add(vote); 
} 

당신은 확인해야합니다를 모델링한다고 가정하자. 이는이를 확인하는 데 가장 방해가되지 않는 방법이며, 그렇지 않으면 투표를 중재하는 다른 도메인 모델을 추가해야합니다. 어쩌면이 새로운 객체가 다른 투표 비즈니스 규칙을 만들 때 더 이해할 수 있지만 기사가 충분하면 한 번 독자가 투표하도록하고 가장 단순한 솔루션 (DB 제약 조건을 설정하는 것)이라고 생각합니다. DDD는 학습 과정이며, 우리가 도메인에 대해 새로운 것을 배울 때 우리는 사용자가처럼 충돌 또는 우리가 지금까지 조금 한 일을 다시 인수에 대해 우리가 생각 있도록 기사에 버튼을 싫어하는 수 있습니다 실현 :

Article.likedBy(aReader) { 
    return Vote.positiveByOn(aReader, this); 
} 

Article.dislikedBy(aReader) { 
    return Vote.negativeByOn(aReader, this); 
} 
을 모두 구현

곳 : 기사 AR에 likedBy/dislikedBy 공장 방법은 투표를 생성하기 때문에

class Vote { 

    readerId 
    articleId 
    typeId 

    Vote(aReaderId, anArticleId, aType) { 
    readerId = aReaderId 
    articleId = anArticleId 
    type = aType 
    } 

    public Enum VoteType { POSITIVE, NEGATIVE } 

    Vote static positiveByOn(aReader, anArticle) { 
    return new Vote(aReader.id, anArticle.id, POSITIVE); 
    } 

    Vote static negativeByOn(aReader, anArticle) { 
    return new Vote(aReader.id, anArticle.id, NEGATIVE); 
    } 
} 

또한,이 기사를 말하는 제약이 N 시간 또는 다른 비즈니스 시나리오보다 더 많은 투표 수 없습니다 배치 할 수 있습니다.

도움이 되었으면 좋겠다.

세바스찬.

+0

DB 제약 조건 저장소 저장 조작 중? 그리고 우리가 데이터베이스를 사용하지 않는다면 어떨까요? –