[java] 의존성 주입 생성자 광기를 피하는 방법?

내 생성자가 다음과 같이 보이기 시작했습니다.

public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )

매개 변수 목록이 계속 증가합니다. “컨테이너”는 의존성 주입 컨테이너이므로 왜 이렇게 할 수 없습니까?

public MyClass(Container con)

모든 수업에 대해? 단점은 무엇입니까? 이렇게하면 영광스러운 정적을 사용하고있는 것 같습니다. IoC 및 Dependency Injection 광기에 대한 의견을 공유하십시오.



답변

컨테이너를 서비스 로케이터로 사용하면 다소 영광스러운 정적 팩토리입니다. 여러 가지 이유로 나는 이것을 안티 패턴이라고 생각합니다 .

생성자 주입의 놀라운 이점 중 하나는 단일 책임 원칙을 위반하는 것이 눈에 띄게 한다는 것 입니다.

그런 일이 발생하면 Facade Services리팩토링해야합니다 . 요컨대, 현재 필요한 세밀한 종속성의 일부 또는 전부 간의 상호 작용을 숨기는 새롭고 더 세분화 된 인터페이스를 만듭니다 .


답변

클래스 생성자가 IOC 컨테이너 기간에 대한 참조를 가져야한다고 생각하지 않습니다. 이것은 클래스와 컨테이너 사이의 불필요한 종속성을 나타냅니다 (IOC가 피하려고하는 종속성 유형입니다!).


답변

매개 변수를 전달하기가 어렵다는 것은 문제가 아닙니다. 문제는 당신의 수업이 너무 많은 일을하고 있고, 더 세분화되어야한다는 것입니다.

의존성 주입은 클래스가 너무 커질 때, 특히 모든 의존성에 통과하는 고통이 커지기 때문에 조기 경고 역할을 할 수 있습니다.


답변

생성자 기반 종속성 인젝션과 모든 종속성을 전달하는 것이 얼마나 복잡한 지에 대해 비슷한 질문을 받았습니다.

필자가 과거에 사용한 접근법 중 하나는 서비스 계층을 사용하여 애플리케이션 파사드 패턴을 사용하는 것입니다. 이것은 거친 API를 가질 것입니다. 이 서비스가 저장소에 의존하는 경우 개인 특성의 세터 주입을 사용합니다. 이를 위해서는 추상 팩토리를 작성하고 저장소를 작성하는 로직을 팩토리로 이동해야합니다.

설명과 함께 자세한 코드는 여기에서 찾을 수 있습니다

복잡한 서비스 계층의 IoC 모범 사례


답변

나는이 글 전체를 두 번 읽었고, 사람들은 질문에 의한 것이 아니라 그들이 아는 것에 의해 응답한다고 생각합니다.

JP의 원래 질문은 리졸버와 많은 클래스를 전송하여 객체를 생성하는 것처럼 보이지만 이러한 클래스 / 객체는 자체적으로 서비스이며 주입에 적합하다고 가정합니다. 그들이 아닌 경우 어떻게?

JP, 당신이 활용 DI를 찾는 경우 상황에 맞는 데이터를 주입 혼합의 영광을 원하는, 이러한 패턴 (또는 가정 “안티 패턴”)의 아무도 특별히 주소가. 실제로 그러한 노력으로 당신을 지원할 패키지를 사용하는 것으로 요약됩니다.

Container.GetSevice<MyClass>(someObject1, someObject2)

…이 형식은 거의 지원되지 않습니다. 구현과 관련된 비참한 성능에 추가 된 이러한 지원의 프로그래밍 어려움은 오픈 소스 개발자에게는 매력적이지 않다고 생각합니다.

그러나 MyClass에 대한 팩토리를 생성하고 등록 할 수 있어야하고 해당 팩토리는 전달을 위해 “서비스”로 푸시되지 않은 데이터 / 입력을 수신 할 수 있어야하기 때문에 수행되어야합니다. 데이터. “반 패턴 (anti-pattern)”이 부정적인 결과에 관한 것이라면, 데이터 / 모델을 전달하기위한 인공적인 서비스 유형의 존재를 강요하는 것은 확실히 부정적입니다 (클래스를 컨테이너로 묶는 것에 대한 느낌과 동일합니다. 동일한 본능이 적용됩니다).

비록 조금보기에 좋지 않더라도 도움이 될만한 프레임 워크가 있습니다. 예를 들어, Ninject :

생성자에서 추가 매개 변수와 함께 Ninject를 사용하여 인스턴스 만들기

그것은 .NET 용이며 인기가 있으며 여전히 깨끗한 곳은 아니지만, 당신이 선택한 언어가 무엇인지 확신합니다.


답변

컨테이너를 주입하는 것은 결국 후회할 수있는 지름길입니다.

과다 주입은 문제가되지 않으며, 일반적으로 다른 구조적 결함의 증상이며, 특히 우려의 분리입니다. 이것은 하나의 문제는 아니지만 많은 출처를 가질 수 있으며 이것을 고치기 어렵게 만드는 것은 때로는 동시에 동시에 모든 문제를 해결해야한다는 것입니다 (스파게티 풀림을 생각할 때).

다음은 찾아야 할 것들의 불완전한 목록입니다.

불완전한 도메인 디자인 (Aggregate root ‘s…. etc)

문제 분리 불량 (서비스 구성, 명령, 쿼리) CQRS 및 이벤트 소싱을 참조하십시오.

또는 매퍼 (주의 : 이로 인해 문제가 발생할 수 있음)

모델 및 기타 DTO보기 (다시 재사용하지 말고 최소로 유지하십시오 !!!!)


답변

문제 :

1) 매개 변수 목록이 계속 증가하는 생성자.

2) 클래스가 상속되면 (예 🙂 RepositoryBase생성자 서명을 변경하면 파생 클래스가 변경됩니다.

해결책 1

패스 IoC Container생성자

  • 더 이상 매개 변수 목록을 증가시키지 않습니다
  • 생성자의 서명이 간단 해집니다

왜 안돼?

  • 클래스를 IoC 컨테이너에 단단히 연결합니다. (1. 다른 IoC 컨테이너를 사용하는 다른 프로젝트에서 해당 클래스를 사용하려는 경우 문제가 발생합니다. 2. IoC 컨테이너를 변경하기로 결정 함)
  • 수업을 덜 설명 적으로 만듭니다. (실제로 클래스 생성자를보고 기능에 필요한 것을 말할 수는 없습니다.)
  • 클래스는 잠재적으로 모든 서비스에 액세스 할 수 있습니다.

해결책 2

모든 서비스를 그룹화하여 생성자에게 전달하는 클래스를 만듭니다.

 public abstract class EFRepositoryBase
 {
    public class Dependency
    {
        public DbContext DbContext { get; }
        public IAuditFactory AuditFactory { get; }

         public Dependency(
            DbContext dbContext,
            IAuditFactory auditFactory)
        {
            DbContext = dbContext;
            AuditFactory = auditFactory;
        }
    }

    protected readonly DbContext DbContext;
    protected readonly IJobariaAuditFactory auditFactory;

    protected EFRepositoryBase(Dependency dependency)
    {
        DbContext = dependency.DbContext;
        auditFactory= dependency.JobariaAuditFactory;
    }
  }

파생 클래스

  public class ApplicationEfRepository : EFRepositoryBase
  {
     public new class Dependency : EFRepositoryBase.Dependency
     {
         public IConcreteDependency ConcreteDependency { get; }

         public Dependency(
            DbContext dbContext,
            IAuditFactory auditFactory,
            IConcreteDependency concreteDependency)
        {
            DbContext = dbContext;
            AuditFactory = auditFactory;
            ConcreteDependency = concreteDependency;
        }
     }

      IConcreteDependency _concreteDependency;

      public ApplicationEfRepository(
          Dependency dependency)
          : base(dependency)
      {
        _concreteDependency = dependency.ConcreteDependency;
      }
   }

  • 클래스에 새로운 종속성을 추가해도 파생 클래스에는 영향을 미치지 않습니다
  • 클래스는 IoC 컨테이너와 무관합니다
  • 클래스는 (종속성 측면에서) 설명 적입니다. 규칙에 따라 어떤 클래스가 A의존 하는지 알고 싶다면 해당 정보가 누적됩니다.A.Dependency
  • 생성자 서명이 간단 해짐

왜 안돼?

  • 추가 수업을 만들어야합니다
  • 서비스 등록이 복잡 해짐 (매번 등록해야 함 X.Dependency)
  • 통과와 개념적으로 동일 IoC Container
  • ..

솔루션 2는 단지 원시 일이지만 그것에 대한 확실한 주장이 있으면 설명적인 의견을 부탁드립니다.