В последнее время я много читал о внедрении зависимостей, и в теории это имело большой смысл.Идея иметь простые для тестирования классы с одной ответственностью просто звучит умно.Тем не менее, я борюсь с тем, как далеко это сделать.
Я сейчас работаю над веб-приложением PHP, которое имеет компонент CMS и в значительной степени управляется базой данных.В CMS вы можете создавать страницы, а сами страницы создаются с использованием различных виджетов.Виджеты могут быть простым HTML (из WYSIWYG-редактора) или могут быть немного более сложными, например, фотогалерея.И это важная часть, виджет фотогалереи зависит от других моделей БД, таких как PhotoGallery
и PhotoGalleryImages
, для правильного функционирования.
Согласно Miško Hevery , яне следует передавать ссылки на зависимости через разные уровни моего приложения.Вместо этого каждый класс должен просто «запрашивать» любые зависимости, которые ему требуются.Используя его пример, вот как это выглядит:
$db = new Database()
$repo = new UserRepository($db);
$page = new LoginPage($repo);
Хотя я вижу, что это работает нормально для сервисных уровней моего приложения, я действительно не понимаю, как это будет работать с моими объектами / сущностями значений,Мне кажется, что этот шаблон требует от меня создания экземпляров всех моих моделей на самом высоком уровне моего приложения.Тем не менее, как я могу создать все свои виджеты на этом уровне, когда мне нужен класс моей страницы, чтобы сказать мне, какие виджеты мне нужно создать?И, не зная, какие виджеты я создаю, как я могу узнать, в каких зависимостях виджетов нужно создавать и внедрять?
Теоретически DI имеет для меня большой смысл.Однако на самом деле реализовать этот шаблон в моем новом веб-приложении оказывается сложнее.Есть ли еще что-то, что мне не хватает в отношении DI и IoC?Спасибо!
Обновление: ответ Танду
Большое спасибо за ответ Танду.Я думаю, что 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, потому что они являются объектами-экземплярами?
Вы также можете заметить, что мои модели несут ответственность за взаимодействие с базой данных.Я подозреваю, что это также проблема с моим дизайном.Должен ли я использовать какое-либо отображение данных, чтобы снять эту ответственность с моих моделей?
Учитывая этот более конкретный пример того, как я в настоящее время реализую свой код, есть ли у вас какие-либо другие рекомендации или вы можете проиллюстрировать, какЯ должен делать это по-другому?