Symfony 4: Buenas prácticas

Symfony 4 se publicará en Noviembre de 2017. Esta serie de artículos explica sus principales novedades:


Cuando se publica una nueva versión major de un proyecto (como por ejemplo Symfony 2.0, 3.0, 4.0, etc.) es el momento perfecto para repensar sus buenas prácticas y modernizarlas si hace falta. Symfony 4 no será una excepción y por eso vamos a adaptar algunas de las buenas prácticas actuales a las nuevas funcionalidades que introduce Symfony 4.

Estandarizar todo lo que se pueda

El primer paso de la evolución de las buenas prácticas de Symfony será la utilización de tantas herramientas estándar como sea posible.

Symfony no para de adoptar estándares tanto web como PHP, así que cuesta creer que cuando comenzamos a desarrollar Symfony 2, Composer todavía no existía. Desde entonces, han surgido iniciativas como el "FIG Group", que desarrolla estándares dentro del ámbito PHP, llamados PSR (PHP Standards Recommendations).

Symfony fue uno de los primeros frameworks importantes en adoptar la mayoría de PSR y lo hizo sin romper la compatibilidad con las aplicaciones existentes: PSR-3 para los logs, PSR-4 para la carga automática de clases y PSR-6 para la cache. En Symfony 3.3 hemos añadido soporte para PSR-16 (caché simplificada) y PSR-11 (contenedores de servicios).

El uso de estándares aumenta la interoperabilidad entre aplicaciones y permite desacoplar el código de tus proyectos respecto al framework Symfony.

Aplicaciones sin bundles

En el artículo anterior explicamos la decisión de hacer que las aplicaciones Symfony dejen de usar bundles. Lo mencionamos de nuevo aquí simplemente como recordatorio porque es uno de los cambios más importantes de las nuevas buenas prácticas de Symfony.

Variables de entorno

En el libro Las Buenas Prácticas Oficiales de Symfony se explica con detalle cómo gestionar la configuración de las aplicaciones Symfony. Por ejemplo, cómo usar app/config/parameters.yml para las opciones de configuración relacionadas con la infraestructura (por ejemplo, tu base de datos) y cómo usar app/config/config.yml para las opciones de configuración relacionadas con la aplicación.

Nuestra primera recomendación es que no utilices opciones de configuración de las que se guardan en app/config/config.yml a menos que sea imprescindible. De hecho, en nuestra opinión, se pueden contar con los dedos de una mano los casos en los que es necesario definir una opción de ese tipo.

Por otra parte, en Symfony 4 también desaparece el archivo app/config/parameters.yml. En su lugar se utilizan variables de entorno, tal y como hacen la mayoría de frameworks en otros lenguajes de programación. Además, esta es una de las recomendaciones recogidas en el 12-Factor Application Manifesto que siguen la mayoría de plataformas de hosting modernas.

Aunque las variables de entorno no son perfectas, tienen varias ventajas respecto a usar el archivo parameters.yml. Para empezar, las variables de entorno son el mecanismo estandar en la industria para gestionar la configuración que depende del entorno de ejecución (son mucho más cómodas por ejemplo que tener que lidiar con el archivo parameters.yml.dist).

Además, las variables de entorno se pueden leer desde distintas herramientas, ya que son independientes del código, del framework y del lenguaje de programación. Las variables de entorno también son útiles en los sistemas de archivos de solo lectura, ya que están desacopladas de tu código y su valor se puede cambiar dinámicamente sin tener que desplegar de nuevo la aplicación (y sin tener que borrar la caché de la aplicación Symfony).

Su única pega es que, a diferencia de lo que algunos programadores creen, las variables de entorno son igual de inseguras que los archivos de configuración a la hora de guardar valores secretos como contraseñas y tokens de APIs.

Utilizar variables de entorno mientras se desarrolla la aplicación es un poco pesado, así que vamos a recomendar el uso de un archivo estándar llamado .env. Symfony 3.3 incluye un nuevo componente llamado Dotenv que se utilizará por defecto en las aplicaciones Symfony 4. Así que el cambio entre un archivo .env y las variables de entorno "de verdad" será automática y transparente para ti.

Si lo prefieres, puedes seguir definiendo las variables de entorno en un archivo llamado parameters.yaml, aunque esta ya no será la forma estándar de trabajar. Por cierto, el nombre parameters.yaml no es un error al escribir parameters.yml. De hecho, este será otro cambio de Symfony 4 que discutiremos más adelante.

Una ventaja añadida de usar variables de entorno es que simplifica la forma en la que se gestiona el entorno de ejecución (dev, prod, etc.) y el valor de la opción debug tanto en la consola como en los controladores frontales.

Actualmente, se pueden definir el entorno y el debug que utiliza ./bin/console tanto con las opciones --env y --no-debug como con las variables de entorno SYMFONY_ENV y SYMFONY_DEBUG. En Symfony 4 esto ya no es necesario, ya que se utilizarán las variables de entorno APP_ENV y APP_DEBUG tanto en la consola como en los controladores frontales.

Así que ta te puedes ir olvidando de ./bin/console foo:bar --env=prod --no-debug o SYMFONY_ENV=prod SYMFONY_DEBUG=0 ./bin/console foo:bar. Simplemente utiliza ./bin/console foo:bar y todo funcionará como esperas. Tanto en desarrollo como en producción. Por cierto, Symfony 4 está lleno de simplificaciones de este tipo.

Un solo controlador frontal

Symfony 3 tiene dos controladores frontales. Uno está optimizado para producción (app.php) y el otro para desarrollo (app_dev.php). Symfony 4 solo tiene un controlador frontal, así que ya no tienes que borrar el controlador frontal de desarrollo cuando despliegues la aplicación. Y ya no sufrirás ningún problema de seguridad si te olvidas de hacerlo.

A lo mejor estás pensando que esto hará que el código sea más complejo que antes. No es el caso, porque hemos podido borrar un montón de código antiguo. Y todo gracias a las variables de entorno, gracias a PHP 7 (que hace innecesarios los archivos de bootstrap y la caché de clases) y gracias a Symfony 3.3 (que elimina la necesidad de usar un cargador automático de clases).

El archivo Makefile

En muchos proyectos es habitual tener scripts propios para ejecutar tareas: ejecutar los tests unitarios o de integración, arrancar el servidor web interno de PHP, etc. En estos casos no tiene mucho sentido crear un comando de Symfony para ejecutar este tipo de scripts.

También es habitual, por comodidad, definir algunos de esos scripts en el archivo composer.json de la aplicación. Silex por ejemplo hace eso con el script que arranca el servidor web interno de PHP. Lo malo es que es difícil gestionar cosas como los timeouts o la falta de soporte de las secuencias de escape ANSI de los comandos.

En cualquier caso, sea en el archivo composer.json o en otro lugar, tener todos estos scripts centralizados en un sitio es muy útil. ¿Y si usamos para ello un archivo Makefile? Este es posiblemente el cambio más controvertido de Symfony 4. Hemos estado dudando muchísimo sobre si hacer este cambio o no. Al final hemos decidido hacerlo porque aporta un gran valor y resuelve algunos de nuestros problemas.

Puede que ya conozcas la herramienta make, porque es bastante conocida y "estándar" en el ámbito de la programación. Se trata de una herramienta mucho más poderosa que los scripts que ejecuta Composer. Además no requiere del uso de PHP. Se puede utilizar para desplegar aplicaciones, conectarte mediante SSH a servidores remotos, ejecutar npm, gulp, webpack, Blackfire, etc. En definitiva, muchos casos de uso en los que los comandos tradicionales de Symfony no son prácticos.

Make además es muy poderoso, ya que puede ejecutar tareas en paralelo, evitar la ejecución de tareas si no ha habido cambios, etc.

Vamos a ver un ejemplo: el borrado de la caché. Symfony tiene un comando para borrar la caché y otro para pre-generar la caché. Sin embargo, hacer las dos cosas en el mismo proceso no funciona bien porque PHP no es capaz de recargar una clase cuando su contenido cambia. Pero hacerlo con make es facilísmo:

cache-clear:
    @test -f bin/console && bin/console cache:clear --no-warmup || rm -rf var/cache/*
.PHONY: cache-clear
 
cache-warmup: cache-clear
    @test -f bin/console && bin/console cache:warmup || echo "cannot warmup the cache (needs symfony/console)"
.PHONY: cache-warmup

Otro ejemplo práctico: la mayoría de mis proyectos PHP tienen estas dos tareas para ejecutar los tests de Blackfire automáticamente:

bf-dev:
    blackfire-player --endpoint=http://`bin/console server:status --filter=address` run tests/bkf/all.bkf
.PHONY: bf-dev
 
bf-prod:
    blackfire-player --endpoint=https://twig.sensiolabs.org run tests/bkf/all.bkf --variable="env=prod"
.PHONY: bf-prod

Otro caso de uso de make es poner una aplicación en modo "mantenimiento" mientras haces cambios. Mucho más cómodo que hacerlo con un comando de Symfony.

Gestionando los assets

La versión 3.0 de la edición estándar de Symfony eliminó Assetic. Por el momento no recomendamos ninguna herramienta para sustituir a Assetic, ya que el mundo JavaScript está todavía inmerso en la búsqueda de una herramienta estándar para gestionar los assets de las aplicaciones web.

No obstante, Symfony 4 recomendará el uso de una herramienta y proporcionará integración con ella. Los detalles los anunciaremos dentro de unas semanas. Por el momento, queríamos mencionar que Symfony 4 seguirá existiendo el comando assets:install para copiar o enlazar simbólicamente los assets de los bundles dentro del directorio public/bundles/. En Symfony 5 seguramente cambiaremos todo esto, ya que no tiene mucho sentido ahora que las aplicaciones ya no tienen bundles.

La implementación de todas estas buenas prácticas supondrá algunos cambios en la estructura de directorios de las aplicaciones Symfony. Y ese será precisamente el tema del próximo artículo. No te lo pierdas.


Este artículo es una traducción del artículo Symfony 4: Best Practices publicado por Fabien Potencier.

Comentarios

Publicada el

7 de abril de 2017

Etiquetas

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.