SlideShare a Scribd company logo
1 of 23
Download to read offline
План
PHP Используем Dependency Injection
и Container
• Что такое Dependency Injection (DI)?
• Что такое Контейнер служб (контейнер внедрения
зависимости)?
• Как пришли к понятию Dependency Injection?
• Использование DI и Контейнера в Symfony 2.
Обо мне
Александр Неманов
https://www.facebook.com/alexander.nemanov
bug@tut.by
Skype: gftrades.support
DI - что это?
Внедрение зависимости (англ. Dependency injection) — процесс
предоставления внешней зависимости программному компоненту. Является
специфичной формой “Обращения контроля” (Inversion of control, IoC)
IoS - это важный принцип объектно-ориентированного программирования,
используемый для уменьшения связанности в коде программы.
• Модули верхнего уровня не должны зависеть от модулей нижнего уровня.
Оба должны зависеть от абстракции.
• Абстракции не должны зависеть от деталей. Детали должны зависеть от
абстракций.
Корнями иерархий должны быть абстрактные классы, в то время как конкретные классы в этой
роли выступать не должны. Абстрактные базовые классы должны беспокоиться об определении
функциональности, но не о ее реализации.
Контейнер служб - это реализация принципа внедрения зависимости
bug@tut.by skype: gftrades.support
Покодируем. И это работает…
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
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
Строки которые сведут с ума
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
Для теста немного “подшаманим”
(принцип открытости/закрытости)
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
Рефакторим на пути к 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
Что мы еще можем сделать?
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
Используем Dependency Injection Container (DIC)
(Рискнем!)
Используем
Dependency Injection
Container (DIC)
(Рискнем!)
bug@tut.by skype: gftrades.support
Реализуем свой, простой 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); }
}
Используем
$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
Symfony DI
Контейнер служб (или же контейнер внедрения
зависимости) - это также PHP объект, который
управляет созданием служб (т.е. объектов).
bug@tut.by skype: gftrades.support
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
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
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
Symfony DI
• Параметры службы
• Массивы параметров
• Импорт конфигурации
• Использование одних служб внутри других
• Опциональные зависимости
• constructor injection, setter injection, property injection
• Опциональные ссылки на службы
• Основные службы Symfony и службы от сторонних
разработчиков (session, templating, mailer, request)
• Разные конфиги для разных окружений
(prod, dev, test)
bug@tut.by skype: gftrades.support
SF DI - продвинутая конфигурация
• Публичные и приватные службы
• Псевдонимы (alias)
• Таги (tags) templating.helper, twig.extension...
bug@tut.by skype: gftrades.support
Фреймворки использующие 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
To be, or not to be: that is the question
Используйте мудро, но
bug@tut.by skype: gftrades.support
DI это требование, если вы используете TDD
Сильная связанность затрудняет тестирование
Работа с внешними ресурсами затрудняет
тестирование
Пример внешних ресурсов:
• Обращение к сторонним сервисам
• Файловая система
• Файлы конфигурации
• …
bug@tut.by skype: gftrades.support
Почему мы используем DI
• Late Binding - сервисы могут быть заменены
другими сервисами
• Extensibility - код может быть легко расширен и
повторно использован
• Parallel development - разработка кода с низкой
связанностью упрощает командную
параллельную разработку
• Maintainability - классы с четкими границами
легко сопровождать
• Testability - модули могут быть протестированы
bug@tut.by skype: gftrades.support
Вопросы
bug@tut.by skype: gftrades.support

More Related Content

Viewers also liked

Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right wayThibaud Desodt
 
Sergii Shymko - Code migration tool for upgrade to Magento 2
Sergii Shymko - Code migration tool for upgrade to Magento 2Sergii Shymko - Code migration tool for upgrade to Magento 2
Sergii Shymko - Code migration tool for upgrade to Magento 2Meet Magento Italy
 
Инъекция зависимости и Инверсия Контроля
Инъекция зависимости и Инверсия КонтроляИнъекция зависимости и Инверсия Контроля
Инъекция зависимости и Инверсия КонтроляVladimir Ignatev
 
SOLID. Принципы объектно ориентированного дизайна
SOLID. Принципы объектно ориентированного дизайнаSOLID. Принципы объектно ориентированного дизайна
SOLID. Принципы объектно ориентированного дизайнаМихаил Польгун
 
Создание дистрибутивов Drupal. Почему, зачем и как?
Создание дистрибутивов Drupal. Почему, зачем и как?Создание дистрибутивов Drupal. Почему, зачем и как?
Создание дистрибутивов Drupal. Почему, зачем и как?Alexei Gorobets
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8Alexei Gorobets
 
Media management in Drupal @Moldcamp
Media management in Drupal @MoldcampMedia management in Drupal @Moldcamp
Media management in Drupal @MoldcampAlexei Gorobets
 
Extending media presentation
Extending media presentationExtending media presentation
Extending media presentationAlexei Gorobets
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampAlexei Gorobets
 
Real-time search in Drupal. Meet Elasticsearch
Real-time search in Drupal. Meet ElasticsearchReal-time search in Drupal. Meet Elasticsearch
Real-time search in Drupal. Meet ElasticsearchAlexei Gorobets
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Fabien Potencier
 
GRASP – паттерны Объектно-Ориентированного Проектирования
GRASP – паттерны Объектно-Ориентированного ПроектированияGRASP – паттерны Объектно-Ориентированного Проектирования
GRASP – паттерны Объектно-Ориентированного ПроектированияAlexander Nemanov
 
Dependency injection with Symfony 2
Dependency injection with Symfony 2Dependency injection with Symfony 2
Dependency injection with Symfony 2cammanderson
 
Plantas Magic Garden Houses Freguesia
Plantas Magic Garden Houses FreguesiaPlantas Magic Garden Houses Freguesia
Plantas Magic Garden Houses FreguesiaINVEXO Imobiliária
 
Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIHugo Hamon
 

Viewers also liked (20)

Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right way
 
Sergii Shymko - Code migration tool for upgrade to Magento 2
Sergii Shymko - Code migration tool for upgrade to Magento 2Sergii Shymko - Code migration tool for upgrade to Magento 2
Sergii Shymko - Code migration tool for upgrade to Magento 2
 
Инъекция зависимости и Инверсия Контроля
Инъекция зависимости и Инверсия КонтроляИнъекция зависимости и Инверсия Контроля
Инъекция зависимости и Инверсия Контроля
 
SOLID. Принципы объектно ориентированного дизайна
SOLID. Принципы объектно ориентированного дизайнаSOLID. Принципы объектно ориентированного дизайна
SOLID. Принципы объектно ориентированного дизайна
 
Создание дистрибутивов Drupal. Почему, зачем и как?
Создание дистрибутивов Drupal. Почему, зачем и как?Создание дистрибутивов Drupal. Почему, зачем и как?
Создание дистрибутивов Drupal. Почему, зачем и как?
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
Why drupal
Why drupalWhy drupal
Why drupal
 
Media management in Drupal @Moldcamp
Media management in Drupal @MoldcampMedia management in Drupal @Moldcamp
Media management in Drupal @Moldcamp
 
Extending media presentation
Extending media presentationExtending media presentation
Extending media presentation
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @Moldcamp
 
Real-time search in Drupal. Meet Elasticsearch
Real-time search in Drupal. Meet ElasticsearchReal-time search in Drupal. Meet Elasticsearch
Real-time search in Drupal. Meet Elasticsearch
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
 
Migrate in Drupal 8
Migrate in Drupal 8Migrate in Drupal 8
Migrate in Drupal 8
 
Apresentação landscape
Apresentação landscapeApresentação landscape
Apresentação landscape
 
GRASP – паттерны Объектно-Ориентированного Проектирования
GRASP – паттерны Объектно-Ориентированного ПроектированияGRASP – паттерны Объектно-Ориентированного Проектирования
GRASP – паттерны Объектно-Ориентированного Проектирования
 
Dependency injection with Symfony 2
Dependency injection with Symfony 2Dependency injection with Symfony 2
Dependency injection with Symfony 2
 
Plantas Magic Garden Houses Freguesia
Plantas Magic Garden Houses FreguesiaPlantas Magic Garden Houses Freguesia
Plantas Magic Garden Houses Freguesia
 
Container Patterns
Container PatternsContainer Patterns
Container Patterns
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CI
 

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

  • 1. План PHP Используем Dependency Injection и Container • Что такое Dependency Injection (DI)? • Что такое Контейнер служб (контейнер внедрения зависимости)? • Как пришли к понятию Dependency Injection? • Использование DI и Контейнера в Symfony 2.
  • 3. DI - что это? Внедрение зависимости (англ. Dependency injection) — процесс предоставления внешней зависимости программному компоненту. Является специфичной формой “Обращения контроля” (Inversion of control, IoC) IoS - это важный принцип объектно-ориентированного программирования, используемый для уменьшения связанности в коде программы. • Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракции. • Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. Корнями иерархий должны быть абстрактные классы, в то время как конкретные классы в этой роли выступать не должны. Абстрактные базовые классы должны беспокоиться об определении функциональности, но не о ее реализации. Контейнер служб - это реализация принципа внедрения зависимости bug@tut.by skype: gftrades.support
  • 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. 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. Строки которые сведут с ума 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. Для теста немного “подшаманим” (принцип открытости/закрытости) 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. Рефакторим на пути к 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. Что мы еще можем сделать? 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. Используем Dependency Injection Container (DIC) (Рискнем!) Используем Dependency Injection Container (DIC) (Рискнем!) bug@tut.by skype: gftrades.support
  • 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. Используем $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. Symfony DI Контейнер служб (или же контейнер внедрения зависимости) - это также PHP объект, который управляет созданием служб (т.е. объектов). bug@tut.by skype: gftrades.support
  • 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. 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. 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. Symfony DI • Параметры службы • Массивы параметров • Импорт конфигурации • Использование одних служб внутри других • Опциональные зависимости • constructor injection, setter injection, property injection • Опциональные ссылки на службы • Основные службы Symfony и службы от сторонних разработчиков (session, templating, mailer, request) • Разные конфиги для разных окружений (prod, dev, test) bug@tut.by skype: gftrades.support
  • 18. SF DI - продвинутая конфигурация • Публичные и приватные службы • Псевдонимы (alias) • Таги (tags) templating.helper, twig.extension... bug@tut.by skype: gftrades.support
  • 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. To be, or not to be: that is the question Используйте мудро, но bug@tut.by skype: gftrades.support
  • 21. DI это требование, если вы используете TDD Сильная связанность затрудняет тестирование Работа с внешними ресурсами затрудняет тестирование Пример внешних ресурсов: • Обращение к сторонним сервисам • Файловая система • Файлы конфигурации • … bug@tut.by skype: gftrades.support
  • 22. Почему мы используем DI • Late Binding - сервисы могут быть заменены другими сервисами • Extensibility - код может быть легко расширен и повторно использован • Parallel development - разработка кода с низкой связанностью упрощает командную параллельную разработку • Maintainability - классы с четкими границами легко сопровождать • Testability - модули могут быть протестированы bug@tut.by skype: gftrades.support