3

필자는 Dependency Injection을 한동안 사용 해왔다. 이제는 IoC와 DI에 대한 이야기를 새로운 개발자 그룹에게주고 싶다. 나는 개인적으로 한 사람에게 설명하는 기억하고 그가 나에게 물었다 :왜 새 키워드와의 종속성에 문제가 있다고 생각합니까?

는 "왜 그냥 사용합니다.

private IMyInterface _instance = new MyImplementaion(); 

를 대신 모든 DI의 문제를 통해가는"

내 대답했다 : "단위 테스트에는 모의 (mock)와 스텁 (stub)이 필요합니다. " -하지만 우리 회사에서 단위 테스트를 작성하지 않아서 그를 설득하지 못했습니다. 나는 당신에게 하나의 구현에 단단히 결합되어 있기 때문에 구체적인 구현이 나쁜 것이라고 말했습니다. 하나의 구성 요소를 변경하면 다른 구성 요소가 변경됩니다.

그런 코드에 대한 예를 들려 줄 수 있습니까? 이 코드가 나쁜 이유를 더 많이 설명해 주시겠습니까?

그것은 내가 문제가 다음 커플 링

public class MyClass 
{ 
    private IMyInterface _instance = new MyImplementation(); 
    ... 

+0

실제로 상황에 따라 다르며 DI가 필요할 때가 아니라고 생각합니다. 그러나 추상화와 DI는 훌륭한 설계 원칙입니다. – SMA

+2

OO 디자인에 관한 [Robert C. Martin의 위대한 이야기] (http://www.infoq.com/presentations/principles-agile-oo-design)를보십시오. Dependency Injection의 주요 동인 인 Dependency Inversion Principle에 대해 이야기합니다. 마틴은 소스 코드 의존성과 클래스 커플 링의 문제가 무엇인지 설명하는 "복사 프로그램"(그가 지난 수년간 사용한 예)에 대해 이야기합니다. 우리는 클래스 결합을 낮추기 위해 DI를 사용합니다. 이것이 당신의 동료들에 대한 당신의 주된 논거가되어야하기 때문에이 대화를보십시오. – Steven

답변

2

문제 :-) 그것을 설명을 가지고 내게 너무 명백한 것 언제든지 MyClass가에 의해 여부를 직접 (생성, 또는된다는 것을 의미한다 IoC 컨테이너)는 항상 즉시 MyImplementation 콘크리트를 만들고이 종속 구현을이 구체 구현에 바인딩합니다. 차례대로, MyImplementation에는 다른 종속성이있을 가능성이 있으며이 종속성도이 방식으로 결합됩니다. MyClass는 종속성의 인터페이스에 의존하고,되도록 클래스의 디커플링의

장점하지 종속성의 구체적인 구현 (SOLID principles의 D 즉)을 포함한다 :

단위 테스트에 대한
  1. - 당신으로 위에서 언급했듯이 MyClass을 독립적으로 테스트하려면 new'ed 종속성을 사용하기 때문에 MyImplementation 종속성을 조롱하려면 Moles/Fakes과 같은 불쾌한 일에 의지해야합니다.

  2. 대체 용 - 인터페이스에만 연결하여 MyClass의 코드를 변경하지 않고도 IMyInterface의 구체적인 구현을 (예 : 전략 패턴을 통해) 바꿀 수 있습니다. 종속성에 추가 종속성이있을 수 있으므로 시스템에서 종속성을 명백하고 명확하게 만들기 위해

  3. 이 필요합니다.이 종속성은 해결해야하며 구성 고려 사항이 필요할 수도 있습니다. MyClass이 내부적으로 IMyInterface 종속성을 숨기면 호출자는 MyClass의 종속성을 볼 수 없습니다. 1990 년대의 전통적인 OO에서는 이것이 일반적인 것이었지만 (즉, 캡슐화 + 구성), 모든 종속성의 배포가 여전히 필요하므로 구현이 불투명해질 수 있습니다. 그러나 인터페이스 수준에서 수행되는 연결 (즉, MyClass의 소비자는 IMyClass을 통해서만 수행됨), 연결 표시 인터페이스는 에 대한 종속성을 다시 숨길 수있는 IMyClass입니다 (생성자는 인터페이스에서 볼 수 없기 때문에).

  4. 구성 가능한 종속 수명 제어.IMyInterface을 삽입하면 MyImplementation을 새로 작성하는 대신 MyImplementation 오브젝트의 수명 관리와 관련하여 추가 구성 옵션을 허용하게됩니다. 원래 하드 와이어로 만든 MyImplementation의 생성이 MyClass에서 수행되었을 때, 실제로는 MyImplementation의 수명을 소유하고있었습니다. 이것을 IoC 컨테이너에 남겨두면 더 효율적인 MyImplementation의 수명 옵션을 사용할 수 있습니다. MyImplementation 인스턴스가 스레드로부터 안전 할 경우 MyClass의 여러 인스턴스에서 인스턴스를 공유하도록 선택할 수 있습니다. 요약

, 나는 리팩토링은 IOC의 생성자 의존성 주입에 적합한 보일 것으로 판단 방법은 다음과 :

public class MyClass 
{ 
    // Coupled onto the the interface. Dependency can be mocked, and substituted 
    private readonly IMyInterface _instance; 

    public MyClass(IMyInterface instance) 
    { 
     _instance = instance; 
    } 
    ... 

IOC의 컨테이너 부트 스트랩이 IMyInterface 요구 사항의 구현을 준수 할 것에를 정의하며, 또한 것이다 의존성의 수명을 정의한다. in Ninject :

Bind<IMyInterface>() 
    .To<SomeConcreteDependency>() // Which implements IMyInterface 
    .InSingletonScope();