Dependency Injection (внедрение зависимостей) -- что это такое

Dependency Injection - это концепция построения приложения, при которой за каждую функцию приложения отвечает один, условно независимый объект (сервис), который может иметь необходимость использовать другие объекты (зависимости), известные ему интерфейсами. Концепция реализуется в различных языках программирования: PHP, Java, JavaScript, С#, Python и др.

Такой подход, когда функциональные блоки выделяются в сервисы, принято называть сервисно-ориентированной архитектурой (Service-oriented architecture, SOA).

Термин переводится как "внедрение зависимостей".

Как это работает

Если некий сервис использует какие-то данные, он получает их в готовом виде. И он "не знает, и не зависит, и не истересуется" логикой их получения. За это отвечает отдельный сервис.

Для чего это нужно

Инкапсуляция, разделение отвественности за определённый функционал между разными сервисами.

Пример

<?php
/**
 * Класс конфигурация базы данных
 */
class DbConfiguration{
    private $host;
    private $port;
    private $username;
    private $password;

    public function __construct(string $host, int $port, string $username, string $password){
        // вся соль Di находится в строчках ниже
        $this->host = $host;
        $this->port = $port;
        $this->username = $username;
        $this->password = $password;
    }

    public function getHost(){
        return $this->host;
    }

    public function getPort(){
        return $this->port;
    }

    public function getUsername(){
        return $this->username;
    }

    public function getPassword(){
        return $this->password;
    }
}

/**
 * Класс соединение с базой данных
 */

class DbConnection{
    private $configuration;

    public function __construct(DbConfiguration $config){
        // вся соль Di находится в строчке ниже
        $this->configuration = $config;
    }

    public function getDsn(){
        // примечание: это не реальный dsn, разделители в реальном dsn другие
        return sprintf(
            '%s:%s@%s:%d',
            $this->configuration->getUsername(),
            $this->configuration->getPassword(),
            $this->configuration->getHost(),
            $this->configuration->getPort()
        );
    }
}

// создаем объект конфигурации базы данных, передав в конструктор параметры
$config = new DbConfiguration('localhost', 3306, 'username', 'password');

// создаем объект соединения с базой, передав в конструктор объект конфигурации
// использование Di дает слабосвязность кода
$connection = new DbConnection($config);

В Symfony (PHP) эта концепция реализуется с помощью Контейнера (Conteiner Component). Примеры реализации и правила конфигурации сервисов в Symfony можно посмотреть здесь.

Источники

vedro-compota's picture

из статьи не ясен уровень абстракции. Ведь можно очень по-разному разбивать приложение на функции. Чем это отличатся от "чистого" ООП?

_____________
матфак вгу и остальная классика =)

melisa's picture

Как я поняла, от ООП инъекции отличаются тем, что

  1. Каждый класс (сервис) реализует свой функционал, который абсолютно не связан с другими сервисами. Т.е. речь идёт о бизнес-логике.
  2. Данные каждый сервис получает в виде "готовой конфетки", а не достаёт сам с помощью методов родительского/реализуемого класса.
vedro-compota's picture

Каждый класс (сервис) реализует свой функционал, который абсолютно не связан с другими сервисами. Т.е. речь идёт о бизнес-логике.
Данные каждый сервис получает в виде "готовой конфетки", а не достаёт сам с помощью методов родительского/реализуемого класса.

это как-то очень невнятно. Во первых "абсолютно" не бывает -- у вас в заметке уже написано, что интерфейс фиксированный:

может иметь необходимость использовать другие объекты (зависимости), известные ему интерфейсами.

А значит эксплуатирующий класс чего-то уже ожидает от используемого. Но это всегда происходит когда применяются интерфейсы.

_____________
матфак вгу и остальная классика =)

melisa's picture

Во первых "абсолютно" не бывает -- у вас в заметке уже написано, что интерфейс фиксированный

здесь слово "абсолютно" относится к функционалу, а не сервису.