La traducción del artículo fue preparada específicamente para estudiantes del curso "Prácticas y herramientas de DevOps" .
Este artículo analiza la relación entre la estructura del código y la estructura de la organización en el desarrollo de software. Discuto por qué el software y los equipos no pueden escalar fácilmente, qué lecciones podemos tomar en la naturaleza e Internet, y muestro cómo podemos reducir la conectividad del software y los equipos para superar los problemas de escalado.
Este artículo se basa en mis 20 años de experiencia en la creación de grandes sistemas de software y en la impresión del libro
"Acelerar: la ciencia de Lean Software y DevOps: crear
y escalar organizaciones de tecnología de alto rendimiento
" (Nicole Forsgren, Jez Humble y Gene Kim), que Investigue evidencia para respaldar la mayoría de mis afirmaciones aquí. Este libro es muy recomendable para leer.

El software y los comandos no se escalan
A menudo, el primer lanzamiento, quizás escrito por una o dos personas, es sorprendentemente simple. Puede tener una funcionalidad limitada, pero está escrito rápidamente y cumple con los requisitos del cliente. La interacción con el cliente en esta etapa es excelente, porque el cliente generalmente está en contacto directo con los desarrolladores. Los errores se corrigen rápidamente y se pueden agregar nuevas funciones sin problemas. Después de un tiempo, el ritmo se ralentiza. La versión 2.0 tarda un poco más de lo esperado. Es más difícil corregir errores, y se dan nuevas características, no es tan simple. La respuesta natural a esto es agregar nuevos desarrolladores al equipo. Aunque parece que cada empleado adicional agregado al equipo reduce la productividad. Existe la sensación de que a medida que crece la complejidad del software, se atrofia. En casos extremos, las organizaciones pueden encontrar que usan programas con soporte muy costoso que son casi imposibles de realizar cambios. El problema es que no necesita cometer ningún "error" para que esto suceda. Es tan común que se puede decir que esta es una propiedad "natural" del software.
¿Por qué está pasando esto? Hay dos razones: las relacionadas con el código y el equipo. Tanto el código como los comandos no se escalan bien.
A medida que crece el código base, se hace cada vez más difícil para una persona entenderlo. Hay límites cognitivos fijos de una persona. Y, aunque, una persona puede tener en cuenta los detalles de un sistema pequeño, pero solo hasta que se vuelva más que su rango cognitivo. Tan pronto como un equipo crece a cinco o más personas, es casi imposible que una persona sepa cómo funcionan todas las partes del sistema. Y cuando nadie comprende todo el sistema, aparece el miedo. En un sistema grande y estrechamente acoplado, es muy difícil comprender el efecto de cualquier cambio significativo, ya que el resultado no está localizado. Para minimizar el impacto de los cambios, los desarrolladores comienzan a usar soluciones alternativas y duplicación de código en lugar de identificar características comunes, creando abstracciones y generalizaciones. Esto complica aún más el sistema, reforzando estas tendencias negativas. Los desarrolladores ya no se sienten responsables del código que no entienden y son reacios a refactorizar. La deuda técnica está creciendo. También hace que el trabajo sea desagradable e insatisfactorio y estimula un "drenaje de talento" cuando los mejores desarrolladores se van y pueden encontrar trabajo fácilmente en otro lugar.
Los equipos tampoco escalan. A medida que los equipos crecen, la comunicación se vuelve más compleja. Una fórmula simple entra en juego:
c = n(n-1)/2
(donde n es el número de personas y c es el número de posibles conexiones entre los miembros del equipo)A medida que su equipo crece, sus necesidades de comunicación y coordinación crecen exponencialmente. Si se supera un cierto equipo, es muy difícil que un equipo siga siendo una estructura integral, y la tendencia social humana natural a dividirse en grupos más pequeños conducirá a la formación de subgrupos informales, incluso si la gerencia no participa en él. La comunicación con colegas se vuelve más difícil y será reemplazada naturalmente por nuevos líderes y comunicaciones de arriba hacia abajo. Los miembros del equipo se transforman de pares en el sistema en trabajadores de producción regulares. La motivación sufre, no hay sentido de propiedad debido al
efecto de difusión de la responsabilidad .
La administración a menudo interviene en esta etapa y se acerca formalmente a la creación de nuevos equipos y estructuras de administración. Pero, no importa formal o informalmente, es difícil para las grandes organizaciones mantener la motivación y el interés.
Por lo general, los desarrolladores sin experiencia y la administración deficiente culpan a estas patologías de escala. Pero esto es injusto. Los problemas de escala son una propiedad "natural" del software en crecimiento y evolución. Esto es lo que siempre sucede si no encuentra el problema en una etapa temprana, no comprende el punto de desviación y no hace ningún esfuerzo para resolver el problema. Los equipos de desarrollo de software se crean constantemente, la cantidad de software en el mundo crece constantemente y la mayoría del software es relativamente pequeño. Por lo tanto, con bastante frecuencia, un equipo que no tiene experiencia en el desarrollo a gran escala crea un producto exitoso y en desarrollo. Y no es realista esperar que los desarrolladores reconozcan el punto de inflexión y comprendan qué hacer cuando los problemas de escala comienzan a manifestarse.
Lecciones de escala natural
Hace poco leí el excelente libro de
Geoffrey West "Escala" . Habla de matemáticas de escala en sistemas biológicos y socioeconómicos. Su tesis es que todos los sistemas complejos grandes obedecen las leyes fundamentales de la escala. Esta es una lectura fascinante y lo recomiendo encarecidamente. En este artículo, quiero centrarme en su punto de vista de que muchos sistemas biológicos y sociales escalan sorprendentemente bien. Mira el cuerpo de un mamífero. Todos los mamíferos tienen los mismos tipos de células, estructura ósea, sistemas nervioso y circulatorio. Sin embargo, la diferencia de tamaño entre el mouse y la ballena azul es de aproximadamente 10 ^ 7. ¿Cómo usa la naturaleza los mismos materiales y estructura para organismos de tamaños tan diferentes? La respuesta parece ser que la evolución ha descubierto estructuras ramificadas fractales. Mira el arbol. Cada parte se ve como un pequeño árbol. Lo mismo es cierto para los sistemas circulatorio y nervioso de los mamíferos, son redes fractales ramificadas donde una pequeña parte de sus pulmones o vasos sanguíneos se parece a una versión más pequeña del conjunto.

¿Podemos tomar estas ideas de la naturaleza y aplicarlas al software? Creo que podemos aprender lecciones importantes. Si podemos construir sistemas grandes que constan de pequeñas partes que parecen sistemas completos, será posible contener las patologías que afectan a la mayoría de los programas a medida que crecen y se desarrollan.
¿Existen sistemas de software que escalen con éxito en varios órdenes de magnitud? La respuesta es obvia: Internet, un sistema de software global con millones de nodos. Las subredes realmente se ven y funcionan como versiones más pequeñas de todo Internet.
Señales de software débilmente acoplado
La capacidad de aislar componentes separados, acoplados libremente en un sistema grande es el método principal de escalamiento exitoso. Internet, de hecho, es un ejemplo de arquitectura débilmente acoplada. Esto significa que cada nodo, servicio o aplicación en la red tiene las siguientes propiedades:
- Se utiliza un protocolo de comunicación común.
- Los datos se transfieren mediante un contrato claro con otros nodos.
- La comunicación no requiere conocimiento de tecnologías de implementación específicas.
- El control de versiones y la implementación son independientes.
Internet es escalable porque es una red de nodos que se comunican a través de un conjunto de protocolos bien definidos. Los nodos interactúan solo por protocolos, cuyos detalles de implementación no deben ser conocidos por los nodos interactuantes. Internet global no se implementa como un sistema único. Cada nodo tiene su propia versión y procedimiento de implementación. Los nodos individuales aparecen y desaparecen independientemente uno del otro. La sumisión a los protocolos de Internet es lo único que realmente importa para todo el sistema. Quién creó cada sitio, cuándo fue creado o eliminado, qué versión tiene, qué tecnologías y plataformas específicas utiliza, todo esto no tiene nada que ver con Internet en su conjunto. Esto es lo que queremos decir con software poco acoplado.
Señales de una organización débilmente acoplada
Podemos escalar equipos siguiendo los mismos principios:
- Cada sub-equipo debería verse como una pequeña organización de desarrollo de software.
- Los procesos internos y la comunicación del equipo no deben ir más allá del equipo.
- Las tecnologías y procesos utilizados para implementar el software no deben discutirse fuera del equipo.
- Los equipos deben comunicarse entre sí solo sobre cuestiones externas: protocolos comunes, funcionalidad, niveles de servicio y recursos.
Los equipos de desarrollo pequeños son más efectivos que los grandes, por lo que debe dividir los equipos grandes en grupos más pequeños. Las lecciones de la naturaleza e Internet son que los subgrupos deberían verse como organizaciones pequeñas de desarrollo de software. ¿Qué tan pequeños son? Idealmente, de una a cinco personas.
Lo importante es que cada equipo se vea como una pequeña organización independiente de desarrollo de software. Otras formas de organizar equipos son menos efectivas. A menudo existe la tentación de dividir un gran equipo en funciones. Por lo tanto, tenemos un equipo de arquitectos, un equipo de desarrollo, un equipo de DBA, un equipo de prueba, un equipo de implementación y un equipo de soporte, pero esto no resuelve ninguno de los problemas de escala de los que hablamos anteriormente. Todos los equipos deben participar en el desarrollo de una función y, a menudo, de forma iterativa si desean evitar la gestión de proyectos al estilo de una cascada.
Las barreras de comunicación entre estos equipos funcionales se están convirtiendo en un obstáculo importante para la entrega eficiente y oportuna. Los equipos están estrechamente conectados porque necesitan compartir detalles internos importantes para trabajar juntos. Además, los intereses de los diferentes equipos no coinciden: los desarrolladores generalmente reciben un premio por las nuevas funciones, los evaluadores por la calidad, el soporte por la estabilidad. Estos intereses diferentes pueden conducir a conflictos y malos resultados. ¿Por qué los desarrolladores deberían preocuparse por los registros si nunca los leen? ¿Por qué los evaluadores deberían preocuparse por la entrega si son responsables de la calidad?
En su lugar, deberíamos organizar equipos para servicios acoplados de manera flexible que admitan funciones comerciales, o para un grupo lógico de funciones. Cada subcomando debe diseñar, codificar, probar, implementar y mantener su propio software. Lo más probable es que los miembros de dicho equipo sean especialistas de un perfil amplio, y no especialistas limitados, porque en un equipo pequeño será necesario separar estos roles. Deben centrarse en la máxima automatización posible de los procesos: pruebas automatizadas, implementación, monitoreo. Los equipos deben elegir sus propias herramientas y diseñar la arquitectura para sus sistemas. Aunque los protocolos utilizados para la interacción de los servicios deben determinarse a nivel de la organización, la elección de las herramientas utilizadas para implementarlos debe delegarse en los equipos. Y eso encaja muy bien con el modelo DevOps.
El nivel de independencia que posee un equipo es un reflejo del nivel de conexión de toda la organización. Idealmente, la organización debería ocuparse de la funcionalidad del software y, en última instancia, del valor comercial que proporciona el equipo, así como del costo de los recursos del equipo.
En este caso, el arquitecto de software juega un papel importante. No debe centrarse en herramientas y tecnologías específicas que utilizan los equipos, ni interferir con los detalles de la arquitectura interna de los servicios. En cambio, debería centrarse en los protocolos e interacciones entre los diferentes servicios y la salud del sistema en su conjunto.
Ley invertida de Conway: la estructura organizativa debe modelar la arquitectura objetivo
¿Cómo encajan la coherencia de software débil y la de equipo débil?
La ley de Conway establece:
"Las organizaciones que diseñan sistemas se limitan a un diseño que copia la estructura de comunicación de esta organización".
Esto se basa en la observación de que la arquitectura de un sistema de software reflejará la estructura de la organización que lo crea. Podemos "piratear" la ley de Conway dándole la vuelta. Organice nuestros equipos para reflejar nuestra arquitectura deseada. Con esto en mente, debemos alinear equipos débilmente acoplados con componentes de software débilmente acoplados. ¿Pero debería ser una relación uno a uno? Creo que, idealmente, sí. Aunque parece que es bueno si un pequeño equipo trabaja en varios servicios acoplados libremente. Diría que el punto de inflexión para el escalado es mayor para los equipos que para el software, por lo que este estilo de organización parece aceptable. Es importante que los componentes del software permanezcan separados, con sus propias versiones e implementación, incluso si algunos de ellos son desarrollados por un equipo. Nos gustaría poder dividir el equipo si es demasiado grande, con la transferencia de servicios desarrollados a diferentes equipos. Pero no podemos hacer esto si los servicios están estrechamente acoplados o comparten un proceso, control de versiones o implementación.
Debemos evitar el trabajo de varios equipos en los mismos componentes. Este es un antipatrón. Y, en cierto sentido, incluso peor que el trabajo de un equipo grande con una base de código grande, porque las barreras de comunicación entre equipos conducen a un sentimiento aún más fuerte de falta de propiedad y control.

La interacción entre los equipos acoplados libremente que crean software acoplado libremente se minimiza. Tome el ejemplo de Internet nuevamente. A menudo, puede usar la API proporcionada por otra compañía sin ninguna comunicación directa con ella (si el proceso es simple y hay documentación). Cuando los equipos interactúan, no deben discutirse los procesos internos de desarrollo e implementación del equipo. En cambio, la funcionalidad, los niveles de servicio y los recursos deben ser discutidos.
La gestión de equipos acoplados libremente que crean software acoplado libremente debería ser más fácil que las alternativas. Una gran organización debería centrarse en proporcionar a los equipos objetivos y requisitos claros en términos de funcionalidad y niveles de servicio. Los requisitos de recursos deben provenir del equipo, aunque pueden ser utilizados por la organización para medir el retorno de la inversión.
Los equipos acoplados libremente desarrollan software acoplado libremente
La conectividad débil en software y entre equipos es la clave para construir una organización altamente efectiva. Y mi experiencia confirma este punto. Trabajé en organizaciones donde los equipos estaban divididos por función, por nivel de software o incluso donde había una separación de clientes. También trabajé en grandes equipos caóticos en una sola base de código. Pero en todos estos casos, hubo problemas con la escala, que se mencionaron anteriormente. La experiencia más agradable siempre ha sido cuando mi equipo era una unidad de pleno derecho, que se dedicaba de forma independiente a la creación, prueba y despliegue de servicios independientes. Pero no necesitas confiar en las historias de mi vida. Acelerar (descrito anteriormente) tiene evidencia de investigación para respaldar esta opinión.
Si ha leído este material hasta el final, le recomendamos que vea una grabación de un seminario web abierto sobre el tema "Un día en la vida de DevOps" .