문제

기본 구현을 기본 생성자로 하드코딩하는 것보다 IOC 컨테이너를 사용하는 것의 이점을 누군가 나에게 설명해 줄 수 있습니까?

즉, 이 코드의 문제점은 무엇입니까?

public class MyClass
{
    private IMyInterface _myInterface;

    public MyClass()
    {
        _myInterface = new DefaultMyInterface();
    }

    public MyClass(IMyInterface myInterface)
    {
        _myInterface = myInterface;
    }
}

내가 아는 한, 이 클래스는 생성자 주입을 충분히 지원하므로 단위 테스트 및 조롱이 쉽게 수행됩니다.게다가 기본 생성자는 IOC 컨테이너의 계산 오버헤드를 제거합니다(전체 프로세스가 훨씬 더 투명하다는 것은 말할 것도 없습니다).

IOC 컨테이너를 사용할 때 얻을 수 있는 유일한 이점은 인터페이스 구현을 자주 전환해야 하는 경우입니다.뭔가 빠졌나요?

도움이 되었습니까?

해결책

IoC의 개념은 구성 요소 기능의 일부를 시스템의 다른 부분에 위임하는 것입니다.IoC 세계에는 서로에 대해 모르는 구성 요소가 있습니다.귀하의 예는 MyClass와 IMyInterface의 일부 구현 사이에 긴밀한 결합을 생성하므로 이를 위반합니다. 주요 생각 그게 네 구성품이야? 지식이 없다 어떻게 사용될지에 대해.귀하의 예에서는 구성 요소 몇 가지 가정을 하게 된다 그 용도에 대해.

실제로 이 접근 방식은 작동할 수 있지만 IoC와 명시적 객체 초기화를 혼합하는 것은 IMO에서 좋은 습관이 아닙니다.

IoC는 코드 명확성을 위해 후기 바인딩을 수행하여 느슨한 결합을 제공합니다.이 프로세스에 추가 동작을 추가하면 상황이 더욱 복잡해지고 일부 구성 요소가 원치 않거나 예측하지 못한 동작이 있는 개체를 잠재적으로 수신할 수 있는 경우 버그가 발생할 수 있습니다.

다른 팁

면을 선택하세요 :)

간단히 말해서 IOC가 권장됩니다.코드의 문제는 마지막에 언급한 대로 코드를 다시 컴파일하지 않고는 종속성의 기본 구현을 교체할 수 없다는 것입니다.IOC를 사용하면 재컴파일하지 않고도 외부 파일에서 개체의 구성이나 구성을 변경할 수 있습니다.
IOC는 코드의 나머지 부분에서 "구성 및 조립" 책임을 맡습니다.IOC의 목적은 코드를 테스트 가능하게 만드는 것이 아닙니다.그것은 기분 좋은 부작용이다.(TDD 코드가 더 나은 디자인을 만드는 것처럼)

이 코드에는 아무런 문제가 없으며 Spring 및 Guice와 같은 종속성 주입 프레임워크와 함께 계속 사용할 수 있습니다.

많은 개발자들은 Spring의 XML 구성 파일을 컴파일 단계 없이 구현을 전환할 수 있으므로 코드 내에서 종속성을 연결하는 것보다 장점으로 보고 있습니다.이 이점은 클래스 경로에 이미 여러 구현이 컴파일되어 있고 배포 시 구현을 선택하려는 상황에서 실제로 실현됩니다.배포 후 타사에서 구성 요소를 제공하는 상황을 상상할 수 있습니다.마찬가지로 배포 후 패치로 추가 구현을 제공하려는 경우가 있을 수 있습니다.

그러나 모든 DI 프레임워크가 XML 구성을 사용하는 것은 아닙니다.예를 들어 Google Guice에는 다른 Java 클래스처럼 컴파일해야 하는 Java 클래스로 작성된 모듈이 있습니다.

그렇다면 컴파일 단계가 필요한 경우 DI의 장점은 무엇입니까?그러면 원래 질문으로 돌아가게 됩니다.다음과 같은 장점을 볼 수 있습니다.

  1. 애플리케이션 전반에 걸쳐 DI에 대한 표준 접근 방식입니다.
  2. 구성은 다른 로직과 깔끔하게 분리되어 있습니다.
  3. 프록시를 주입하는 기능.예를 들어 Spring을 사용하면 구현 대신 프록시를 주입하여 선언적 트랜잭션 처리를 수행할 수 있습니다.
  4. 구성 로직을 더 쉽게 재사용할 수 있습니다.DI를 광범위하게 사용하면 시간이 지남에 따라 발전하는 복잡한 종속성 트리를 볼 수 있습니다.명확하게 분리된 구성 레이어와 프레임워크 지원 없이 이를 관리하는 것은 악몽이 될 수 있습니다.DI 프레임워크를 사용하면 상속 및 기타 수단을 통해 구성 논리를 쉽게 재사용할 수 있습니다.

내가 가진 유일한 관심사는 (1) 기본 서비스 종속성 자체에 다른/보조 서비스 종속성이 있는 경우(등...DefaultMyInterface가 ILogger에 종속됨) 및 (2) 첫 번째 서비스 종속성을 두 번째 서비스 종속성에서 격리해야 한다는 것입니다( 스텁 ILogger를 사용하여 DefaultMyInterface를 테스트해야 합니다.이 경우 기본 "새 DefaultMyInterface"를 잃고 대신 다음 중 하나를 수행해야 합니다.(1) 순수 종속성 주입 또는 (2) 서비스 로케이터 또는 (3) 컨테이너.BuildUp(new DefaultMyInterface());

나열된 다른 포스터에 대한 우려 사항 중 일부는 귀하의 질문에 공정하지 않을 수 있습니다.여러 "프로덕션" 구현에 대해 묻지 않았습니다.당신은 단위 테스트. 귀하의 접근 방식을 단위 테스트하는 경우 첫 번째 경고에 따르면 합법적인 것 같습니다.나 역시 간단한 단위 테스트 사례에서 이를 사용하는 것을 고려할 것입니다.

마찬가지로 응답자 몇 명도 반복성에 대한 우려를 표명했습니다.나도 반복을 좋아하지 않지만 (1) 기본 구현이 실제로 기본값인 경우(YAGNI:기본값을 변경할 계획이 없으며 (2) 내가 언급한 첫 번째 주의 사항이 적용된다고 생각하지 않으며 (3) 공유한 더 간단한 코드 접근 방식을 선호한다면 이 특정 형식은 적합하지 않다고 생각합니다. 복수가 문제다.

느슨한 결합 외에도 IoC는 코드 중복을 줄여줍니다.IoC를 사용하고 인터페이스의 기본 구현을 변경하려면 한 곳에서만 변경해야 합니다.기본 생성자를 사용하여 기본 구현을 주입하는 경우 인터페이스가 사용되는 모든 곳에서 이를 변경해야 합니다.

다른 의견 외에도 이러한 경우에는 DRY(Do Not Repeat Yourself) 원칙을 주장할 수 있습니다.모든 클래스에 기본 구성 코드를 넣어야 하는 것은 중복됩니다.또한 반드시 처리할 필요가 없는 특별한 경우 처리를 도입했습니다.

기본 구현을 하드코딩하는 기술을 IOC 컨테이너와 함께 사용할 수 없는 이유를 모르겠습니다.단지 구성에서 지정하지 않은 종속성은 기본 구현을 사용합니다.

아니면 내가 뭔가를 놓치고 있는 걸까?

IOC 컨테이너를 사용하려는 한 가지 이유는 소프트웨어의 후반 구성을 용이하게 하기 위한 것입니다.

예를 들어 특정 인터페이스의 여러 구현을 제공한다고 가정해 보겠습니다. 고객(또는 전문 서비스 팀)은 IOC 구성 파일을 수정하여 사용할 인터페이스를 결정할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top