빈혈 도메인 모델 (아래 링크 참조) 사용에 대한 장단점이 무엇인지 알고 싶습니다.
답변
장점 :
- 도메인 모델이라고 주장하고 개발자 친구에게 자랑하고 이력서에 올릴 수 있습니다.
- 데이터베이스 테이블에서 자동으로 생성하는 것은 쉽습니다.
- 놀랍도록 잘 데이터 전송 개체에 매핑됩니다.
단점 :
- 도메인 논리는 아마도 클래스 (정적) 메서드로 가득 찬 클래스에있을 것입니다. 또는 GUI 코드. 또는 논리가 상충되는 여러 곳에서.
- 안티 패턴이므로 다른 개발자가 객체 지향 디자인의 개념을 이해하는지 묻습니다.
답변
“빈혈 도메인 모델”이 안티 패턴인데 왜이를 구현하는 시스템이 그렇게 많습니까?
몇 가지 이유가 있다고 생각합니다
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을 사용하면 논리를 넣을 클래스를 알기가 더 어렵 기 때문일 수 있습니다. 새 수업은 언제 만들까요? 어떤 패턴을 사용할까요? 기타..
상태 비 저장 서비스를 사용하면 가장 가까운 이름으로 서비스를 제공 할 수 있습니다.
답변
그 이후로 오랫동안 머릿속에 생각이 떠 올랐습니다. “OOP”라는 용어가 진정 의도하지 않은 의미를 가지고 있다고 생각합니다. 애너그램은 우리 모두가 잘 알고 있듯이 “객체 지향 프로그래밍”을 의미합니다. 물론 초점은 “지향적”이라는 단어에 있습니다. “객체 필수 프로그래밍”을 의미하는 “OMP”가 아닙니다. ADM과 RDM은 모두 OOP의 예입니다. 개체, 속성, 메서드 인터페이스 등을 사용합니다. 그러나 ADM과 RDM은 캡슐화하는 방법에 차이가 있습니다. 그들은 두 가지 다른 것입니다. ADM이 잘못된 OOP라고 말하는 것은 정확한 진술이 아닙니다. 대신 다양한 수준의 캡슐화에 대해 다른 용어가 필요할 수 있습니다. 또한 저는 안티 패턴이라는 용어를 좋아하지 않았습니다. 일반적으로 반대 그룹의 구성원이 무언가에 할당합니다. ADM과 RDM은 모두 유효한 패턴이며 단순하게 다른 목표를 염두에두고 있으며 다른 비즈니스 요구를 해결하기위한 것입니다. DDD를 실행하는 사람들은 적어도 이것을 감사해야하며 ADM을 구현하기로 선택한 사람들을 강타함으로써 다른 사람들의 수준에 떨어지지 않아야합니다. 내 생각뿐입니다.
답변
“반 패턴이기 때문에 다른 개발자들이 객체 지향 디자인의 개념을 이해하는지 물어볼 것입니다.”
“빈혈 도메인 모델은 안티 패턴입니다. 안티 패턴에는 전문가가 없습니다.”
빈혈 도메인 모델이 반 패턴인지 여부는 의견의 문제입니다. Martin Fowler는 OO를 완전히 알고있는 많은 개발자들이 그렇지 않다고 말합니다. 의견을 사실로 말하는 것은 거의 도움이되지 않습니다.
An, 비록 그것이 일반적으로 반 패턴으로 받아 들여 졌다고하더라도, 여전히 약간의 (비교적 적은) 상승 여력이있을 가능성이 있습니다.
답변
Fowler의 주된 반대는 다음과 같은 의미에서 ADM이 OO가 아니라는 것 같습니다. 다른 코드에 의해 조작되는 수동적 데이터 구조를 중심으로 “처음부터”시스템을 설계한다면, 이것은 확실히 객체 지향 설계보다 절차 적 설계에 더 가깝습니다.
나는 이런 종류의 디자인을 만들 수있는 적어도 두 가지 힘이 있다고 제안합니다.
-
새 시스템 을 생성하기 위해 객체 지향 환경에서 작업해야한다고 생각하는 디자이너 / 프로그래머 (또는 … 할 수 있다고 가정)
-
언어에 관계없이 OO가 아닌 방식으로 설계된 레거시 시스템 에 서비스와 같은 “얼굴”을 배치하기 위해 노력하는 개발자 .
예를 들어 기존 COBOL 메인 프레임 애플리케이션의 기능을 노출하기 위해 서비스 세트를 구축하는 경우 내부 COBOL 데이터 구조를 미러링 하지 않는 개념적 모델 측면에서 서비스 및 인터페이스를 정의 할 수 있습니다 . 그러나 서비스가 기존의 숨겨진 구현을 사용하기 위해 새 모델을 레거시 데이터에 매핑하는 경우 새 모델은 Fowler의 기사 (예 : TransferObject 스타일 정의 집합)의 의미에서 “빈혈”이 될 수 있습니다. 실제 행동이없는 관계.
이러한 종류의 타협은 이상적으로 순수한 OO 시스템이 기존의 비 OO 환경과 상호 작용해야하는 경계에서 매우 일반적 일 수 있습니다.
답변
빈혈 도메인 모델 (ADM)은 팀이 리치 도메인 모델 (RDM)을 구축 할 수 없거나 시간이 지남에 따라 유지 관리 할 수없는 경우 좋은 선택이 될 수 있습니다. RDM으로 성공하려면 시스템에서 사용되는 지배적 인 추상화에주의를 기울여야합니다. 어떤 개발 그룹에서든 구성원의 절반 이상, 아마도 10 분의 1만이 추상화에 능숙하다는 것을 알 수 있습니다. 이 간부 (아마도 한 명의 개발자 만)가 전체 그룹의 활동에 대한 영향력을 유지할 수 없다면 RDM은 엔트로피에 굴복 할 것입니다.
그리고 엔트로피 RDM은 특히 상처를줍니다. 개발자는 가혹한 교훈을 배울 것입니다. 처음에는 살아갈 역사가 없기 때문에 이해 관계자의 기대를 충족시킬 수 있습니다. 그러나 그들의 시스템이 더 복잡 해짐에 따라 ( 복잡하지 않음) 취약해질 것입니다. 개발자는 코드를 재사용하려고하지만 새로운 버그를 유발하거나 개발 과정에서 역 추적하는 경향이 있습니다 (따라서 추정치가 초과 됨).
반대로 ADM 개발자는 새로운 기능에 많은 코드를 재사용 할 것으로 기대하지 않기 때문에 스스로에 대한 기대치를 낮출 것입니다. 시간이 지남에 따라 많은 불일치가있는 시스템을 갖게되지만 예상치 않게 고장 나지는 않을 것입니다. 그들의 시장 출시 시간은 성공적인 RDM보다 길지만 이해 관계자는 이러한 가능성을 인식하지 못할 것입니다.
답변
“(언어에 관계없이) OO가 아닌 방식으로 설계된 레거시 시스템에 서비스와 같은”얼굴 “을 배치하기 위해 노력하는 개발자.”
많은 LOB 응용 프로그램을 생각한다면 이러한 레거시 시스템은 종종 동일한 도메인 모델을 사용하지 않습니다. Anemic Domain Model은 서비스 클래스에서 비즈니스 로직을 사용하여이를 해결합니다. 이 모든 인터페이스 코드를 모델에 넣을 수는 있지만 (전통적인 OO 의미에서) 일반적으로 모듈성을 잃게됩니다.