의존성 주입 스타일의 실제 차이점은 무엇입니까?


12

나는 의존성 주입에 익숙하지 않으며 응용 프로그램에서 어떤 스타일을 사용 해야하는지에 대한 몇 가지 질문이 있습니다. Martin Fowler의 Inversion of Control Containers 및 Dependency Injection 패턴 을 읽었 지만 생성자, setter 및 인터페이스 주입의 실제 차이점을 알 수 없습니다.

나에게 하나를 사용하는 이유는 코드 정리 및 / 또는 명확성의 문제 일뿐입니다. 차이점은 무엇입니까? 하나를 다른 것보다 사용하는 것의 장점이나 단점이 있습니까? 아니면 이전에 언급 한 것입니까?

제 생각에는 생성자 주입 이 가장 직관적이며 인터페이스 주입 이 가장 적습니다. 반면에 setter injection 은 중간 용어이지만 처음 주입 한 의존성 객체의 인스턴스를 변경할 수 있습니까? 이 스타일의 주입은 의존성이 필요한 객체가 항상 주입되도록 보장합니까? 나는 믿지 않지만 틀렸다면 정정하십시오.


길을 따라 무엇을 찾거나 읽었는지 확실하지 않습니다. 나는 여기여기에 비슷한 스레드를 발견 했다 . 나는 나 자신이고, 당신이 얻을 수있는 답변에 호기심이있을 것입니다 :)

@ user1766760 당신은 저를 여기에서 도와 줘야합니다. 제 질문은 닫히기로 투표되었습니다. 두 번 더 투표했습니다. 질문이나 무언가를 투표하십시오. 닫기를 피하기 위해 무엇을 할 수 있는지 모르겠습니다.
ecampver

음 .. 나 자신이 처음이므로 너무 어떻게 도울 수 있는지 / 왜 닫히기로 투표되는지 이유가 확실하지 않습니다 (표시가 보이지 않습니다 ??). 추측을 던진다면 아마도 특정 프로그래밍 질문이 아니라 더 많은 토론 일 것입니다.

질문을 조금 확장하고 싶을 수도 있습니다. 의존성 주입은 "제어의 반전"의 한 형태입니다. 대안이 있습니다. 유용하지만 악용 될 수있는 대안은 예를 들어 서비스 위치입니다.
Ian

답변:


12

생성자 주입 은 종속성을 명시 적으로 만들고 클라이언트가 인스턴스를 제공하도록하는 이점이 있습니다. 또한 클라이언트가 나중에 인스턴스를 변경할 수 없도록 보장 할 수 있습니다. 단점 중 하나는 생성자에 매개 변수를 추가해야한다는 것입니다.

Setter Injection 은 생성자에 매개 변수를 추가 할 필요가 없다는 장점이 있습니다. 또한 클라이언트가 인스턴스를 설정하지 않아도됩니다. 이는 선택적 종속성에 유용합니다. 예를 들어, 기본적으로 실제 데이터 저장소와 같은 클래스를 작성하고 테스트에서 세터를 사용하여 테스트 인스턴스로 대체 할 수있는 경우에도 유용 할 수 있습니다.

내가 알 수있는 한, 인터페이스 주입 은 세터 주입과 크게 다르지 않습니다. 두 경우 모두 나중에 변경 될 수있는 종속성을 선택적으로 설정합니다.

궁극적으로 그것은 선호 와 의존이 필요한지의 문제 입니다. 개인적으로 생성자 주입은 거의 독점적으로 사용합니다. 클라이언트가 생성자에 인스턴스를 제공하도록 강제함으로써 클래스의 종속성을 명시 적으로 만드는 것이 좋습니다. 또한 클라이언트는 사실 후에 인스턴스를 변경할 수 없다는 것을 좋아합니다.

종종 두 가지 별도의 구현을 전달하는 유일한 이유는 테스트 때문입니다. 프로덕션에서는을 전달할 수 DataRepository있지만 테스트에서는을 전달합니다 FakeDataRepository. 이 경우 일반적으로 매개 변수가없는 생성자와 a를 허용하는 생성자를 제공합니다 IDataRepository. 그런 다음 매개 변수가없는 생성자에서 두 번째 생성자에 대한 호출을 연결하고을 전달합니다 new DataRepository().

다음은 C #의 예입니다.


public class Foo
{
  private readonly IDataRepository dataRepository;

  public Foo() : this(new DataRepository())
  {
  }

  public Foo(IDataRespository dataRepository)
  {
    this.dataRepository = dataRepository;
  }
}

이것은 가난한 사람의 의존성 주입으로 알려져 있습니다. 프로덕션 클라이언트 코드에서는 다음과 같은 여러 반복문을 사용하여 반복 할 필요가 없기 때문에 좋아합니다.

var foo = new Foo(new DataRepository());
그러나 테스트를 위해 대체 구현을 계속 전달할 수 있습니다. 나는 가난한 사람의 DI로 의존성을 하드 코딩하고 있다는 것을 알고 있지만 테스트를 위해 주로 DI를 사용하기 때문에 받아 들일 수 있습니다.


고마워, 그것은 내가 이해하는 것에 매우 가깝지만 여전히 생성자 주입을 사용할 수없는 시나리오가 있습니까?
ecampver

1
선택적 종속성에 대해 생성자 삽입을 사용하고 싶지 않을 것입니다. 그것을 사용하지 않는 다른 이유는 생각할 수 없습니다.
jhewlett

속성 설정자 주입을 사용하여 많은 값을 포함하는 일부 구성 클래스를 채 웁니다. 다른 곳에서는 사용하지 않습니다. 단일 책임 규칙을 위반할 가능성이 높기 때문에 선택적 매개 변수에 대한 사례를 만드는 데는 항상 모호합니다. 물론 규칙은
Ian

@jhewlett - 환상적이다 즉, 내가 이상 내 솔루션을 복잡하게하지 않는 단위 테스트에 대한 좋은 간단의 스터 빙 기술을 찾고 있었어요 - 그리고 나는 이것이 :) 그것을 생각
Rocklan

2

생성자와 setter injection의 차이점은 이미 위에서 충분히 설명되었으므로 더 자세히 설명하지 않습니다.

인터페이스 주입은 고급 주입 방식으로, 사용할 오브젝트를 초기화 할 때가 아니라 사용 시점에 종속성을 결정할 수 있기 때문에 유용합니다. 이것은 많은 유용한 옵션을 허용합니다 :

  • 의존성은 주입되는 객체에 따라 다르게 나타날 수 있습니다. 예를 들어, 인터페이스 주입을 사용하여 사용자 세션 또는 스레드 당 존재하는 오브젝트를 글로벌 싱글 톤에 제공 할 수 있습니다. 객체가 종속성을 필요로 할 때마다 프레임 워크에서 제공하는 getter 메소드를 호출하며, 호출 된 상황에 따라 다른 결과를 리턴 할 수 있습니다.

  • 지연 초기화가 가능합니다. 사용하려고 할 때까지 종속성을 초기화 할 필요가 없습니다.

  • 캐시 된 사본에서 종속성이 존재하거나 존재하지 않을 때 다시 초기화 될 때 (예 : SoftReferenceJava 에서 사용) 종속성을로드 할 수 있습니다 .

이와 같은 고급 기술에는 단점이 있습니다. 이 경우 주된 문제는 코드가 명확하지 않게되고 (코드에 사용 된 클래스가 추상적이되고 명확하게 구현되지 않으며, 익숙하지 않은 경우 혼동 될 수 있음) 더 의존하게됩니다. 당신의 의존성 주입 프레임 워크 (그것은 여전히 가능 물론, 수동으로 객체를 생성 할 수 있지만, 다른 주입 스타일보다 단단하다).

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