В последнее время я много читаю об инъекции зависимостей, и теоретически это имеет большой смысл. Идея иметь простой тест, отдельные классы ответственности просто звучит разумно. Тем не менее, я борюсь с тем, как далеко его принять.
Я работаю над веб-приложением PHP прямо сейчас, у которого есть компонент CMS и сильно управляется базой данных. В CMS вы можете создавать страницы, а сами страницы создаются с использованием различных виджетов. Виджеты могут быть прямым HTML (из редактора WYSIWYG), или могут быть немного сложнее, например, в фотогалерее. И это важная часть, виджет фотогалереи зависит от других моделей db, таких как PhotoGallery
и PhotoGalleryImages
, чтобы нормально функционировать.
Согласно Miško Hevery, я не должен передавать ссылки на зависимости через разные уровни моего приложения. Вместо этого каждый класс должен просто "запрашивать" любые зависимости, которые он требует. Используя его пример, вот как это выглядит:
$db = new Database()
$repo = new UserRepository($db);
$page = new LoginPage($repo);
Пока я вижу этот рабочий режим для уровней обслуживания моего приложения, я действительно не понимаю, как это будет работать с моими объектами/объектами ценности. Мне кажется, что эта модель требует от меня экземпляров всех моих моделей на самом высоком уровне моего приложения. Однако как я могу создать экземпляр всех моих виджетов на этом уровне, когда мне нужен мой класс, чтобы рассказать мне, какие виджеты мне нужно создать? И не зная, какие виджеты я создаю, как я могу узнать, какие зависимости виджета нужно создавать и вводить?
В теории DI имеет для меня большой смысл. Однако фактически реализация этого шаблона в моем новом веб-приложении оказывается более сложной. Есть ли что-то, что мне не хватает в отношении DI и IoC? Благодарю!
Обновление: ответ на Tandu
Большое спасибо за ответ Танду. Я думаю, что DI не может быть на самом деле моей проблемой здесь, потому что я думаю, что я очень четко понимаю, что это такое, будь то инсталляция конструктора или сеттера, или это делается с использованием контейнера или бедных людей. То, что я действительно думаю, происходит потому, что DI бросает вызов мне переосмыслить, как я сейчас программирую. Я думаю, что мой проект ООП - это проблема. Чтобы проиллюстрировать это, вот как я обычно запрограммировал бы эту проблему:
class Page
{
public $id;
public $name;
public function widgets()
{
// Perform SQL query to select all widgets
// for this page from the database, and then
// return them as Widget objects.
}
}
interface Widget
{
public $id;
public $page_id;
public $type;
public function widgetize();
}
class PhotoGallery_Widget implements Widget
{
public $id;
public $page_id;
public $type;
public function widgetize()
{
$gallery = new Photogallery();
foreach($gallery->images())
{
// Create gallery HTML code
}
}
}
// Finally, to create the page, I would:
$page = new Page(1);
foreach($page->widgets() as $widget)
{
$widget->widgetize();
}
Ясно, что здесь есть некоторые проблемы. Модель Page
зависит от моделей Widget
. Модель PhotoGallery_Widget
зависит от модели PhotoGallery
, и даже более того модель PhotoGallery
зависит от модели PhotoGalleryImages
. Дело в том, что развитие этого пути хорошо сработало для меня. По мере того как я становлюсь все глубже и глубже в слоях моего приложения, каждый слой берет на себя ответственность за создание требуемых объектов. Введение DI бросает важный ключ в мой образ мыслей. Тем не менее, я хочу узнать, как это сделать должным образом. Просто потому, что это работает для меня прямо сейчас, не означает, что я должен продолжать делать это таким образом.
Вы упоминаете использование фабрик. Но разве фабрики не разрушают DI, потому что они создают объекты?
Вы также можете заметить, что мои модели несут ответственность за взаимодействие с базой данных. Я подозреваю, что это также проблема с моим дизайном. Должен ли я использовать сопоставление данных какого-либо типа, чтобы удалить эту ответственность из моих моделей?
Учитывая этот более конкретный пример того, как я в настоящее время реализую свой код, есть ли у вас какие-либо другие рекомендации или вы можете проиллюстрировать, как я должен делать это по-другому?