Modularización Ruby on Rails con Packwerk Episodio II
Nicolas Nisoria
En el segundo episodio de nuestra modularización Ruby on Rails con Packwerk vamos a examinar detenidamente el concepto de aplicación como paquete.
Aplicación como paquete
El enfoque para modularizar nuestra aplicación consiste en convertir toda la aplicación en un paquete.
Crear la estructura
En primer lugar, debemos crear app/paquetes donde colocaremos todos nuestros paquetes. Para aislar nuestros paquetes tenemos que separar cada Concepto MVC en una carpeta. Tomando la CodeTriage proyecto como ejemplo tendremos algo como la siguiente imagen.
Si intentamos ejecutar el servidor, no encontrará las constantes. Es por eso que tenemos que añadir una línea de configuración a nuestra application.rb
Ahora la aplicación funciona, pero no puede encontrar las vistas, por lo que tenemos que añadir otra línea de configuración a nuestro application_controller.rb
Nuestra estructura está lista, así que ahora podemos empezar a crear los paquetes. Para ello, sólo tenemos que añadir unpaquete.yml a cada carpeta con la siguiente configuración:
enforce_privacy: false
enforce_dependencies: true
reforzar_la_privacidadnos da la posibilidad de aislar todas las constantes del paquete y trabajar con una API pública. Para exponer las constantes públicas, necesitamos añadir las constantes en, por ejemplo packages/users/app/public.Por ahora vamos a establecer esta configuración en falso.
aplicar_dependencias impondrá la dependencia de un paquete y comprobará todas las referencias constantes. Si una dependencia no está definida explícitamente será una violación del límite.
Validación del sistema de paquetes
Packwerk estableció un criterio que debemos seguir para tener un sistema de paquetes válido. Podemos empezar a ejecutar packwerk validate en nuestra consola.
Esto comprobará nuestra estructura de carpetas, configuración del paquetey autocargar la caché de rutas.
Ahora mismo, nuestra aplicación no es válida y tenemos que arreglar las rutas de carga enpackwerk.yml. Para ello, sólo tenemos que añadir las rutas que faltan.
En este punto, estamos listos para comprobar las violaciones de los límites en nuestra aplicación. Para comprobar las violaciones podemos ejecutarpackwerk update-deprecations este comando generará deprecated_references.yml para cada paquete. En cada archivo encontraremos el nombre del paquete, el tipo de violación y la ruta del archivo. Con toda esta información sabemos dónde se está produciendo la infracción y podemos tomar una decisión para resolverla.
Tomando el ejemplo vamos a describir cada parte de la información generada por Packwerk.
– app/paquetes/repos - donde la violación constante es encontrado.
– ::Repo - ruta al archivo que contiene la constante violada.
– dependencia - un tipo de violación, ya sea de la dependencia o de la intimidad.
– app/paquetes/usuarios/modelos/usuario.rb - ruta al archivo que contiene la constante violada.
Como paso final de esta sección, no olvide añadir las nuevas rutas de archivo generadas a packwerk.yml y vuelva a ejecutar las validaciones.
Visualización de la dependencia
Con toda la información en package.yml y deprecated_references.ymlpodemos entonces visualizar un gráfico de dependencias. Para ello necesitamos añadir otra gema, en este caso usaremos Pocky.
Rastrillo pocky:generar generaremos un archivo llamado packwerk.png donde podemos visualizar nuestro primer gráfico de dependencias.
Con todos los paquetes definidos nuestro gráfico tendrá este aspecto.
dependencias ya existen, pero eso no significa que sean aceptadas por Packwerk. A aceptar una dependencia tenemos que añadir la configuración de dependencias al archivo paquete.yml en cada paquete. Nos centraremos en mail_builders ya que es un paquete sin dependencia circular. Cabe mencionar que Packwerk no nos permitirá aceptar dependencias circulares.
Después de añadir esta configuración, Pocky coloreará en verde las dependencias aceptadas.
Podemos eliminar deprecated_references.yml de app/paquetes/mail_builders y ejecuta packwerk update-deprecations de nuevo. El archivo no se generará de nuevo ya que todos los para este paquete. Es importante mencionar que aunque no Graph con dependencias aceptadas
Ruby on Rails modularización con Packwerk aceptar dependencias nuestra aplicación seguirá funcionando como antes, pero ahora tenemos más información para tomar decisiones y refactorizar.
Eliminar las dependencias circulares
En nuestro gráfico anterior, teníamos muchas dependencias circulares que había que resolver de alguna manera. Tenemos diferentes estrategias para hacerlo:
- Realizar inyección de dependencias o inyección de dependencias con tipado.
Una cuestión aquí es que para hacer una refactorización adecuada, necesitamos conocer el código base. No estoy muy familiarizado con la base de código de este proyecto, ya que lo tomé como ejemplo, así que por razones prácticas vamos a ir con la primera estrategia, no hacer nada. Incluso si vamos a evitar la mayor parte de la refactorización, queremos trabajar en las dependencias en el raíz paquete.
El paquete raíz contiene toda la cola del Marco Rails, todas las clases de las que heredamos y hacemos que funcionen todas juntas. Por lo tanto, con el fin de resolver las dependencias circulares, vamos a crear un nuevo paquete llamado rieles dentro de los siguientes pasos:
Mueve todos los archivos y carpetas de la aplicación_ a app/paquetes/rails.
Crear unpaquete.yml para el paquete con la misma configuración que los paquetes anteriores.
Añade todas las nuevas rutas de archivos a packwerk.yml.
Añadir app/paquetes/rails como dependencia del resto de paquetes.
Una vez creado el paquete empezaremos a notar una gran cantidad de archivos que pueden ser reestructurados. Después de mover todo al paquete correspondiente y aceptar dependencias tendremos una nueva estructura y un gráfico más limpio.
Eliminar dependencias del paquete raíz
Ahora nuestro gráfico se ve mucho mejor, sería genial si pudiéramos eliminar todas las dependencias del paquete raíz. Si comprobamos deprecated_references.yml en el paquete raíz, nos daremos cuenta de que la mayoría de ellas son de prueba , lib/tareas , db y config carpeta. Para resolver estas dependencias, vamos a crear una carpeta de prueba dentro de cada paquete. Tener algo como app/paquetes/usuarios/prueba. A continuación, vamos a excluir lib/tareas , db y configentre otras carpetas de Packwerk ya que esas dependencias no son realmente importantes en nuestro análisis y no tenemos una forma fácil de resolverlas. Añadiremos lo siguiente a nuestro packwerk.yml.
Después de mover todas las pruebas del paquete raíz y excluir las carpetas del análisis tendremos un nuevo gráfico sin dependencias raíz.
Como vemos, seguimos teniendo dependencias circulares enusuarios , repos y docs . Aunque no los resolvimos, ahora tenemos información importante que transmitir. Sabemos que cada equipo que realice cambios en uno de esos paquetes probablemente tendrá que realizar cambios en los paquetes con la dependencia circular. Por otro lado, sabemos que un equipo puede trabajar en github_fetchers únicamente, saber qué paquetes son viéndose afectado por los cambios de cada momento.
Puede consultar el resultado final del proyecto aquí.
Siguiente paso
Como siguiente paso, podrías imponer una privacidad constante en cada paquete y exponer sólo la API pública que será accesible desde otros paquetes. Puedes configurar fácilmente dónde se colocará tu API en paquete.yml.
Packwerk nos da mucha información sobre nuestra aplicación y con esa información podemos tomar decisiones para mejorar el flujo de trabajo de nuestros equipos. Aunque el proceso parecía largo y con muchas configuraciones, no tiene por qué ser así siempre. Podemos empezar creando paquetes sólo para el nuevo código que se añada a nuestra aplicación y luego modularizar poco a poco. Así que ahora podemos empezar a hablar de Modularización Gradual este es el concepto introducido por Stephan Hagemann "Podemos, por primera vez, decidir empezar a modularizar una parte del código de forma aspiracional... Esto nos permite crear un sistema de apoyo que se amplía gradualmente hacia una mejor estructura de la aplicación".