Monorepositorios: por favor

imagen


Se preparó una traducción del artículo para los estudiantes del curso de Prácticas y herramientas de DevOps en el proyecto educativo OTUS .




Debe elegir un mono-repositorio, porque el comportamiento que promueve en sus equipos es la transparencia y la responsabilidad colectiva, especialmente cuando los equipos crecen. En cualquier caso, tendrá que invertir en herramientas, pero siempre es mejor cuando el comportamiento predeterminado es el comportamiento que desea ver en sus comandos.


¿Por qué estamos hablando de esto?


Matt Klein escribió un artículo, "Monorepos: ¡Por favor no lo hagas!" (comentario del traductor: traducción en un centro "Monorepositorios: por favor no" ). Me gusta Matt, creo que es muy inteligente, y deberías leer su punto de vista. Originalmente tuiteó la encuesta:


imagen


Traducción:
En este día de Año Nuevo, discutiré sobre lo ridículos que son los monorepositorios. 2019 comenzó desapercibido. En el espíritu de esto, te ofrezco una encuesta. ¿Quiénes son los grandes fanáticos? Partidarios:
- Monorepository
- óxido
- Encuesta incorrecta / ambos y aquellos


Mi respuesta fue: "Literalmente soy ambas personas". En lugar de hablar sobre qué tipo de droga Rust, averigüemos por qué creo que está equivocado acerca de los mono-repositorios. Un poco sobre ti. Soy el director de tecnología de Chef Software. Tenemos alrededor de 100 ingenieros, una base de código de aproximadamente 11-12 años y 4 productos principales. Parte de este código está en el polyrepository (mi posición inicial), parte en el monorepository (mi posición actual).


Antes de comenzar: cada argumento que cito aquí se aplicará a ambos tipos de repositorios. En mi opinión, no hay razones técnicas por las que deba elegir uno u otro tipo de repositorio. Puedes hacer que cualquier enfoque funcione. Me alegra hablar de esto, pero no me interesan las razones técnicas artificiales por las cuales una es superior a la otra.


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


Porque a gran escala, el monorepository resolverá los mismos problemas que resuelve el polyrepository, pero al mismo tiempo provoca una gran coherencia de su código y requiere esfuerzos increíbles para aumentar la escalabilidad de su sistema de control de versiones.


Tiene que resolver los mismos problemas, independientemente de si elige un monorepository o polyrepository. ¿Cómo se lanzan lanzamientos? ¿Cuál es su enfoque para las actualizaciones? Compatible con versiones anteriores? Dependencias entre proyectos? ¿Qué estilos arquitectónicos son aceptables? ¿Cómo gestionas tu 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 las opiniones compartidas por muchos ingenieros (y gerentes) que respeto. Esto sucede desde el punto de vista del ingeniero que trabaja en el componente o del equipo que trabaja en el componente. Escuchas cosas como:


  • La base del código es engorrosa: no necesito toda esta basura.
  • Esto es más difícil de probar porque tengo que verificar toda esta basura que no necesito.
  • Es más difícil trabajar con dependencias externas.
  • Necesito mis propios sistemas virtuales de control de versiones.

Por supuesto, todos estos puntos son razonables. Esto sucede en ambos casos: en el polirrepositorio tengo mis propias cosas, además de la que se necesita para el ensamblaje ... También podría necesitar otras cosas. Por lo tanto, "solo" creo herramientas que verifican el proyecto completo. ¿O estoy creando un falso repositorio mono con submódulos? Podríamos caminar todo el día alrededor de esto. Pero creo que el argumento de Matt no tiene en cuenta la razón principal, que prácticamente volví a favor del monorepositivo:


Provoca la comunicación y muestra problemas.


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


Con la complejidad de la arquitectura, un equipo ya no puede administrarla solo. Muy pocos ingenieros mantienen todo el sistema en su cabeza. Suponga que controla un componente común A, que es utilizado por los comandos B, C y D. Los refactores del equipo A, mejoran la API y también cambian la implementación interna. Como resultado, los cambios son incompatibles con versiones anteriores. ¿Qué consejo le darías?


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

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


Nadie realmente quiere hacer esto. Esto es mucho menos divertido que simplemente arreglar la maldita API. Todo esto es humano y confuso. En el repositorio, simplemente puede hacer cambios, dar una revisión a aquellos que están trabajando en este componente (probablemente no B, C o D), y seguir adelante. Los equipos B, C y D simplemente pueden permanecer en su versión actual. ¡Se actualizarán cuando se den cuenta de tu genio!


En un único repositorio, la responsabilidad se desplaza por defecto. El equipo A cambia su componente y, si no tiene cuidado, rompe inmediatamente B, C y D. Esto hace que B, C y D aparezcan en la puerta A, preguntándose por qué el equipo A rompió la asamblea. Esto le enseña a A que no pueden omitir mi lista anterior. Deben hablar sobre 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 antiguo algoritmo?


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


  1. Soporte para múltiples API internas, mientras que el antiguo algoritmo se marcará como obsoleto hasta que D pueda dejar de usarlo.
  2. Soporte para múltiples versiones de lanzamientos, uno con la interfaz anterior y otro con la nueva.
  3. Retraso en la liberación de los cambios en A hasta que B, C y D puedan aceptarlo.

Supongamos que seleccionamos 1, varias API. En este caso, tenemos dos piezas de código. Viejos y nuevos. Bastante útil en algunas situaciones. Devolvemos el código anterior, lo marcamos como obsoleto y acordamos un cronograma para su eliminación con el comando D. Es esencialmente idéntico para poly y para el mono-repositorio.


Para lanzar varias versiones, necesitamos una rama. Ahora tenemos dos componentes: A1 y A2. Los equipos B y C usan A2, y D usa A1. Necesitamos que cada componente esté listo para su lanzamiento, porque antes de que D pueda continuar, es posible que se requieran actualizaciones de seguridad y otras correcciones de errores. En el repositorio, podemos ocultarlo en una rama de larga vida que se siente bien. En el mono-repositorio, forzamos el código en el nuevo módulo. El equipo D aún tendrá que hacer cambios en el componente "antiguo". Todos pueden ver el costo que pagamos 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 usar ramas en un repositorio, esto se oculta detrás de cherry-pick. Consideramos que el costo es menor porque no hay duplicación. Desde un punto de vista práctico, el costo es el mismo: creará, publicará y mantendrá dos bases de código, básicamente idénticas, hasta que pueda eliminar una de ellas. La diferencia es que en el monorepository este dolor es directo y es visible. Esto es aún peor y bueno.


Finalmente, llegamos al tercer punto. Retraso de liberación. Es posible que los cambios realizados por A mejoren la vida del equipo A. Es importante, pero no urgente. ¿Podemos esperar? En el repositorio, estamos impulsando esto para consolidar el artefacto. Por supuesto, estamos hablando de este equipo D. ¡Solo permanece en la versión anterior hasta que te pongas al día! Esto configura un juego cobarde. El Equipo A continúa trabajando en su componente, ignorando el hecho de que el Equipo D usa una versión cada vez más obsoleta (esto es un problema para el 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 eso. Pasan los meses Finalmente, el equipo D decide echar un vistazo a la opción de actualización, pero solo hay más cambios en A. El equipo A apenas recuerda cuándo y cómo se rompieron D. La actualización es más dolorosa y tomará más tiempo. Lo que lo envía más abajo en la pila de prioridad. Hasta ese día, hasta que tengamos un problema de seguridad en A, lo que nos obliga a hacer una sucursal. El equipo A debe retroceder en el tiempo, encontrar el momento en que D era estable, solucionar el problema allí y prepararlo para el lanzamiento. Esta es la elección de facto que hace la gente, y es, con mucho, la peor. Esto parece ser bueno tanto para el equipo A como para el D, siempre y cuando podamos ignorarnos.


En el monorepository, el tercero realmente no es una opción. Estás obligado a lidiar con la situación de una de dos maneras. Necesita ver los costos de tener dos ramas de lanzamiento. Aprenda a protegerse de las actualizaciones que rompen la compatibilidad con versiones anteriores. Pero lo principal: no se puede evitar una conversación difícil.


En mi experiencia, cuando los equipos se hacen grandes, ya no es posible tener en cuenta todo el sistema, y ​​esta es la parte más importante. Necesita mejorar la visibilidad de los desacuerdos en el sistema. Debe trabajar activamente para que los equipos quiten la vista de sus componentes y observen el trabajo de otros equipos y consumidores.


Sí, puede crear herramientas que tratarán de resolver el problema de los polirrepositorios. Pero mi experiencia en la enseñanza de la entrega continua y la automatización en grandes empresas me dice lo siguiente: el comportamiento predeterminado sin usar herramientas adicionales es el comportamiento que espera ver. El comportamiento predeterminado del repositorio es el aislamiento, de eso se trata. El comportamiento predeterminado de un mono-repositorio es responsabilidad compartida y transparencia, de eso se trata. En ambos casos, voy a crear una herramienta que suavizará las esquinas afiladas. Como líder, elegiré un mono-repositorio cada vez, porque los instrumentos deben fortalecer la cultura que quiero, y la cultura proviene de pequeñas decisiones y del trabajo diario del equipo.

Source: https://habr.com/ru/post/453958/


All Articles