A los humanos nos resulta difícil ver el panorama general de un problema sin dedicarle mucho tiempo y esfuerzo. Esto ocurre especialmente cuando se trabaja con aplicaciones grandes y complejas. ¿Cuáles son los efectos secundarios de mis cambios? ¿Por qué esta línea de aquí afecta a las pruebas de una parte remota del código base? No existe una solución perfecta o completa, pero Shopify sacó una herramienta que probablemente te ayudará a ti y a tu equipo.
Introducción
Para hablar de PackwerkEn primer lugar, debemos introducir algunos conceptos.
- Cohesión: se refiere a la medida de la pertenencia de los elementos de un módulo o clase.
- Acoplamiento: se refiere al nivel de dependencia entre módulos o clases.
- Límites: se refiere a las barreras entre código. En este caso, un límite de código se refiere a diferentes dominios de interés dentro de la misma base de código.
- Modularización: el proceso de dividir un sistema de software en varios módulos separados en los que cada módulo funciona de forma independiente.
Problemas
Como sabemos, Ruby no proporciona una buena solución para hacer cumplir los límites del código. Podemos especificar la visibilidad, pero todas las dependencias se cargarán en el espacio de nombres global. En aplicaciones grandes o monolitos, esta falta de límites produce los siguientes problemas.
- Baja cohesión,
- Acoplamiento alto,
- Código espagueti.
En un intento de modularizar el monolito de Shopify y reforzar los límites, probaron diferentes soluciones sin conseguir los resultados esperados:
- Establecer constantes privadas,
- Establecer límites mediante gemas,
- Uso de pruebas para evitar asociaciones entre componentes,
- Usando la gema Modulación de Ruby,
- Creación de microservicios.
Con todos los conocimientos de intentos anteriores, decidieron crear su propia herramienta: Packwerk.
Packwerk
¿Qué es Packwerk?
Packwerk es una herramienta de análisis estático utilizada para imponer límites entre grupos de Ruby archivos llamados paquetes.
¿Qué es un paquete?
A paquete es una carpeta que contiene código autocargado. La carpeta equipo anima a utilizar las mejores prácticas de diseño a la hora de crear paquetes.
- Deberíamos empaquetar juntos cosas que tengan una alta funcionalidad cohesión,
- Los paquetes deben estar relativamente poco acoplados entre sí.
Tipos de controles fronterizos
Podemos imponer límites de privacidad y dependencia, comprobar las violaciones de los límites y las dependencias cíclicas.
Packwerk en la práctica
No existe una única forma específica de estructurar o reestructurar tu aplicación al crear paquetes. En este artículo, vamos a seguir el enfoque sugerido por
Stephan Hagemann en Modularización gradual para Ruby on Rails.
Elija el proyecto
Puede crear un nuevo proyecto o elija uno de sus proyectos. Decidí utilizar un proyecto de código abierto llamado CodeTriage. Es importante mencionar que necesitamos una aplicación Rails 6 ya que Packwerk utiliza Zeitwerk.
Inicializar Packwerk
En primer lugar, tenemos que añadir la gema a nuestro Gemfile como gema 'packwerk
y luego ejecute paquete
en la consola. Entonces estamos listos para inicializar la gema ejecutando packwerk init
.
Después, observamos que Packwerk nos ha generado tres archivos:
-
packwerk.yml
-
paquete.yml
-
inflexiones.yml
packwerk.yml es el archivo de configuración de Packwerk donde definiremos los ficheros incluidos y excluidos, listaremos las rutas de carga, definiremos el fichero de inflexiones, entre otras cosas;
paquete.yml es el archivo de configuración de un paquete. En este archivo, añadiremos la configuración para los límites de nuestro paquete. Cualquier carpeta con package.yml será reconocida como paquete por Packwerk. Ya está, Packwerk creó nuestro primer
y lo llamamos raíz paquete.
inflexiones.yml es donde colocaremos nuestras inflexiones y siglas personalizadas en caso de que las utilicemos.
Encontrará más información sobre los ficheros y su configuración en
Packwerk.
Propiedades de Packwerk
Para que la modularización funcione necesitamos tres propiedades básicas: un contenedor con nombresu contenidoy explícita dependencias en otros contenedores. Así que definamos esas propiedades en Packwerk:
-
Nombre: El nombre de un paquete es su ruta relativa desde la raíz del archivo
aplicación.
-
Contenido: Cuando colocamos un package.yml en una carpeta, todos los archivos de la carpeta son ahora el contenido del paquete.
-
Dependencias: Podemos definir dependencias de otros paquetes añadiendo la clave dependencies al campo paquete.yml.
Otro archivo que no se incluye por defecto pero que se recomienda es README. Es importante para proporcionar información sobre el uso del paquete.
Fin del Episodio I
Seguir leyendo
GraphQL Ruby. ¿Y el rendimiento?
Ferrocarriles y otros medios de transporte
Desarrollo Rails con TMUX, Vim, Fzf + Ripgrep