불변 개체와 DDD가 함께 사용됩니까?


18

DDD를 사용하는 시스템 (ORM을 사용하는 모든 시스템)을 고려하십시오. 거의 모든 사용 사례에서 현실적으로 모든 시스템의 요점은 해당 도메인 객체를 조작하는 것입니다. 그렇지 않으면 실제 효과 나 목적이 없습니다.

변경 불가능한 객체를 수정하면 객체가 지속 된 후 새 레코드를 생성하여 데이터 소스에 큰 팽창을 일으 킵니다 (수정 후 이전 레코드를 삭제하지 않는 한).

불변 객체를 사용하면 얻을 수있는 이점을 볼 수 있지만 이런 의미에서 불변 객체를 사용하는 데 유용한 사례를 볼 수는 없습니다. 이것이 잘못 되었습니까?


답변:


16

함수형 프로그래밍에서와 같이 변경 불가능한 객체를 사용한 계산이 반드시 생성 된 모든 객체를 유지하는 것은 아닙니다!


어쨌든 그 시나리오가 불변의 객체를 사용하는 인스턴스를 보지 못합니다. 따라서 특정 목적을 위해 존재하지 않았습니다. 내가 잘못?
Steven Evers

1
불변의 객체가 중간 계산 (병렬 스레드)에 유용 할 것이라고 생각했습니다.
Steven A. Lowe

11

도메인에서 불변이 데이터베이스에서 불변이어야 함을 의미합니까? 예를 들어 고객에게 항상 하나의 주소가 있다고 가정하면 다음을 고려하십시오.

customer.address = new Address('My Castle', 'Kings street');
customer_repo.save(customer);

이제 고객 ID가 1임을 고려하여 다음 SQL이 실행됩니다.

INSERT INTO addresses (customer_id, name, street)
VALUES (1, 'My Castle', 'Kings street');

이제 주소가 다음과 같이 변경되었습니다.

customer.address = new Address('Pauper palace', 'Outlands');
customer_repo.save(customer);

영속 계층은 다음과 같은 SQL을 실행합니다.

UPDATE addresses SET name='Pauper palance', street='Outlands'
WHERE customer_id = 1;

이렇게하면 별도의 DELETE AND INSERT 문의 오버 헤드를 피할 수 있습니다. 또한 일부 RDBMS에는 INSERT REPLACE 또는 무언가가 있다고 생각합니다. MySql에는 REPLACE가 있습니다.


+1 일반적인 원칙에 동의합니다. 불변 도메인 개체가 불변 DB 행을 반드시 의미해야하는 이유는 모르겠습니다.
Andres F.

위의 경우 주어진 고객에 대해 주소 클래스의 도시 속성을 변경해야하는 경우 어떻게 처리 할 수 ​​있습니까? 고객이 여러 주소를 가질 수 있다고 가정하면 고객과 주소 사이의 일대 다 관계 선박
Sudarshan

1
@ Sudarshan 이것은 데이터베이스에서 실제로 변경할 수없는 '불변 값 객체'를 만드는 방법 일뿐입니다. 성능상의 이유로. 각 상황은 물론 당연히 처리되어야합니다. 나는 지금 내 도메인에 이벤트 소싱을 선호하지만, 나는 그것에 중독되어 있습니다.
andho

@ Sudarshan은 질문에 구체적으로 대답하기 위해 행을 새로운 값으로 업데이트하는 업데이트 쿼리를 실행하면됩니다. 일대 다인 경우, 주소는 Customer Aggregate Root 내에서 DB에서 고유하게 식별하는 데 사용되는 일종의 식별자를 갖습니다. 그런 다음이 식별자와 customer_id는 '주소'테이블에서 해당 행을 업데이트하는 데 사용됩니다.
andho

@andho "이것은 데이터베이스에서 실제로 불변이 아닌 '불변 값 객체'를 만드는 방법입니다." 이것은 정말 내 하루 감사를 만들어
Sudarshan

6

DDD에서 불변의 객체는 값 객체와 거의 같습니다. 이 객체들은 엔티티가 아니며, 정체성이 없습니다. 따라서 나는 항상 값 객체를 포함 된 엔티티의 열로 유지합니다 (N / Hibernate를 사용하면 구성 요소를 사용할 수 있습니다). 그들은 자신의 테이블이 없습니다.


4

변경 불가능한 오브젝트가 데이터베이스에서 맵핑되는 방법에 따라 다릅니다. Joda Time 라이브러리의 DateTime과 같은 구성 요소 인 경우 값을 변경하면 삽입이 아닌 업데이트가 발생합니다. 그러나 불변이 테이블에 행을 요구하는 더 복잡한 경우에는 팽창 문제가 있습니다.

나는 그것이 약한 논쟁이지만, 이런 방식으로 감사 추적을 구현할 수 있다고 생각합니다. 인서트를 통해 불변의 모든 변경 사항을 추적 할 수 있습니다. 이 작업을 수행하는 더 좋은 방법이 많이 있습니다.

구성 요소가 아닌 불변 도메인 개체를 갖는 것은 지속성과 약간 일치하지 않는 것 같습니다.


전혀. 구성 요소는 도메인 개체를 동일한 기본 데이터와 다르게 구성 할 수 있으므로 매우 유용합니다. 불변성을 강제하는 데 문제가 있습니다. 개인적으로 도메인 객체를 기본 키 필드를 제외하고 변경 가능한 것으로 취급하고 단순하게 유지하려고합니다.
게리 로우 2013

"모두 구성 요소가 아닌 불변의 도메인 개체를 갖는 것은 지속성과 약간 일치하지 않는 것 같습니다." 당신은 구성 요소로 모델링해서는 안되는 가치 객체가 필요한 곳이 어디라고 생각합니다 (Hibernate 용어)? --- 마지막 댓글을 잘못 입력하여 삭제했습니다.
Sudarshan

단일 엔티티가 행으로 완전히 표시되고 다른 도메인 오브젝트가 데이터를 공유하지 않는 경우 구성 요소를 피하십시오.
게리 로우

4

도메인에 따라 다릅니다. DDD는 프로그래밍 패러다임을 객체 지향으로 지정하지 않습니다. 그러나 객체 지향 패러다임은 데이터베이스에 유지되어야하는 일반적인 응용 프로그램에 적합합니다.

DDD는 단순히 소프트웨어가 해결하려고하는 실제 문제를 나타내는 도메인 모델을 중심으로 소프트웨어를 빌드해야한다고 말합니다. 그 문제가 예를 들어 수학적으로 수학적이라면, 기능적 프로그래밍과 불변의 데이터 구조를 사용하여 도메인 계층을 구현하는 것은 많은 의미가 있습니다.

반면에 문제가 일반적인 엔터프라이즈 응용 프로그램에 더 가깝고 모든 도메인 개체에 대해 불변 개체 구조를 사용하는 경우 DDD를 따르지 않는다고 주장합니다. 적어도 두 가지 주장을 할 수 있습니다.

  • 구현이 문제 도메인의 도메인 모델을 나타내지 않습니다. 이 경우 문제 도메인은 수정할 상태가있는 엔터티로 구성됩니다. 그리고 그것이 당신이 그것을 구현 한 방법이 아닙니다.

  • 유비쿼터스 언어가 없습니다. 도메인 모델의 언어와 개념은 도메인 전문가가 사용하는 것을 따르지 않습니다.

참고 : DDD는 적절한 경우 불변 개체를 사용하며,이를 단순히 값 개체라고합니다.

따라서 순전히 기능적인 데이터 구조를 사용하여 데이터베이스 응용 프로그램을 만들 수 없다는 말은 아니며,해서는 안된다는 말은 아닙니다. 응용 프로그램의 유형에 따라 DDD라고 부를 수 없다고 생각합니다.


피터, 좋은 대답입니다. 내 질문을 여기에서 살펴볼 수 있습니까? stackoverflow.com/questions/13783666/… 내 문제를 파악하는 데 도움이 될 수 있습니다. 불변의 가치 객체는 엔터프라이즈와 관련이없는 소프트웨어에 적합하다고 생각합니다. 대부분의 엔터프라이즈 응용 프로그램 객체는 제 생각에 변경 가능합니다. 깊은 중첩 값 개체를 변경할 수 있다고 가정하십시오. ContactInfo-> PhysicalLocation-> 주소. 우편 번호를 업데이트하고 싶습니다 ... 전체 개체 그래프를 만드는 것은 반 패턴뿐만 아니라 적 그리스도인 것 같습니다. 어떻게 생각해?
Pepito Fernandez

3

Hibernate / NHibernate와 같은 ORM을 사용하는 경우 고아 개체를 자동으로 삭제하도록 계단식 옵션을 설정할 수 있습니다. 개인에게 값 개체 주소가있는 경우, 주소를 변경하면 새 주소가 저장되고 기존 주소가 분리되어 이전 주소가 삭제됩니다.


0

값 객체는 거의 항상 DDD에서 변경할 수 없으며 플라이급 패턴을 사용하여 .NET이 문자열을 사용하는 것처럼 메모리에서 해당 값 객체의 복제를 유지합니다. 주요 트레이드 오프는 한면의 메모리이고 다른면은 창조 효율성입니다. 플라이급 패턴을 사용하면 새로운 또는 재구성 된 값 객체가 이미 플라이급 캐시 내에 있는지 여부를 판별하기 위해 값 기반 비교를 수행해야하지만, 단일 인스턴스가 시행되므로 해당 지점 이후의 다른 비교는 일반적으로 참조로 안전하게 수행 할 수 있습니다. 플라이 웨이트 사용 여부에 관계없이 가치 객체는 고유 한 정체성 만 가지고 있으므로 값을 변경하면 정체성이 변경되기 때문에 여전히 불변입니다.


-1

불변 개체를 사용하는 또 다른 방법이 있습니다 ...

5.0, 6.0, 7.0, 8.0 값을 저장하고 매번 전체 레코드를 복사하는 대신 5.0, +1.0, +1.0, +1.0과 같은 것을 저장 한 다음 시퀀스 5.0을 재구성하기 위해 종속성을 올바르게 빌드 할 수 있습니다. , 6.0, 7.0, 8.0. 이런 식으로 작은 수정은 적은 양의 메모리 만 필요합니다 ...

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