DDD-빈혈 도메인 모델은 반 패턴입니까? 리치 도메인 모델을 사용하고 있습니까? [닫은]


11

에반스와 파울러 (Avans and Fowler) 는 오래 전에 빈혈 도메인 모델을 비판했다. 왜냐하면 그것은 객체 지향 원칙 등에 위배되기 때문이다.

그러나 최근에는 반 패턴이 아니며 SOLID 원칙을 따르는 예라고 주장하는 의견에 반대하는 의견이있었습니다.

나는 Spring Framework를 사용하여 수년 동안 일해 왔습니다. 모든 회사의 모든 프로젝트에는 빈약 한 모델 (JPA 엔티티)에서 작동하는 저장소를 사용하여 비즈니스 로직을 포함하는 서비스 계층이 항상 있습니다. 또한 대부분의 샘플, 심지어 Spring 직원의 공식 샘플도 이러한 방식으로 작동합니다.

내 질문은 : 빈혈 도메인 모델이 여전히 반 패턴으로 간주됩니까? 우리 모두 (DDD와 관련하여) 잘못하고 있습니까? 리치 도메인 모델이 SOLID 원칙을 위반한다고 생각하지 않습니까?


2
" 빈혈 도메인 모델은 여전히 ​​반 패턴으로 간주됩니까? ". 그렇습니다. 나 자신도 포함하여 다른 사람들이 코드를 작성하는 가장 좋은 방법이라고 생각하지만 RDM이 적합하다면 사용하십시오. 따라서이를 순수한 의견 기반으로 마무리하기로 투표했습니다.
David Arno

1
이것은 토론 / 토론 포럼에 대한 환상적인 질문입니다. 그러나 현재 권위있는 답변은 없습니다. 우리는 단지 논의되지 않고 대답 할 수있는 질문을 선호합니다.
VoiceOfUnreason

답변:


9

ADM은 마이크로 서비스와 같은 분산 서비스 솔루션에 적합한 패턴입니다. 오늘날의 많은 웹 기반 비즈니스 사례에 적합합니다.

주문 도메인 오브젝트가 있는지 고려하십시오. OOP 방식을 사용하면 Order.Purchase () Order.Cancel () 등을 추가 할 수 있습니다. 데스크톱 앱에서는 주문을 메모리에 보관하고 동일한 인스턴스에 여러 작업을 수행하는 데스크톱 앱에서 잘 작동합니다.

그러나 우리가 분산 시스템을 가지고 있다면, 하나의 일, 즉 주문 목록에 액세스하고 차례로 주문을 구매하거나, 주문 목록을 가져 와서 각각 취소하고 동일한 객체에 두 메소드를 갖는 것이 감각. 두 개의 도메인 또는 경계 컨텍스트가 있어야합니다.

PurchaseSystemOrder.Purchase()

CancelSystemOrder.Cancel();

이 객체가 공유 할 수있는 유일한 것은 속성의 데이터 구조입니다.

점점 더 많은 마이크로 서비스를 추가함에 따라 수십 가지 유형의 주문이 발생합니다. 이러한 모든 시스템에서 처리되는 것과 동일한 개념적 순서이지만 더 이상 도메인 오브젝트로 주문 에 대해 이야기하는 것은 이치에 맞지 않습니다 .

데이터 만 캡슐화하고 그에 따라 서비스 이름을 바꾸는 Anemic 모델 Order를 사용하는 것이 훨씬 더 합리적입니다.

PurchaseService.Purchase(Order order)

이제 Order에 대해 다시 이야기하고 현재 배치 된 다른 서비스에 영향을주지 않고 처리 할 새로운 서비스를 추가 할 수 있습니다.

Fowler와 Co는 단일체 시스템 배경에서 비롯되었으며, ADM 접근 방식은 메모리에서 인스턴스화되고 OrderDTO가 전달되고 변경되는 모든 개별 서비스가 포함 된 단일 앱을 의미합니다. 이 방법을 풍부한 주문 모델에 적용하는 것보다 훨씬 나쁩니다.

그러나 분산 시스템에는 많은 프로그램이 있으며 각 프로그램에는 단일 주문 메소드 만 필요하며 여러 주문에서 실행하여 각각로드하여 메소드를 실행 한 다음 버립니다. 단일 서비스와 데이터 개체 스트림 만 필요합니다.

하나의 모델 만 호출 한 다음 거의 즉시 객체를 폐기하기 위해 모든 메소드의 요구 사항 및 종속성에 대해 걱정하면서 풍부한 모델을 완전히 채 웁니다.

또한 단일 방법 중 하나를 변경하려면 논리의 리치 모델에 따라 모든 분산 구성 요소를 업데이트해야합니다.

코드베이스에 필요없는 것들을 넣을 공간이 없습니다.


4
DDD가 제한된 컨텍스트 개념으로 인해 마이크로 서비스에 특히 적합하다고 생각하기 때문에 하향 조정되었습니다. 귀하의 답변에 대한 문제는 귀하가 주문 개념과 클래스가 각 마이크로 서비스에서 동일하다는 것이지만 그것이 필요하거나 정확하지 않다고 생각합니다.
RibaldEddie

동의하지 않습니다. 구매 서비스 CashRegister에 전화하여 도메인 언어의 일부로 만들면 ADM이 DDD가 될 수 있습니다
Ewan

정교하게 할 수 있습니까? ADM과 DDD가 SOLID J2EE 또는 .NET C # MVC EF 코드베이스에있을 때 항상 YMMV라고 생각했습니다.
RibaldEddie

내 말은 바운드 컨텍스트 Order, PurchaseSystemOrder.Purchase ()는 CashRegister.Purchase (Order order)와 거의 동일한 코드가 도메인 언어의 이름 변경이라는 것입니다. 리치 도메인 모델은 같은 클래스에 Purchase 및 Cancel 메서드가 모두 있음을 의미합니다.
Ewan

1
@RibaldEddie, "자바 스크립트, 좋은 부분"책의 두께의 정점에서, 이 이미지 를 마이크로 서비스 구현을 위해 DDD를 사용하는 것에 대한 (완전히 심각하지는 않은) 주장으로 제공 합니다 .)
David Arno

3

SOLID와 DDD는 서로 직교하므로 실제로 서로 다른 방향으로 가고 있습니다. 하나는 다른 하나를 배제하는 데 사용된다고 말해서는 안됩니다. 왜냐하면 그것들은 같은 코드베이스에 함께 존재할 수 있고 아마도 있어야하기 때문입니다.

문제 도메인에 동작이 많고 복사 붙여 넣기 논리 또는 서비스 계층 메소드가 다른 서비스 계층 메소드를 호출하여 작업을 수행해야하는 종속성이 많은 수백 개의 서비스 메소드가있는 경우 빈혈 방지 도메인 모델은 안티 패턴이됩니다.

DDD는 제한된 컨텍스트 개념으로 인해 마이크로 서비스에 대한 훌륭한 패러다임 입니다.

도메인의 일부로 인프라 코드를보고 싶은 유혹에주의하십시오. 인프라 코드는 직접 작성하지 않은 것 또는 타사 시스템과 상호 작용하는 프레임 워크 또는 라이브러리에 연결된 것입니다. 데이터베이스 연결, SMTP 메일러, ORM 라이브러리, 응용 프로그램 서버 런타임, 모든 것이 인프라이므로이를 피할 수 있으면 도메인에 포함하거나 의존해서는 안됩니다.

SOLID 원칙은보다 나은 OOP 코드를 만들기 위해 사용할 수있는 범용 OOP 개념 세트입니다. 그것들을 사용하여 좋은 DDD 코드베이스를 작성할 수 있습니다.


도메인에서 인프라 코드를 분리하는 것과 관련하여. 지금까지 컨트롤러-> 서비스-> 저장소-> 도메인 (JPA 엔티티) 애플리케이션 계층이있는 JPA 엔티티를 내 도메인으로 간주했습니다. 자신의 요점에 따라 그것을 모델링하는 올바른 방법은 무엇입니까? 컨트롤러-> 풍부한 모델-> x? 거래를 어떻게 그리고 어디서 다루어야합니까? 그리고 JPA 매핑은 어떻습니까? 분리 된 JPA 엔티티로 리치 모델을 복제하지 않아도됩니까?
공동 의존

JPA 엔티티는 평범한 오래된 Java 객체입니다. 매핑은 인프라의 일부이지만 클래스 자체 일 필요는 없습니다. 인프라의 일부로 처리하기로 선택한 경우 팩토리 또는 리포지토리에서 도메인 엔터티를 만드는 데 사용되는 데이터 전송 개체로 고려해야합니다.
RibaldEddie

1

잘하면 풍부한 도메인이 좋습니다. 그렇지 않은 악몽. 빈혈 영역은 항상 나쁩니다. 그러나 익숙한 편안한 종류의 나쁜 것입니다.

빈혈 도메인이 원하는 경우 범용 언어를 선택할 때 잘못된 언어를 선택했습니다. 4 세대 언어는 특정 용도를 전문으로합니다. 빈혈이 충분하다면 당신의 삶을 더 편하게 만들었을 것입니다.

더 이상 자바 작업으로 광고를 광고 할 수 없을 때까지 많은 프레임 워크가 언어 영역으로 웜을 생성합니다. Java / Spring 작업입니다. 그들이하는 일은 당신이 그들에게 의존하게하는 것 외에도 범용 언어를 4 세대 언어의 개자식으로 바꾸는 것입니다.

이것이 모범 사례입니까 아니면 반 패턴입니까? 글쎄요, 상사는 대부분 코드 기반 작업을 위해 사람들을 고용 할 수 있는지에 관심이 있습니다. 우리가 가장해야 할 경우에 우리는 사람들을 고용하기 위해 범용 언어를 사용하고 있습니다.

그것으로 괜찮다면 괜찮습니다. 당신은 확실히 유일한 사람이 아닙니다.

그러나 그것이 어떻게되어야하는지 말하지 마십시오. 그것이 나를 위해 더 많은 일을하고 있다고 말하지 마십시오. 나는 그것없이 사는 법을 안다. 나는 그것을 밀어 넣는 방법을 알고 있으므로 몇 가지만이 그것에 의존합니다. 만약 당신이 나에게 포기를 요구하고 그것이 싸우는 것이 힘들 기 때문에 모든 것을 인계하도록한다면, 그래, 그게 나쁘다고 생각합니다.

코드베이스에 필요없는 것들을 넣을 공간이 없습니다.

SOLID 및 기타 설계 원칙에 관해서는 빈혈 영역에서도이를 따를 수 있습니다. 그것들을 따르지 않으면 다른 종류의 문제가 발생합니다.


귀하의 답변에 감사 드리며 Spring 또는 JPA-Hibernate와 같은 일부 프레임 워크가 Java 환경을 정복 한 것에 동의합니다. 그러나 Java (JEE)가 전혀 다루지 않았거나 잘못 수행 한 여러 가지 모범 사례와 단순화를 제공했다는 사실 또한 부인할 수 없습니다. 경험, 순수한 DDD 앱 (리치 도메인 모델 사용)과 함께 사용할 수있는 최고의 플랫폼 / 언어 / 프레임 워크는 무엇입니까? 내가 잘하고 싶은 말은 나쁜 실천에 따르지 않는 것입니다.
의존해

여기서는 자원 권장 사항을 수행하지 않습니다. 그러나 프레임 워크를 다루는 적절한 인프라 계층은 원하는 모든 종류를 사용할 수 있다고 생각합니다. 라이브러리처럼 취급하십시오. 도메인 외부의 지식을 유지하십시오. 또한 마법에 의존하지 마십시오. 자신이 할 수 없었던 것들을 사용하려는 충동에 저항하십시오. 언젠가 필요할 수도 있습니다.
candied_orange

원래 지점으로 돌아갑니다. SOLID 원리는 어떻습니까? 리치 도메인 모델은 많은 책임, 지속성 (JPA), 비즈니스 로직 (트랜잭션 성을 처리해야 함) 등을 가정합니다. 반면 빈혈 모델은 비즈니스 로직을 처리하는 분리 된 서비스가있는 지속성에만 관심이 있습니다. 테스트하기도 쉬운 소리. 그렇다면 무엇이 잘못 되었습니까?
의존해

가장 중요한 것은 시맨틱 요구보다는 시스템 요구에 따라 디자인 선택을 시작한다는 것입니다. 미묘하고 무시하기 쉬운 비용은 명확하지 않으며 수정을 정당화하기가 어렵습니다. 즉, 여론 조사보다는 전력선을 묻어 야한다고 주장하는 것과 같습니다. 사람들이 찍소리 대안에 익숙해지면 바뀌지 않을 것입니다. 허리케인이 힘을 빼앗아도.
candied_orange

1
"부자가 잘하면 좋은 도메인입니다. 그렇지 않으면 악몽입니다."라는 주장에 대한 의심의 이점을 주려고합니다. 어쩌면 나는 그것이 잘 된 것을 본 적이 없지만 "빈혈 영역은 항상 나쁘다"는 말도 안되는 주장을합니다. 의견이 무의미한 의견을 제시합니다. -1
David Arno
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.