엔티티 / 비즈니스 객체에 대한 종속성을 해결하기 위해 IoC 컨테이너를 사용하지 않는 이유는 무엇입니까?


82

DI의 개념을 이해하지만 다른 IoC 컨테이너가 무엇을 할 수 있는지 배우고 있습니다. 대부분의 사람들은 상태 비 저장 서비스를 연결하기 위해 IoC 컨테이너를 사용하는 것을 옹호하는 것처럼 보이지만 엔티티와 같은 상태 저장 객체에 사용하는 것은 어떻습니까?

그것이 옳든 그르 든, 나는 그 행동에 외부 클래스가 필요하더라도 일반적으로 내 엔티티에 행동을 채운다. 예:

public class Order : IOrder
{

    private string _ShipAddress;
    private IShipQuoter _ShipQuoter;

    public Order(IOrderData OrderData, IShipQuoter ShipQuoter)
    {
        // OrderData comes from a repository and has the data needed 
        // to construct order
        _ShipAddress = OrderData.ShipAddress;  // etc.
        _ShipQuoter = ShipQuoter;

    }

    private decimal GetShippingRate()
    {
        return _ShipQuoter.GetRate(this);
    }
}

보시다시피 종속성은 Constructor Injected입니다. 이제 몇 가지 질문입니다.

  1. 엔티티가 ShipQuoter와 같은 외부 클래스에 의존하도록하는 것이 나쁜 습관으로 간주됩니까? 이러한 종속성을 제거하면 정의를 올바르게 이해하면 빈혈 영역으로 연결되는 것 같습니다.

  2. IoC 컨테이너를 사용하여 이러한 종속성을 해결하고 필요할 때 엔터티를 구성하는 것이 나쁜 습관입니까? 이것이 가능합니까?

통찰력을 가져 주셔서 감사합니다.


3
당신이해야 할 일이기 때문이 아니라 일을 더 쉽게 만들어주기 때문에 당신이 필요한 일을하십시오
Omu

28
독학 프로그래머로서 나는 그 길을 갔고, 그것은 현재 우리 회사에서 사용하는 소프트웨어로 이어졌습니다. 절차 / 트랜잭션 스크립트 기반 소프트웨어가 등장했습니다. 부분적으로는 제가 더 잘 알지 못해서 가장 쉽고 파티 였기 때문입니다. 유지하고 확장하는 것은 절대적으로 고통스럽기 때문에 시간을내어 다시 작성하고 동일한 실수를하지 않는 방법에 대해 이미 이러한 문제를 극복 한 사람들에게 조언을 구하고 있습니다.
Casey Wilkins

답변:


90

첫 번째 질문은 대답하기 가장 어렵습니다. 엔티티가 외부 클래스에 의존하도록하는 것은 나쁜 습관입니까? 확실히 가장 흔한 일은 아닙니다.

예를 들어, 리포지토리를 엔터티에 삽입하면 효과적으로 액티브 레코드 패턴을 구현 한 것입니다 . 어떤 사람들은이 패턴이 제공하는 편의를 위해이 패턴을 좋아하는 반면 다른 사람들 (나와 같은)은 SRP ( Single Responsibility Principle)를 위반하기 때문에 코드 냄새 또는 안티 패턴으로 간주합니다 .

엔터티에 다른 종속성을 주입하면 동일한 방향 (SRP에서 멀어짐)으로 이동한다고 주장 할 수 있습니다. 다른 한편으로, 당신이 이것을하지 않으면, 당김이 빈혈 도메인 모델 쪽으로 향한다는 것은 확실히 맞습니다 .

나는 DDDD에 대한 Greg Young의 (포기한) 논문을 보았을 때까지 오랫동안이 모든 문제를 겪었습니다 . 그는 왜 고정 관념적인 n-tier / n-layer 아키텍처가 항상 CRUDy (따라서 오히려 빈약함 )인지 설명합니다.

도메인 객체를 명사 대신 명령 및 이벤트 로 모델링하는 데 초점을 맞추면 적절한 객체 지향 도메인 모델을 구축 할 수 있습니다.

두 번째 질문은 답하기가 더 쉽습니다. 언제든지 Abstract Factory를 사용하여 런타임에 인스턴스를 만들 수 있습니다 . Castle Windsor를 사용하면 Typed Factory Facility를 사용하여 수동으로 공장을 구현해야하는 부담을 덜어줍니다.


감사합니다 마크. Typed Factory를 보았고 Abstract Factory 메서드에 대한 다른 게시물을 읽었지만 엔티티를 해결하는 데 사용되는 예제는 본 적이 없습니다. 대부분의 사람들이 저장소를 제외하고 종속성없이 엔티티를 설계하기 때문입니까? 외부 종속성이있는 엔티티를 해결하기 위해 Typed Factory와 같은 것을 엄격하게 사용하면 길을 따라 문제가 발생합니까?
Casey Wilkins

제가 말하려고했던 것은 귀하의 엔티티에 다른 엔티티 등에 액세스 할 수있는 다른 공동 작업자가 포함되어 있으면 SRP 위반 및 N + 1 문제는 말할 것도없고 모든 종류의 유지 관리 문제가 발생할 수 있다는 것입니다. 이것이 Evans가 각 엔티티를 집계 루트로 취급하도록 권장하는 이유입니다.
Mark Seemann 2011 년

내 예에서 ShipQuoter는 웹 서비스 (예 : UPS)에서 주문에 대한 배송료를 가져옵니다. 이것을 IOrder를 수락하는 서비스로 만들겠습니까, 아니면 Order.GetRates와 같은 도메인 개체의 일부로 만드시겠습니까?
Casey Wilkins

처음에 동기식 풀을 피할 수있는 방법을 알아내는 데 많은 시간을 할애 할 것입니다. 동기식 차단 방식으로 데이터를 더 많이 가져올수록 설계가 더 취약 해집니다. 이것이 CQRS가 매력적인 대안 인 이유입니다.
Mark Seemann 2011 년

4
그렉의 논문에 대한 당신의 링크가 죽었습니다. 하지만 여기 에서 계속 사용할 수 있습니다 . 처럼 그리고이 나타납니다 최신 버전입니다.
BornToCode

1

나는 이것이 오래된 게시물이라는 것을 알고 있지만 추가하고 싶었습니다. 도메인 엔터티는 ctor에서 추상화 된 저장소를 전달하더라도 자체적으로 유지되지 않아야합니다. 내가 제안하는 이유는 이것이 단순히 SRP를 위반하는 것이 아니라 DDD의 집계에 위배된다는 것입니다. 설명하겠습니다. DDD는 본질적으로 깊은 그래프가있는 복잡한 앱에 적합하므로 집계 또는 복합 루트를 사용하여 기본 "자식"에 대한 변경 사항을 유지합니다. 따라서 개별 어린이에게 지속성을 주입 할 때 우리는 어린이와 라이프 사이클 또는 집계를 "담당"해야하는 컴포지트 또는 집계 루트. 물론 복합 루트 또는 집계는 자체 그래프를 유지하지 않습니다. 다른 하나는 DDD 개체의 종속성을 주입하는 것입니다. 주입 된 도메인 개체는 상태를 수화하기 위해 다른 이벤트가 발생할 때까지 효과적으로 상태가 없습니다. 코드 소비자는 캡슐화를 위반하는 비즈니스 동작을 호출하기 전에 먼저 도메인 개체를 초기화하거나 설정해야합니다.

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