solid and symfony. desymfonyday 2014
DESCRIPTION
SOLID and Symfony. My talk in the deSymfony 2014 conference in BarcelonaTRANSCRIPT
¿QUE SOMOS?
¿QUIÉN SOY YO?
¿QUIÉN SOY YO?Gonzalo Ayuso
@gonzalo123http://gonzalo123.comhttps://github.com/gonzalo123
¿QUIÉN SOY YO?Gonzalo Ayuso
@gonzalo123http://gonzalo123.comhttps://github.com/gonzalo123
katayunos.com
¿QUIÉN SOY YO?Gonzalo Ayuso
@gonzalo123http://gonzalo123.comhttps://github.com/gonzalo123
¿QUE SOMOS?
¿QUE SOMOS?Pogramadores
¿QUE SOMOS?Pogramadores
¿A QUÉ DEDICAMOS NUESTRO TIEMPO?
¿QUE SOMOS?Pogramadores
¿A QUÉ DEDICAMOS NUESTRO TIEMPO?A programar
¿QUE SOMOS?Pogramadores
¿A QUÉ DEDICAMOS NUESTRO TIEMPO?A programar
¿QUE SOMOS?Pogramadores
¿A QUÉ DEDICAMOS NUESTRO TIEMPO?A programarA leer
¿QUE SOMOS?Pogramadores
¿A QUÉ DEDICAMOS NUESTRO TIEMPO?A programarA leer
$this->createUser(true);
$this->createUser(true);¿?¿?¿?
S.O.L.I.D.
S.O.L.I.D.ROBERT. C. MARTIN (THE CLEAN CODE)
Single responsibility, Open-closed, Liskov substitution, Interface segregation,Dependency inversion
SRP - SINGLE RESPONSIBILITY PRINCIPLEPRINCIPIO DE RESPONSABILIDAD ÚNICA
SRP - SINGLE RESPONSIBILITY PRINCIPLEPRINCIPIO DE RESPONSABILIDAD ÚNICA
CADA COMPONENTE => UNA RESPONSABILIDAD
SRP - SINGLE RESPONSIBILITY PRINCIPLEPRINCIPIO DE RESPONSABILIDAD ÚNICA
CADA COMPONENTE => UNA RESPONSABILIDAD
UNA RESPONSABILIDAD = UNA RAZÓN DE CAMBIO
SRP - SINGLE RESPONSIBILITY PRINCIPLEPRINCIPIO DE RESPONSABILIDAD ÚNICA
CADA COMPONENTE => UNA RESPONSABILIDAD
UNA RESPONSABILIDAD = UNA RAZÓN DE CAMBIO
CADA COMPONENTE => UNA ÚNICA RAZÓN PARA CAMBIAR
OCP - OPEN/CLOSED PRINCIPLEPRINCIPIO DE ABIERTO/CERRADO
OCP - OPEN/CLOSED PRINCIPLEPRINCIPIO DE ABIERTO/CERRADO
LAS ENTIDADES DE SOFTWARE DEBEN SER ABIERTAS PARA EXTENDER, PERO CERRADAS PARA MODIFICACIÓN
OCP - OPEN/CLOSED PRINCIPLEPRINCIPIO DE ABIERTO/CERRADO
LAS ENTIDADES DE SOFTWARE DEBEN SER ABIERTAS PARA EXTENDER, PERO CERRADAS PARA MODIFICACIÓN
HTTPKernel
http://stackphp.com
OCP - OPEN/CLOSED PRINCIPLEPRINCIPIO DE ABIERTO/CERRADO
LAS ENTIDADES DE SOFTWARE DEBEN SER ABIERTAS PARA EXTENDER, PERO CERRADAS PARA MODIFICACIÓN
<?phpuse Symfony\Component\EventDispatcher\EventDispatcher;$dispatcher = new EventDispatcher();
$listener = new AcmeListener();$dispatcher->addListener('action', array($listener, 'onFooAction'));
Event Dispatcher (Patrón Mediator)
LSP -LISKOV SUBSTITUTION PRINCIPLEPRINCIPIO DE SUBSTITUCIÓN DE LISKOV
LSP -LISKOV SUBSTITUTION PRINCIPLEPRINCIPIO DE SUBSTITUCIÓN DE LISKOV
DEBE SER POSIBLE UTILIZAR CUALQUIER OBJETO INSTANCIA DE UNA SUBCLASE EN LUGAR
DE CUALQUIER OBJETO INSTANCIA DE SU SUPERCLASE SIN QUE LA SEMÁNTICA DEL
PROGRAMA ESCRITO EN LOS TÉRMINOS DE LA SUPERCLASE SE VEA AFECTADO.
LSP -LISKOV SUBSTITUTION PRINCIPLEPRINCIPIO DE SUBSTITUCIÓN DE LISKOV
DEBE SER POSIBLE UTILIZAR CUALQUIER OBJETO INSTANCIA DE UNA SUBCLASE EN LUGAR
DE CUALQUIER OBJETO INSTANCIA DE SU SUPERCLASE SIN QUE LA SEMÁNTICA DEL
PROGRAMA ESCRITO EN LOS TÉRMINOS DE LA SUPERCLASE SE VEA AFECTADO.SI S ES UN SUBTIPO DE T, ENTONCES LOS OBJETOS DE TIPO T PUEDEN SER
REEMPLAZADOS POR LOS OBJETOS DE TIPO S.
LSP -LISKOV SUBSTITUTION PRINCIPLEPRINCIPIO DE SUBSTITUCIÓN DE LISKOV
CADA CLASE QUE HEREDA DE OTRA PUEDE USARSE COMO SU PADRE SIN NECESIDAD DE CONOCER LAS DIFERENCIAS ENTRE
ELLAS.
LSP -LISKOV SUBSTITUTION PRINCIPLEPRINCIPIO DE SUBSTITUCIÓN DE LISKOV
class Application extends Container
implements HttpKernelInterface, TerminableInterface
{}
CADA CLASE QUE HEREDA DE OTRA PUEDE USARSE COMO SU PADRE SIN NECESIDAD DE CONOCER LAS DIFERENCIAS ENTRE
ELLAS.
Silex\Application
LSP -LISKOV SUBSTITUTION PRINCIPLEPRINCIPIO DE SUBSTITUCIÓN DE LISKOV
class Application extends Container implements HttpKernelInterface, TerminableInterface{}
Silex\Application
use Silex\Application;
$app = new Application();
LSP -LISKOV SUBSTITUTION PRINCIPLEPRINCIPIO DE SUBSTITUCIÓN DE LISKOV
class Application extends Container implements HttpKernelInterface, TerminableInterface{}
Silex\Application
use Silex\Application;
$app = new Application();
Silex\Application
Pimple\Container
ISP - INTERFACE SEGREGATION PRINCIPLEPRINCIPIO DE SEGREGACIÓN DE INTERFACES
ISP - INTERFACE SEGREGATION PRINCIPLEPRINCIPIO DE SEGREGACIÓN DE INTERFACES
MUCHAS INTERFACES ESPECÍFICAS SON MEJORES QUE UNA INTERFAZ DE PROPÓSITO GENERAL.
ISP - INTERFACE SEGREGATION PRINCIPLEPRINCIPIO DE SEGREGACIÓN DE INTERFACES
interface StreamIface
{
public function open();
public function read();
public function write();
}
ISP - INTERFACE SEGREGATION PRINCIPLEPRINCIPIO DE SEGREGACIÓN DE INTERFACES
interface StreamIface
{
public function open();
public function read();
public function write();
}
class File implements StreamIface
ISP - INTERFACE SEGREGATION PRINCIPLEPRINCIPIO DE SEGREGACIÓN DE INTERFACES
interface StreamIface
{
public function open();
public function read();
public function write();
}
class File implements StreamIface
class ReadOnlyFile implements StreamIface
?
ISP - INTERFACE SEGREGATION PRINCIPLEPRINCIPIO DE SEGREGACIÓN DE INTERFACES
interface ReadableStreamIface{ public function open(); public function read();}interface WritableStreamIface{ public function write();}
class ReadOnlyFile implements ReadableStreamIface
class File implements ReadableStreamIface, WritableStreamIface
ISP - INTERFACE SEGREGATION PRINCIPLEPRINCIPIO DE SEGREGACIÓN DE INTERFACES
class Application extends Container
implements HttpKernelInterface, TerminableInterface
{...}
Silex\Application
use Silex\Application;
$app = new Application();
TerminableInterface
HttpKernelInterface
DIP - DEPENDENCY INVERSION PRINCIPLEPRINCIPIO DE INVERSIÓN DE DEPENDENCIAS
LAS ABSTRACCIONES NO DEBERÍAN DEPENDER DE DETALLES SINO QUE LOS DETALLES
DEBERÍAN DEPENDER DE LAS ABSTRACCIONES.
LAS ABSTRACCIONES NO DEBERÍAN DEPENDER DE DETALLES SINO QUE LOS DETALLES
DEBERÍAN DEPENDER DE LAS ABSTRACCIONES.
LOS MÓDULOS DE ALTO NIVEL NO DEBERÍAN DEPENDER DE MÓDULOS DE BAJO NIVEL,
AMBOS DEBERÍAN DEPENDER DE ABSTRACCIONES.
DIP - DEPENDENCY INVERSION PRINCIPLEPRINCIPIO DE INVERSIÓN DE DEPENDENCIAS
class ChickenPizza extends BasePizza{ private $ingredients;
public function __construct() { $this->ingredients[] = new Chicken(); $this->ingredients[] = new Cheese(); $this->ingredients[] = new Fruit(); }}
$chickenPizza = new ChickenPizza();$chickenPizza->make();
DIP - DEPENDENCY INVERSION PRINCIPLEPRINCIPIO DE INVERSIÓN DE DEPENDENCIAS
$chickenPizza = new Pizza();$chickenPizza->appendIngredient(new Chicken());$chickenPizza->appendIngredient(new Cheese());$chickenPizza->appendIngredient(new Fruit());$chickenPizza->make();
DIP - DEPENDENCY INVERSION PRINCIPLEPRINCIPIO DE INVERSIÓN DE DEPENDENCIAS
class Pizza implements IngredientStackIface{ private $ingredients; public function appendIngredient(Ingredient $ingredient) { $this->ingredients[] = $ingredient; } public function make() { }}
DIP - DEPENDENCY INVERSION PRINCIPLEPRINCIPIO DE INVERSIÓN DE DEPENDENCIAS
use Symfony\Component\Config\FileLocator;
$chickenPizza = new Pizza();$locator = new FileLocator(__DIR__);$loader = new YamlFileLoader($chickenPizza, $locator);$loader->load('config.yml');
$chickenPizza->make();
Config component: http://blog.servergrove.com/2014/02/21/symfony2-components-overview-config/
DIP - DEPENDENCY INVERSION PRINCIPLEPRINCIPIO DE INVERSIÓN DE DEPENDENCIAS
SI PERO, ¿MERECE LA PENA TODO ESTO?
SI PERO, ¿MERECE LA PENA TODO ESTO?
TODO ESTO SE HACE POR ...
SI PERO, ¿MERECE LA PENA TODO ESTO?
TODO ESTO SE HACE POR ...
€
SI PERO, ¿MERECE LA PENA TODO ESTO?
EFICIENCIA VS MANTENIMIENTO
TODO ESTO SE HACE POR ...
€
SI PERO, ¿MERECE LA PENA TODO ESTO?
EFICIENCIA VS MANTENIMIENTO
TODO ESTO SE HACE POR ...
€
SYMFONY -> SOLID PERO Y NUESTRA APP?
PROGRAMAR ES FÁCIL. PROGRAMAR BIEN ES MUY COMPLICADO.
GRACIAS / ESKERRIK ASKO&
BE SOLID MY FRIEND!
¿PREGUNTAS? ¿APLAUSOS? :)
Gonzalo Ayuso@gonzalo123http://gonzalo123.comhttps://github.com/gonzalo123