Date post: | 11-Nov-2014 |
Category: |
Technology |
Upload: | gonzalo-ayuso |
View: | 5,344 times |
Download: | 0 times |
PHP (83%)JavaScript (10%)Python (1%)VimL (1%)C# (1%)Shell (1%)
@gonzalo123http://gonzalo123.comhttps://github.com/gonzalo123http://www.linkedin.com/in/gonzaloayuso
Hello my name is ...
Gonzalo Ayuso
(according to github)
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
http://gonzalo123.comhttp://katayunos.com
You can find me at ...
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
Why should we use Dependency Injection?
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
S Single responsibilityO Open/closed principle
L Liskov substitutionI Interface segregation
D Dependency inversion principle
S.O.L.I.D.
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
IoC and TDD
Dependency injection is a requirement if you want to write testable code.
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class Order{ public function generateOrderForUser($user) { $backend = new BackendOrder('dsn:...'); $orderId = $backend->createOrder();
$pdfGenerator = new PDFGenerator(); $pdf = $pdfGenerator->getPDF($orderId);
$mailer = new Mailer('mailCredentials...'); $mailer->sendPdfToUSer($pdf, $user); }}
$order = new Order();
$order->generateOrderForUser('Gonzalo');
One example. It works but ...
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class Order{ public function generateOrderForUser($user) { $backend = new BackendOrder('dsn:...'); $orderId = $backend->createOrder();
$pdfGenerator = new PDFGenerator(); $pdf = $pdfGenerator->getPDF($orderId);
$mailer = new Mailer('mailCredentials...'); $mailer->sendPdfToUSer($pdf, $user); }}
$order = new Order();
$order->generateOrderForUser('Gonzalo');
Be decoupled my friend
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class Order{ public function generateOrderForUser($user) { $backend = new BackendOrder('dsn:...'); $orderId = $backend->createOrder();
$pdfGenerator = new PDFGenerator(); $pdf = $pdfGenerator->getPDF($orderId);
$mailer = new Mailer('mailCredentials...'); $mailer->sendPdfToUSer($pdf, $user); }}
$order = new Order();
$order->generateOrderForUser('Gonzalo');
Magic strings are evil
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class Order{ public function generateOrderForUser($user) { $backend = new BackendOrder('dsn:...'); $orderId = $backend->createOrder();
$pdfGenerator = new PDFGenerator(); $pdf = $pdfGenerator->getPDF($orderId);
$mailer = new Mailer('mailCredentials...'); $mailer->sendPdfToUSer($pdf, $user); }}
$order = new Order();
$order->generateOrderForUser('Gonzalo');
Can we change anything?
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class Order{ public function generateOrderForUser($user) { $backend = new BackendOrder('dsn:...'); $orderId = $backend->createOrder();
$pdfGenerator = new PDFGenerator(); $pdf = $pdfGenerator->getPDF($orderId);
// remember to remove this comment when we deploy //$mailer = new Mailer('mailCredentials...'); //$mailer->sendPdfToUSer($pdf, $user); }}
$order = new Order();
$order->generateOrderForUser('Gonzalo');
Can we change anything?Open/Close Principle
Desymfony 2013. Madrid @gonzalo123 http://gonzalo123.com
class Order{ private $backend, $pdf, $mailer; public function __construct(BackendOrder $backend, PDFGenerator $pdf, Mailer $mailer) { $this->backend = $backend; $this->pdf = $pdf; $this->mailer = $mailer; } public function generateOrderForUser($user) { $orderId = $this->backend->createOrder(); $pdf = $this->pdfGenerator->getPDF($orderId); $this->mailer->sendPdfToUSer($pdf, $user); }}$backend = new BackendOrder('dsn:...');$pdfGenerator = new PDFGenerator();$mailer = new Mailer('mailCredentials...');
$order = new Order($backend, $pdfGenerator, $mailer);$order->generateOrderForUser('Gonzalo');
Refactor -> DI
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class Order{ private $backend, $pdf, $mailer; public function __construct(BackendOrder $backend, PDFGenerator $pdf, Mailer $mailer) { $this->backend = $backend; $this->pdf = $pdf; $this->mailer = $mailer; } public function generateOrderForUser($user) { $orderId = $this->backend->createOrder(); $pdf = $this->pdfGenerator->getPDF($orderId); $this->mailer->sendPdfToUSer($pdf, $user); }}$backend = new BackendOrder('dsn:...');$pdfGenerator = new PDFGenerator();$mailer = new Mailer('mailCredentials...');
$order = new Order($backend, $pdfGenerator, $mailer);$order->generateOrderForUser('Gonzalo');
Refactor -> DI
And that's
all folks!
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
The Hollywood principle
"Don't call us, we'll call you."
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class Order{ private $backend, $pdf, $mailer; public function __construct(BackendOrder $backend, PDFGenerator $pdf, Mailer $mailer) { $this->backend = $backend; $this->pdf = $pdf; $this->mailer = $mailer; } public function generateOrderForUser($user) { $orderId = $this->backend->createOrder(); $pdf = $this->pdfGenerator->getPDF($orderId); $this->mailer->sendPdfToUSer($pdf, $user); }}$backend = new BackendOrder('dsn:...');$pdfGenerator = new PDFGenerator();$mailer = new Mailer('mailCredentials...');
$order = new Order($backend, $pdfGenerator, $mailer);$order->generateOrderForUser('Gonzalo');
Where is the problem now?
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class Order{ private $backend, $pdf, $mailer; public function __construct(BackendOrder $backend, PDFGenerator $pdf, Mailer $mailer) { $this->backend = $backend; $this->pdf = $pdf; $this->mailer = $mailer; } public function generateOrderForUser($user) { $orderId = $this->backend->createOrder(); $pdf = $this->pdfGenerator->getPDF($orderId); $this->mailer->sendPdfToUSer($pdf, $user); }}$backend = new BackendOrder('dsn:...');$pdfGenerator = new PDFGenerator();$mailer = new Mailer('mailCredentials...');
$order = new Order($backend, $pdfGenerator, $mailer);$order->generateOrderForUser('Gonzalo');
What can we do?
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
Dependency Injection Containers (DIC) to the rescue!
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
Dependency Injection Containers (DIC) in PHP? Are u crazy?
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
Yes! DIC in PHP:
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
<?php
class Container {
protected $s=array();
function __set($k, $c) { $this->s[$k]=$c; }
function __get($k) { return $this->s[$k]($this); }
}
TwitteA Dependency Injection Container in a Tweet
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
$c = new Container();$c->backend_driver = function () { return 'dsn:...'; };$c->backend = function ($c) { return new BackendOrder($c->backend_driver);};$c->pdfGenerator = function ($c) { return new PDFGenerator();};$c->mailer_credentials = function () { return 'mailCredentials...'; };$c->mailer = function ($c) { return new Mailer($c->mailer_credentials);};$c->order = function ($c) { return new Order($c->backend, $c->pdfGenerator, $c->mailer);};$order = $c->order;$order->generateOrderForUser('Gonzalo');
TwitteA Dependency Injection Container in a Tweet
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
$c = new Pimple();
$c['backend_driver'] = 'mysql:...';$c['backend'] = function ($c) { return new BackendOrder($c['backend_driver']);};$c['pdfGenerator'] = function ($c) { return new PDFGenerator();};$c['mailer_credentials'] = 'mailCredentials...';$c['mailer'] = function ($c) { return new Mailer($c['mailer_credentials']);};$c['order'] = function ($c) { return new Order($c['backend'], $c['pdfGenerator'], $c['mailer']);};$order = $c['order'];$order->generateOrderForUser('Gonzalo');
PimpleA Simple Dependency Injection Container for PHP 5.3
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
class MyContainer extends Pimple{ public function __construct() { $this['backend_driver'] = 'dsn:...'; $c['backend'] = function ($this) { return new BackendOrder($this['backend_driver']); }; $c['pdfGenerator'] = function ($c) { return new PDFGenerator(); }; $this['mailer_credentials'] = 'mailCredentials...'; $this['mailer'] = function ($this) { return new Mailer($this['mailer_credentials']); }; $this['order'] = function ($this) { return new Order($this['backend'], $this['pdfGenerator'], $this['mailer']); }; }}$c = new MyContainer();$order = $c['order'];$order->generateOrderForUser('Gonzalo');
PimpleA Simple Dependency Injection Container for PHP 5.3
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
composer.json
{
"require": {
"symfony/dependency-injection": "v2.3.0",
"symfony/yaml": "v2.3.0",
"symfony/config": "v2.3.0"
}
}
Symfony DIC
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
services.ymlparameters: backend.driver: dsn:... mailer.credentials: mailCredentials...
services: backend: class: BackendOrder arguments: [%backend.driver%]
pdfGenerator: class: PDFGenerator
mailer: class: Mailer arguments: [%mailer.credentials%]
order: class: Order arguments: [@backend, @pdfGenerator,@mailer]
Symfony DIC
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
index.phpuse Symfony\Component\DependencyInjection\ContainerBuilder;use Symfony\Component\Config\FileLocator;use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
$container = new ContainerBuilder();$loader = new YamlFileLoader($container, new FileLocator(__DIR__));$loader->load('services.yml');
$order = $container->get('order');$order->generateOrderForUser('Gonzalo');
Symfony DIC
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
● Symfony2 (Symfony\DependencyInjection)● Zend Framework2 (Zend\Di)● Silex (Pimple)● Laravel (Illuminate\Container)
Modern frameworks and DIC
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
Usar contenedores o no usarlos
Use an IoC container wisely, not promiscuously
To use or not to use DIC
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
Let's code!
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
services.ymlparameters: twig.cache: /path/to/cache/path twig.auto_reload: true
db.dsn: sqlite::memory db.username: username db.password: password
services: database: class: PDO arguments: [%db.dsn%, %db.username%, %db.password%]
Scaling our services.yml
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
services.ymlimports: - resource: twig.yml - resource: database.yml
twig.ymlparameters: twig.cache: /path/to/cache/path twig.auto_reload: true
database.ymlparameters: db.dsn: sqlite::memory db.username: username db.password: passwordservices: database: class: PDO arguments: [%db.dsn%, %db.username%, %db.password%, ]
Scaling our services.yml
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
require_once __DIR__.'/vendor/autoload.php';
$app = new Silex\Application();
$app->get('/hello/{name}', function($name) { return 'Hello '.strtoupper($name);});
$app->run();
Silex example
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
// services.ymlservices: capitalizer: class: Capitalizer
use Symfony\Component\DependencyInjection\ContainerBuilder;use Symfony\Component\Config\FileLocator;use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
$container = new ContainerBuilder();$loader = new YamlFileLoader($container, new FileLocator(__DIR__));$loader->load('services.yml');
$app = new Silex\Application();$app['container'] = $container;
$app->get('/hello/{name}', function($name) use($app) { $capitalizer = $app['container']->get('capitalizer'); return 'Hello '. $capitalizer->toUpper($name);});
$app->run();
Silex example with DIC
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
Almost the end ...
● Be decoupled my friend● S.O.L.I.D.● DI is good ● DIC are tools to help us.● PHP has different DICs● Symfony DIC is very
easy to implement, configurable and easy to extend
Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
Thank you! - ¡Gracias! - ¡Eskerrik asko!
Your turn. Questions?Desymfony 2013 Madrid @gonzalo123 http://gonzalo123.com
http://gonzalo123.comgonzalo123
http://joind.in/talk/view/8843