수색…


소개

DI (Dependency Injection)는 "전달하는 것"을 의미하는 용어입니다. 실제로 이것은 객체 내부의 객체 생성시 객체를 생성하는 대신 생성자 및 / 또는 설정자를 통해 객체의 종속성을 전달한다는 것을 의미합니다. 의존성 주입 (Dependency Injection)은 구성 및 주입을 자동화하는 종속성 주입 컨테이너 (Dependency Injection Containers)를 의미 할 수도 있습니다.

생성자 삽입

객체는 종종 다른 객체에 의존합니다. 생성자에서 종속성을 만드는 대신 종속성을 생성자에 매개 변수로 전달해야합니다. 이렇게하면 객체간에 긴밀한 결합이 발생하지 않으며 클래스 인스턴스화에 대한 종속성을 변경할 수 있습니다. 종속성을 명시 적으로 지정하여 코드를 읽기 쉽게 만드는 것, 종속성을 전환하고보다 쉽게 ​​조롱 할 수 있으므로 테스트를 단순화하는 것 등 다양한 이점이 있습니다.

다음의 예에서는, ComponentLogger 의 인스턴스에 의존 합니다만, 생성은하지 않습니다. 대신 하나를 인수로 전달하여 생성자에 전달해야합니다.

interface Logger {
    public function log(string $message);
}

class Component {
    private $logger;

    public function __construct(Logger $logger) {
        $this->logger = $logger;
    }
}

의존성 주입없이 코드는 다음과 비슷할 것입니다.

class Component {
    private $logger;

    public function __construct() {
        $this->logger = new FooLogger();
    }
}

new 를 사용하여 생성자에서 새 객체를 만들면 종속성 삽입이 사용되지 않았거나 불완전하게 사용되었으며 코드가 밀접하게 결합되었음을 나타냅니다. 또한 코드가 불완전하게 테스트되었거나 프로그램 상태에 대해 잘못된 가정을하는 취성있는 테스트가있을 수 있다는 신호이기도합니다.

위의 예에서 우리가 의존성 주입을 대신 사용한다면, 필요하다면 다른 로거로 쉽게 변경할 수 있습니다. 예를 들어, 다른 위치에 기록하거나 다른 기록 형식을 사용하거나 파일 대신 데이터베이스에 기록하는 Logger 구현을 사용할 수 있습니다.

세터 주입

의존성은 세터에 의해 주입 될 수도 있습니다.

interface Logger {
    public function log($message);
}

class Component {
    private $logger;
    private $databaseConnection;

    public function __construct(DatabaseConnection $databaseConnection) {
        $this->databaseConnection = $databaseConnection;
    }

    public function setLogger(Logger $logger) {
        $this->logger = $logger;
    }

    public function core() {
        $this->logSave();    
        return $this->databaseConnection->save($this);
    }

    public function logSave() {
         if ($this->logger) {
            $this->logger->log('saving');
        }
    }
}

이는 클래스의 핵심 기능이 작동 종속성에 의존하지 않는 경우 특히 유용합니다.

여기서는 필요한 유일한 종속성이 DatabaseConnection 이므로 생성자에 있습니다. Logger 의존성은 선택 사항이므로 생성자에 속할 필요가 없으므로 클래스를보다 쉽게 ​​사용할 수 있습니다.

세터 주입을 사용하는 경우 기능을 확장하는 대신 확장하는 것이 좋습니다. 종속성을 설정할 때 종속성이 어느 시점에서 변경되지 않음을 확인하는 것은 아무것도 없으므로 예기치 않은 결과가 발생할 수 있습니다. 예를 들어 FileLogger 를 처음 설정하면 MailLogger 설정할 수 있습니다. 이것은 캡슐화를 중단하고 로그를 찾기 어렵게 만듭니다. 왜냐하면 우리가 의존성을 대체 하기 때문입니다.

이를 방지하기 위해 setter injection에 의존성을 추가 해야 합니다 :

interface Logger {
    public function log($message);
}

class Component {
    private $loggers = array();
    private $databaseConnection;

    public function __construct(DatabaseConnection $databaseConnection) {
        $this->databaseConnection = $databaseConnection;
    }

    public function addLogger(Logger $logger) {
        $this->loggers[] = $logger;
    }

    public function core() {
        $this->logSave();
        return $this->databaseConnection->save($this);
    }

    public function logSave() {
        foreach ($this->loggers as $logger) {
            $logger->log('saving');
        }
    }
}

이와 같이 핵심 기능을 사용할 때마다 로거 종속성이 추가되지 않아도 중단되지 않으며 다른 로거를 추가 할 수있는 경우에도 추가 된 로거가 사용됩니다. 기능을 대체 하는 대신 확장 하고 있습니다.

컨테이너 주입

Dependency Injection Container (DIC)를 사용하는 맥락에서 DI (Dependency Injection)는 생성자 주입의 상위 집합으로 볼 수 있습니다. DIC는 일반적으로 클래스 생성자의 유형 힌트를 분석하고 요구 사항을 해결하여 인스턴스 실행에 필요한 종속성을 효율적으로 주입합니다.

정확한 구현은이 문서의 범위를 넘어서는 것이지만, DIC는 클래스의 서명 사용에 의존합니다.

namespace Documentation;

class Example
{
    private $meaning;

    public function __construct(Meaning $meaning)
    {
        $this->meaning = $meaning;
    }
}

... 자동으로 인스턴스를 생성하기 위해 대부분의 시간을 자동 로딩 시스템 에 의존 합니다 .

// older PHP versions
$container->make('Documentation\Example');

// since PHP 5.5
$container->make(\Documentation\Example::class);

버전 5.5 이상에서 PHP를 사용하고 있고 위에 표시된 것과 같은 방식으로 클래스 이름을 얻으려면 올바른 방법이 두 번째 방법입니다. 그렇게하면 최신 IDE를 사용하여 클래스의 사용법을 빠르게 찾을 수 있으므로 잠재적 인 리팩토링에 큰 도움이됩니다. 당신은 일반적인 문자열에 의존하고 싶지 않습니다.

이 경우, Documentation\ExampleMeaning 필요하다는 것을 알고 DIC는 Meaning 유형을 인스턴스화합니다. 구체적인 구현은 소비 인스턴스에 의존 할 필요가 없습니다.

대신 개체 작성 전에 컨테이너에 규칙을 설정하여 필요한 경우 특정 유형을 인스턴스화하는 방법을 지시합니다.

DIC는 다음과 같은 장점을 가지고 있습니다.

  • 공통 인스턴스 공유
  • 형식 시그니처를 처리 할 팩토리를 제공하십시오.
  • 인터페이스 서명 확인

특정 유형을 관리해야하는 방법에 대한 규칙을 정의하면 어떤 유형을 공유, 인스턴스화 또는 공장에서 생성 할지를 세부적으로 제어 할 수 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow