2016-10-26 6 views
1

사용자 엔티티에 대한 모든 저장소 작업을 담당 할 저장소를 프로젝트에 생성합니다. mongo를 db로 사용하고 mongoreactive를 클라이언트로 사용합니다. 내가 가지고있는 문제는 유형에 관한 것입니다.인프라 코드를 통한 DDD 추상화

trait UserRepository { 
    save(user: User) : ? 
} 

trait MongoUserRepository extends UserRepository { 
    save(user: User) : Future[WriteResult] = { 
     collection.insert(user) 
    } 
} 

내 도메인에서 MongoReactive의 WriteResult를 어떻게 모델링해야합니까? 내 도메인으로 누출되지 않기를 바랍니다. 기존 패턴이나 좋은 연습이 있습니까? 나도 같은 저장소를 구현할 때

답변

1

, 나는 내가 가장 관심 WriteResult 값을 추출 결국 내 경우에는 내가 다음 서명으로 끝났다.

trait UserRepository { 
    save(user: User) : Future[Option[String]] 
} 

반환 일부 오류 메시지 중 하나 또는 nothing. 결과적으로 다음과 같이 구현됩니다 :

trait MongoUserRepository extends UserRepository { 
    save(user: User) : Future[Option[String]] = { 
     collection.insert(user).map(_.errmsg) 
    } 
} 

예외가 발생했을 때 예외 메시지가 손실되지 않기 때문에 구현이 끝났습니다.

trait UserRepository { 
    save(user: User) : Future[Boolean] 
} 

trait MongoUserRepository extends UserRepository { 
    save(user: User) : Future[Boolean] = { 
     collection.insert(user).map(_.ok) 
    } 
} 

을하지만,이 경우는 예외 메시지를 잃게됩니다 :

대체 옵션 Boolean에 삽입 결과를 매핑 할 수 있습니다. 때로는 괜찮을 수도 있지만 귀하의 정확한 경우에 따라 다릅니다.

업데이트 : 위의 답변은 0.11 버전에 유효합니다. 0.12 방법에서 errmsgWriteResult에 제거했습니다. 또는 writeErrors을 사용할 수 있으며 Seq이 비어 있지 않은 경우 errmsg을 모두 WriteError에서 추출 할 수 있습니다.

희망 하시겠습니까?

4

내 도메인에서 MongoReactive의 WriteResult를 어떻게 모델링해야합니까? 내 도메인으로 누출되지 않기를 바랍니다. 기존 패턴이나 좋은 연습이 있습니까?

일반적인 방법은 도메인이 지속성 인프라가 지원해야하는 서비스 프로 바이더 인터페이스 (SPI)로 UserRepository 특성을 정의하는 것입니다. 근본적으로 모델이 지속성에 부과하는 사용 요구 사항을 표현하는 방법입니다. Command Query Separation의 언어를 사용

, save명령이다 : 그것은 저장소의 상태를 변경하는 작업입니다. 따라서 특성을 구현하려면 명령을 구현하기위한 로컬 코딩 표준을 따라야합니다. (generic) repositories

그렉 젊은 : 정확히 첫번째 장소에있는 저장소 패턴의 의도는 무엇

입니까? [DDD, Evans]를 돌아 보면 마치 일련의 객체를 메모리에있는 콜렉션처럼 표현하여 도메인에서 지속성 관련 문제를 해결할 수 있다는 것을 알 수 있습니다. 즉, 목표는 지속성의 객체에 콜렉션 의미를 두는 것입니다.

영감을 얻기 위해 컬렉션 라이브러리에 추가 할 수도 있습니다.

그러나 일반적으로 말해서, 가장 일반적인 선택은 그래서 특정 구현이 만족 예상되는 계약입니다

trait UserRepository { 
    save(user: User) : Unit 
} 

과 같을 것이다.

MongoUserRepository에서 계약을 충족시키기 위해 지속성 솔루션 구현을 조정합니다. 이 경우 Future의 압축을 풀고 WriteResult에 오류가 있는지 검사하고 쓰기가 실패한 경우 예외를 throw하는 것을 의미합니다. 와

저장 (사용자 : 사용자) : 단위는 암시 적으로 (예 : DB 장애시) 저장소 실패를보고 고객의 요구 사항을 넣어 주위

다른 방법 - 저장소 서비스 제공자 인터페이스입니다. 이 디자인은 클라이언트를 제한하지 않고 공급자를 제한합니다. 육각형 아키텍처의 용어에서, 나는 secondary port을 정의하고 2 차 어댑터가 포트 계약에 부합하도록 제약합니다.

동기는 정확히 사용자가 설명하는 것입니다. 저장소 소비자는 선택한 지속성 솔루션과 상호 작용하는 데 필요한 프로토콜과 격리되어 있어야합니다. 도메인 모델은 비즈니스 세계의 한가운데에 자리 잡고 있으며 어댑터는 비즈니스 우주를 현실과 단절시킵니다.

에반스 Chapter 6은 "(도메인 개체) 수명주기 관리의 복잡성으로 인해 모델이 침체되는 것을 방지"라는 관리 과제를 제기합니다. 저장소는 "은 엄청난 인프라가 참여을 캡슐화 동안 영속 객체를 찾아 검색하는 수단을 제공

저장소가 방화벽입니다

것은 우리가 여기서 해결하는 것은의 분리입니다.. 도메인 모델은 비즈니스를 설명 우리는 비즈니스 사례를 명확하게 볼 수 있기를 원합니다. 수정 가능한 상황에서 변경 가능한 메모리 콜렉션이 대격변에서 실패하는 경우 어떻게되는지를 명시 적으로 관리해야한다면 불가능할 것입니다. 응용 프로그램이 처리하지 못하게하십시오.

그건 .. 내가 "당신의 지역 코딩 표준에 부합"한다고 썼을 때 나는 의도적으로 위에 헷지했다. 지역 가이드 라인에서 railway oriented programming 또는 message driven을 사용하는 경우 꼭 확인하십시오. 도메인 모델이 스토리지가 동기 또는 비동기, 로컬 또는 원격인지 여부를 신경 써야하는 이유는 전혀 없습니다.

도메인 모델이 구현 문제를 설명하는 일치 식으로 채워지기 시작하면, 어딘가에서 음모를 잃었습니다.

+1

'save (user : User) : Unit'를 사용하면 다음과 같은 사용법을 강제하는 저장소 실패 (예 : DB 실패의 경우)를 감시하기 위해 클라이언트에 요구 사항을 암시 적으로 넣을 수 있습니다 저장소로) :'try {} catch {case MyFailureException (...) => ...; _ => ...}'. '시도'또는 '미래'가 더 좋을 것이라고 생각하지 않습니까? – tkachuko

+0

또 다른 생각을하면,이 정확한 메서드 서명은 sync (이 메서드 서명에 의해 적용됨)에서 기본 라이브러리 인 비동기 API로 전환 할 수있는 쉬운 방법을 제공하지 않습니다. – tkachuko

관련 문제