빈혈 도메인 모델 : 장점 / 단점


답변:


39

장점 :

  • 도메인 모델이라고 주장하고 개발자 친구에게 자랑하고 이력서에 올릴 수 있습니다.
  • 데이터베이스 테이블에서 자동으로 생성하는 것은 쉽습니다.
  • 놀랍도록 잘 데이터 전송 개체에 매핑됩니다.

단점 :

  • 도메인 논리는 아마도 클래스 (정적) 메서드로 가득 찬 클래스에있을 것입니다. 또는 GUI 코드. 또는 논리가 상충되는 여러 곳에서.
  • 안티 패턴이므로 다른 개발자가 객체 지향 디자인의 개념을 이해하는지 묻습니다.

7
+1 데이터베이스 테이블에서 코드를 생성하는 것에 대한 요점은 일부 사람들에게 매우 중요합니다. 신속한 프로토 타이핑 개발 모드에있는 경우 자동 코드 생성이 매우 유용합니다. 우리는 이것이 적절한 OO 디자인 인 척하지 않으며, 조잡한 방식으로 조합하면 "기술적 부채"가 발생합니다. 그럼에도 불구하고 많은 프로젝트에서 출시 시간이 더 높은 우선 순위입니다.
Bill Karwin 2009

62
아니요. 빈혈 모델이 반 패턴인지 여부는 의견의 문제입니다. 파울러 (내가 존경하고 일반적으로 따르는 일)는 그렇게 말한다. 나는 동의하지 않는다 (내 말에 무게가 없다는 것은 아니다). 그리고 OO 참호의 많은 사람들도 동의하지 않는다. 순수 OO 모델링이 모든 경우에 일반적으로 적용되는 것은 아니며 전체 업계가 경험을 통해 알고 있습니다. 또한 빈혈 모델은 여전히 ​​OO 모델링 지침을 따를 수 있습니다. 따라서 적용되는 특정 사례를 보는 것은 OO 디자인에 대한 이해에 의문을 제기하지 않습니다.
luis.espinal 2011 년

12
어떤 패턴이 반 패턴인지 여부는 의견의 문제입니다. 강력한 도메인 모델은 좋은 OO 디자인이고 빈약 한 도메인 모델은 나쁜 OO 디자인입니다. 따라서 OO의 맥락에서는 반 패턴입니다. 그렇다고 사용되지 않거나 모든 경우에 부적절하다는 의미는 아니지만 개인적인 경험으로 볼 때 싱글 톤 중독보다 더 나쁘다고 생각합니다.
Terry Wilcox 2011 년

7
함수형 프로그래밍에 대한 추세가 있고 도메인 모델에는 많은 부작용이있는 경향이 있다고 생각합니다. 빈약 한 도메인 모델이 복귀하고 있다는 느낌이 들었습니다. 비즈니스 로직이 데이터를 입력하고 처리 된 데이터를 반환하는보다 기능적인 프로그래밍 스타일을 허용하기 때문입니다. 서비스 계층은 어떤 데이터가 어떤 비즈니스 논리 방법으로 처리되어야하는지 파악하여 모든 흐름을 감독합니다.
Didier A.

2
@TerryWilcox 글쎄, 나는 기능 전문가는 아니지만 기능 프로그래밍에도 데이터 구조가 있습니다. 빈약 한 도메인 모델은 데이터의 컨테이너처럼 객체를 사용하며 구조체와 비슷합니다. 내 요점은 ADM을 사용하면 시간이 지남에 따라 새롭고 새로운 상태로 변환되는 변경 불가능한 데이터가있는보다 기능적인 방법으로 이동할 수 있다는 것입니다. 예를 들어 Scala에서 약간의 OOP를 활용하고 일부 FP를 적용하려고 시도하는 것을 볼 수 있습니다. 그들이 여기에서 설명하는 것과 비슷합니다 : slideshare.net/debasishg/qconny-12
Didier A.

131

"빈혈 도메인 모델"이 안티 패턴인데 왜이를 구현하는 시스템이 그렇게 많습니까?

몇 가지 이유가 있다고 생각합니다

1. 시스템의 복잡성

구현하려는 경우 간단한 시스템 (인터넷에서 찾을 수있는 거의 모든 예제 및 샘플 코드)에서 :

주문에 제품 추가

이 기능을 주문에 넣었습니다.

public void Order.AddOrderLine(Product product)
{
    OrderLines.Add(new OrderLine(product));
}

멋지고 슈퍼 객체 지향.

이제 제품이 재고에 있는지 확인하고 그렇지 않은 경우 예외를 throw해야한다고 가정 해 보겠습니다.

주문이 재고에 의존하는 것을 원하지 않기 때문에 더 이상 주문에 넣을 수 없습니다. 이제 서비스를 시작해야합니다.

public void OrderService.AddOrderLine(Order order, Product product)
{
    if (!InventoryService.Has(product)
       throw new AddProductException

    order.AddOrderLine(product);
}

IInventoryService를 Order.AddOrderLine에 전달할 수도 있는데, 이는 또 다른 옵션이지만 여전히 Order가 InventoryService에 종속되도록합니다.

Order.AddOrderLine에는 여전히 일부 기능이 있지만 일반적으로 Order 범위로 제한되는 반면 내 경험으로는 Order 범위를 벗어난 비즈니스 로직이 훨씬 더 많습니다.

시스템이 기본 CRUD 이상이면 OrderService에서 대부분의 로직을 사용하고 Order에서는 거의 사용하지 않습니다.

2. OOP에 대한 개발자의 관점

어떤 논리가 엔티티에 적용되어야하는지에 대해 인터넷에서 열띤 토론이 많이 있습니다.

같은 것

주문. 저장

주문이 스스로를 구하는 방법을 알아야합니까? 이를위한 저장소가 있다고 가정 해 봅시다.

이제 주문이 주문 라인을 추가 할 수 있습니까? 간단한 영어를 사용하여 이해하려고하면 그다지 말이되지 않습니다. 사용자가 주문에 제품을 추가하므로 User.AddOrderLineToOrder ()를 수행해야합니까? 과잉 인 것 같습니다.

OrderService.AddOrderLine ()은 어떻습니까? 이제 말이 되네요!

OOP에 대한 나의 이해는 캡슐화를 위해 함수가 클래스의 내부 상태에 액세스해야하는 클래스에 함수를 배치한다는 것입니다. Order.OrderLines 컬렉션에 액세스해야하는 경우 Order에 Order.AddOrderLine ()을 넣습니다. 이렇게하면 클래스의 내부 상태가 노출되지 않습니다.

3. IoC 컨테이너

IoC 컨테이너를 사용하는 시스템은 일반적으로 완전히 빈혈입니다.

인터페이스가있는 서비스 / 리포지토리를 테스트 할 수 있지만 모든 인터페이스에 인터페이스를 배치하지 않는 한 도메인 개체를 (쉽게) 테스트 할 수 없기 때문입니다.

"IoC"는 현재 모든 프로그래밍 문제에 대한 해결책으로 찬사를 받고 있기 때문에 많은 사람들이 맹목적으로이를 따르고 이런 식으로 Anemic Domain Models로 끝납니다.

4. OOP는 어렵고 절차는 쉬움

나는 이것에 대해 약간의 " 지식의 저주 "를 가지고 있지만, 나는 DTO와 서비스를 가진 신참 개발자들이 Rich Domain보다 훨씬 쉽다는 것을 발견했다.

Rich Domain을 사용하면 논리를 넣을 클래스를 알기가 더 어렵 기 때문일 수 있습니다. 새 수업은 언제 만들까요? 어떤 패턴을 사용할까요? 기타..

상태 비 저장 서비스를 사용하면 가장 가까운 이름으로 서비스를 제공 할 수 있습니다.


얼마나 복잡한 지에 달려 있다고 생각합니다. 1. 1-2 의존성 에서처럼 간단하다면-나는 그것을 Order 클래스에 유지할 것입니다. 2. 중간 정도의 복잡성-OrderLines 클래스를 만들고 Order.OrderLines를 사용하여 Order <-> OrderLines 통신 및 관련 종속성을 처리합니다. 3. 그러나 복잡도가 높은 경우-Order 모듈 범위 논리를 Order에 유지하면서 대부분의 외부 종속성을 허용하기 위해 Application Service OrderService를 사용합니다.
Eric P

13
대단한 요약-이러한 모든 이유가 안티 패턴이 아닌 이유입니다. OO에 대한 노예의 헌신은 반 패턴입니다. 이제 투영없이 동시성을 추가하고 Fowler 스타일 OO로 매듭을 짓는 방법을 확인하십시오. 대규모 동시성 (예 : Google)을 수행하는 회사를 살펴보고 얼마나 많은 OO를 수행하는지 확인하십시오.
DanH 2013 년

멋지게 말했다. Grails를 사용하면 3 °가 빈혈로 이어지는 지 잘 모르겠습니다. 1 °의 경우 실제로는 사소한 응용 프로그램의 서비스 계층에서 논리 이동을 종료합니다. 하지만 여전히 Grails를 사용하는 도메인 중심 접근 방식을 사용하고 있습니다. 도메인이 논리를 선호하는 곳이지만 필요할 때 비트를 한 레이어 위로 이동하기 때문에 실제로 그렇게 좋지 않습니다.
youri

4
IoC와 빈혈의 상관 관계가 보이지 않습니다. 전혀 관련이없는 문제인 것 같습니다. 서비스 / 저장소 또는 도메인 개체가 인터페이스를 구현하는지 여부는 테스트와 관련이 없습니다. 오히려 서비스 / 저장소 / 도메인 개체를 테스트하고 인터페이스를 구현하는 종속성에서 분리합니다. 그리고 당신이이 일을 제대로하든 안하든 내가 볼 수있는 IoC와 어떤 상관 관계가 없습니다.

2
Grok에서 고군분투하고있는 DDD에 대한 것은 첫 번째 요점입니다. "시스템이 기본 CRUD보다 더 많으면 OrderService에서 대부분의 논리를 사용하고 Order에서는 거의 사용하지 않습니다." 그것은 나에게 의미가 있지만 DDD의 목적이 그것보다 더 복잡한 시스템에 사용되는 것이 아닙니까?
Dan Ling

20

그 이후로 오랫동안 머릿속에 생각이 떠 올랐습니다. "OOP"라는 용어가 진정 의도하지 않은 의미를 가지고 있다고 생각합니다. 애너그램은 우리 모두가 잘 알고 있듯이 "객체 지향 프로그래밍"을 의미합니다. 물론 초점은 "지향적"이라는 단어에 있습니다. "객체 필수 프로그래밍"을 의미하는 "OMP"가 아닙니다. ADM과 RDM은 모두 OOP의 예입니다. 개체, 속성, 메서드 인터페이스 등을 사용합니다. 그러나 ADM과 RDM은 캡슐화하는 방법에 차이가 있습니다. 그들은 두 가지 다른 것입니다. ADM이 잘못된 OOP라고 말하는 것은 정확한 진술이 아닙니다. 대신 다양한 수준의 캡슐화에 대해 다른 용어가 필요할 수 있습니다. 또한 저는 안티 패턴이라는 용어를 좋아하지 않았습니다. 일반적으로 반대 그룹의 구성원이 무언가에 할당합니다. ADM과 RDM은 모두 유효한 패턴이며 단순하게 다른 목표를 염두에두고 있으며 다른 비즈니스 요구를 해결하기위한 것입니다. DDD를 실행하는 사람들은 적어도 이것을 감사해야하며 ADM을 구현하기로 선택한 사람들을 강타함으로써 다른 사람들의 수준에 떨어지지 않아야합니다. 내 생각뿐입니다.


16

"반 패턴이기 때문에 다른 개발자들이 객체 지향 디자인의 개념을 이해하는지 물어볼 것입니다."

"빈혈 도메인 모델은 안티 패턴입니다. 안티 패턴에는 전문가가 없습니다."

빈혈 도메인 모델이 반 패턴인지 여부는 의견의 문제입니다. Martin Fowler는 OO를 완전히 알고있는 많은 개발자들이 그렇지 않다고 말합니다. 의견을 사실로 말하는 것은 거의 도움이되지 않습니다.

An, 비록 그것이 일반적으로 반 패턴으로 받아 들여 졌다고하더라도, 여전히 약간의 (비교적 적은) 상승 여력이있을 가능성이 있습니다.


2
... 어떻게? 나는 당신이나 다른 사람을 속이려고하는 것이 아니지만, 나는 프로들에게 정말 궁금합니다. 단점은 수천 번 언급되었지만 여전히 ADM의 탄력적 인 프로를 찾고 있습니다 (논쟁적인 문구 제외).
struppi

6
... 이것은 누군가가 악마의 adovcate를 조금 보여 주려는 것처럼 보입니다. the chances are it would still have some (though relatively little) upside.그럼 이름을 좀 지어주세요! 가설 대신 적어도 하나!
썰매

2
단일 클래스 (실제 비즈니스)와 관련이없는 모든 항목에 대해 일부 논리가 속하는 위치를 더 쉽게 알 수 있습니다. 다른 곳에서 말했듯이 "리치 도메인 모델"은 결국 여러 곳에서 로직을 갖게됩니다 (서비스 레이어, 객체 그래프에 관련된 여러 클래스 등). 또한 RDM은 전체 비즈니스 로직을 쉽게 볼 수 없도록하여주기를 피하는 것을 쉽게 만들지 않습니다. 로직이없는 멍청한 데이터 구조는 OO 애플리케이션에서 자리를 잡습니다.
ymajoros

1
나는이 기사가 ADM이 안티 패턴이 아니라고 말하는 좋은 주장을 제공한다는 것을 발견했다. blog.inf.ed.ac.uk/sapm/2014/02/04/…
syclee

1
반 패턴은 항상 문제를 일으키며 패턴을 사용하는 고품질 솔루션으로 다소 큰 애플리케이션 (10 명의 개발자가 300KLOC를 초과하는 2 ~ 3 년 개발)을 성공적으로 출하했으며 패턴에 문제가 있다는 느낌이 들지 않았으므로 그렇게 나쁠 수 없습니다. 사용하는 동안 좋은 코드를 만들 수 있습니다.
Ignacio Soler Garcia

13

Fowler의 주된 반대는 다음과 같은 의미에서 ADM이 OO가 아니라는 것 같습니다. 다른 코드에 의해 조작되는 수동적 데이터 구조를 중심으로 "처음부터"시스템을 설계한다면, 이것은 확실히 객체 지향 설계보다 절차 적 설계에 더 가깝습니다.

나는 이런 종류의 디자인을 만들 수있는 적어도 두 가지 힘이 있다고 제안합니다.

  1. 시스템 을 생성하기 위해 객체 지향 환경에서 작업해야한다고 생각하는 디자이너 / 프로그래머 (또는 ... 할 수 있다고 가정)

  2. 언어에 관계없이 OO가 아닌 방식으로 설계된 레거시 시스템 에 서비스와 같은 "얼굴"을 배치하기 위해 노력하는 개발자 .

예를 들어 기존 COBOL 메인 프레임 애플리케이션의 기능을 노출하기 위해 서비스 세트를 구축하는 경우 내부 COBOL 데이터 구조를 미러링 하지 않는 개념적 모델 측면에서 서비스 및 인터페이스를 정의 할 수 있습니다 . 그러나 서비스가 기존의 숨겨진 구현을 사용하기 위해 새 모델을 레거시 데이터에 매핑하는 경우 새 모델은 Fowler의 기사 (예 : TransferObject 스타일 정의 집합)의 의미에서 "빈혈"이 될 수 있습니다. 실제 행동이없는 관계.

이러한 종류의 타협은 이상적으로 순수한 OO 시스템이 기존의 비 OO 환경과 상호 작용해야하는 경계에서 매우 일반적 일 수 있습니다.


8

빈혈 도메인 모델 (ADM)은 팀이 리치 도메인 모델 (RDM)을 구축 할 수 없거나 시간이 지남에 따라 유지 관리 할 수없는 경우 좋은 선택이 될 수 있습니다. RDM으로 성공하려면 시스템에서 사용되는 지배적 인 추상화에주의를 기울여야합니다. 어떤 개발 그룹에서든 구성원의 절반 이상, 아마도 10 분의 1만이 추상화에 능숙하다는 것을 알 수 있습니다. 이 간부 (아마도 한 명의 개발자 만)가 전체 그룹의 활동에 대한 영향력을 유지할 수 없다면 RDM은 엔트로피에 굴복 할 것입니다.

그리고 엔트로피 RDM은 특히 상처를줍니다. 개발자는 가혹한 교훈을 배울 것입니다. 처음에는 살아갈 역사가 없기 때문에 이해 관계자의 기대를 충족시킬 수 있습니다. 그러나 그들의 시스템이 더 복잡 해짐에 따라 ( 복잡하지 않음) 취약해질 것입니다. 개발자는 코드를 재사용하려고하지만 새로운 버그를 유발하거나 개발 과정에서 역 추적하는 경향이 있습니다 (따라서 추정치가 초과 됨).

반대로 ADM 개발자는 새로운 기능에 많은 코드를 재사용 할 것으로 기대하지 않기 때문에 스스로에 대한 기대치를 낮출 것입니다. 시간이 지남에 따라 많은 불일치가있는 시스템을 갖게되지만 예상치 않게 고장 나지는 않을 것입니다. 그들의 시장 출시 시간은 성공적인 RDM보다 길지만 이해 관계자는 이러한 가능성을 인식하지 못할 것입니다.


5

"(언어에 관계없이) OO가 아닌 방식으로 설계된 레거시 시스템에 서비스와 같은"얼굴 "을 배치하기 위해 노력하는 개발자."

많은 LOB 응용 프로그램을 생각한다면 이러한 레거시 시스템은 종종 동일한 도메인 모델을 사용하지 않습니다. Anemic Domain Model은 서비스 클래스에서 비즈니스 로직을 사용하여이를 해결합니다. 이 모든 인터페이스 코드를 모델에 넣을 수는 있지만 (전통적인 OO 의미에서) 일반적으로 모듈성을 잃게됩니다.


1
빙고. 이것은 많은 사람들이 배를 놓치는 것처럼 보이는 곳입니다. ADM에는 목적이 있습니다. 그들의 오용은 반 패턴이지만 그들 자체는 그렇지 않습니다.
luis.espinal

4

Anemic Domain Model 기사를 처음 접했을 때 "거룩 해, 그게 내가하는 일이야. 공포!"라고 생각했습니다. 나는 참을성있게 Eric Evan의 책에 대한 참조를 따랐으며 좋은 예라고 생각하고 소스를 다운로드했습니다. "빈혈 도메인 모델을 사용하지 않는다"는 것은 "서비스 클래스를 사용하지 않고, 중재자를 사용하지 않고, 전략을 사용하지 않음"또는 "조작되는 클래스에 논리를 두는 것"을 의미하지 않습니다.

DDD 예제에는 서비스 클래스, XyzUpdaters, 싱글 톤 및 IoC가 있습니다.

빈혈 도메인 모델이 정확히 무엇인지 혼란스러워합니다. 나는 "내가 그것을 볼 때 그것을 알 것이다"를 기대한다. 지금은 좋은 디자인의 긍정적 인 예에 만족합니다.


1
나는 나중에 Eric Evan의 책을 구입했고 그것을 강력히 추천합니다. 빈혈 도메인 모델의 반대에 대한 확실한 예를 제공합니다.
제이미

4

ADM과 함께 '성숙한'시스템으로 작업 한 후이 질문에 대한 일화적인 피드백을 제공 할 수 있다고 생각합니다.

1) 캡슐화 부족

ADM이있는 라이브 시스템에서는 예를 들어 'obj.x = 100; obj.save ', 이것이 비즈니스 로직을 위반하더라도. 이로 인해 불변성이 객체에서 모델링 된 경우 발생하지 않는 여러 버그가 발생합니다. ADM에 대해 가장 심각한 부정적이라고 생각하는 것은 이러한 버그의 심각성과 만연 성입니다.

여기서는 이것이 기능적 솔루션이고 ADM의 절차 적 솔루션이 크게 다르며 다른 사람들이 ADM과 기능적 솔루션 간의 표면 유사성에 대해 그린 유사점은 부수적이라는 점을 지적하는 것이 중요하다고 생각합니다.

2) 코드 팽창

ADM에서 생성되는 코드의 양은 OOP / RDM 솔루션이 생성 할 수있는 코드의 5 ~ 10 배라고 추정합니다. 이는 아마도 50 %는 코드 반복, 30 %는 보일러 플레이트 코드, 20 %는 RDM 부족으로 인해 발생하는 문제를 해결하거나 해결하는 것으로 설명됩니다.

3) 도메인 문제에 대한 이해 부족

ADM과 도메인 문제에 대한 이해 부족은 어느 정도 밀접한 관련이 있습니다. 순진한 솔루션이 발생하고 기존 DM으로 지원하기 어렵 기 때문에 요구 사항을 제대로 고려하지 않으며 ADM은 더 긴 개발 시간과 유연성 부족을 고려할 때 비즈니스 혁신에 중요한 장벽이됩니다.

4) 유지 보수의 어려움

개념이 단순히 복사 및 붙여 넣기 재 구현이 아닐 수 있다는 점을 감안할 때 도메인 개념이 표현 된 모든 위치에서 변경되도록하려면 일정 수준의 엄격함이 필요합니다. 이로 인해 동일한 버그가 여러 번 조사되고 수정되는 경우가 많습니다.

5) 온 보딩 난이도 증가

RDM의 이점 중 하나는 도메인을 더 빨리 이해할 수있는 개념의 결합이라고 생각합니다. ADM을 사용하면 개념이 조각화되고 명확성이 부족하여 새로운 개발자가 습득하기가 더 어려울 수 있습니다.

또한 ADM에 대한 운영 지원 비용이 RDM보다 더 높았지만 이는 여러 요인에 따라 달라집니다.

다른 사람들이 지적했듯이 RDM의 이점에 대해서는 DDD (Greg Evans, Vince Vaughn 및 Scott Millett)를 살펴보십시오.


1
Greg Evans는 Greg Young과 Eric Evans의 비밀 아이입니까? 나는 Vince Vaughn도 DDD 책을 쓰고 있다는 것을 몰랐지만, Vaughn Vernon도 연기를 시작했을 것입니다. :)
knittl

오 이런, 내가 위의 글을 썼을 때의 기억이 다소 혼란 스러웠던 것 같습니다. 그 밖에 :) 가리키는 주셔서 감사합니다
미스터 Morphe을

2

대부분의 안티 패턴과 동일한 프로입니다. 많은 사람들이 오랫동안 바쁘게 지낼 수 있습니다. 관리자는 더 많은 사람을 관리 할 때 더 많은 임금을받는 경향이 있으므로 개선하지 않을 강력한 인센티브가 있습니다.


7
이 경우 다시 말하겠습니다. ^^^ 일반적으로 들리는 명제를 추론하는 데 사용되는 순전히 일화적인 증거.
luis.espinal 2011 년

충분한 일화적인 증거를 찾으면 패턴을 도출 할 수 있습니다. 그리고이 패턴은 변경 관리에 관한 문헌에서 잘 알려져 있고 적절하게 설명되어 있습니다.
Stephan Eggermont 2011

4
"그리고이 패턴은 변경 관리에 관한 문헌에서 잘 알려져 있고 적절하게 설명되어 있습니다." -인용 부탁드립니다. 더 많은 지점으로, 상관 관계는 인과 관계를 의미하는 것은 아니다 . 즉, 제자리에있는 안티 패턴 (특히 소프트웨어 패턴, 빈약 한 도메인 모델) 때문에 사람들이 빨간 테이프로 바퀴를 돌리는 것을 본다고 해서 나중에 전자를 정당화하기 위해 존재한다는 것을 의미하지는 않습니다. 방금 트럼펫을 낸 것. 수사적 슬로건은 복잡한 문제에 대한 설명에 대한 잘못된 캐리커처입니다. 다시 말하지만 상관 관계는 인과 관계를 의미하지 않습니다.
luis.espinal 2011

4
Gerald M. Weinberg의 Quality Software Management, 특히 Volume 4를 읽고 싶을 것입니다. 그리고 저는 그 발생이 아닌 지속적인 존재에 대한 가능한 원인만을 주장합니다. Peter Principle은 적절한 대안을 제공합니다.
Stephan Eggermont 2011

감사합니다. 기회가되면 읽어 보겠습니다 (인용을 제공하면 +1). 그 책은 그것을 잘 알려진 반 패턴으로 제시하고 있습니까? 또한 상관 관계 뿐만 아니라 인과 관계 도 주장 / 보여주는가 ? 당신은 "가능"설명으로 주장 지금 . 귀하의 원본 텍스트는 세부 사항보다 더 많은 수사학을 사용하여 확실성으로 표시합니다 (그래서 '순수한 추측'이라고 불렀습니다). 그게 당신의 의도 였든 , 단순히 편집 사고 였든, 누가 알겠는가. 나는 그것을 읽을 때 텍스트에 존재하는 것에서 만 추론 할 수 있습니다.
luis.espinal 2011

2

Eric P의 답변과 위의 다른 사람들이 작성한 내용에 따라 ADM의 주요 단점은 OOD의 손실, 특히 구현 세부 사항이 숨겨 지도록 도메인 개념의 논리와 데이터를 함께 유지하는 것입니다. API는 풍부 할 수 있습니다.

Eric은 주문에 항목을 추가하기 전에 인벤토리를 확인하는 것과 같이 해당 클래스에서 작동하는 로직에 필요한 정보가 도메인 클래스 외부에있는 경우가 많다는 점을 지적합니다. 하지만 대답이이 중요한 논리를 보유하는 서비스 계층인지 아니면 객체 디자인의 일부로 처리하는 것이 더 나은지 의문입니다. 누군가 는 Inventory 개체, Product 개체 및 Order 개체에 대해 알아야합니다. 아마도 인벤토리 멤버, 주문 목록 등이있는 단순히 OrderSystem 개체 일 수 있습니다. 이것은 서비스와 크게 다르지 않지만 개념적으로 더 일관 적이라고 생각합니다.

또는 다음과 같이보십시오. 내부 크레딧 잔액이있는 사용자를 가질 수 있으며 User.addItemToOrder (item)가 호출 될 때마다 항목의 가격을 가져 와서 추가하기 전에 크레딧을 확인하는 등의 작업이 합리적으로 보입니다. 디자인. Service.addItemToUserOrder (user, item)로 대체하여 잃어버린 것이 무엇인지 정확히 모르겠지만 무엇을 얻었는지 확실하지 않습니다. 손실은 코드의 추가 레이어와 더 어설픈 스타일의 작성 및 기본 도메인 모델의 강제 무지 일 것입니다.


1

시스템의 복잡성과 변형 세분화가 증가함에 따라 잘 설계된 메시지 전달 객체 모델이 제공하는 인터페이스 포인트의 캡슐화 및 통합은 광범위한 리팩토링없이 중요한 코드를 변경하고 유지하는 것이 훨씬 더 안전하다는 점에 유의해야합니다.

ADM에 의해 생성 된 서비스 계층은 확실히 구현하기 쉽지만 (상대적으로 생각할 필요가없고 분산 된 인터페이스 포인트가 많기 때문에) 라이브 및 성장하는 시스템을 수정할 때 문제를 일으킬 수 있습니다.

또한 모든 사례가 도메인 모델을 요구하지는 않는다고 덧붙일 수 있습니다 (ADM 모델은 고사). 때로는보다 절차 적 / 기능적 작업 스타일을 사용하는 것이 데이터 중심이며 애플리케이션 전체 논리 / 비즈니스 규칙에 의존하지 않는 것이 좋습니다.

전체 앱의 장단점을 결정하려는 경우 한 줄의 코드 작성을 시작하기 전에 먼저 주어진 응용 프로그램에 대해 각각의 모양을 디자인하는 것이 중요하다고 생각합니다. 두 가지 스타일로 애플리케이션을 CRC하거나 와이어 프레임 한 후에는 뒤로 물러서서 어느 것이 더 합리적이고 애플리케이션에 더 잘 맞는지 결정하십시오.

또한 어느 것이 유지하기 더 쉬울 지 미리 생각하십시오.


1

더 나은 예측 가능성을 제공합니다. 관리자는 특히 프로젝트가 시간과 재료를 지불하는 경우 좋아합니다. 모든 변경은 많은 작업을 의미하므로 어려운 작업은 많은 반복 작업 뒤에 숨겨 질 수 있습니다. 잘 설계된 DRY 시스템에서는 지속적으로 새로운 작업을 수행하므로 예측 가능성이 매우 낮습니다.


1

도메인 기반 설계에 대한 Eric Evans 책을 처음 읽은 후 좋은 도메인 모델 클래스를 설계하기위한 전술적 패턴이 아니라는 사실을 이해하지 못했습니다.

주제에 대해 더 많이 배우고 전략적인 패턴을 사용한 후에 마침내 나는 처음 에는 해결하려는 비즈니스 문제깊이 이해하는 것이 전부 라는 것을 이해하기 시작했습니다 .

그리고 단지 그 후에는 시스템의 일부를 적용하기에 적합합니다 결정할 수있는 전술 패턴 과 같은 집계 기관 소위와 함께 등, 저장소, 부자 (반대로 도메인 모델 빈혈 사람 ). 그러나 이러한 패턴의 혜택을 받으려면 시스템의 해당 부분에 대한 비즈니스 로직과 관련하여 충분히 복잡 해야합니다.

따라서 당면한 문제에 대한 솔루션을 구현할 때 CRUD 기반 접근 방식을 사용 하거나 언급 된 전술 패턴과 함께 풍부한 도메인 모델에 투자 하여이 특정 문제에 더 잘 접근하는지 먼저 결정해야 합니다.

CRUD가 더 합리적이라면, 예를 들어 복잡한 비즈니스 로직이없고 대부분의 로직이 변환과 관련된 경우 도메인 모델을 구현하는 데이터를 전송 및 유지하는 것은 불필요한 과잉 일 수 있습니다. 이것은 할 일이 많지 않다는 것을 의미하는 것이 아니라 가장 많은 구현 노력을 생성하는 것이 비즈니스 규칙이 아니라는 것을 의미합니다. 그러나이 경우 빈혈 도메인 모델 과 같은 것은 없습니다 . 단순히 도메인 모델이 전혀 없기 때문 입니다 . 오히려 당신이 보게 될 것은 DTO (데이터 전송 객체) 또는 DAO 와 같은 것입니다.(데이터 액세스 개체) 및 데이터에서 작동 할 서비스 클래스. 그리고 해당 작업은 데이터를 한 표현에서 다른 표현으로 변환하고 비즈니스 로직이 거의 또는 전혀없이 데이터를 이동하는 것과 관련이 있습니다.

도메인 모델에 투자하는 것보다 시간이 지남에 따라 변경 될 복잡한 비즈니스 로직많이 있다고 판단했다면 내 경험에 비추어 볼 때 좋은 생각입니다. 그 이유는 코드를 통해 비즈니스 관점을 표현하는 것이 더 쉽고 비즈니스 도메인과 규칙을 미러링하는 해당 작업을 더 쉽게 이해할 수 있기 때문입니다. 그렇다고 모든 사용 사례에 도메인 모델 클래스가 있어야한다는 의미는 아닙니다. 예를 들어, 변경 및 지속될 상태가없는 경우 도메인 로직을 포함하는 도메인 서비스 만 더 순수한 기능처럼 구현 될 수 있습니다.

그러나 비즈니스 도메인에서 목적과 의미를 갖는 변경되고 지속되는 상태도 있으면이 상태를 변경하는 상태와 동작을 캡슐화 해야합니다 . 그것으로 아무도 비즈니스 규칙을 쉽게 피할 수 없으며 심각한 실패와 함께 잘못된 상태로 이어질 수 있습니다. 소위 빈혈 도메인 모델은 종종 이러한 문제의 원인 입니다. 다른 구성 요소가 동일한 "빈혈"도메인 모델 클래스에서 작동하는 코드가 상태의 일부를 확인하고 해당 비즈니스 항목의 전체적인 불변성을 고려하거나 알지 못해도 상태의 일부를 변경하는 경우가 종종 있습니다. 이를 반 패턴이라고 할 필요는 없지만 이해하는 것이 중요합니다.언급 된 문제와 함께 DDD 기반 접근 방식에서 풍부한 도메인 모델 의 많은 이점을 잃게됩니다 . 동작과 데이터가 동일한 클래스에 배치 된 도메인 모델을 사용할 때 해당 클래스의 작업을 호출하는 서로 다른 "클라이언트"가 많이있을 수 있지만 비즈니스 엔터티의 비즈니스 불변이 다음과 같이 준수되는지 신경 쓸 필요가 없습니다. 도메인 모델 클래스는 항상이를 처리하고 "클라이언트"에게 유효하지 않은 작업에 대해 알리거나 안전망으로 예외를 throw 할 수도 있습니다.

그래서 결론은 , 나는 그것이 중요하다고 생각 빈혈 도메인 모델 클래스와 클래스와 같이하지 혼동 데이터 구조 (예 : DTO들 또는 DAO를 등) . 신중하고 의도적으로 선택한 CRUD 기반 접근 방식에서는 비즈니스 논리가 너무 덜 복잡하기 때문에 도메인 모델을 사용하는 이점이 없습니다.

에 의해 빈혈 도메인 모델 나는 오히려 가까운 이러한 논리가 변경되는 데이터를해야 다른 구성 요소에 걸쳐 확산은 복잡한 비즈니스 로직 및 비즈니스 규칙이 많이 있다는 것을 볼 수있는 코드를 참조한다.

또한 제가 배운 또 다른 교훈 이 있습니다. 코드에서 스테이크 홀더가 일상 생활에서 사용하는 것과 동일한 비즈니스 언어 ( 유비쿼터스 언어 라고도 함 )를 사용하려고하면 이미 이해와 관련하여 많은 이점을 얻게됩니다. CRUD 기반 또는 도메인 모델 기반 접근 방식을 사용하든 상관없이 비즈니스 도메인 및 코드의 가독성을 향상시키는 것이 좋습니다.


0

Michael의 대답을 확장하려면 해당 코드가 어디로 가야하는지 (상당히) 명확하다고 생각했을 것입니다. 주문과 인벤토리 사이의 상호 작용을 처리하는 전담 중재자입니다.

내 POV에서 도메인에 대한 핵심은 isInThisState()메소드 등 의 간단한 테스트 동작을 유지해야한다는 것입니다 . 내 경험상 이것들은 대부분의 회사에서 서비스 눈물 (sic :)) 전체에 흩어져 있으며 끝없이 다시 작성되었습니다. 모두 표준 결합 규칙을 위반합니다.

내 관점에서 접근 방식은 은 실질적인 비즈니스 행동을 최대한 많이 유지하는 DM 목표 로하고 나머지는 명확하게 지정된 영역 (즉, 서비스가 아님)에 배치하는 것이어야합니다.


중재자에 관한 것은 어쨌든 절차 적 프로그래밍과 거의 차이가 없다는 것입니다. 두 개체에 속하지 않는 일부 함수를 그룹화하는 것입니다. 다른 개체로 그룹화한다는 사실은 큰 차이가 없습니다.
Rob Grant

0

우리 팀은 개인적으로 ADM을 선호합니다. 도메인의 특정 부분을 나타내는 비즈니스 개체 집합이 있습니다. 우리는 서비스를 사용하여 이러한 개체를 db에 저장합니다. 비즈니스 객체에는 메서드가 있지만 이러한 메서드는 내부 상태 만 조작합니다.

RDM보다 ADM을 사용할 때의 이점은 객체를 db에 유지하는 방법에서 볼 수 있습니다. 레거시 코드 시스템에서 작업하는 개발자는 새 시스템의 비즈니스 객체를 사용하고 현재 데이터 액세스 레이어를 계속 사용하여 이러한 객체를 db에 유지할 수 있습니다. RDM을 사용하면 레거시 시스템의 개발자가 리포지토리 개체를 비즈니스 모델에 주입해야합니다. 이는 현재 데이터 액세스 계층과 일치하지 않습니다.


-15

빈혈 도메인 모델은 안티 패턴이다. 안티 패턴에는 전문가가 없습니다.


10
동의하지 않습니다. 대부분의 Antipatterns에는 다른 대안보다 더 나은 솔루션 인 코너 케이스가 있습니다.
Bill Karwin 2009

19
안티 패턴에는 장점이 있습니다. 그것이 사람들이 일반적으로 나쁜 생각이지만 사용하는 이유입니다.
Kristopher Johnson

6
무언가가 단지 의견 일 때 (파울러의 수준이더라도) 사실로서 반 패턴이라는 사실을 패러 팅하는 것은 유효한 응답 형식이 아닙니다.
luis.espinal

@luis : 당신이 댓글을 남기기 전에 제가 쓰려고했던 것입니다. 추가로, 도구는 목적을 위해 존재합니다. Fowler가 그것을 OO라고 부르고 싶지 않다면 괜찮습니다. 그러나 이것이 자동으로 잘못된 솔루션 / 아키텍처 등을 나타내는 것은 아닙니다.
JensG 2011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.