Silex - настоящий DI против внедрения $app, который выглядит как ServiceLocator?

Вчера прочитал статью: https://igor.io/2012/11/09/scaling-silex.html

И еще один http://davedevelopment.co.uk/2012/10/03/Silex-Controllers-As-Services.html

Итак, в моей голове возник концептуальный вопрос:

В настоящее время у меня есть много контроллеров в отдельных классах. Я перезаписываю controller_resolver для создания экземпляра класса контроллера и вставляю $app в конструктор контроллера.

Я определяю маршруты, подобные этому $app->get('/hello', 'HelloController::indexAction') ‹- мой преобразователь контроллера создаст new HelloController($app); - пока все хорошо. Но, если честно, это стало шаблоном ServiceLocator, а не DependencyInjection, потому что я ввожу весь $app, который выглядит как использование ServiceLocator.

Теперь я в раздумьях: оставить как есть (потому что работает хорошо) или попробовать "контроллеры как сервисы" внедрять только те сервисы, от которых действительно зависит мой контроллер? Может быть, мой подход SeviceLocator когда-нибудь поразит меня? (люди говорят, что DI лучше для тестов).

Я также изучил Symfony Framework Bundle: класс Controller расширяет абстрактный класс ContainerAware, в который также вводится весь $container! Подход ServiceLocator в рамках полного стека?

Любая рекомендация? За и против?


person Petr    schedule 10.11.2012    source источник


Ответы (2)


Фреймворк с полным стеком Symfony2

Платформа использует шаблон внедрения зависимостей, а не шаблон локатора служб.

Все контроллеры по умолчанию не являются службами. Класс ContainerAware включает методы для получения доступа к контейнеру службы, поэтому вы можете вызывать службы внутри контроллера.

Если вы собираетесь использовать контроллер как услугу, вам необходимо удалить расширение Controller. Все зависимости, которые вы хотите использовать внутри контроллера, должны быть внедрены сервисным контейнером.

Подробнее об этом читайте в сообщении в блоге Ричарда Миллера. , один из основных участников Symfony2.

Микрофреймворк Silex

Микрофреймворк Silex обеспечивает основу каркаса, и вам решать, как будет выглядеть архитектура и какие шаблоны использовать.

В документации Silex используются контроллеры, которые не являются службами. Он внедряет полный сервисный контейнер внутрь самого контроллера:

$app->post('/post/{id}-{slug}', function($id, $slug) use ($app) {
    // ...
});

Если вы хотите использовать контроллеры в качестве службы, вам следует внедрять только те службы, которые вы хотите использовать внутри контроллера.

РЕДАКТИРОВАТЬ: синтаксис Controller::action также относится к контроллеру, который не является службой. Обозначение Controller:action используется для обозначения контроллеров как служб.

person Wouter J    schedule 10.11.2012

Здесь много личных предпочтений. То, что вы уже сделали, является хорошим (достаточным) шагом к организации вашей кодовой базы. Некоторые люди, такие как я, идут еще дальше и перемещают наши контроллеры в контейнер, а не внедряют их в какой-то BaseController. Это происходит как в Silex, так и в полнофункциональной среде Symfony.

Я бы посоветовал оставить все, что у вас есть, как есть, а затем попробовать определить свой следующий контроллер как службу, практикуя BDD.

Например, поведение действия представления UserController:

  • Он должен получить пользователя из базы данных
  • Он должен отображать пользователя с помощью шаблона

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

person Dave Marshall    schedule 15.11.2012