Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

PHP Используем Dependency Injection и Container

12,171 views

Published on

Dependency Injection - базовые понятия, и использование DI в Symfony 2.Выступление на Минской встрече PHP разработчиков.

Published in: Technology

PHP Используем Dependency Injection и Container

  1. 1. План PHP Используем Dependency Injection и Container • Что такое Dependency Injection (DI)? • Что такое Контейнер служб (контейнер внедрения зависимости)? • Как пришли к понятию Dependency Injection? • Использование DI и Контейнера в Symfony 2.
  2. 2. Обо мне Александр Неманов https://www.facebook.com/alexander.nemanov bug@tut.by Skype: gftrades.support
  3. 3. DI - что это? Внедрение зависимости (англ. Dependency injection) — процесс предоставления внешней зависимости программному компоненту. Является специфичной формой “Обращения контроля” (Inversion of control, IoC) IoS - это важный принцип объектно-ориентированного программирования, используемый для уменьшения связанности в коде программы. • Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракции. • Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. Корнями иерархий должны быть абстрактные классы, в то время как конкретные классы в этой роли выступать не должны. Абстрактные базовые классы должны беспокоиться об определении функциональности, но не о ее реализации. Контейнер служб - это реализация принципа внедрения зависимости bug@tut.by skype: gftrades.support
  4. 4. Покодируем. И это работает… class Invoice { public function createUserInvoice($user) { $order = new PayedOrder('paypal'); $orderId = $order->createOrder(); $pfdGenerator = new PDFGenerator(); $invoice = $pfdGenerator->generate($orderId); $mailer = new Mailer('sendmail'); $mailer->send($user, $invoice); } } $invoice = new Invoice(); $invoice->createUserInvoice('Alex'); bug@tut.by skype: gftrades.support
  5. 5. SOLID (S) Single responsibility principle - Принцип единственности ответственности (O) The Open Closed Principle - Принцип открытости/закрытости (L) The Liskov Substitution Principle - Принцип замещения Лисков (I) Interface segregation - Принцип разделения интерфейса (D) Dependency inversion - Принцип инверсии зависимости bug@tut.by skype: gftrades.support
  6. 6. Строки которые сведут с ума class Invoice { public function createUserInvoice($user) { $order = new PayedOrder('paypal'); $orderId = $order->createOrder(); $pfdGenerator = new PDFGenerator(); $invoice = $pfdGenerator->generate($orderId); $mailer = new Mailer('sendmail'); $mailer->send($user, $invoice); } } bug@tut.by skype: gftrades.support
  7. 7. Для теста немного “подшаманим” (принцип открытости/закрытости) class Invoice { public function createUserInvoice($user) { $order = new PayedOrder('paypal'); $orderId = $order->createOrder(); $pfdGenerator = new PDFGenerator(); $invoice = $pfdGenerator->generate($orderId); // TODO: Не забудь на проде раскоменьтить, а то будет как всегда!!! /* $mailer = new Mailer('sendmail'); $mailer->send($user, $invoice); */ } } bug@tut.by skype: gftrades.support
  8. 8. Рефакторим на пути к DI class Invoice { private $order, $generator, $mailer; public function __construct(PayedOrder $order, PDFGenerator $generator, Mailer $mailer) { $this->order = $order; $this->generator = $generator; $this->mailer = $mailer; } public function createUserInvoice($user) { $orderId = $this->order->createOrder(); $invoice = $this->generator->generate($orderId); $this->mailer->send($user, $invoice); } } $order = new PayedOrder('paypal'); $pfdGenerator = new PDFGenerator(); $mailer = new Mailer('sendmail'); $invoice = new Invoice($order, $pfdGenerator, $mailer); $invoice->createUserInvoice('Alex'); bug@tut.by skype: gftrades.support
  9. 9. Что мы еще можем сделать? class Invoice { private $order, $generator, $mailer; public function __construct(PayedOrder $order, PDFGenerator $generator, Mailer $mailer) { $this->order = $order; $this->generator = $generator; $this->mailer = $mailer; } public function createUserInvoice($user) { $orderId = $this->order->createOrder(); $invoice = $this->generator->generate($orderId); $this->mailer->send($user, $invoice); } } $order = new PayedOrder('paypal'); $pfdGenerator = new PDFGenerator(); $mailer = new Mailer('sendmail'); $invoice = new Invoice($order, $pfdGenerator, $mailer); $invoice->createUserInvoice('Alex'); bug@tut.by skype: gftrades.support
  10. 10. Используем Dependency Injection Container (DIC) (Рискнем!) Используем Dependency Injection Container (DIC) (Рискнем!) bug@tut.by skype: gftrades.support
  11. 11. Реализуем свой, простой DIC bug@tut.by skype: gftrades.support class Container { protected $s=array(); function __set($k, $c) { $this->s[$k] = $c; } function __get($k) { return $this->s[$k]($this); } }
  12. 12. Используем $c = new Container(); $c->payment_system = function ($c) { return 'paypal'; }; $c->order = function ($c) { return new PayedOrder($c->payment_system); }; $c->pfdGenerator = function ($c) { return new PDFGenerator(); }; $c->mailer_transport = function ($c) { return 'sendmail'; }; $c->mailer = function ($c) { return new Mialer($c->mailer_transport); }; $c->invoice = function ($c) { return new Invoice($c->order, $c->pfdGenerator, $c->mailer); }; $invoice = $c->invoice; $invoice->createUserInvoice('Alex'); bug@tut.by skype: gftrades.support
  13. 13. Symfony DI Контейнер служб (или же контейнер внедрения зависимости) - это также PHP объект, который управляет созданием служб (т.е. объектов). bug@tut.by skype: gftrades.support
  14. 14. Symfony DIC composer.json { "require": { "symfony/dependency-injection": "v2.3.0", "symfony/yaml": "v2.3.0", "symfony/config": "v2.3.0", } } bug@tut.by skype: gftrades.support
  15. 15. Symfony DIC services.yml parameters: payment.type: paypal mailer.transport: sendmail services: order: class: PayedOrder arguments: [%payment.type%] generator_pdf: class: PDFGenerator mailer: class: Mailer arguments: [%mailer.transport%] invoice: class: Invoice arguments: [@order, @generator_pdf, @mailer] bug@tut.by skype: gftrades.support
  16. 16. Symfony DIC // index.php use SymfonyComponentDependencyInjectionContainerBuilder; use SymfonyComponentConfigFileLocator; use SymfonyComponentDependencyInjectionLoaderYamlFileLoader; $container = new ContainerBuilder(); $loader = new YamlFileLoader($container, new FileLocator(__DIR__)); $loader->load('services.yml'); $invoice = $container->get('invoice'); $invoice->createUserInvoice('Alex'); bug@tut.by skype: gftrades.support
  17. 17. Symfony DI • Параметры службы • Массивы параметров • Импорт конфигурации • Использование одних служб внутри других • Опциональные зависимости • constructor injection, setter injection, property injection • Опциональные ссылки на службы • Основные службы Symfony и службы от сторонних разработчиков (session, templating, mailer, request) • Разные конфиги для разных окружений (prod, dev, test) bug@tut.by skype: gftrades.support
  18. 18. SF DI - продвинутая конфигурация • Публичные и приватные службы • Псевдонимы (alias) • Таги (tags) templating.helper, twig.extension... bug@tut.by skype: gftrades.support
  19. 19. Фреймворки использующие DIC Реализация внедрения зависимостей PHP5 • DiContainer • Garden • Xyster Framework • Lion Framework • TYPO3 Flow • Symfony 2 Dependency Injection • Zend Framework 2 • Laravel's IoC Container bug@tut.by skype: gftrades.support
  20. 20. To be, or not to be: that is the question Используйте мудро, но bug@tut.by skype: gftrades.support
  21. 21. DI это требование, если вы используете TDD Сильная связанность затрудняет тестирование Работа с внешними ресурсами затрудняет тестирование Пример внешних ресурсов: • Обращение к сторонним сервисам • Файловая система • Файлы конфигурации • … bug@tut.by skype: gftrades.support
  22. 22. Почему мы используем DI • Late Binding - сервисы могут быть заменены другими сервисами • Extensibility - код может быть легко расширен и повторно использован • Parallel development - разработка кода с низкой связанностью упрощает командную параллельную разработку • Maintainability - классы с четкими границами легко сопровождать • Testability - модули могут быть протестированы bug@tut.by skype: gftrades.support
  23. 23. Вопросы bug@tut.by skype: gftrades.support

×