Используя pimple в качестве контейнера внедрения зависимостей, я смело рефакторил небольшие классы, чтобы полагаться на внедрение внедрения зависимостей, устраняя жестко закодированные зависимости, которые я мог видеть, будут легко удалены.
Моя методология для этой задачи очень проста, но я понятия не имею, правильна ли она, поскольку у меня очень мало опыта в области внедрения зависимостей и модульного тестирования, если не считать того, что я узнал здесь за последний месяц.
Я создал класс ContainerFactory, который является подклассом pimple, и в этом подклассе создал методы, которые просто возвращают контейнер для определенного объекта.
Конструктор вызывает правильный метод создателя в зависимости от типа:
function __construct($type=null, $mode = null){
if(isset($type)){
switch ($type) {
case 'DataFactory':
$this->buildDataFactoryContainer($mode);
break;
case 'DbConnect':
$this->buildDbConnectContainer($mode);
break;
default:
return false;
}
}
}
Сигнатура метода для создания объекта-контейнера выглядит следующим образом:
public function buildDataFactoryContainer($mode=null)
Идея состоит в том, что я могу установить $mode для тестирования при вызове этого контейнера и загрузить тестовые значения вместо фактических настроек времени выполнения. Я хотел избежать написания отдельных классов контейнеров для тестирования, и я думал, что это простой способ не иметь кода, связанного с тестами, повсюду.
Вместо этого я мог бы создать подкласс ContainerFactory, т.е.: ContainerFactoryTesting extends ContainerFactory
, и переопределить его вместо того, чтобы смешивать тестовый код с кодом приложения и загромождать сигнатуры методов с помощью $mode=null, но это не является целью этого поста. Двигаясь дальше, чтобы создать контейнер для определенного объекта, я просто делаю это:
// returns container with DataFactory dependencies, holds $db and $logger objects.
$dataFactoryContainer = new ContainerFactory('DataFactory');
// returns container with test settings.
$dataFactoryTestContainer = new ContainerFactory('DataFactory','test');
// returns container with DbConnect dependencies, holds dbconfig and $logger objects.
$dbConnectContainer = new ContainerFactory('DbConnect');
Я только что столкнулся с проблемой, которая заставляет меня подозревать, что стратегия, на которой я строю, ошибочна.
Глядя на вышеизложенное, DataFactory содержит объект $db, который содержит соединения с базой данных. Сейчас я реорганизую этот dbclass, чтобы удалить его зависимости от объекта $registry, но как мне создать $dataFactoryContainer, когда я добавлю объект $db, которому нужен $dbConnectContainer?
Например, в контейнере datafactory я добавляю экземпляр dbconnect, но теперь ИТ-специалистам потребуется переданный ему контейнер...
Я понимаю, что мой английский не так уж хорош, и надеюсь, что объяснил достаточно хорошо, чтобы товарищ SO'er понял.
Мой вопрос состоит из двух частей: как вы, ребята, справляетесь с созданием объектов для зависимостей, которые сами содержат зависимости, простым способом?
И... как вы разделяете конфигурацию контейнера для создания объектов в целях тестирования?
Как всегда, любой комментарий или ссылка на соответствующий пост приветствуются.