값 대 엔터티 개체 (도메인 기반 디자인)


91

방금 DDD를 읽기 시작했습니다. Entity 대 Value 개체의 개념을 완전히 이해할 수 없습니다. Value 개체가 Entity 개체로 설계되었을 때 시스템이 직면 할 수있는 문제 (유지 보수성, 성능 등)를 누군가가 설명해 주시겠습니까? 예가 좋을 것입니다 ...


3
: 여기 둘 사이의 차이의 전체 (IMO) 목록 작성 enterprisecraftsmanship.com/2016/01/11/...
블라디미르

답변:


109

본질적인 구별로 축소하면 정체성은 엔티티에 중요하지만 가치 객체에는 중요하지 않습니다. 예를 들어 누군가의 이름은 값 개체입니다. Customer 엔터티는 고객 이름 (값 개체), List <Order> OrderHistory (엔티티 목록) 및 기본 주소 (일반적으로 값 개체)로 구성 될 수 있습니다. 고객 엔티티에는 ID가 있고 각 주문에는 ID가 있지만 이름은 그렇지 않습니다. 일반적으로 객체 모델 내에서 주소의 신원은 아마도 중요하지 않을 것입니다.

값 객체는 일반적으로 불변 객체로 표현 될 수 있습니다. 값 객체의 한 속성을 변경하면 기본적으로 기존 객체가 파괴되고 새 객체가 생성됩니다. 콘텐츠만큼 정체성에 관심이 없기 때문입니다. 적절하게 Name의 Equals 인스턴스 메서드는 개체의 속성이 다른 인스턴스의 속성과 동일하면 "true"를 반환합니다.

그러나 Customer와 같은 엔티티의 일부 속성을 변경해도 고객이 파괴되지는 않습니다. 고객 엔티티는 일반적으로 변경 가능합니다. ID는 동일하게 유지됩니다 (적어도 객체가 지속 된 경우).

당신은 아마도 그것을 깨닫지 못하고 가치 객체를 만들 것입니다. 세분화 된 클래스를 생성하여 엔티티의 일부 측면을 표현할 때마다 값 객체가 있습니다. 예를 들어 유효한 값에 대한 제약이 있지만 더 간단한 데이터 유형으로 구성된 IPAddress 클래스는 값 객체가됩니다. EmailAddress는 문자열이거나 자체 동작 집합이있는 값 개체 일 수 있습니다.

데이터베이스에 ID가있는 항목도 개체 모델에 ID가 없을 가능성이 높습니다. 그러나 가장 간단한 경우는 함께 의미가있는 몇 가지 속성의 합성입니다. Customer.Name으로 함께 구성 할 수있을 때 Customer.FirstName, Customer.LastName, Customer.MiddleInitial 및 Customer.Title을 사용하고 싶지 않을 것입니다. 지속성에 대해 생각할 때 데이터베이스의 여러 필드가 될 수 있지만 개체 모델은 상관하지 않습니다.


공유되지 않는 가변 객체는 어디에 적합합니까? 전체 우주에 개체에 대한 참조가 하나만있는 경우 개체의 정체성은 변경 가능하더라도 관련이 없습니다. 내가 볼 수 있듯이, 사용 가능한 참조가 존재한다면 사물은 그 참조가 그것을 변경하는 데 사용되지 않고 변경 수있는 상태의 측면을 관찰하는 입니다. 사물이 외부 세계에 연결되지 않고 불변이거나 우주 어디에나 하나의 참조 만 존재한다면 위의 시나리오는 발생할 수 없으며 가치입니다.
supercat 2014

an과 같은 것은 int[1]공유되지 않는 변경 가능한 값, 공유 가능한 변경 불가능한 값 (참조를 보유하는 것 중 어느 것도 여기에 기록하지 않는 경우) 또는 엔티티 (두 개 이상의 참조가 존재하는 경우 그 중 하나를 작성하는 데 사용될 수 있음) 일 수 있습니다. 다른 것을 사용하여 읽을 수있는 값). 불행히도, 변경 가능한 값을 캡슐화하는 클래스 객체가 실수로 엔티티로 바뀌는 것을 방지하기 위해 Java 또는 .NET에서 언어 지원이 없다는 것을 알고 있습니다.
supercat 2014-02-20

@supercat, 직접적인 간단한 지원이 없다면 동의하지만, 생성자에 대한 공개 액세스를 제거하고, 정적 팩토리 만 사용하여 새 인스턴스를 만들고, 읽기 전용 속성을 통해 상태에 대한 모든 액세스를 제한합니다 (세터 없음). .
Charles Bretana 2014-06-04

40

모든 속성에 의해 집합 적으로 정의 된 모든 개체는 값 개체입니다. 속성이 변경되면 값 개체의 새 인스턴스가 있습니다. 이것이 값 객체가 불변으로 정의되는 이유입니다.

개체가 모든 속성에 의해 완전히 정의되지 않은 경우 개체의 ID를 구성하는 속성의 하위 집합이 있습니다. 나머지 속성은 객체를 재정의하지 않고 변경할 수 있습니다. 이런 종류의 객체는 불변에서 정의 할 수 없습니다.

구별하는 더 간단한 방법은 값 객체를 절대 변경되지 않는 정적 데이터로 생각하고 엔터티를 애플리케이션에서 진화하는 데이터로 생각하는 것입니다.


7

값 유형 :

  • 값 유형은 자체적으로 존재하지 않으며 엔티티 유형에 따라 다릅니다.
  • 값 유형 객체는 엔티티 유형 객체에 속합니다.
  • 값 유형 인스턴스의 수명은 소유하는 엔티티 인스턴스의 수명으로 제한됩니다.
  • 세 가지 값 유형 : 기본 (기본 데이터 유형), 복합 (주소) 및 컬렉션 (지도, 목록, 배열)

엔티티 :

  • 엔티티 유형은 자체적으로 존재할 수 있습니다 (ID).
  • 엔티티에는 자체 수명주기가 있습니다. 다른 엔티티와 독립적으로 존재할 수 있습니다.
  • 예 : 사람, 조직, 대학, 모바일, 집 등. 모든 개체에는 고유 한 정체성이 있습니다.

DDD와 관련이 없음 :(
HydTechie

6

다음이 올바른지 모르겠지만 주소 개체의 경우 엔터티 변경 사항이 연결된 모든 개체에 반영되므로 엔터티 대신 값 개체로 사용하고 싶습니다 ( 예를 들어 사람).

이 경우를 생각해보십시오 : 당신은 다른 사람들과 함께 집에서 살고 있습니다. 주소에 Entity를 사용한다면 모든 Person 객체가 연결되는 하나의 고유 한 주소가 있다고 주장합니다. 한 사람이 이사하면 주소를 업데이트하고 싶습니다. 주소 엔티티의 속성을 업데이트하면 모든 사람이 다른 주소를 갖게됩니다. 값 개체의 경우 주소를 편집 할 수 없으며 (변경할 수 없기 때문에) 해당 개인에 대한 새 주소를 제공해야합니다.

이 말이 맞습니까? 나는 DDD 책을 읽은 후에도이 차이에 대해 여전히 혼란 스러웠다 고 말해야한다.

한 단계 더 나아가, 이것이 데이터베이스에서 어떻게 모델링됩니까? Address 개체의 모든 속성을 Person 테이블의 열로 가지고 있습니까? 아니면 고유 식별자를 가진 별도의 Address 테이블을 만들겠습니까? 후자의 경우 같은 집에 사는 사람들은 각각 Address 개체의 다른 인스턴스를 가지지 만 해당 개체는 ID 속성을 제외하고는 동일합니다.


1
"이 경우를 생각해보십시오 : 당신은 다른 사람들과 함께 집에 살고 있습니다. 우리가 주소에 Entity를 사용한다면, 모든 Person 객체가 연결되는 하나의 고유 한 주소가있을 것이라고 주장합니다." 나는 그 사람들 각각이 자신의 주소 인스턴스를 가지고 있다고 생각하지만 그들은 단지
우연히

"하지만 그것이 같은 지폐라는 것을 의미하지는 않습니다."-나는 이것이 지폐에 추가 속성을 할당하는지 여부 (예 : 방출 된 날짜, 공간에서의 물리적 위치 등)에 달려 있다고 생각합니다. 그렇지 않으면 동일합니다. 그리고 소프트웨어도 마찬가지라고 생각합니다. 주소는 우리가 고려하고 싶은 속성에 따라 같거나 같지 않습니다.
adrhc

4

주소는 바쁜 프로세스에 의존하는 엔티티 또는 값 객체 일 수 있습니다. 주소 개체는 택배 서비스 응용 프로그램의 엔터티 일 수 있지만 주소는 다른 응용 프로그램의 값 개체 일 수 있습니다. 택배 응용 프로그램에서 주소 개체에 대한 신원 문제


2

나는 이것에 대해 다른 스레드에서 물었고 여전히 혼란 스럽습니다. 성능 고려 사항과 데이터 모델링을 혼동 할 수 있습니다. 카탈로그 애플리케이션에서 고객은 필요할 때까지 변경하지 않습니다. 그것은 어리석은 것처럼 들리지만 고객 데이터의 '읽기'는 '쓰기'보다 훨씬 많으며 많은 웹 요청이 모두 '활성 개체 집합'에 도달하기 때문에 계속해서 고객을로드하고 싶지 않습니다. 그래서 저는 Customer 객체에 대한 불변의 길로 향했습니다.로드하고, 캐시하고, 고객을보고 싶어하는 99 %의 (다중 스레드) 요청에 동일한 객체를 제공합니다. 그런 다음 고객이 무언가를 변경하면 '편집자'를 받아 새 고객을 만들고 이전 고객을 무효화합니다.

내 관심사는 많은 스레드가 동일한 고객 객체를보고 변경 가능한 경우 한 스레드가 변경되기 시작하면 다른 스레드에서 혼란이 발생한다는 것입니다.

내 문제는 1)이 정도의 합리적이며 2) 속성에 대한 많은 코드를 복제하지 않고이를 수행하는 가장 좋은 방법입니다.


1

3 구분 사이 EntitiesValue Objects

  • 식별자 대 구조적 동등성 : 엔티티에는 식별자가 있고, 동일한 식별자가 있으면 엔티티는 동일합니다. 손 너머의 값 객체는 구조적으로 동일하며 모든 필드가 동일 할 때 두 값 객체가 같다고 간주합니다. 값 개체는 식별자를 가질 수 없습니다.

  • 가변성 대 불변성 : 값 객체는 불변 데이터 구조 인 반면 엔티티는 수명 동안 변경됩니다.

  • 수명 : 값 개체는 엔터티에 속해야합니다.


1

아주 간단한 문장에서 우리는 세 가지 유형의 평등을 가지고 있습니다.

  • 식별자 동등성 : 클래스에 ID가 입력되어 있고 두 개체가 ID 필드 값과 비교됩니다.
  • 참조 평등 : 두 개체에 대한 참조가 메모리에서 동일한 주소를 갖는 경우.
  • 구조적 동등성 : 두 개체의 모든 구성원이 일치하면 두 개체가 동일합니다.

식별자 동등성 엔티티만을 의미 하고 구조적 동등성은 Value Object만을 의미합니다. 실제로 Value Object에는 ID가 없으며 서로 바꿔서 사용할 수 있습니다. 또한 값 객체는 변경 불가능해야하며 엔티티는 변경 가능해야하며 값 객체는 데이터베이스에 테이블이 없어야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.