Должен ли я использовать внедрение зависимостей в моем проекте php? - PullRequest
5 голосов
/ 20 января 2012

Я недавно узнал о преимуществах внедрения зависимостей, но мне интересно, стоит ли мне использовать его в моем проекте, поскольку мне даже не требуется полноценный mvc.Теперь, когда я использую его, я осознаю дополнительные издержки на каждой странице, которую я пишу.Например ...

    require_once '../../include/session.class.php';
    require_once '../../include/db.class.php';
    require_once '../../include/account.class.php';

    $objSession = new Session();
    $objDb      = new Db();
    $objAccount = new Account( $objSession, $objDb );

account.class.php

class Account {
    ...
    public function __construct( Session $objSession, Db $objDb ) {
        $this->session = $objSession;
        $this->db = $objDb;
    }
}

... классу Account всегда будут нужны Db и Session, а ятолько один класс каждого.Поэтому мой вопрос заключается в том, должен ли я использовать DI в такой ситуации или просто использовать ...

account.class.php

require_once '../../include/session.class.php';
require_once '../../include/db.class.php';

class Account {
    ...
    public function __construct() {
        $this->session = new Session();
        $this->db = new Db();
    }
}

...

Ответы [ 3 ]

6 голосов
/ 20 января 2012

Внедрение зависимостей не имеет ничего общего с MVC. Это действительно хорошо для написания модульных тестов, и в итоге я обнаружил, что это заставляет меня задуматься о ресурсах, которые я использую, и о том, должна ли эта реализация использовать этот ресурс.

Лично я не вижу вреда в создании внедренного объекта, так что у вас есть пара строк, где вы должны создать объект? Он рассказывает пользователю намного больше о том, что происходит. Я предпочел бы иметь ясность по сравнению с магией.

Лично я думаю, что большая часть беспорядка в коде исходит из операторов require. Я бы сказал, что автозагрузчик решил бы эту проблему.

Мне очень понравилось это Google Clean Code Talk на DI . Это помогло мне лучше понять концепцию и ее преимущества.

1 голос
/ 20 января 2012

Вы читали о достоинствах внедрения зависимости.Почему вы начали его использовать?

Было ли это из-за возможности поменять эти конкретные зависимости для тестирования или в других средах?Было ли это выделить и сделать явным порядок круговой цепочки зависимостей?

Предположим, например, что это было желание вводить разные классы для целей тестирования (заслуга DI заставила меня его использовать).Как вы справляетесь с этим без DI?

Посмотрите на свой класс учетной записи.Вы можете либо изменить конструктор с помощью проверки if для некоторого предиката testMode (), либо вы можете изменить конструкторы Db и Session, либо вы можете изменить файл конфигурации.Какое решение не DI вы выберете, вы согласны с этим?А как насчет других зависимостей (emailer, logger и т. Д.)?Есть ли у вас какие-либо интерфейсы к внешним системам, которые вы должны использовать для тестирования?

В любом случае, ответом может быть то, что вы удовлетворены без DI-решения и что ваше приложение достаточно маленькое, чтобы обходиться без него.Но все равно важно задать себе вопрос.

Точно так же примените ту же самую линию вопросов к другим достоинствам DI, побудившим вас начать его использовать.

Кстати, у вас есть одинэкземпляр Db в учетной записи и другой в каждом из ваших других классов?Не могли бы вы иметь только один экземпляр?Д. помогает с этим.Вы можете иметь одноэлементные классы, фактически не кодируя их как синглетоны, всегда внедряя один и тот же экземпляр.

Из любопытства, почему вы делаете собственное внедрение зависимостей вместо использования библиотеки DI?Половина преимущества использования DI состоит в том, что он полностью абстрагируется от реализации других людей.Пишите только тот код, который вам нужен, и пусть библиотеки позаботятся о том, чтобы сделать за вас инъекцию.Это похоже на предложение drrcknlsn, но без написания фактической реализации класса DependencyInjectionContainer:

$ account = DependencyInjectionContainer :: build ('Account');

и привинтить остальные.

Хорошая библиотека DI должна видеть конструктор для Account, понимать, что ей нужны Db и Session, и продвигаться по цепочке конструкторов (в этом случае она заканчивается там, поскольку оба имеют пустые конструкторы).Это означает наличие того же объема кода, что и в случае без DI (плюс аргументы для конструктора, минус обращения к конструкторам внутри, но без лишней хрени наверху), с какими бы преимуществами вы ни привели вас в DI.

0 голосов
/ 20 января 2012

Для решения этой проблемы были изобретены контейнеры для инъекций зависимости. Рассмотрим:

$account = DependencyInjectionContainer::build('Account');

Класс DependencyInjectionContainer будет обрабатывать инъекцию:

public static function build($class) {
    switch ($class) {
        case 'Account':
            $session = new Session();
            $db = new Db();
            return new Account($session, $db);

        // ...
    }
}
...