Hello World• Ricard Clau Pintado• Trabajo en SocialPoint• Antes en Emagister, Ulabox y Privalia• Fundador Symfony-Barcelona• Blogger http://www.ricardclau.com• Twitter @ricardclau
¿Qué vamos a ver?• Arquitectura orientada a servicios (SOA)• La capa de modelo en Symfony2• Servicios en Symfony2• Componente Configuration• Inyección de dependencias• Experiencias en el desarrollo de Ulabox.com
Arquitectura SOA Teoría y filosofía
El concepto SOA• Arquitectura Orientada a Servicios• Los Servicios son clases creadas para desarrollar una función específica y se pueden utilizar en cualquier punto de nuestra aplicación.• Encapsulando la lógica de negocio en servicios podemos desacoplar las clases de nuestra aplicación, que podrá crecer “sin problemas”• Todas las plataformas grandes lo usan (o deberían)
No todo es tan fácil• Es una filosofía entorno al patrón de diseño Service Layer• Parece que estamos trabajando más• Es muy importante delimitar la responsabilidad de cada servicio y no acoplarlos• Hay que concienciar a todo el equipo, formar a los juniors y convencer a la gente con malos hábitos• Puede ser complicado de aplicar en código legado• Pero... ¡se puede hacer gradualmente!
Servicios acoplados
Servicios desacoplados :)
El modelo en Symfony2 Introducción a los servicios
La evolución del MVC• Symfony2 no es un framework MVC estrictamente• De hecho, la carpeta “Model” no existe por defecto!• Es tan flexible que nos da la libertad de construir la capa de Modelo como convenga a nuestra aplicación• Y eso puede ser peligroso...
Y entonces... ¿Doctrine2?• Doctrine2 abstrae el acceso al sistema de almacenamiento, tanto SQL como algunos No-SQL• Las “Entities” mapean tablas (ORM) / documentos (ODM)• Los “Repositories” permiten encapsular operaciones y realizar consultas algo más complejas• Pero ahí no debería ir la lógica de negocio!
El modelo en Symfony2• En Symfony2, más que hablar del modelo, podemos hablar de la capa de servicios• Hay que evitar los controllers de 2000 líneas• En los repositories no deberíamos poner lógica de negocio, son para querys complejas• Las vistas deben tener la mínima lógica posible• Cada servicio debe recibir sólo lo que necesita y exponer unas interficies claras para su uso. Nunca usar el Request ni modificar la Response.
Servicios en Symfony2 Ejemplos prácticos
Servicios en Symfony2• Muchos de los componentes de Symfony2 están disponibles como servicios• Algunos: Doctrine2 Entity Manager, Swiftmailer, Validator, Translator, Templating, Routing, ...• Muchos bundles añaden nuevos servicios y podemos crear nuestros propios servicios!• Acceso mediante el “Dependency Injection Container” desde las clases con interface “ContainerAware”
Listado de servicios• php app/console container:debug
¿Qué tengo en el container?• https://github.com/Elao/WebProfilerExtraBundle
Debug del container (I)• https://github.com/schmittjoh/JMSDebuggingBundle
Debug del container (II)• https://github.com/schmittjoh/JMSDebuggingBundle
Validator Service
Mailer Service
Configurando la aplicación Carga de nodos y inyección al container
Configuraciones en Symfony2• app/config -> aplicación Resources/config -> Bundles• Configuración base que extendemos para el resto de entornos• Conveniente separarlo en varios archivos
[parameters]• Se suelen definir constantes de configuración• Permite que cada usuario tenga el setup como quiera• Los valores bajo la clave [parameters] se inyectan en el container directamente. Podemos usarlos en otras secciones con %valor%• Podemos crear nuestras propias claves para configurar nuestros bundles, que deberán ser leídas en los archivos de la carpeta DependencyInjection
Configuración compleja• Se inyecta bien pero no tenemos validación!
Bundle complejo -> a validar!• Creamos los parámetros bajo la clave de nuestro bundle
TreeBuilder• Creamos un TreeBuilder en una clase Configuration dentro de la carpeta DependencyInjection
Validando parámetros texto
Validando estructura array
Jugueteando con el array
Exprimiendo el componente!
BundleExtension• Inyectamos la configuración en la Extension:
Creación de servicios Inyección de dependencias
Hello world Servicios• Servicio para recuperar información de Sensio Connect!
Config y uso del servicio• En el config de la aplicación• Modificamos services.yml en Resources/config• Y desde el controller
Dependencias de un servicio• Un servicio puede depender de parámetros de configuración y/o de otros servicios• Nos referimos a los parámetros con %param% y los servicios con @nombre_servicio• Constructor Injection -> arguments:
Dependencias opcionales• Setter Injection y otras inicializaciones -> calls• Podemos combinarlo todo en servicios complejos
Antipattern: setContainer
Aplicaciones complejas Servicios parent, factories y tags
Servicios abstract / parent
Service Factories• El mejor ejemplo son los repositories• Pero si hacemos esto• Los controllers quedan así de limpios!
Service Tags (I)• Agrupación de servicios• El tag en sí no significa nada pero puede ser útil para extender componentes con nuevos loaders / adapters. Suelen procesarse en las CompilerPass• Lo usamos en Twig para cargar extensiones
Service Tags (II)• El componente Translator lo usa para los loaders• O cuando necesitamos crear un Event Listener
E-commerce con servicios Web Backoffice API (Iphone, ...)KernelController Listeners / Before hooks (autenticaciones, ...) Controllers ligeros que traducen Request a parámetros Servicios de primer nivel / unidades de negocio M (Customer, Cart, Order, Catalogue) O Servicios auxiliares a modo de Helpers (Logger, Translator, Validator, Mailer, ...) D Interacción Storage / 3rd party E (Entities, Repositories, Solarium, PRedis, OpenInviter...) L BBDD No-SQL / Caches 3rd Party APIs
Agradecimientos• A los Ulaboxers PHPeros: Sergi, Albert, Marc• Al equipo #rigor de @EmagisterTech• A la organización y sponsors de DeSymfony• A todos vosotros :)
¿Preguntas?• E-mail: ricard.clau@gmail.com• Twitter: @ricardclau• Github: https://github.com/ricardclau• O si os da corte ahora... en otro momento :)