도메인 기반 디자인의 도메인 개체는 쓰기 전용이어야합니까?


13

나는 거의 2 년 동안 Domain Driven Design에 대해 읽었으며, 일상 업무에 몇 가지 개념을 조심스럽게 소개하거나 최소한 Domain Driven Design 내에서 정기적으로 수행하는 작업에 대한 계획을 세우고 있습니다.

도메인 개체가 쓰기 목적으로 만 사용된다는 이벤트 소싱 및 CQRS (Command Query Responsibility Segregation)에 대한 자세한 내용을 읽은 결과로 특히 시작하기 시작했다는 결론에 도달했습니다. 더 명확하게 말하면, 사람들이 많은 문서에서 미묘하게 제안하는 것은 도메인 객체가 도메인 중심 작업 / 계산, 유효성 검사를 수행하고 주로 지속성을 향한 길을 제공한다는 것을 읽은 것 같습니다 리포지토리 구현 내에서 제공되는 인프라 이것이 도메인 상태를 노출시키는 책임을 제거함으로써 도메인 모델을 크게 단순화 할 수 있다는 사실을 좋아하지만.

실제로 도메인 객체가 주로 쓰기 전용 객체로 사용되는 것이 맞다면 누군가 대답 할 수 있기를 바랍니다.

  1. setter가있는 객체 나 객체의 상태를 수정하지만 C #의 속성 getter와 같은 상태를 읽을 수있는 외부 공용 인터페이스를 제공하지 않는 객체에 대해 단위 테스트를 수행하는 방법은 무엇입니까? 객체를 테스트 할 수 있도록 목적으로 만 상태를 공개해도 괜찮습니까?
  2. 도메인에서 수행 한 계산 또는 작업의 결과를 유지하지 않고 사용자에게 표시 한 다음 도메인 컨텍스트 외부의 지속 저장소에서 결과를 가져 오는 방법은 무엇입니까? 결과를 보여주기위한 목적으로 만 상태를 공개해도 괜찮습니다.

경험상 유일한 getter (get 접근 자)가 도메인에서도 쓸 수있는 규칙이어야합니까? 또는 읽기 전용 속성은 읽기 목적으로 만 존재하므로 실제 도메인 모델에서 필요한 역할을 수행하지 않기 때문에 피해야 할 유일한 속성이라고 다르게 말했습니까?

관련 자료 :

  1. TDD, DDD 및 캡슐화

답변:


9

공정하게 발전하고있는 설계 접근 방식에 대한 '하나의 진정한 방법'이 있는지 확실하지 않습니다. 첫째, CQRS 사람들이 DDD에 영향을받는 출발점에서 파생 된 것으로 보이지만 DDD와 CQRS는 같은 것이 아닙니다.

DDD 사고 방식에는 많은 일이 일어나고 있으며, 코드의 특정 구현은 아니지만 올바르게 정의 된 문제의 경계, 이해 관계자 간의 커뮤니케이션 및 시스템 간의 상호 작용과 관련이 있습니다. 핵심은 미덕이다.

도메인 객체의 변경 가능 여부와 방법, 그리고 도메인 객체가 시스템에서 전체적으로 어떤 기능을 수행하는지에 대한 토론이있을 수 있습니다. CQRS는 시스템을 읽기 및 쓰기 경로로 분할하므로 쓰기 경로에있을 때 실제로 읽기 액세스가 필요하지 않다는 결론을내는 것이 합리적입니다. 그런 다음 읽기는 일부 도메인 객체에 의해 발생하고 다른 도메인 객체에 의해 소비 (처리) 된 이벤트에 대해 수행하는 작업이됩니다. CQRS 히스토리에서 약간 돌아 가면 도메인 오브젝트에 setter가없고 getter와 단일 'handler'메소드 만 있어야한다는 인수가 있습니다. 여기서의 논리는 이벤트 만 소비하면 상태가 변경되고 해당 변경은 도메인 개체에 의해 내부적으로 처리된다는 것입니다.

변경 결과를 별도의 변경 아티팩트로 처리하고 별도의 평평한 영구 구조 (예 : 테이블)에 배치하고 시스템의 현재 및 과거 상태에 대한 보고서를 읽는 것처럼 읽음으로써 변경 결과를 표시합니다. . 예를 들어, 읽을 데이터를 추출하여 시스템의 단일보기 (예 : 화면)에 밀접하게 맵핑되는 데이터베이스 테이블에 저장하여 이벤트를 사용할 수 있습니다.

이 스타일을 실험 해보면 다른 프로그래머들도이 방법에 익숙하지 않을 것입니다. 그리고 디자인 방식으로 정당화 될 수있는 (그러나 흥미로운) 시나리오는 비교적 적습니다.

단위 테스트에는 몇 가지 접근 방식이 있습니다. 첫 번째로 가장 자연스러운 것은 도메인 개체에서 발생하는 것으로 예상되는 이벤트가 올바른지 확인하는 것입니다. 도메인 객체는 변경 사항에 대한 정보를 담고있는 일반 변경 이벤트를 발생시킬 수 있습니다. 당신은 그것을 확인할 수 있습니다. 이벤트가 전혀 발생하지 않았으며 다른 이벤트가 발생하지 않았 음을 확인할 수 있습니다.

또 다른 방법은 도메인 개체에서 읽을 수있는 특성을 노출시키는 테스트 스파이를 사용하여 상태 변경을 확인할 수 있습니다. 예를 들어 도메인 개체에서 상속하고 접근자를 추가하여 캡슐화 된 상태를 읽고 올바른지 확인할 수 있습니다.

다시 말하지만, 이러한 접근 방식은 혼란 스럽기 때문에 혼란스러워합니다. 프로그래밍에 좋은 아이디어를 적용하려면 먼저 수분을 섭취하십시오. DDD 경계와 역할을 명시 적으로 만드는 것은 코드와의 커뮤니케이션에 대한 사고 방식의 변화입니다. CQRS는 최소한 데이터 읽기와 데이터 쓰기가 분리 가능한 작업임을 제안합니다. 이러한 통찰력은 데이터의 역할이 무엇인지, 실제로 필요한지, 누가 소비하는지, 얼마나 신선한 지 등을 매우 명확하게 생각하게합니다. 코딩에서 더 나은 캡슐화를 채택하기위한 완전한 이벤트 소싱 구현. 객체 인터페이스 디자인에 대한 "Tell, Do n't Ask"접근법,


1
쥬시 비트로 시작하는 경우 +1 또한 CQS를 물고 ( '이벤트'부분을 생략) 시작하는 것이 좋습니다.
cottsak

1

도메인 기반 디자인의 도메인 개체는 쓰기 전용이어야합니까?

CQRS은 DDD와 함께 사용 할 수 있습니다.


그러나 CQRS의 쿼리 부분은 도메인 모델에서 모델에 변경 사항을 기록하는 데 사용되는 데이터를 쿼리하거나 사용자에게 값을 표시 할 수있는 응용 프로그램 계층의 데이터를 쿼리하는 데 사용할 수 있습니까? DDD가 변경 조정에 관한 것이므로 도메인 모델 내의 다른 개체에 대한 변경을 조정하는 것 이외의 다른 목적으로 읽지 말아야한다는 의견을 듣고 있습니다. 어떤 방법 으로든 다른 방법으로 결정한다는 것은 도메인 객체에 노출 된 데이터가 도메인에서만 소비되는 경우 제한적으로 변한다는 것을 보는 완전히 다른 모델 설계를 의미합니다.
jpierson

0

도메인 모델 단위 테스트는 실행 된 각 명령에 대해 올바른 도메인 이벤트가 발생하는지 확인해야합니다. 도메인 명령 및 캡처 된 이벤트를 상태에 대해 조사 할 수 있습니다.

ToString()사람이 읽을 수있는 상태를 자동으로보고하도록 도메인 명령 및 이벤트를 재정의 할 수도 있습니다 .

두 번째 질문에 답하기 위해 명령 결과를 표시하려면 도메인 이벤트가 읽기 모델에 '게시'되도록해야합니다.


이벤트 소싱을 사용하지 않을 때 이것이 여전히 적용되는지 여부를 조금 더 자세히 설명해 주시겠습니까?
jpierson

1
이벤트 소싱이 없다면 아마도 내 제안은 효과가 없을 것입니다. 코드의 방법을 모르겠습니다. 속성을 노출시키지 않는 도메인 개체의 경우 테스트하려는 속성을 노출하는 테스트 인터페이스를 명시 적으로 구현할 수 있습니다 . 테스트 코드 만이 그러한 도메인 객체를 테스트 인터페이스로 캐스트 할 수 있습니다.
Ed James

그 제안에 감사드립니다. 테스트를 위해 도메인 클래스를 수정한다는 생각이 다소 불안하지만 테스트하기를 원한다면 이것이 도메인 기반 디자인의 회색 영역 중 하나 일 수 있다고 생각합니다. 또 다른 생각은 동일한 인터페이스를 통해 안정성과 테스트 가능성을 노출하려는 경우 적어도 두 가지가 아닌 하나의 인프라 종속성 만 도입한다는 것입니다. 다른 사람들은 어떻게 생각합니까?
jpierson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.