도메인 기반 설계 및 도메인 간 상호 작용


10

나는 상대적인 DDD 초보자이지만, 나는 내 지식을 쏟아 내고 증류시킬 수있는 모든 것을 읽고 있습니다.

나는이 DDD 질문을 보았고 그 대답 중 하나가 흥미로웠다.

DDD 경계 컨텍스트 및 도메인?

답 중 하나에서 포스터는 전자 상거래 시스템의 예를 제공하며 제품이 2 개 이상의 도메인에 있습니다.

1) 제품 카탈로그 2) 재고 관리

전자 상거래 프론트 엔드에서는 제품 정보를 표시하고 재고 관리에는 관심이 없습니다.

그러나. 웹 페이지에 재고 레벨을 표시하거나 재고의 재고 버전 번호를 표시 할 수 있습니다 (재고가 책, 잡지 등이라고 가정). 이 정보는 인벤토리 도메인에서 제공됩니다.

그럼 어떻게 처리할까요? 당신은

a) 제품 도메인과 인벤토리 도메인 집계를 모두로드합니까? b) 제품 도메인 엔터티에 일부 재고 및 재고 버전을 보유한 다음 인벤토리 엔터티가 업데이트 될 때 도메인 이벤트를 사용하여 속성을 업데이트 하시겠습니까?

마지막 질문입니다. 나는 우리가 도메인의 지속성을 잊거나 무시하고 도메인에 대해 생각해야한다는 것을 알고 있습니다. 그러나 이것을 생각하기 위해 위의 예에서 제품 카탈로그 및 제품 인벤토리에 대해 잠재적으로 2 개의 DB 테이블이 생길 것입니다. 이제 동일한 제품이므로 동일한 식별자를 사용합니까? 또는 데이터에 1 개의 테이블과 1 개의 테이블 행을 사용하고 관련 데이터를 집계 속성에 간단히 매핑 할 수 있습니까?

답변:


8

웹 페이지에 재고 레벨을 표시하거나 재고의 재고 버전 번호를 표시 할 수 있습니다 (재고가 책, 잡지 등이라고 가정). 이 정보는 인벤토리 도메인에서 제공됩니다.

이 시점에서 주목해야 할 것은 뷰에 대해 이야기하고 있다는 것입니다. 즉, 오래된 데이터 사용이 허용됩니다.

즉, 변경 사항이 비즈니스 불변을 위반하는 것을 방지하는 책임이있는 집계와 상호 작용할 필요는 없지만 최근 집계 상태의 복사본을 나타냅니다.

따라서 일반적으로 기대하는 것은 제품 카탈로그에 대한 쿼리 실행과 인벤토리에 대한 실행 및 뷰를 지원하는 데 필요한 두 가지를 DTO로 구성하는 것입니다.

제품 도메인과 인벤토리 도메인 집계를 모두로드 하시겠습니까?

그래서 가까이에 있습니다. 아무것도 변경하지 않으므로 집계를로드 할 필요가 없습니다. 그러나 우리는 그들의 상태가 필요합니다. 로드 할 수 있습니다. 즉, 일반적으로 두 도메인이 다른 프로세스에서 실행될 것으로 예상합니다. 따라서 둘 다로드하지 않고 둘 다 호출합니다.

재고 도메인 번호 및 재고 에디션에 대한 제품 도메인 엔티티의 일부 특성을 보유한 후 재고 엔티티가 업데이트 될 때 도메인 이벤트를 사용하여이를 업데이트 하시겠습니까?

"하천을 가로 지르지 마십시오. 나쁠 것입니다."

도메인 컨텍스트에서 정보를 조정하기 위해 이벤트 사용 : 좋은 아이디어. 한 도메인에 속한 개념을 다른 도메인으로 푸시 : 더 많은 것을 제외하고 좋은 아이디어의 반대.

도메인을 깨끗하게 유지하려고합니다. 도메인과 상호 작용 하는 응용 프로그램 은 그렇게 중요하지 않습니다. 예를 들어, Inventory 애플리케이션은 제품 애플리케이션에서 서비스를 호출하여 일부 제품 특정 개념을 조회하여 뷰에 추가하는 것이 합리적입니다. 혹은 그 반대로도.

단일 응용 프로그램을 단일 도메인으로 제한 해야하는 이유를 모르겠습니다. 진실의 원천이있는 한, 원하는 방식으로 거래를 배포 할 수 있습니다.

그러나 이것을 생각하기 위해 위의 예에서 제품 카탈로그 및 제품 인벤토리에 대해 잠재적으로 2 개의 DB 테이블이 생길 것입니다. 이제 동일한 제품이므로 동일한 식별자를 사용합니까?

쉬운 방법이 될 것입니다. 실세계 엔터티가 동일하므로 더 큰 용어로 동일한 식별자를 사용합니다. 두 개의 다른 경계 컨텍스트 모델 다르게 그 실체를하지만,이 모델은 현실 세계의 실체가 아닙니다.

그래도 문제가 해결되지 않으면 갭을 메우기 위해 사용할 쿼리가 필요합니다. 가장 일반적인 변형은 새로운 엔터티가 이전 엔터티의 ID를 유지한다는 것입니다. BC 주 내에서도이를 확인할 수 있습니다. 신청자가 승인되면 고객이됩니다. 다른 집계입니다 (클라이언트와 관련된 상태는 신청자의 상태와 다릅니다.). 따라서 지속성 계층이 이벤트 스트림을 사용하는 경우 새 집계의 스트림에는 다른 식별자가 필요합니다. 어딘가에 "이 신청자가이 고객이되었습니다"라는 문구가있을 것입니다.

또는 데이터에 1 개의 테이블과 1 개의 테이블 행을 사용하고 관련 데이터를 집계 속성에 간단히 매핑 할 수 있습니까?

이봐! 아뇨, 그렇게하지 마십시오. 비즈니스상의 이유없이 거래 경합을 추가하고 있습니다.


나는 이것을 대답으로 똑딱 거리었다. 뷰에 표시하기 위해 데이터를 읽는 것은 집계를로드 할 필요가 없다는 것을 지적한 아래의 @guillaume에게도 신용했다. 자세한 답변을 주셔서 감사합니다. "전통적인"데이터 모델의 첫 번째 접근 방식으로 인해 지속성 계층을 잊고 도메인 언어에 집중하는 것이 어렵다는 것을 알게되었습니다. 내가 이해했다고 생각할 때, 나는 나의 이해를 불식시키는 또 다른 기사를 읽습니다.
PendorPaul

이 기사 msdn.microsoft.com/en-us/magazine/dn802601.aspx 를 읽고 도메인 이벤트를 사용하여 컨텍스트간에 일부 데이터를 복제하는 방법에 대해 자세히 설명합니다. 고객 서비스와 주문 처리 시스템간에 고객 목록을 공유하는 예입니다. 주문 시스템에서 고객 데이터를 복제하고 이벤트를 사용하여 데이터를 동기화합니다. 이것은 우리가 여기에 대답 한 것에 직면하여 날아갑니다. 확실히 링크 된 샘플에서 주문 컨텍스트에는 customerID가 필요하며, 이는 고객 서비스 컨텍스트에 액세스 할 수있는 애플리케이션에서 채울 수 있습니다.
PendorPaul

당신은 여기에 당신의 생각에 매우 정확하기를 원할 것입니다. 시스템 간 데이터 복사는 도메인 모델 간 데이터 복사와 동일하지 않습니다. "read only [mumble]"가 표시 될 때마다 데이터가 해당 도메인에 속하지 않는다는 큰 힌트입니다 (응용 프로그램이 여전히 신경 쓰이더라도).
VoiceOfUnreason

네, 저도 그렇게 생각했습니다. 사고 과정의 변화는 물을 흐릿하게 만드는 기사를“전문가”없이는 충분히 어렵다. 나는 오늘 내 도메인을 분석하고 BC와 골재 뿌리가 어디에 있는지 완전히 이해하려고 노력했습니다. 나는 거의 거기에 있지만, 내가 갈 때 내 모델을 구체화하고 리팩터링 할 수 있다는 것을 알고 있습니다. 나는 며칠 동안 분석 지옥에 갇혀 있었고 DDD가 내 머리에 똑바로 있지 않을까 염려하는 코드 작성을 걱정하고 있습니다. 나는 균열을 일으키고 코드에 계속 의문을 제기하는 것이 가장 좋으며 모델이 올바른지 여부를 생각합니다. 나는 거기에 갈 것이다. 감사합니다
PendorPaul

어쩌면 내가 잘못 읽은 것으로 생각되는 관행은 Event-Carried State Transfer (Event-Carried State Transfer)라고하며 데이터를 필터링하고 페이지 해야하는 대시 보드 / 테이블보기에 특히 강력한 모델 일 수 있습니다 여러 서비스. 도메인 이벤트에서 "투영"(기본적으로보기)을 구축하여 이러한 대시 보드를 구동 할 수 있습니다. 나는 그것을 꽤 성공적으로 사용하기 전에 사용했습니다. 올바른 시나리오에서 매우 강력한 도구가 될 수 있습니다. 여기서 더 중요한 것은 이러한 예측이 도메인 모델을 나타내지 않으며 비즈니스 로직을 포함해서는 안된다는 것을 인식한다는 것입니다.
Jordan

3

귀하의 질문에 실제로 2 개의 직교 옵션 세트가 필요하다고 생각합니다.

  • 두 개의 객체를로드하고 데이터를 함께 표시하거나 원하는 모든 것을 포함하는 1 개의 객체를로드합니까?

  • 물건이나 다른 것을 표시하기 위해 집계를 사용합니까?

CQRS 접근 방식을 믿는다면 집계가 읽기에 가장 적합하지 않을 수 있습니다. 데이터를 표시하든 수정하든 집계를로드 할 때마다 시스템에 동시성과 경합이 추가됩니다. 또한 표시에 맞게 조정 된 임시 읽기 모델을 사용하는 경우보다 집계가 더 커지고로드 속도가 느릴 수 있습니다.

Q)의 해결책 a)는 이러한 많은 함정의 영향을받는 것으로 보입니다. 옵션 b)는 유효 할 수 있지만 집계를 변경할 InventoryManagement때 불변량을 적용하기 위해 BC주의 데이터 가 필요한 경우에만 사용합니다 Product. 집계에 수정시 비즈니스 규칙을 확인하는 데 필요한 모든 데이터가 포함되어있는 것이 더 좋지만 읽기 측에서는 어디에나 앉아있을 수 있습니다.

데이터와 관련하여 일반적인 권장 사항은 Bounded Contexts에 자체 데이터베이스 (배포 가능성 및 SoC 이유로)를 제공하는 것입니다. 두 BC 간의 제품을 일치 시키려면 동일한 식별자를 사용해야합니다.

BC 주 간 상호 작용에 대해서는 /programming/16713041/communicating-between-two-bounded-contexts-in-ddd참조하십시오.


1
알았어. 본질적으로 우리는 불변이 일관되고 데이터가 유효한지 확인하기 위해 Aggregate Roots 및 BC를 사용하고 있으며 수행하려는 작업은 집계 또는 BC 내에 래핑됩니다. 해당 데이터를 읽고 표시 할 때 모든 집계 / BC가 수화되지 않고 별도로 경량으로 처리 할 수 ​​있습니다. 결국 보고서 나 화면에 데이터를 표시하기 만하면 집계를로드해야하는 이유는 무엇입니까? 이것은 완벽하게 이해됩니다. 감사.
PendorPaul

이것이 바로 CQRS가 실제로 빛나는 곳입니다. SQL 쿼리를 수행하고 테이블을 조인하며 특정 뷰에 대해 맞춤형 쿼리를 반환하면됩니다. 또한 쿼리 방법 엉망에서 repo를 지 웁니다. 또한 ElasticSearch와 같은 서비스의 데이터를 복제하여 쿼리 할 수도 있습니다.
notnotmatter 2016 년

1

DDD는 비즈니스 로직이 복잡한 애플리케이션을위한 것입니다. "인쇄"는 복잡한 비즈니스 로직이 아닙니다. 실제로 비즈니스 로직이 아닙니다.

한 컨텍스트에서 비즈니스 로직이 일부 사용 사례를 올바르게 처리하기 위해 일부 정보가 필요한 경우 해당 정보는 해당 컨텍스트의 일부입니다. 따라서 하나의 경계 컨텍스트에 다른 경계 컨텍스트에서 사용 가능한 정보가 필요할 수 있다는 아이디어는 의미가 없습니다. 경계 컨텍스트에는 필요한 모든 정보가 있기 때문입니다.


좋아, 아마존과 같은 것을 생각해보십시오. 복잡한 비즈니스 로직을 갖춘 복잡한 시스템입니다. 카탈로그 관리 및 재고 관리가 있습니다. 카탈로그를 관리하기 위해 재고 총계가 필요하지 않습니다. 즉, 제품 이름, 설명, 유형, 조건 등을 의미합니다. 그러나 매장 첫 페이지에 재고 품목 수를 표시합니다. 이 시나리오에서 제품 카탈로그 관리와 제품 인벤토리 도메인을 분리하려고하지만 제품 페이지에 재고에 대한 정보를 표시해야하는 경우 어떻게합니까?
PendorPaul

내가 말하는 것은 제품 카탈로그 도메인에 제품 카탈로그를 관리하는 데 필요한 모든 정보가 있다는 것입니다. 재고 도메인에는 재고를 관리하는 데 필요한 모든 정보가 있습니다. 그러나 사용자에게 일부 정보를 표시하려고 할 때 해당 데이터는 2 개의 도메인에서 가져옵니다. UI에 두 도메인을 모두로드하고 표시하려는 속성을 바인딩합니까? 또는 UI에 필요한 데이터가 포함 된 익명 형식 또는 DTO를 반환하는보고 / 읽기 메커니즘이 있습니까?
PendorPaul

11 개월 전의 저의 오래된 의견을 되돌아 보면 코믹하지만 평생 인 것 같습니다. 내가 이해하고있는 응용 프로그램이 상당히 발전했습니다. 이제 Jimmy Bogards Mediatr을 통해 CQRS 방법을 사용하고 있습니다. 집계와 상호 작용하는 명령이 있지만 쿼리 및 쿼리 처리기를 사용하여 표시에 필요한 모든 것을 가져 오는 유연성이 뛰어납니다. 해당 QueryHandler를 호출하는 Views로 묶으십시오. 디커플링은 이것으로 좋습니다. 감사합니다
PendorPaul

@PendorPaul, 난 당신이 11 개월 (현재 13)했던 곳이라고 생각합니다. 지금 어디로 갔습니까?
Greg Bell

1
@GregBell 사고 방식을 변경해야합니다. "데이터베이스 디자인, 데이터 계층 구축, 비즈니스 로직 구축 등"이라는 접근 방식에 갇혀있었습니다. 그리고 모든 엔터티를 만드는 데 집중했습니다. 즉, 전자 상거래 사이트의 "제품"은 가격, 설명, 재고, 재고 위치 등 모든 것을 처리하지만 매우 복잡합니다. 제한된 컨텍스트 접근 방식은 인벤토리 컨텍스트에서 "제품"은 인벤토리 관리를위한 정보 및 동작 만 포함 함을 의미합니다. 설명 및 이미지는 가격 컨텍스트에서 가격이 결정되는 컨텐츠 컨텍스트에서 관리됩니다.
PendorPaul

1

내 관점에서 볼 때 "Product"에 대한 정의가 다릅니다. 모든 경계 컨텍스트에는 "product"-domain에 대한 자체 정의가 없습니다.

  • Content-Management-Bounding-Context에서 제품에는 이미지와 설명 텍스트가 있습니다.
  • 재고 경계 컨텍스트에서 제품은 재고 수량, 제품 판매자, 제품이 사용 가능할 때까지 예측됩니다.
  • 가격 계산 경계 상황에는 수량 당 제품 가격이 얼마인지에 대한 규칙이 있습니다.

외에도 자체 제품 정의 (다른 경계 컨텍스트의 제품 도메인과 관련된 조합)와 함께 추가 Shop-Bounding-Context추가합니다 .

Shop-Product는 "Inventory"의 컨텐츠 및 가용성에서 "이미지 및 설명 텍스트"를 가지지 만 인벤토리의 "제품 판매자"는 아닙니다.

이 추가 Shop-Bounding-Context는 Bounding-Context-s 컨텐츠, 인벤토리, 가격에 따라 다릅니다.


Shop-Product BC를 어떻게 만드십니까? 이러한 맥락에서 Product 및 Inventory BC에 대한 참조가 있으며 Store-Product BC를로드 할 때 지속성 저장소에서 해당 항목을 수화 한 다음 StoreProduct 속성을 통해 해당 BC에서 원하는 속성을 제공하고 있습니까? 나는이 기사를 실제로 생각하고, BC 이벤트를 가로 지르는 선을 따라 있지만 위의 @ guillaume13은 표시 목적으로 BC를 피하고 내 견해에 필요한 데이터를 다시 가져올 수 있다고 지적했습니다. msdn.microsoft.com/ko-kr/magazine/dn802601.aspx
PendorPaul
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.