Los acuerdos son una parte esencial del desarrollo de software. Reducen los costos de desarrollo y facilitan la vida de los desarrolladores. Pero hay un problema: a menudo complican las cosas porque no están debidamente documentados y transmitidos al equipo de boca en boca, como en los viejos cuentos de hadas. Mientras se propagan, los acuerdos cambian. De repente, aparecen nuevos detalles y los antiguos desaparecen. Al final, cada miembro del equipo tiene su propia imagen de acuerdo en la cabeza, e incluso esa imagen a veces se desvanece.
Peor aún: cuando los equipos comienzan a documentar estos acuerdos, lo hacen al azar y, a menudo, crean un lío de documentos poco acoplados, la mitad de los cuales ni siquiera están actualizados.
En este artículo, te diré la forma correcta de documentar los acuerdos, para que te ayuden.
Entonces, ¿cómo podemos hacer que los acuerdos sean útiles? No solo tenemos que documentarlos sino también hacerlo para que:
eran fáciles de usar;
seguir estos acuerdos requería un esfuerzo mínimo;
sería fácil de entender si estos acuerdos siguen siendo válidos;
sería fácil entender por qué existen estos acuerdos;
idealmente, estaban automatizados.
Se pueden encontrar muchas maneras de clasificar los acuerdos. Los dividiré por su nivel de abstracción:
Los acuerdos en diferentes niveles requieren diferentes formas de documentarlos y traer diferentes beneficios. Echemos un vistazo a cada nivel.
El objetivo de estos acuerdos es hacer que el código sea uniforme, completo y legible. Aquí hay unos ejemplos:
Usamos comillas dobles en lugar de simples.
No llamamos a ENV directamente desde el código excepto en la clase Config
, donde envolvemos estas llamadas en métodos.
Los objetos de servicio tienen Service
de sufijo y una call
de método público.
Este tipo de acuerdos se crean para reducir la carga cognitiva del lector y ayudarlo a acostumbrarse más rápido al código desconocido. Como dijo Martin, el código se lee hasta 10 veces más de lo que se escribe.
A pesar de su opinión sobre el marco Ruby on Rails, tiene una convention over configuration
en su núcleo, lo que permite a cualquier desarrollador de Rails abrir el proyecto de otra persona e inmediatamente navegarlo bastante bien.
Entonces, ¿cómo documentar estas convenciones? ¡Herramienta de pelusa! Si no existe una regla de pelusa adecuada, escriba su propia pelusa. Casi todos los linter le permiten hacer eso: aquí hay un ejemplo en lenguaje Go , y aquí está para Ruby .
El uso de linter para tales convenciones le brinda tres beneficios:
No es necesario que un desarrollador piense en ellos: linter resaltará todos los errores y, a menudo, incluso los arreglará por usted.
Si usa revisiones de código en su equipo, libera a sus revisores de pensar en estas cosas y les da más tiempo para ver cosas más importantes.
El desarrollador verá un problema al comienzo del ciclo de desarrollo, por lo que lo solucionará de inmediato sin perder tiempo para volver al contexto más adelante. Se vuelve más barato mantener el acuerdo.
Una ventaja más: escribir una nueva regla de linter es un excelente entrenamiento para un desarrollador junior. Mientras completa esta tarea, aprenderá mucho sobre el análisis de código y la construcción de AST y comprenderá el lenguaje más profundamente.
Este es un tipo de acuerdo de nivel superior que tiene como objetivo hacer que su arquitectura sea reflexiva, coherente y uniforme. Algunos ejemplos:
Usamos Python para escribir servicios regulares y Elixir en las partes más cargadas del sistema.
El backend devuelve errores en el formato descrito.
Se requiere que cada servicio envíe métricas en Prometheus, en el punto final /metrics
, el puerto para enviar métricas está configurado por la variable de entorno PROMETHEUS_PORT
.
Dichos acuerdos no solo reducen la carga cognitiva, sino que también resuelven tres problemas más:
Reducir los costos operativos. Si los servicios se lanzan de la misma manera, con el mismo formato de registros y publicando las mismas métricas, entonces es mucho más fácil mantener el servicio y hacer frente a los incidentes.
Reducir los costos de diseño. El desarrollador no necesita diseñar la arquitectura desde cero cada vez; lo pensó de antemano y ahora solo necesita diseñar una característica o servicio específico, sin preocuparse por las cosas básicas.
Reducir los costes de comunicación. Si la respuesta del servidor o el formato del evento en Kafka está predeterminado, los desarrolladores no necesitan discutir su interacción cada vez, sino que simplemente pueden consultar la convención.
Dichos acuerdos son más complejos y prefiero arreglarlos en dos pasos.
Paso 1 - Describir
Architecture Decision Record (ADR) es una herramienta para documentar dichos acuerdos. Su encanto es que captura metainformación junto con un acuerdo: por qué se adoptó dicho acuerdo; qué alternativas se discutieron; cuándo se revisó por última vez; ¿Sigue siendo válido el acuerdo?
Esto permite que el nuevo miembro del equipo entienda las razones de las decisiones tomadas y no pregunte a la gente al respecto.
ADR consta de varios bloques principales:
¿Qué problema resuelve el acuerdo?
¿Qué opciones se consideraron para resolver el problema y cuáles fueron sus ventajas y desventajas?
¿Qué opción se eligió al final?
Puede haber bloques adicionales, por ejemplo, cálculo de costos de implementación.
Es más conveniente mantener ADR en un sistema donde se puede ver el historial de cambios y discusiones. Mi elección es Github y Notion, cada uno con sus pros y sus contras. La ventaja de Github es que tiene una herramienta de revisión y un historial de versiones listo para usar. Notion puede ser una buena solución debido a la conveniencia de trabajar con bases de datos y etiquetas. Y también, los no desarrolladores pueden manejarlo fácilmente.
Si quieres empezar con ADR, te recomiendo mirar el repositorio , donde puedes encontrar diferentes plantillas de ADR y ejemplos de cómo usarlas.
Paso 2 - Automatizar
Los ADR son más difíciles de automatizar que las convenciones a nivel de código: aún no se han inventado los linters de diseño (¡qué pena!). No obstante, es posible automatizarlos parcialmente, dependiendo de qué tipo de acuerdo se trate.
Cree y actualice plantillas de servicio para acuerdos sobre idiomas, bibliotecas e integración de servicios en la infraestructura. Luego, el desarrollador no escribirá nuevos servicios desde cero, sino que los copiará de la plantilla e inmediatamente recibirá el Dockerfile configurado, la publicación de métricas, etc.
De manera similar, puede crear generadores de clases dentro de una aplicación. Supongamos que hubiera acordado varias capas de aplicación (controlador => formulario => objeto de servicio). En ese caso, puede crear un comando de consola simple que generará todas las capas para una nueva función a la vez.
Si ha acordado algunos principios que no se pueden automatizar de esta manera, puede organizar listas de verificación que se agregan automáticamente a una solicitud de combinación o una tarea en el rastreador; por lo tanto, el desarrollador puede revisarlos rápidamente antes de pasar la tarea.
Hay muchos convenios por procesos en cada empresa, por ejemplo:
Descripción de cómo funciona la contratación en la empresa.
Descripción del proceso de implementación de la versión.
Requisito de revisiones de diseño para tareas grandes.
Llevar a cabo una reunión de equipo dos veces por semana con una discusión de las tareas y obstáculos actuales.
Hasta hace poco, no pensaba en documentar estos acuerdos, aunque afectan significativamente el éxito de la empresa. La documentación de estos acuerdos no solo conlleva beneficios de los tipos mencionados anteriormente sino que también permite racionalizar los procesos, trasladarlos al plano visible y pensar en su conveniencia.
Obtuve la idea de . Propuso una herramienta similar a ADR - Process Decision Record (PDR). La única diferencia es que en lugar de decisiones arquitectónicas, describe decisiones sobre procesos. Además, sugirió poner una "fecha de replanteamiento" en cada PDR: una fecha en la que vuelva al documento para ver si aún resuelve sus problemas de la mejor manera, n meses después de la adopción (por cierto, se puede hacer lo mismo con ADR).
En cuanto a la automatización, es poco lo que puedes hacer. Puede automatizar algunos procesos configurando un flujo de trabajo en Jira, configurando recordatorios para reuniones o creando un bot que prepara automáticamente una presentación de los resultados de la semana (sin embargo, hice esto en una empresa extranjera).
Pero a menudo, realmente no puede automatizar los procesos, y su objetivo principal es hacerlos más fáciles de seguir que no seguir. Sin embargo, la documentación de los acuerdos seguirá siendo útil, incluso si sus procesos ya son fáciles de seguir: la formalización y la racionalización le permitirán mejorarlos.
La documentación y la automatización posterior son beneficiosas: el tiempo dedicado al desarrollo disminuye, las aplicaciones se vuelven más compatibles y los procesos se vuelven más inteligentes.
Uno podría pensar que todo esto es una burocracia innecesaria porque "somos buenos, podemos desarrollar código sin ella". Pero, de hecho, los acuerdos le ahorrarán cantidades sustanciales de tiempo y dinero y protegerán las células nerviosas de los empleados. Claro, no necesita tratar en absoluto y rechazar cualquier cosa que vaya en contra de los acuerdos; esto puede ser una señal de que el acuerdo debe actualizarse o de que inicialmente no pensó en algunos de sus aspectos.
Si aún no ha comenzado a documentar acuerdos en su equipo, pase de niveles de abstracción más bajos a niveles más altos: comience con acuerdos a nivel de código, luego a nivel de arquitectura y solo luego haga frente al nivel de procesos. La documentación de acuerdos es un hábito a desarrollar en su equipo, y comenzar con conceptos menos abstractos es mucho más fácil.
Además, no todos los tipos se describen en el artículo. Por ejemplo, puede documentar el acuerdo de diseño como componentes de biblioteca.
Cada nuevo tipo de acuerdo pasa por las mismas tres etapas:
Averigua cómo documentarlo.
Descubre cómo automatizarlo.
A medida que pasa el tiempo, asegúrese de que ahorre más recursos de los necesarios para mantenerlo.
Y el último. Durante el proceso de documentación, se puede encontrar que algunos de los acuerdos existentes aparentemente no están justificados por nada, hacen perder el tiempo a su equipo y, en general, son perjudiciales, pero usted ya está acostumbrado a ellos. En este caso, debe superar la barrera del hábito en la mente del equipo y convencer a su equipo de que el rechazo de los acuerdos a veces es más importante que aceptarlos. Pero esa es una historia completamente diferente.
También publicado aquí .