Entendiendo las Buenas Prácticas Oficiales de Symfony

El lunes 13 de octubre se publicó la primera versión del documento Buenas Prácticas Oficiales de Symfony donde se recogen las prácticas que los autores del framework recomiendan seguir al desarrollar aplicaciones web con Symfony.

Como era previsible, las reacciones positivas y negativas no se hicieron esperar. Como el libro de buenas prácticas solamente tiene 50 páginas, es una lectura rápida y sencilla. Así que te recomiendo leer el libro de buenas prácticas Symfony para formar tu propia opinión y no dejar que otros lo hagan por tí.

Para los que no tengáis tiempo de leerlo, hemos extraído a continuación tres de las recomendaciones más importantes, para razonarlas con más detenimiento.

1. Crea un solo bundle llamado AppBundle para la lógica de tu aplicación

Las buenas prácticas oficiales de Symfony

Esta es una de las recomendaciones que más han chocado y una de las que provocará más cambios a aquellos que la sigan. El problema de muchas aplicaciones Symfony actuales es que crean bundles internos para separar lógicamente sus funcionalidades: UserBundle, ProductBundle, ContactBundle, etc.

No obstante, según la filosofía original de Symfony, un bundle debe ser capaz de funcionar completamente por si solo. En otras palabras, si no puedes coger tu bundle, soltarlo en otra aplicación y hacer que funcione, entonces ese bundle no está bien hecho.

De forma que muchas aplicaciones Symfony, en vez de bundles tienen "carpetas raras que molestan a tu código". Siempre deberías empezar creando un AppBundle y extraer funcionalidades en otros bundles solo cuando la aplicación te lo pida.

2. Guarda todas tus plantillas en el directorio app/Resources/views/

Las buenas prácticas oficiales de Symfony

Se trata de nuevo de una buena práctica que ha provocado malestar entre algunos programadores. Las ventajas de hacerlo así son claras: 1) tu equipo de diseñadores tendrá su trabajo mucho más fácil porque todas las plantillas están centralizadas; 2) la sintaxis para referirse a las plantillas se simplifica drásticamente; 3) evitas duplicar el directorio Resources/views/ en todos tus bundles.

Si te fijas bien, que un bundle tenga su propio directorio Resources/views/ es debido a que el bundle debe funcionar por si solo y entonces no puede confiar en que haya un archivo app/Resources/views/. Sin embargo, cuando el bundle es solo para tu aplicación y jamás vas a compartirlo, resulta redundante crear tu propio Resources/views/. La aplicación ya ha creado ese directorio por tí y deberías utilizarlo.

¿Pero no será caótico guardar todas las plantillas en el mismo sitio? En la mayoría de aplicaciones, no. El motivo es que dentro de app/Resources/views/ creas un directorio para cada bundle, por lo que en ese nivel tendrás como mucho 10 o 15 directorios, a menos que tu aplicación sea extremadamente compleja. Y luego ya dentro de cada directorio de cada bundle tienes la misma estructura que tenías antes (si quieres, puedes eliminar el subdirectorio Default/) así que si ahora es demasiado complejo, es porque antes también lo era.

3. No utilices una configuración semántica para tus bundles

Las buenas prácticas oficiales de Symfony

Esta es probablemente la práctica peor adoptada para aplicaciones web. En un bundle pensado para compartir en público o con varias aplicaciones internas, dedicar un tiempo a crear todas estas clases tiene sentido.

Pero para los bundles utilizados internamente en la aplicación, casi nunca tiene sentido hacerlo. Solamente estaría justificado si en tu caso necesitas sí o sí validar la configuración. Si no lo necesitas, crear los parámetros directamente en el archivo app/config/config.yml sería suficiente.

Para acabar este artículo, me gustaría agradecer a todos los que me habéis enviado mensajes privados comentándome lo que os parecen estas recomendaciones. La inmensa mayoría han sido comentarios a favor, pero también ha habido comentarios negativos. Aunque me gusta recibir estos comentarios, preferiría que los hiciérais en público, en vuestros blogs o cuentas de Twitter. Así las discusiones serán más abiertas y todos ganaremos con ello.

Comentarios

  1. Enhorabuena por el trabajo realizado en el manual de buenas prácticas Javier, creo que es un gran aporte a la comunidad Symfony que acaba con muchos mitos infundados que provocaban que aquellos que nos esforzábamos en seguir las "supuestas buenas prácticas" hasta la fecha, invirtiéramos más esfuerzo del necesario en nuestros desarrollos. También agradecerte este artículo aclaratorio que también me parece muy útil.

    Un saludo!

    Jesús Miguel Benito Calzada el 15 de octubre de 2014, 8:40:30

  2. Gracias por vuestro trabajo. El concepto de AppBundle puede es interesante, aunque para poder probarlo debemos esperar, pues creo que ahora sólo se puede usar con Symfony 2.6.

    Juan Cobacho el 15 de octubre de 2014, 10:27:05

  3. @Juan, no hace falta esperar a la versión 2.6 para usar el AppBundle. Esto es algo que funciona en cualquier versión anterior de Symfony.

    El único problema es que con el comando generte:bundle no puedes generar un bundle sin vendor. Esto se arreglará muy pronto, ya que el pull request está listo: https://github.com/sensiolabs/SensioGeneratorBundle/pull/299

    El "truco" (o "chapuza") que puedes usar ahora mismo es añadir un "vendor" ficticio (por ejemplo "Acme") y luego borrarlo a mano. Hacerlo te costará 1 minuto, así que puede merecer la pena si quieres probar ya mismo la idea de tener un único AppBundle.

    Javier Eguiluz el 15 de octubre de 2014, 10:33:57

  4. Hola, desde mi punto de vista (y no soy un desarrollador avanzado) creo que las "Buenas practicas" que han publicado son un acierto. Muchos de las soluciones que proponen para los problemas que hay son cierto, yo he creado una aplicación web dividiendo las cosas en distintos bundles y al final se vuelve caótico buscar entre tantos directorios donde esta el archivo que buscas, por poner un simple ejemplo, y es algo de lo que me he dado cuenta ya que lo sufro continuamente.

    Supongo que las quejas vienen porque la gente no diferencia una aplicación web de un bundle en si, no todo lo que conlleva una web va a ser reutilizable, simplemente no lo va a ser o no ves la ventaja de dividir y hacer como bien dices, que funciones por si solo, ya que simplemente es algo que no tiene sentido o que no vas a utilizar más, o seamos realistas, por cuestión de tiempo, no puedas pensar de esta forma (mi cliente no me deja tiempo para pensar en dejarlo todo cool, lo quieren y ya, y por mucho que le expliques le da igual, por lo que te toca hacerlo y si alguna vez tienes tiempo dejarlo todo cool).

    Personalmente creo que ha faltado algún punto más para como por ejemplo alguna mencion a crear repositorios y manager.

    Alberto Vioque Muñoz el 15 de octubre de 2014, 11:04:49

  5. En primer lugar, felicitar a los autores de ese conjunto de buenas prácticas, tanto por el esfuerzo, como por los resultados. Algunas son realmente interesantes, no obstante intentaré llevarlas todas a la práctica.

    Y en segundo lugar, aunque no menos importante, felicitarte por tus aportaciones a la comunidad y por la traducción del documento de buenas prácticas, que supongo que habrá sido labor tuya.

    Santiago Lozano el 15 de octubre de 2014, 11:52:50

  6. Hola Javier, leí el libro y me pareció excelente, felicitaciones a las personas involucradas! Sin embargo, confieso que algunas practicas me sorprendieron un poco, ya que difieren radicalmente de lo que sueles ver en blogs, aunque supongo que ese era precisamente el punto :)

    Javier, tengo dudas respecto al punto 2, que pasa si yo tengo un solo bundle (AppBundle) como recomiendan, pero necesito utilizar bundles de terceros (FOSUserBundle por ejemplo) y necesito reescribir varias de sus plantillas, puedo hacerlo en app/Resources/views?, o en ese caso si necesito crear un UserBundle que me permita sobrescribir plantillas o acciones del controlador? Pregunto en el caso de que quiera manejar usuarios dentro de AppBundle y no crear un bundle aparte, pero obteniendo el beneficio de utilizar FOSUserBundle.

    Saludos!

    Moises Burgos el 15 de octubre de 2014, 12:08:56

  7. Hola Moises,

    Para ese caso tienes dos opciones, puedes crear las plantillas en app/Resources/FOSUserBundle/views/ o puedes indicar en tu clase Bundle que estas extendiendo el bundle FOSUserBundle: http://symfony.com/doc/current/cookbook/bundles/inheritance.html

    No necesariamente deberás crear otro bundle para poder reescribir los templates.

    Para sobreescribir acciones, creo que eso si no es posible, lo que si puedes es sobreescribir los archivos de rutas y hacer que apunten a tus controladores.

    Saludos!

    manuel_j555 el 15 de octubre de 2014, 13:03:33

  8. @Mosiés, tal y como te comenta @manuel_j555, no sólo puedes redefinir las plantillas de FOSUserBundle en app/Resources/views/ sino que es la buena práctica recomendada para hacerlo. En este artículo puedes encontrar más información sobre este tema.

    Javier Eguiluz el 15 de octubre de 2014, 14:13:35

  9. Acostumbro a separar los bundles por ámbito digamos de ejecución. Si a mi aplicación se puede acceder vía web y también vía REST, hago un bundle para cada uno, aunque sólo uno tiene el acceso a la base de datos. Y si me creo una librería más o menos compleja también me creo un bundle a parte, aunque nunca llegue a compartirla.

    Cristian Martin el 15 de octubre de 2014, 14:50:12

  10. Realmente como decía en twitter las buenas prácticas (aunque no estoy 100% de acuerdo con todas) son un acierto para los que llegan por primera vez al framework y reduce mucho la fricción de éstos con Symfony2.

    Para proyectos pequeños realmente solucionan muchos malos comienzos, la cuestión está en que si estás trabajando en un proyecto Symfony2 pequeño y luego va a ir creciendo eventualmente terminarás necesitando hacer cosas más avanzadas por una simple cuestión de ir gravitando hacia lo que el framework.

    En mi opinión el AppBundle es una solución que aunque atenta contra todo lo que hemos escuchado sobre el desarrollo de bundles en sf2 nos obliga a hacernos una pregunta ¿realmente cuando desarrollas un bundle para una aplicación siempre garantizas que ese bundle se pueda efectivamente desacoplar de tu aplicación y utilizarlo en otro proyecto sin realizar cambios al código? La mayoría de las veces no creo que sea así, simplemente porque require más trabajo y si no vamos a publicar el bundle (intencionado desde un inicio) generalmente el esfuerzo y la dinámica del trabajo atentan contra ello.

    Mi opinión general es que aunque las buenas prácticas atentan contra lo que hemos escuchado en infinidad de charlas (ya nos advertían que los viejos hábitos no mueren fácil) si propone una buena base para que comencemos a trabajar y luego el propio framework nos facilita poder evolucionar ese diseño inicial hacia algo más elaborado.

    Jorge Luis Betancourt el 15 de octubre de 2014, 15:01:08

  11. El punto 2 me sigue resultando confuso, si bien las ventajas citadas son ciertas: que ocurre con la reutilización de bundles??? Se supone que si dejas todas las plantillas en app y no dentro del propio bundle (src), si alguien lo quiere instalar y hacer uso de él, tendría que volver a crearlas. Me equivoco?

    Ignacio Giménez el 15 de octubre de 2014, 15:34:12

  12. Javier, sería posible tener una "version" de Cupon que cumpla con (al menos) la mayoria de las buenas practicas oficiales de Symfony? Esto seria una referencia valiosisima para nuevos y actuales desarrolladores que usan este framework.

    Ademas te felicito por tu excelente trabajo en Sensio y en la comunidad Symfony!

    Saludos!

    Brian Debuire el 15 de octubre de 2014, 16:50:56

  13. Hola Javier. Estoy leyendo el documento y he encontrado algunos fallos. ¿Se pueden reportar de algún modo?.

    Pablo Braulio el 15 de octubre de 2014, 16:52:36

  14. @Ignacio, entiendo que te resulte confuso. En tu caso, supongo que estás hablando de un bundle diferente a AppBundle. Si es así, las plantillas de ese bundle sí que deben estar en su directorio Resources/views/. Si no, como tú bien dices, no podrás reutilizar el bundle en otras aplicaciones. En resumen, la recomendación sería: si tus bundles no son en realidad bundles reutilizables, crea un solo AppBundle y mueve las plantillas a app/Resources/views/.

    @Brian, muchas gracias por tus comentarios y estate atento a las noticias que anunciaremos pronto en relación a Cupon y al libro.

    @Pablo, tengo pendiente de corregir algunos errores que me han llegado vía email. Si te parece cómoda esa forma, envíame por favor todo lo que veas mal a javier.eguiluz @gmail ¡Muchas gracias!

    Javier Eguiluz el 15 de octubre de 2014, 17:49:38

  15. @manuel_j555, @Javier muchas gracias por sus respuestas!

    Moises Burgos el 16 de octubre de 2014, 8:01:48

  16. La verdad es que encuentro muy sensatas las cosas que indicáis en el manual de buenas prácticas. Aunque algunas me han chocado un poco, como lo de "@Templates". Si no se recomienda su uso me pregunto que por qué no se pasa a deprecated.

    En cualquier caso, gracias por el manual, creo que a la gente de nivel bajo/medio nos viene muy bien. Por el momento tenía previsto subir mi Trabajo Fin de Grado realizado con Symfony a github, pero voy a ver si lo refactorizo para poder cumplir con la mayoría de cosas que se dicen aquí antes de hacerlo. Y por cierto, que ya tengo convencida a más gente para hacer sus TFG con Symfony.

    Sergio Gomez el 16 de octubre de 2014, 8:03:37

  17. Tengo una duda respecto el punto "2. Guarda todas tus plantillas en el directorio app/Resources/views/" que se toca en este post, listo, las plantillas deberían colocarse en "app/Resources/views/" pero que pasa con los assets? Deberian colocarse en "AppBundle/Resources/public/*"? O deberian colocarse en "/web"?

    Reynier Perez Mira el 20 de octubre de 2014, 16:37:24

  18. @Reynier, si utilizas assets compilados como archivos CSS y JavaScript normales, la recomendación es guardarlos en web/css/ y web/js/.

    Si utilizas preprocesadores como Sass, LESS y CoffeeScript, los assets originales puedes guardarlos en app/Resources/assets/ y la compilación de esos archivos en web/css/ y web/js/

    Javier Eguiluz el 22 de octubre de 2014, 9:01:02

  19. @Javier, si la mayoria son assets compilados, muchos manejados a traves de Bower con SpBowerBundle, algunos referentes al proyecto y que aun estan cambiando, aun asi la recomendacion es colocarlos en web/css y /web/js? En tal caso como los referencio desde las plantillas que las estoy moviendo todas a app/Resources/views?

    Reynier Perez Mira el 22 de octubre de 2014, 17:59:42

  20. Hola Javier, muy buen post! Te cuento que yo estoy migrando recién ahora a sf2, por un lado se debe a que estoy manteniendo una app propia en 1.4 y en la empresa que trabajo aun seguimos con 1.4 :( Ya leí el libro de symfony oficial de 2.4 y este libro de buenas prácticas que justo salio para no me meta la pata en los primeros pasos, je je. El tema es que te quería consultar algo que venia pensando en como hacerlo en sf2 hasta que leí que "mejor hacerlo todo en el AppBundle" :( Imaginate un sistema ERP, donde tenemos módulos como Inventario, Libro de direcciones (Clientes, Proveedores, Empleados), Ventas, Compras, Warehouse, etc.. yo había pensado en crear un bundle por cada uno para tenerlo mas modularizado y desacoplado, así cuando tienes una instalación a un cliente puedes optar que modulo instalar según lo que se le haya vendido. En estos casos, aun sigue siendo conveniente hacerlo todo en el AppBundle?? Saludos

    Matias Fessia el 1 de noviembre de 2014, 2:25:32

  21. Hola Matias,

    La recomendación es, AppBundle cuando la app realmente va enfocada a una lógica en particular, es decir, dirigida hacia una aplicación concreta.

    En tu caso, no está mal que crees varios bundles ya que (en teoria) esos bundles serán reutilizables para cada cliente que tengas, ahora, cada app de cada cliente, posiblemente deberá tener un AppBundle (que haga uso de tus bundles reusables) con la lógica concreta de cada aplicación.

    A nivel general, hay que verlo como el bundle de Doctrine, Monolog o SwiftMailer, son bundles que no estan enfocados en ninguna aplicación en particular, por lo que allí tiene sentido tener cada uno separado. Por otro lado, un bundle que conosca y maneje la lógica requerida para el cliente, no es un bundle correcto, y esa lógica deberá residir en AppBundle.

    Saludos!!!

    manuel_j555 el 5 de noviembre de 2014, 21:10:40

  22. Creo que el punto 1 es bastante conflictivo, realmente depende del caso. Cuando comencé a desarrollar en Symfony2 tuve discusiones con mi equipo de trabajo por este tema y creo que la afirmación "si no puedes coger tu bundle, soltarlo en otra aplicación y hacer que funcione, entonces ese bundle no está bien hecho." pasa por un tema de interpretación.

    Un bundle mal hecho es cuando, por ejemplo: creas varios bundles, vuelcas algunas funcionalidades en uno y te quedaron algunas otras en otro bundle, y encima las entidades por otro lado (un desastre, pero he visto cosas así). Obviamente si lo desacoplas, no va a funcionar".

    La práctica recomendada debería ser "si creas bundles, hazlo con criterio".

    Pero creo que tranquilamente se puede hacer un conjunto de bundles que tengan o no dependencias entre sí.


    Por otro lado, un tema que no tocan las "buenas prácticas" es el de la utilización de Managers como servicios para manejar la persistencia de datos. Como lo hace FOSUserBundle.

    Symfony no está hecho para eso, pero viendo a FOSUserBundle, quizás el bundle más utilizado; y como fue un tema en las charlas de deSymfony2013, le vi potencial.

    Adopté esa práctica, aunque tiene algunas desventajas (lleva tiempo, a veces se escriben métodos sólo para hacer $this->getRepository()->findAlgo(), a veces hay que inyectar varios servicios, etc), pero el código queda bastante limpio.

    ¿Si no usamos eso, cómo se pretende tener actions con menos de 20 líneas de código?


    Bueno, hice un poco de catarsis! :D

    Saludos!

    Marcelo Strappini el 4 de mayo de 2015, 20:31:00

Este artículo ya no permite añadir más comentarios.
¿Por qué? Los artículos cierran sus comentarios automáticamente unos meses después de su publicación para asegurar que estos sigan siendo relevantes.

Publicada el

15 de octubre de 2014

Proyectos Symfony destacados

La forma más sencilla de generar el backend de tus aplicaciones Symfony. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.