예, 컨테이너가 주사 범위의 의존성이 public
확장되도록 it generally requires1 인스턴스화 공급 종속 할 수 있도록하기 위해서이다.
실제로, 종속성 변환 원칙의 또 다른 흔한 (그리고 잘못된) "gripe"은 이제 주입되는 모든 클래스의 내부 종속성이 일반적으로 공용 생성자에 노출된다는 것입니다. 원래 겉으로는 " 3 Amigos "OO의 교장, 이는 대중의 관점에서 단호하게 숨겨진 한 부류의 내부 의존성을 가졌습니다.
당연히이 클래스는 클래스를 종속성과 직접 결합하여 new
인스턴스화를 통해 디커플링을 방지하고 최악의 경우 혼란스런 시대 코드에서 첫 번째 클래스 설계 관심사로 인식됩니다.
규칙에 따라 클래스 간의 결합은 항상 인터페이스를 통해 이루어져야한다는 점을 기억해야합니다. 이러한 공용 클래스와 생성자를 실제로 "사용"하는 유일한 액터는 컨테이너 테스트와 유닛 테스트 일 것입니다. 예를함으로써
:
저장소 조립
public interface IFooRepo
{
Task<IEnumerable<Foo>> FindFoos(Predicate predicate);
// ...
}
// For IoC and testing purposes, MyFooRepo must be public
public class MyFooRepo : IFooRepo
{
// .. Implement
}
서비스 조립
// Note : No indication of the IFooRepository dependency here
public interface IMyService
{
Task DoAmazingThingsWithFoo();
}
// MyService class must also be public for IoC and tests
public class MyService : IMyService
{
private readonly IMyRepo _repo;
// Dependencies are publically visible on the constructor
public MyService(IMyRepo repo)
{
_repo = repo;
}
// ... Implement
}
IOC의 부트 스트랩
Bind<IFooRepo>().To<MyFooRepo>(); // Can also specify lifetimes etc
Bind<IMyService>().To<MyService>();
추가 읽기 - Mark Seemann은 public scope을 방어합니다.
[1] 스티븐 넌 및 인터페이스에 대하여도 내 예 "비록 커플 링은 일반적으로 인터페이스 대하여 있어야"지적 SimpleInject의 주요 저자
이지만, 인터페이스 자체에 결합 공용 클래스 (IRepository), 따라서 커플 링이 인터페이스 대신 클래스에 대해 여전히 더 나은 방법으로 인터페이스를 유지할 수 있습니까? –
다른 클래스에 종속 된 클래스는 인터페이스 (D의 SOLID)를 통해서만 연결되어야한다는 것을 의미합니다. IoC 부트 스트래핑 자체는 절대로 우아하지 않습니다. 일반적으로 인터페이스 종속성이 필요할 때 사용할 구체적인 클래스를 정의합니다 (일부 IoC는 명명 규칙을 기반으로 자동 바인딩됩니다). 나는 예제를 업데이트했다. – StuartLC