DDD 및 값 객체. 변경 가능한 Value Objects는 비 Aggr에 적합한 후보입니다. 루트 엔티티?


9

여기 약간의 문제가 있습니다

값 객체가있는 엔터티가 있어야합니다. 문제가 아니다. 새 값에 대한 값 객체를 교체 한 다음 nhibernate는 새 값을 삽입하고 이전 값을 고아로 만든 다음 삭제합니다. 좋아, 문제 야

내 도메인의 내 엔터티는 보험입니다. 그는 주소 (값 개체) 모음을 가지고 있습니다. 주소 중 하나는 MailingAddress입니다. 우리가 우편 주소를 업데이트하고 싶을 때, 우편 번호가 잘못되었다고 가정 해 봅시다. Evans 교리에 따르면, 이전 객체는 불변이기 때문에 새로운 것으로 교체해야합니다 (가치 객체 권리?).

그러나 해당 주소의 PK는 MailingHistory 테이블의 FK이므로 행을 삭제하고 싶지 않습니다. 에반스 교리에 따르면, 우리는 여기에 거의 망쳐 져 있습니다. 주소 엔터티를 만들지 않으면 "바꾸기"할 필요가없고 이전의 좋은 날과 같이 단순히 우편 번호 멤버를 업데이트 할 필요가 없습니다.

이 경우에 무엇을 제안 하시겠습니까? 내가 보는 방식으로 ValueObjects는 데이터베이스 테이블 열 그룹 (nhibernate의 구성 요소)을 캡슐화하려는 경우에만 유용합니다. 데이터베이스에 지속성 ID가있는 모든 항목을 엔티티 (집계 루트 일 필요는 없음)로 만드는 것이 더 좋으므로 전체 오브젝트 그래프를 다시 작성하지 않고 멤버를 업데이트 할 수 있습니다.

동의합니까? Evans가 변경 가능한 값 객체를 가질 수 있습니까? 또는 변경 가능한 값 객체가 엔티티의 후보입니까?

감사


2
「가변 값 객체」등이 있습니까? 항상 노출 값 개체를 변경할 수 없었습니다.
herby

@ herby 코드에서 DDD 값 객체를 나타내는 가변 객체를 가질 수 있다고 생각하지만 일단 객체를 일단 변경하면 동일한 논리적 DDD 값 객체를 참조하는 것이 아니라 새로운 객체를 참조한다는 것을 고려해야합니다. 이것은 바람직 할 수도 있지만 혼동에 대한 레시피입니다. 코드에서 값 객체를 변경할 수없는 것은 현명한 규칙입니다.
MattDavey

답변:


8

아이덴티티가있는 모든 것은 엔터티 여야하며, 아이덴티티가 없는 모든 것은 단순한 가치이므로 가치 객체입니다.

Martin Fowler (Eric Evans 를 인용 )

  • 엔터티 : 시간과 다른 표현을 통해 실행 되는 고유 한 ID 를 가진 개체 "참조 개체"라고하는 소리도 들립니다.
  • 값 개체 : 중요한 개체는 속성의 조합 만 갖습니다.

주소를 가치 개체로 만드는 이유 :

주소가 변경 가능한 경우 결국 메일 기록을 망칠 수 있습니다. 예를 들어 고객에게 물품을 배송하는 경우 MailingHistory 테이블이 참조하는 주소가 변경된 경우 과거에 실제로 배송 한 주소를 확실하게 알 수 없습니다.

MailingHistory 항목 우리는 주소 657에 A764을 출하는 의미 할 수 있었다 우리는 보스턴에 문서 A764을 제공 어제 우리는 뉴욕으로 문서 A764을 제공 내일.

우편 주소를 변경해야 한다면 이전 주소를 삭제할 필요가 없습니다 . 그것을 유지하고 비활성으로 표시 하고 새 것을 active로 표시하십시오 .


물론 주소를 엔티티로 취급 할 수 있지만 업데이트 할 때만 주소가 참조하는 실제 위치가 변경되지 않으므로 오타 수정 만 허용됩니다.

확실하다면 엔티티를 사용하는 것보다 가능합니다.


그러나 최상의 솔루션 IMHO는 메일 기록에서 주소 엔티티를 참조하는 것이 아니라 특정 주소를 메일 기록 테이블에 직접 저장하는 것입니다 (기본적으로 주소 데이터 복사).

이런 식으로, 당신은 당신이 물건을 어디로 옮겼는지 (또는 당신이 우편으로 보내는 무엇이든) 항상 알고 있으며, 변경 가능한 엔티티를 사용할 것이기 때문에 주소 테이블이 복잡해지지 않을 것입니다.

나는 여러 ERP 시스템과 협력하여 작업했으며 거의 ​​모든 시스템 이이 접근법을 사용했습니다.

데이터베이스에 약간의 중복성이 있지만 IMHO에서 가장 실용적인 방법입니다.


아마도 가장 두통이없는 솔루션 일 것입니다. 향후 통신 채널에 추가 열이 필요할 것으로 예상되고 데이터베이스가 너무 커서 ALTER별도의 테이블에있는 엔티티를 사용해야 할 수 있습니다. 결과적으로 "항상 최신 주소 / 전화 / 이메일에 참여"와 같은 전략 SELECT을 요구하므로 유지 관리 효율성 을 유지하기가 어렵습니다 . 가능하면 간단하게 유지하십시오.
Timo

@Timo는 단순히 active-flag 를 추가하여 데이터를 약간 비정규 화하면 "항상 최신 주소 / 전화 / 이메일에 가입하십시오"는 어렵지 않습니다 . 물론 and active = true조인에서 항상 사용 하고 플래그를 최신 상태로 유지하고 테이블에 제약 조건을 추가하여 각 고객에 대해 하나의 전자 메일 만이 플래그를 true로 설정할 수 있도록해야합니다.
나무 늘보

이것은 이전 것을 비활성화하는 문제를 소개합니다. 코드에서 인스턴스의 "현재"주소 개체를 교체하고 데이터 액세스 코드로 이동하면 (1) 새로운 것이 있는지 없는지 (2) 기존의 것이 무엇인지 알 수 없습니다 하나였다. 따라서 모든 저장 작업은 "먼저 데이터베이스에서 모든 관련 주소를 비활성화하고 비활성화"와 같은 복잡한 작업을 수행 한 다음 현재 주소를로 저장해야합니다 active=true. 이것이 내가 간단하게 부르는 것이 아니기 때문에 솔루션을 좋아하는 것입니다.
Timo

2

나는 두 가지를 봅니다.

  1. 히스토리 레코드에 영향을주는 우편 번호 변경이 가능합니까? 역사 기록이 변경되지 않은 이전 주소를 가리키는 것이 논리적이라고 생각하므로 잘못된 주소로 보낸다는 것을 알고 있습니다.

  2. MailingHistory가 주소에서 FK를 갖는 순간 주소는 값 개체가되고 개체가되었습니다. 가치 개체에는 다른 개체가이 ID를 참조 할 수 있도록하는 ID가 없습니다. 다른 테이블을 가리키는 단일 테이블에 주소를 가질 수 있지만 공간 절약 효과 만 있습니다. 도메인 관점에서 두 엔터티가 동일한 유형의 값 개체를 참조하는 경우 어떠한 종류의 정보도 공유하지 않습니다.


2

IMO 주소 개체는 도메인의 엔터티입니다. 여러 엔터티가 공유하며 고유 한 ID를 가지며 시스템 전체에서 고유합니다.

에반스는 말한다 :

ID에 의해 주로 정의 된 객체를 엔티티라고합니다.


내가 이해 한 도메인 아이덴티티는 지속성 아이덴티티와 아무 관련이 없다. 에반 씨의 책에 따르면
Pepito Fernandez

네 말이 맞아 내 답변을 편집합니다. 내 말은 객체 주소가이 특정 도메인에서 중요하다는 것입니다. IMO 외래 키 및 기본 키는 실제로 전체 도메인에서 고유 한 개체라는 표시이므로 ID가 있습니다.
margabit

1
"주소 객체 ... 고유 한 ID가 있습니다" -주소의 어떤 속성이 고유하게 식별됩니까? 주소의 단일 속성은 고유하지 않지만 속성 조합은 ID 역할을합니다. 이것은 가치 객체의
MattDavey

@MattDavey : 좋은 결론이지만, Tony가 "주소를 PK가 MailingHistory 테이블의 FK이기 때문에 행을 삭제하고 싶지 않다"고 말하면 혼란스러워집니다. 이것은 Address 객체가 Aggregate 'Insured'외부에서도 의미가 있음을 의미합니다. 이것은 '주소'객체가 ValueObject가되어서는 안된다는 것을 지적합니다. 어떻게 생각해?
margabit

우리는 Value Objects가 항상 부모에 의해 완전히 소유 된 컴포지션 (UML)이 될 것이라고 말할 수 있습니까? 또한 Value Object는 부모가 없으면 의미가 없으며 부모간에 공유 할 수 없습니까?
Sudarshan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.