Monorepositorios: por favor, debe

Monorepositorios: por favor, debe

Traducción del artículo elaborado para los alumnos del curso. "Prácticas y herramientas de DevOps" en el proyecto educativo OTUS.

Debes elegir un monorepositorio porque el comportamiento que promueve en tus equipos es la transparencia y la responsabilidad compartida, especialmente a medida que los equipos crecen. De cualquier manera, tendrá que invertir en herramientas, pero siempre es mejor si el comportamiento predeterminado es el que desea en sus comandos.

¿Por qué estamos hablando de esto?

Matt Klein escribió el artículo. "Monorepos: ¡Por favor no lo hagas!"  (nota del traductor: traducción sobre Habré “Monorrepositorios: por favor no”). Me gusta Matt, creo que es muy inteligente y deberías leer su punto de vista. Originalmente publicó la encuesta en Twitter:

Monorepositorios: por favor, debe

Traducción:
Este día de Año Nuevo, voy a discutir sobre lo ridículos que son los monorepositorios. 2019 empezó tranquilo. Con este espíritu, les ofrezco una encuesta. ¿Quiénes son los grandes fanáticos? Partidarios:
- Monorepo
- Herrumbre
- Encuesta incorrecta/ambas

Mi respuesta fue: "Soy literalmente ambas personas". En lugar de hablar de cómo Rust es una droga, veamos por qué creo que se equivoca acerca de los monorepositorios. Un poco sobre ti. Soy el CTO de Chef Software. Tenemos alrededor de 100 ingenieros, una base de código que se remonta a entre 11 y 12 años y 4 productos principales. Parte de este código está en un polirepositorio (mi posición inicial), parte está en un monorepositorio (mi posición actual).

Antes de comenzar: todos los argumentos que planteo aquí se aplicarán a ambos tipos de repositorios. En mi opinión, no existe ninguna razón técnica por la que debas elegir un tipo de repositorio sobre otro. Puedes hacer que cualquier enfoque funcione. Me alegra hablar de ello, pero no me interesan las razones técnicas artificiales por las que uno es superior a otro.

Estoy de acuerdo con la primera parte del punto de Matt:

Porque a escala, un monorepositorio resolverá los mismos problemas que resuelve un polirrepositorio, pero al mismo tiempo lo obligará a acoplar estrechamente su código y requerirá esfuerzos increíbles para aumentar la escalabilidad de su sistema de control de versiones.

Tendrás que resolver los mismos problemas independientemente de si eliges un monorepositorio o un polirepositorio. ¿Cómo se publican los lanzamientos? ¿Cuál es su enfoque respecto de las actualizaciones? ¿Compatibilidad con versiones anteriores? ¿Dependencias cruzadas del proyecto? ¿Qué estilos arquitectónicos son aceptables? ¿Cómo gestiona su infraestructura de construcción y prueba? La lista es interminable. Y los resolverás todos a medida que crezcas. No hay queso gratis.

Creo que el argumento de Matt es similar a los puntos de vista compartidos por muchos ingenieros (y gerentes) que respeto. Esto ocurre desde la perspectiva del ingeniero que trabaja en el componente o del equipo que trabaja en el componente. Escuchas cosas como:

  • El código base es voluminoso; no necesito toda esta basura.
  • Es más difícil realizar pruebas porque tengo que probar toda esta basura que no necesito.
  • Es más difícil trabajar con dependencias externas.
  • Necesito mis propios sistemas de control de versiones virtuales.

Por supuesto, todos estos puntos están justificados. Esto sucede en ambos casos: en el polirepositorio tengo mi propia basura, además de la necesaria para la compilación... Es posible que también necesite otra basura. Así que “simplemente” creo herramientas que verifican todo el proyecto. O creo un monorepositorio falso con submódulos. Podríamos caminar alrededor de esto todo el día. Pero creo que el argumento de Matt pasa por alto la razón principal, que invertí bastante a favor del monorepositorio:

Provoca comunicación y muestra problemas.

Cuando separamos los repositorios, creamos un problema de facto de coordinación y transparencia. Esto corresponde a la forma en que pensamos sobre los equipos (especialmente la forma en que los miembros individuales piensan sobre ellos): somos responsables de un determinado componente. Trabajamos en relativo aislamiento. Los límites están fijados en mi equipo y los componentes en los que estamos trabajando.

A medida que la arquitectura se vuelve más compleja, un equipo ya no puede gestionarla por sí solo. Muy pocos ingenieros tienen todo el sistema en la cabeza. Supongamos que administra un componente compartido A que utilizan los equipos B, C y D. El equipo A está refactorizando, mejorando la API y también cambiando la implementación interna. Como resultado, los cambios no son compatibles con versiones anteriores. ¿Que Consejo tienes?

  • Encuentre todos los lugares donde se utiliza la API anterior.
  • ¿Hay lugares donde no se puede utilizar la nueva API?
  • ¿Puedes arreglar y probar otros componentes para asegurarte de que no se rompan?
  • ¿Pueden estos equipos probar sus cambios ahora mismo?

Tenga en cuenta que estas preguntas son independientes del tipo de repositorio. Necesitará encontrar los equipos B, C y D. Necesitará hablar con ellos, averiguar la hora y comprender sus prioridades. Al menos esperamos que lo hagas.

En realidad nadie quiere hacer esto. Esto es mucho menos divertido que simplemente arreglar la maldita API. Es todo humano y desordenado. En un polirrepositorio, simplemente puede realizar cambios, entregárselos a las personas que trabajan en ese componente (probablemente no B, C o D) para que los revisen y seguir adelante. Los equipos B, C y D pueden quedarse con su versión actual por ahora. ¡Se renovarán cuando se den cuenta de tu genio!

En un monorrepositorio, la responsabilidad se transfiere de forma predeterminada. El equipo A cambia su componente y, si no tiene cuidado, inmediatamente rompe B, C y D. Esto lleva a que B, C y D se presenten en la puerta de A, preguntándose por qué el equipo A rompió el ensamblaje. Esto le enseña a A que no pueden saltarse mi lista anterior. Deben hablar de lo que van a hacer. ¿Pueden moverse B, C y D? ¿Qué pasa si B y C pueden, pero D estaba estrechamente relacionado con un efecto secundario del comportamiento del antiguo algoritmo?

Luego tenemos que hablar de cómo saldremos de esta situación:

  1. Soporte para múltiples API internas y marcará el algoritmo anterior como obsoleto hasta que D pueda dejar de usarlo.
  2. Soporte para múltiples versiones, una con la interfaz anterior y otra con la nueva.
  3. Retrase la publicación de los cambios de A hasta que B, C y D puedan aceptarlos simultáneamente.

Digamos que hemos seleccionado 1 o varias API. En este caso tenemos dos fragmentos de código. Viejo y nuevo. Bastante conveniente en algunas situaciones. Volvemos a verificar el código anterior, lo marcamos como obsoleto y acordamos un cronograma de eliminación con el equipo D. Esencialmente idéntico para los repositorios poli y mono.

Para lanzar múltiples versiones, necesitamos una rama. Ahora tenemos dos componentes: A1 y A2. Los equipos B y C usan A2 y D usa A1. Necesitamos que todos los componentes estén listos para su lanzamiento porque es posible que se requieran actualizaciones de seguridad y otras correcciones de errores antes de que D pueda seguir adelante. En un polirrepositorio, podemos ocultar esto en una rama de larga duración que se sienta bien. En un monorepositorio, forzamos la creación del código en un nuevo módulo. El equipo D aún tendrá que realizar cambios en el componente "antiguo". Todos pueden ver el costo que estamos pagando aquí: ahora tenemos el doble de código y cualquier corrección de errores que se aplique a A1 y A2 debe aplicarse a ambos. Con el enfoque de ramificación en un polirepositorio, esto queda oculto detrás de la selección selectiva. Consideramos que el coste es menor porque no hay duplicaciones. Desde un punto de vista práctico, el costo es el mismo: creará, publicará y mantendrá dos bases de código prácticamente idénticas hasta que pueda eliminar una de ellas. La diferencia es que con un monorepositorio este dolor es directo y visible. Esto es aún peor y eso es bueno.

Finalmente llegamos al tercer punto. Retraso en la liberación. Es posible que los cambios realizados por A mejoren la vida del Equipo A. Importante, pero no urgente. ¿Podemos simplemente retrasarnos? En un polirrepositorio, presionamos esto para fijar el artefacto. Por supuesto, le estamos contando esto al Equipo D. ¡Quédate en la versión anterior hasta que te pongas al día! Esto te prepara para hacerte el cobarde. El equipo A continúa trabajando en su componente, ignorando el hecho de que el equipo D está usando una versión cada vez más desactualizada (ese es el problema del equipo D, son estúpidos). Mientras tanto, el Equipo D habla mal de la actitud descuidada del Equipo A hacia la estabilidad del código, si es que hablan de ello. Pasan los meses. Finalmente, el equipo D decide considerar la posibilidad de actualizar, pero A solo tiene más cambios. El equipo A apenas recuerda cuándo o cómo rompieron D. La actualización es más dolorosa y llevará más tiempo. Lo que lo envía más abajo en la pila de prioridades. Hasta el día que tenemos un problema de seguridad en A que nos obliga a hacer una sucursal. El equipo A debe retroceder en el tiempo, encontrar un punto en el que D estuviera estable, solucionar el problema allí y prepararlo para su lanzamiento. Ésta es la elección de facto que hace la gente y es, con diferencia, la peor. Parece ser bueno tanto para el Equipo A como para el Equipo D siempre que podamos ignorarnos unos a otros.

En un monorepositorio, el tercero realmente no es una opción. Te ves obligado a lidiar con la situación de dos maneras. Necesita ver los costos de tener dos sucursales de lanzamiento. Aprenda a protegerse de las actualizaciones que rompen la compatibilidad con versiones anteriores. Pero lo mas importante: No puedes evitar tener una conversación difícil.

En mi experiencia, cuando los equipos crecen, ya no es posible tener en mente todo el sistema, y ​​esa es la parte más importante. Debes mejorar la visibilidad de la discordia en el sistema. Debe trabajar activamente para lograr que los equipos dejen de mirar sus componentes y observen el trabajo de otros equipos y consumidores.

Sí, puedes crear herramientas que intenten resolver el problema del polirepositorio. Pero mi experiencia enseñando entrega continua y automatización en grandes empresas me dice esto: el comportamiento predeterminado sin el uso de herramientas adicionales es el comportamiento que espera ver. El comportamiento predeterminado de un polirepositorio es el aislamiento, ese es el punto. El comportamiento predeterminado de un monorepositorio es responsabilidad compartida y transparencia, ese es el punto. En ambos casos, voy a crear una herramienta que suavizará los bordes ásperos. Como líder, siempre elegiré un monorepositorio porque las herramientas necesitan reforzar la cultura que quiero, y la cultura surge de pequeñas decisiones y del trabajo diario del equipo.

Solo los usuarios registrados pueden participar en la encuesta. Registrarsepor favor

¿Quiénes son los mayores fanáticos? Partidarios:

  • Monorepo

  • Herrumbre

  • Encuesta incorrecta/ambas

33 usuarios votaron. 13 usuarios se abstuvieron.

Fuente: habr.com

Añadir un comentario