[dependency-injection] 생성자 또는 속성 설정자를 통한 종속성 주입?

클래스를 리팩토링하고 새로운 의존성을 추가하고 있습니다. 클래스는 현재 생성자에서 기존 종속성을 사용하고 있습니다. 일관성을 위해 생성자에 매개 변수를 추가합니다.
물론 단위 테스트를위한 몇 가지 서브 클래스와 그 밖의 여러 클래스가 있으므로 이제 모든 생성자를 변경하여 게임을 진행하고 있습니다.
setter와 함께 속성을 사용하는 것이 종속성을 얻는 더 좋은 방법이라고 생각합니다. 주입 된 의존성이 클래스의 인스턴스를 구성하는 인터페이스의 일부라고 생각하지 않습니다. 종속성을 추가하면 이제 모든 사용자 (서브 클래스 및 직접 인스턴스화하는 사람)가 갑자기이를 알게됩니다. 캡슐화가 깨지는 것 같습니다.

이것은 기존 코드의 패턴이 아닌 것 같으므로 생성자 대 속성의 장단점에 대한 일반적인 합의가 무엇인지 찾고 있습니다. 속성 설정기를 사용하는 것이 더 낫습니까?



답변

글쎄, 그것은 :-)에 달려 있습니다.

클래스가 종속성없이 작업을 수행 할 수 없으면 생성자에 추가하십시오. 클래스 에는 새로운 종속성이 필요 하므로 변경 사항이 변경되기를 원합니다. 또한 완전히 초기화되지 않은 클래스 ( “2 단계 구성”)를 만드는 것은 반 패턴 (IMHO)입니다.

클래스가 종속성없이 작동 할 수 있다면 setter가 좋습니다.


답변

클래스의 사용자가되는 가정 주어진 클래스의 종속성에 대해 알고. 예를 들어 데이터베이스에 연결된 클래스가 있고 지속성 계층 종속성을 주입하는 수단을 제공하지 않은 경우 사용자는 데이터베이스에 대한 연결을 사용할 수 있어야한다는 것을 절대 알 수 없습니다. 그러나 생성자를 변경하면 지속성 계층에 대한 종속성이 있음을 사용자에게 알립니다.

또한 이전 생성자의 모든 사용을 변경하지 않으려면 이전 생성자와 새 생성자의 임시 브리지로 생성자 체인을 적용하기 만하면됩니다.

public class ClassExample
{
    public ClassExample(IDependencyOne dependencyOne, IDependencyTwo dependencyTwo)
        : this (dependnecyOne, dependencyTwo, new DependnecyThreeConcreteImpl())
    { }

    public ClassExample(IDependencyOne dependencyOne, IDependencyTwo dependencyTwo, IDependencyThree dependencyThree)
    {
        // Set the properties here.
    }
}

의존성 주입의 포인트 중 하나는 클래스가 갖는 의존성을 밝히는 것입니다. 클래스가 너무 많은 의존성을 가지고 있다면, 일부 리팩토링이 일어날 시간이다 : 클래스의 모든 메소드가 모든 의존성을 사용 하는가? 그렇지 않다면, 그것은 수업이 어디로 나뉘어 질 수 있는지를보기에 좋은 출발점입니다.


답변

물론 생성자를 착용하면 한 번에 모두 확인할 수 있습니다. 사물을 읽기 전용 필드에 할당하면 생성 시점부터 개체의 종속성에 대해 약간의 보증이 제공됩니다.

새로운 의존성을 추가하는 것은 큰 고통이지만 적어도 이런 식으로 컴파일러는 정확해질 때까지 계속 불평합니다. 좋은 것 같아요.


답변

많은 수의 선택적 종속성 (이미 냄새 임)이있는 경우 아마도 setter injection이 좋습니다. 생성자 주입은 의존성을 더 잘 드러냅니다.


답변

일반적으로 선호되는 방법은 생성자 주입을 가능한 많이 사용하는 것입니다.

생성자 주입은 객체가 올바르게 작동하기 위해 필요한 종속성이 무엇인지 정확하게 나타냅니다. 일부 종속성이 설정되지 않았기 때문에 객체를 새로 고치고 메소드를 호출 할 때 충돌하는 것보다 더 성가신 것은 없습니다. 생성자가 반환 한 객체는 작동 상태에 있어야합니다.

생성자를 하나만 사용하면 디자인이 단순하고 모호함을 피할 수 있습니다 (인간이 아닌 경우 DI 컨테이너의 경우).

Mark Seemann 이 자신의 저서 “.NET에 의존성 주입 (Dependency Injection in .NET)”에서 로컬 기본값 을 호출 할 때 특성 주입을 사용할 수 있습니다 . 종속성은 선택 사항입니다. 제대로 작동하는 구현을 제공 할 수 있지만 호출자가 다른 경우를 지정할 수 있기를 바랍니다. 필요합니다.

(아래의 이전 답변)


주입이 필수 인 경우 생성자 주입이 더 좋다고 생각합니다. 생성자가 너무 많으면 생성자 대신 팩토리를 사용하는 것이 좋습니다.

주입이 선택 사항이거나 반쯤 통과 시키려면 세터 주입이 좋습니다. 나는 일반적으로 세터를 좋아하지 않지만 맛의 문제입니다.


답변

그것은 개인적인 취향의 문제입니다. 개인적으로 나는 setter 주입을 선호하는 경향이 있습니다. 왜냐하면 런타임에 구현을 대체 할 수있는 방식으로 더 많은 유연성을 제공하기 때문입니다. 또한 많은 인수를 가진 생성자는 내 의견으로는 깨끗하지 않으며 생성자에서 제공되는 인수는 비 선택적 인수로 제한되어야합니다.

클래스 인터페이스 (API)가 작업을 수행하는 데 필요한 것이 명확하다면, 좋습니다.


답변

나는 개인적으로 생성자에 의존성을 주입 하는 것보다 추출 및 재정의 “패턴”을 선호합니다 . 주로 귀하의 질문에 요약 된 이유 때문입니다. 속성을로 설정 virtual한 다음 파생 된 테스트 가능 클래스에서 구현을 재정의 할 수 있습니다 .