¿El scrum y un desarrollo estable crean una contradicción?

11

Soy parte de un grupo de desarrollo con 5 equipos, un total de aproximadamente 40 desarrolladores. Estamos siguiendo la metodología Scrum, con sprints de 3 semanas. Tenemos una configuración de integración continua (Jenkins), con una tubería de construcción que demora varias horas (debido a extensas pruebas automatizadas). Básicamente, el proceso de desarrollo funciona bien.

Sin embargo, observamos que después de unos días en un nuevo sprint, nuestra construcción a menudo se vuelve inestable y permanece inestable hasta que el sprint finaliza "commit stop". El efecto adverso de esto es que los pasos de compilación en el futuro, especialmente las pruebas de IU / Web no se ejecutan durante varios días (porque solo se activan en una compilación 'verde'). En consecuencia, los errores recientemente introducidos a menudo solo se detectan muy tarde en el sprint.

  • Cada confirmación se verifica contra un conjunto básico de pruebas. Una vez verificado, el cambio se envía al maestro después de una revisión de código (Gerrit)
  • Las pruebas unitarias básicas se ejecutan cada 30 minutos, duración inferior a 10 minutos
  • Las pruebas de integración se ejecutan cada 2 h, duración 1 h
  • UI- / Webtests se ejecutan en pruebas de integración exitosas, duración varias horas

Dependiendo de quién sea responsable de la estabilidad de la construcción durante el sprint (esa responsabilidad se transfiere por sprint), puede haber "paradas de compromiso" intermedias y ad-hoc para que la construcción vuelva a ser estable.

Entonces, queremos:

  1. Nuestros equipos de desarrollo para desarrollar y cometer cambios durante un sprint sin obstáculos
  2. Nuestro proceso de compilación se abandonará si falla un paso de compilación, ya que los resultados de compilación posteriores tienen poco significado
  3. Nuestro proceso de construcción para brindar a los desarrolladores comentarios de calidad de manera oportuna

Dado (2), los puntos (1) y (3) parecen contradecirse entre sí. ¿Alguien tiene una buena práctica de cómo lidiar con esto?

( Actualmente estamos aflojando el punto (2), y estamos permitiendo la continuación de la construcción incluso en los pasos de construcción fallidos. Todavía no tengo comentarios sobre cómo eso influye en nuestra calidad )

Gracias simon

Simón
fuente
3
Yo diría que si está tomando una compilación several hours, ese es el verdadero problema. significa que la solución combinada es demasiado grande y demasiado amplia. Debe buscar componentes de la solución y luego tener pequeños fragmentos de código como paquetes (disponibles de una forma u otra en todos los idiomas principales en todas las plataformas). Por lo tanto, cualquier cambio iría solo a los componentes y se detectará mucho más rápido. La compilación completa esencialmente solo juntará componentes ya combinados, y también será más rápido. Entonces, posiblemente solo ejecute algunas pruebas para asegurarse de que se hayan resuelto los componentes correctos.
zaitsman
¿Está su entorno de construcción en las instalaciones o basado en la nube?
Lauri Laanti
@LauriLaanti, nuestro entorno de construcción es local, 1 instancia de Jenkins con 3 esclavos.
Simon

Respuestas:

7

Primero, un par de principios básicos: - Los cambios importantes siempre deben realizarse en una rama de características en su VCS - Las ramas de características deben pasar todas las pruebas antes de fusionarse en el tronco. Agregado : los commits siempre deben compilarse : un build roto requiere una acción inmediata del committer y / o del resto del equipo. - Una prueba fallida solo debe abortar las pruebas restantes si es una prueba crítica .

Si usted, como equipo, sigue estas prácticas y las aplica, por ejemplo: "nombre y vergüenza" cuando se rompe la compilación, entonces debería ser bueno ya que cualquier confirmación que pueda romper la compilación estará en una rama de características. Otros compromisos que rompen la compilación deberán abordarse de inmediato y luego obtendrá los resultados de las pruebas posteriores.

También puede agregar una prueba automática de la última compilación "exitosa" (no necesariamente una que pase las pruebas de integración), para las pruebas UI / Web como una ejecución nocturna que informa a primera hora de la mañana.

Steve Barnes
fuente
3
Una buena práctica para agregar aquí es que las ramas de características deben pasar todas las pruebas antes de fusionarse con la línea principal
Bart van Ingen Schenau
@BartvanIngenSchenau - ¡Buen punto agregado!
Steve Barnes
@SteveBarnes, gracias por el aporte. Una confirmación en Gerrit siempre está en una rama, y ​​solo se combina en el éxito (mi primer punto en el proceso de compilación). Después de eso comienza el problema. Con 30 desarrolladores que realizan cambios varias veces al día, necesitamos fusionarnos temprano y luego verificar. No es una acción inmediata después de una acumulación roto, pero como el tiempo entre comprometerse y retroalimentación de construcción es de 2 horas, habrá varias otras confirmaciones en el ínterin. Posiblemente rompiendo la próxima construcción.
Simon
@Simon, ¡el punto del "nombre y la vergüenza" es hacer que tus desarrolladores dejen de cometer código roto! En la mayoría de los sistemas, es posible realizar una compilación de prueba en poco tiempo utilizando herramientas como ant, make, scons, etc. Si su proyecto está bien estructurado, la mayoría de los lenguajes permiten reconstrucciones parciales para probar si las cosas se construirán (completo / limpio las construcciones aún deben hacerse, por supuesto).
Steve Barnes
8

No tiene nada que ver con Scrum. Su construcción debe ser continuamente estable, independientemente.

Nadie debería registrar nada a menos que hayan realizado una compilación local y ejecuten las pruebas unitarias localmente (y ambas pasaron, por supuesto). Su proceso local de compilación y prueba debe ser sensible a las modificaciones y puede omitir las pruebas de código que no ha cambiado.

Cualquier persona que presente algo que haga que falle la construcción o que falle una prueba unitaria debe ser avergonzado públicamente . Si la compilación se rompe, debe repararse de inmediato.

John Wu
fuente
2
Por un lado, debe enfatizarse que la estabilidad de la construcción es responsabilidad de todos. Por otro lado, recomendaría no avergonzar al público, porque (1) los miembros del equipo más experimentados tienen una mayor responsabilidad en ayudar a los miembros junior a lograr la estabilidad de la construcción (mediante revisión de código, programación de pares o simplemente trabajando juntos antes de un compromiso, o por arreglar una estructura rota juntos), (2) la vergüenza quita la seguridad psicológica del equipo .
rwong
1
Si las personas no quieren ser avergonzadas, entonces no deberían romper la construcción. No es que sea un estándar irrazonablemente alto. Si tienes desarrolladores que no pueden piratearlo, deja que tengan su propia rama para jugar hasta que descubran cómo no romper los comunes comunes del equipo. (Dicho esto, cualquier vergüenza real debe ser de buen gusto).
John Wu
En nuestro proceso, cualquier commit se ramifica (en Gerrit) y tiene que pasar un conjunto básico de pruebas antes de fusionarse con master. Esas pruebas básicas no pueden ejecutarse durante una hora, ya que queremos revisar el código y fusionarlo rápidamente. Es después de la fusión donde comienza el problema, vea mi comentario a @SteveBarnes
Simon
6

Su problema parece ser que las pruebas tardan demasiado en ejecutarse. Afortunadamente, la ley de Moore nos ha proporcionado una solución a ese problema. Hoy en día, las CPU de servidor de gama alta pueden tener fácilmente más de 10 núcleos (y más de 10 HyperThreads). Puede haber múltiples CPU de este tipo en una sola computadora.

Si tuviera pruebas que llevaran tanto tiempo, resolvería el problema con más hardware. Compraría un servidor de alta gama y luego paralelizaría las pruebas para que las pruebas aprovechen al máximo todos los núcleos de CPU. Si sus pruebas son de un solo subproceso, aprovechar 10 núcleos y 10 HyperThreds probablemente hace que las pruebas se ejecuten 15 veces más rápido. Por supuesto, esto significa que también usan 15 veces la memoria, por lo que la computadora debe tener suficiente RAM.

Entonces, las varias horas se convertirán en 10-30 minutos.

No dijo cuánto tiempo lleva la compilación, pero las herramientas de compilación estándar como make permiten paralelizar también la compilación. Si paraleliza sus pruebas unitarias y la computadora típica del desarrollador tiene 4 núcleos y 4 HyperThreads, los menos de 10 minutos de pruebas unitarias se convertirán en menos de 2 minutos. Entonces, ¿tal vez podría hacer cumplir una política de que todos deberían ejecutar las pruebas unitarias antes de comprometerse?

Sobre la falla de la prueba que detiene las pruebas adicionales: ¡no haga eso en el servidor de compilación! Desea tanta información como sea posible sobre la falla, y las pruebas adicionales pueden revelar algo importante. Por supuesto, si la construcción en sí falla, no puede ejecutar pruebas unitarias. Si el desarrollador ejecuta pruebas unitarias en su propia máquina, es posible que desee abortar en el primer fallo.

No veo ninguna conexión entre Scrum y tus problemas. Los problemas realmente podrían ocurrir con cualquier proceso de desarrollo.

juhist
fuente
Estoy de acuerdo, con una construcción más rápida las cosas serían mucho más fáciles. Nuestro TechTeam ha pasado días mejorando la velocidad de nuestro proceso de construcción, de lo contrario estaríamos esperando días en lugar de horas. Por ahora, esa duración de retroalimentación se da en aprox. 2 horas. Así que estoy buscando un enfoque que lo tome como "dado". (Por supuesto, estamos continuamente tratando de acelerar la construcción. Pero para el futuro cercano, serán 2 horas)
Simon
Algunas pruebas pueden entrar en conflicto con la ejecución paralela
deFreitas
Solo es posible lanzar más hardware si las pruebas se escriben de manera que puedan ejecutarse independientemente entre sí sin introducir efectos secundarios. Cuanto más se aleje del hardware, más difícil será esto ... la mayoría de los desarrolladores no hazlo bien, así que si bien estoy de acuerdo contigo, primero me enfocaría en estructurar las pruebas de la manera correcta.
c_maker
2

¿No es posible tener más instalaciones de Jenkins y que los desarrolladores verifiquen una instancia de Jenkins separada?

Creo que la mejor solución aquí es hacer que el código pase todas las pruebas antes de que sea revisado en la rama maestra y compilado / probado por la instancia principal de Jenkins. No permita que la gente registre el código que rompe la compilación.

Verifico mi código en la rama de desarrollo, veo si pasa las pruebas y creo una solicitud de extracción. Pero obviamente podría hacer que Jenkins extraiga una rama de características y pruebe esa.

xyious
fuente
1

El punto (2) parece ser el punto más doloroso, así que me enfocaré en eso.

Tal vez sea hora de dividir el proyecto en múltiples módulos.

https://en.wikipedia.org/wiki/Dependency_inversion_principle

A. Los módulos de alto nivel no deberían depender de los módulos de bajo nivel. Ambos deberían depender de abstracciones.

B. Las abstracciones no deberían depender de los detalles. Los detalles deben depender de las abstracciones.

Si un módulo no puede compilarse, la compilación para otros módulos podrá continuar, siempre y cuando esos otros módulos puedan depender de una interfaz, y el código que conforma esa interfaz se compiló con éxito.

Esto le dará retroalimentación sobre qué otras fallas de compilación podrían ocurrir, de modo que tenga tiempo para reparar más de un módulo roto antes de que ocurra la próxima compilación.

En general, los principios SOLID están concebidos para tratar con bibliotecas y generar problemas. En otras palabras, este conjunto de principios está concebido para resolver el tipo exacto de problemas que enfrenta.


Como nota al margen (vea la respuesta de juhist), no puede hacer que la compilación se ejecute más rápido (por paralelización) si no divide la compilación en módulos separados.

rwong
fuente
0

Creo que a su equipo le falta uno de los principios clave de scrum: el software hecho y funcionando. Un PBI no debe marcarse como hecho hasta que pase la definición de hecho que su equipo ha establecido. La definición de Done es diferente para cada equipo, pero probablemente incluiría cosas como:

  • El código tiene pruebas unitarias
  • Prueba de unidad aprobada como parte de una compilación automatizada
  • El código se ha fusionado en main (y los conflictos se han resuelto)
  • etc.

Entonces, esencialmente, lo que está sucediendo es que su equipo está marcando cosas que de hecho no se han hecho. Eso es un problema en sí mismo.

Aparte de eso, se reduce a la gestión adecuada del control de versiones. Si está utilizando Git, todo el trabajo se realiza en el repositorio local del desarrollador y no deberían empujar nada al control remoto a menos que esté "hecho" y sea potencialmente liberable. El trabajo incompleto nunca debe ser empujado a su repositorio principal. Si el desarrollador necesita trabajar en una rama de características más longeva y quiere pasar al control remoto para asegurarse de que no pierdan su trabajo, entonces debería estar trabajando en una bifurcación, y luego fusionaría esa bifurcación en main cuando el la función está "terminada" y es potencialmente liberable, no antes.

Para TFVC, es un poco más complicado porque todo sucede en "remoto". Eso significa que, por lo tanto, los desarrolladores siempre deberían estar trabajando fuera de las ramas, a menos que sea una solución rápida. Sin embargo, las mismas reglas se aplican aquí que con Git: el software incompleto no se compromete. Período. En el control de versión administrado adecuadamente, "main" siempre debe ser liberable. Si se ha realizado una confirmación que borks "main", entonces no lo estás haciendo bien.

Chris Pratt
fuente