Una forma sencilla de mejorar la calidad de la versión en el entorno RAD

15

Un poco de antecedentes aquí: somos un pequeño equipo (de 5) de desarrolladores de RAD responsables del desarrollo de software interno en una gran empresa que no es de software. El "software interno" varía desde una aplicación .NET de escritorio que utiliza un servidor MSSQL como back-end para scripts de Python que se ejecutan en segundo plano para documentos y plantillas de MS Word, un zoológico de tecnologías.

Todo el equipo está formado por todos los agentes capaces de obtener los requisitos de los usuarios, codificarlos, probarlos e implementarlos en producción. Una vez que el software en la producción está siendo atendido por otro equipo, pero generalmente es fácil para nosotros intervenir si algo sale mal.

Todo suena bien hasta ahora, pero hay un problema: al ser un equipo RAD, tenemos que lanzar a menudo, y no hay día sin que lancemos nuevas versiones de una o dos aplicaciones (o podría ser un script, un documento de Word actualizado , Aplicación de consola C ++, etc.) en la producción. Hacemos una prueba de desarrollo y también involucramos a los usuarios finales al permitirles ejecutar el software en el entorno UAT ...

... pero de todos modos los errores están llegando a la producción. Los usuarios entienden que estos errores y la inestabilidad ocasional es el precio que están pagando por obtener lo que quieren realmente rápidamente, pero al mismo tiempo nos hizo pensar: tal vez podríamos mejorar nuestro desarrollo o las prácticas de lanzamiento para mejorar la estabilidad del software y reducir la cantidad de errores que presentamos al agregar una nueva funcionalidad.

Lo bueno: realmente no tenemos muchos de los procesos en primer lugar, por lo que debería ser fácil comenzar a mejorar, lo malo: al ser un pequeño equipo de RAD, realmente no tenemos mucho tiempo y recursos para implementar algo grande, pero hemos estado pensando en las siguientes iniciativas y agradeceríamos cualquier comentario, sugerencia, sugerencia o sugerencia.

  1. Actualmente, algunas de las aplicaciones se lanzan a la producción inmediatamente después de la prueba del desarrollador, pasando por alto la prueba de aceptación del usuario. Esa práctica debe suspenderse e incluso un pequeño cambio debe ser probado por un usuario final. Cada aplicación tendrá un beta-tester dedicado seleccionado entre los usuarios finales. Solo después de que un beta-tester haya aprobado la nueva versión, se promociona del entorno de prueba al entorno de producción.

  2. No realizamos revisiones de código, pero comenzaremos a hacer revisiones de código antes de que uno de nosotros registre el conjunto de cambios. También estaba pensando en una "revisión de implementación": básicamente, uno de los desarrolladores tiene que sentarse junto con el otro y ver cómo realiza la implementación del software (copiar binarios, actualizar configuraciones, agregar una nueva tabla a la base de datos, etc.), generalmente solo toma de 5 a 10 minutos, por lo que no tomará mucho tiempo de "revisión de implementación".

  3. Cómo minimizar el tiempo de reversión cuando se demuestra que una nueva versión tiene errores suficientes para retirarse de la producción y ser reemplazada por una buena versión anterior. Almacenamos un historial de todos los lanzamientos (como archivos binarios) para facilitar el regreso de una versión, y aunque es rápido "sobrescribir los archivos binarios recién lanzados con los archivos binarios de versiones anteriores", sigue siendo un proceso manual que es propenso a errores y exigiendo a veces "qué pasa si la reversión fallará y hará que el sistema sea inutilizable en lugar de tener errores".

Aquí es donde nos quedamos sin nuestras ideas y nos gustaría recibir sus comentarios sobre estas y si pudiera compartir algunos consejos simples de mejora del proceso de lanzamiento / desarrollo, sería increíble.

PeterT
fuente
Las pruebas unitarias automatizadas y el CI parecen ser el tipo de cosa que necesita.
Raynos

Respuestas:

14

+1 por tocar un gran tema. Cuando realizamos la línea de desarrollo "Lanzamiento temprano a menudo", las cosas se aceleran y, a medida que aumenta el impulso, surgen muchos problemas (como usted describió) que, de lo contrario, no estamos muy preparados para enfrentar. El peor temor es cuando la gente ve la velocidad como un enemigo del buen trabajo.

Sin embargo, he visto literatura muy limitada sobre esto, esto es lo que practicamos que definitivamente ayuda:

1. Seguimiento eficaz de
errores Haga que el seguimiento de errores sea más eficaz: lo que hacemos no solo es mantener una lista de errores y marcas de verificación, sino que, cuando se cierra, debemos definir ciertas cosas como "¿los problemas eran reproducibles?", "¿Es esta una solución permanente? o solución de trabajo? "," ¿cuál es la causa raíz "de los problemas? Esto permite saber qué sucedió cuando este error fue visible la última vez. Esta es la clave para garantizar que los errores no se repitan con frecuencia.

2. Definir puntos clave de retroceso
Todos sabemos que llegarán errores, por lo que tendremos que proporcionar un retroceso efectivo que funcione con mayor frecuencia. Una y otra vez finalizamos (con una proporción de aproximadamente 1 de cada 10 en nuestro caso) una versión más común que funciona en todas partes de la manera más confiable. El número total de lanzamientos puede ser muchos, pero si algo sale mal, los retrocesos son pocos y no tiene que retroceder más. Una de las formas más sencillas de conocer la mejor alternativa es ver qué versión más antigua ha estado funcionando más tiempo en producción sin muchos problemas.

3. Distinga las versiones riesgosas y estables o pequeñas de correcciones de errores
Cuando sabemos que tenemos cambios importantes en el algoritmo, es más probable que los errores puedan aparecer en escenarios que no están previstos. Donde, ya que hay momentos en que los problemas son muy pequeños (o bien entendidos), así como poco riesgo. Hacer NO club de dicha funcionalidad y los errores simples en los comunicados mismos. Siempre arregle primero un error más pequeño, que debe ir donde sea necesario. Realice lanzamientos dedicados para conjuntos de características especiales, en el mejor de los casos puede desaprobar esa característica, pero todos los demás errores importantes aún están disponibles reparados en versiones anteriores.

4. Ramificación para el desarrollo de características significativas
Cualquier cosa que asocie cambios que tenga efecto de diseño debe hacerse por separado en una rama. El desarrollo más grande no se completa rápidamente en comparación con los errores más pequeños. Si introducimos confirmaciones intermedias donde el trabajo 'parcial' relacionado con la característica que aún no está en uso es una posible región de introducción de errores; los errores que no habrían surgido si el trabajo completo de la característica se hubiera completado atómicamente, por lo tanto, estos son errores que no tendríamos que resolver si hubiera ramas.

5. Planifique siempre las versiones basadas en temas
Muchas veces, muchos errores diferentes llegan de versiones diferentes, pero es mejor organizar errores (y características) que afectan a módulos similares, facilita el trabajo repetido y minimiza la cantidad de errores originados por ese trabajo. Siempre prepare la hoja de ruta de lanzamiento con mucha anticipación; los errores siguen apareciendo, y eso se divide en diferentes lanzamientos de destino para tener de manera óptima un buen grupo de errores que se pueden disparar juntos en un buen lanzamiento. Cuando se combinan errores similares, siempre da una mejor idea sobre los escenarios contradictorios.

6. Extienda cualquier lanzamiento nuevo primero a unos pocos clientes.
En nuestro caso, vemos probarlo en un par de sitios primero y todos los otros sitios aplican un lanzamiento solo cuando hay una demanda. Muchas veces, algunos (o la mayoría) de los usuarios saltan solo de una versión estable a otras versiones estables solamente.

7. Pruebas de regresión
A lo largo de las líneas de errores que se están recolectando, cree un traje de regresión. Además, si es posible, marque los errores críticos y haga que la prueba sea más importante y se convierta en un criterio de calificación mínimo para ser probado antes de que un candidato de liberación se convierta en una liberación.

8. Pausa y reflexiona
Cuando muchas cosas van a toda velocidad, debería haber tiempo para hacer algunos descansos: toma una pausa y obtén liberaciones que funcionalmente no sean mejores. De hecho tienen vacaciones de lanzamientos por algún tiempo. (La duración es inversamente proporcional a la frecuencia). Por ejemplo, muchas veces tenemos estas llamadas versiones de "limpieza" que no logran nada nuevo desde el punto de vista de la funcionalidad, pero eso ayuda mucho a mantener el código mantenible. La mayoría de estos lanzamientos son excelentes puntos de retroceso que casi nunca recuerdas la historia anterior a eso.

9. Quizás lo más extraño es
que este es difícil de implementar a menudo, pero es un buen truco. Cambiar el propietario de ciertos módulos. Cuando a las personas se les pide que realicen revisiones de código, no se obtiene mucho de esta práctica. Pero cuando tiene que lidiar seriamente con ese nuevo código, cuando intercambia autores, las dolencias "malas" potenciales se notan rápidamente mucho antes de que comiencen a contaminar el código. Por supuesto, esto reduce la velocidad, pero si lo hace con frecuencia, es probable que las personas dominen varias partes del código y aprendan sobre el producto completo, que de otra manera es muy difícil de enseñar.

10. Por último, pero no menos importante,
aprenda a volver a la pizarra con frecuencia. Cuanto más vuelva a pensar como si esta característica hubiera sido parte de nuestro diseño más inicial, ¿cómo habríamos pensado en el diseño en ese momento? A veces, el mayor desafío con el trabajo incremental es simplemente que estamos demasiado constreñidos por el orden de funcionalidad que construimos primero y con bastante frecuencia no podemos volver a lo básico. El truco es seguir viendo cómo generalizaríamos en lugar de acomodar esta nueva característica o escenario. Esto requiere que el diseño permanezca actualizado, y eso sucede solo si volvemos a ir a la mesa de dibujo a menudo. Además, a medida que los programadores de nueva generación se unen, se convierten en parte del grupo de reflexión en lugar de simplemente poner parches.

EDITAR
11. Realizar un seguimiento de las lagunas de trabajo y diseño.
Muy a menudo estamos bajo presión de plazos para corregir el error y liberarlo en producción. Sin embargo, cuando el error está en el nivel de diseño, es necesario que cambien algunas cosas, pero a menudo la gente lo solucionará con algunos atajos para cumplir con la fecha límite. Esto esta bien . Sin embargo, a medida que aumentan varias soluciones alternativas, el código se vuelve frágil. Mantenga una pista especial sobre cuántos espacios de diseño ya se han eliminado. Por lo general, cuando negocia los plazos con el gerente del proyecto, es mejor hacer que se comprometa a que lo entreguemos en un atajo para ahorrar producción, pero también tendremos línea de tiempo y recursos para obtener una solución permanente.

Dipan Mehta
fuente
1
Prestigio. Esta respuesta es mucho mejor que la mayoría de los tutoriales en línea
Ubermensch
Estas son algunas herramientas muy útiles e importantes para ayudar a los equipos "resistentes a la agilidad" a aprender a ser ágiles sin necesariamente comprometerse todo de una vez a cambiar la metodología establecida. Su noveno punto ofrece efectivamente una oportunidad para revisar el código, sin necesidad de un proceso de revisión formal o cambiar a programación de pares, pero requiere una mentalidad sin culpas ni orgullo para evitar el desarrollo de fricciones innecesarias. Sin embargo, al bifurcar, sugiero minimizar esto a una sola rama con el objetivo de volver a la línea principal lo antes posible ...
S.Robins
@DipanMehta La pregunta parecía ser de un recién llegado y justificaba una respuesta que podría darle una perspectiva amplia para construir sobre las cosas existentes a pesar de ser demasiado específica y su respuesta es realmente cercana.
Ubermensch
1
... como administrar múltiples sucursales puede ser muy problemático de administrar a medida que pasa el tiempo, por lo que querrá mantener sus cambios ramificados pequeños y adecuados para resolver un problema específico, fusionar, volver a ramificar, etc. Un buen sistema de control de versiones con soporte para espacios de trabajo y que diferencia entre una "promoción" versionada y una "conservación" no versionada puede ayudar a evitar la ramificación por completo. Sin embargo, en mi humilde opinión, es mejor acertar con el proceso y luego encontrar herramientas que se ajusten, en lugar de unir los procesos con las herramientas.
S.Robins
+1 para "es mejor acertar con el proceso y luego encontrar herramientas que se ajusten, en lugar de unir los procesos con las herramientas"
Ubermensch
4

También trabajo en un pequeño equipo de desarrollo (solo 2 de nosotros) y experimentamos problemas similares que usted ha mencionado. El problema principal para nosotros es que ambos tendemos a trabajar en tareas separadas y se estaba volviendo demasiado común para nosotros completar una tarea / función, probarla (probada solo por el desarrollador) y lanzarla rápidamente. Esto resultó en una gran cantidad de lanzamientos pequeños con usuarios que informaron pequeños errores que deberían haberse detectado fácilmente en las pruebas.

Para mejorar nuestro proceso, comencé introduciendo un tablero Kanban . Para empezar, el tablero era muy simple y solo tenía unas pocas columnas (configuración usando una pizarra, fichas e imanes de colores):

Backlog | Hacer | Hecho

Sin embargo, esto evolucionó rápidamente para reflejar nuestro proceso real:

Backlog | Desarrollo | Dev. Prueba | UAT | Hecho | Liberado

Junto con el tablero, tenemos la regla de que cada tarea / función debe ser probada por otro desarrollador (así como por el desarrollador que implementó la función). Entonces, cuando la tarjeta llegue a la columna 'Listo', debería haber sido probada por al menos 2 desarrolladores y también la Prueba de aceptación del usuario.

Hay muchos otros beneficios al usar Kanban. Para nosotros, ha mejorado la comunicación y nos ha ayudado a compartir conocimientos, ya que ambos estamos involucrados hasta cierto punto en cada tarea. También ha mejorado nuestro proceso de lanzamiento, ya que ahora podemos ver exactamente qué tareas / características están listas para lanzar / realizar y, a veces, puede retrasar el lanzamiento si sabemos que otras tareas se realizarán pronto. Para las personas fuera del equipo, la junta también actúa como una referencia rápida para ver qué tareas hemos programado, el trabajo actual en progreso y lo que se lanzó recientemente.

Por otro lado, usamos imanes de colores (uno por desarrollador) para marcar la tarjeta en la que estamos trabajando actualmente, pero otra opción es agregar carriles de natación (filas), uno por desarrollador y colocar las tarjetas Kanban en los carriles de natación relevantes. Nuevamente, esto ayuda como una referencia rápida para ver en qué está trabajando actualmente cada desarrollador.

Otros enlaces que encontré útiles:

Kanban aplicado al desarrollo de software: de ágil a delgado

Un sistema Kanban para ingeniería de software - Video

Esperemos que Kanban aborde el punto 1. en su pregunta. En relación con las revisiones de código, hacemos esto en la etapa de prueba de desarrollo para que cualquier cambio requerido después de la revisión se vuelva a probar antes de ir a UAT. La reversión depende de su entorno, pero implementamos archivos de aplicación en los servidores de Terminal Server utilizando archivos por lotes que cambian el nombre de los archivos actuales y copian los archivos nuevos desde un servidor central y podemos retroceder con bastante facilidad colocando la copia de seguridad (archivos anteriores) en la ubicación central y volver a ejecutar scripts.

Matt F
fuente
4

Ya ha identificado que sabe que hay problemas con sus procesos que afectan la calidad de su software, y si bien esta pregunta provocará una variedad de respuestas, mi sugerencia sería mirar el tema de la ingeniería de software e intentar aprender qué Los desarrolladores en general se encuentran haciendo más y más en esa área. Le sugiero que comience a leer algunos buenos recursos para comenzar. Algunos que vienen a la mente:

  • Lean Software Development de Mary y Tom Poppendeick ofrece una excelente lectura para las personas interesadas en aprender a identificar "desperdicios" y qué hacer para cambiar los procesos para ser más ágiles y más eficientes.
  • Head First Software Development de Dan Pilone y Russ Miles es un poco como uno de esos libros "para tontos" a primera vista, pero al mirar un poco más allá del estilo de presentación caótica, contiene la mayor parte de la información relacionada con los conceptos básicos de ingeniería de software y tiene una breve reseña sobre Test Driven Development.
  • Presentar BDD es la página de Dan North sobre cómo entrar en el desarrollo impulsado por el comportamiento, o tal vez prefiera un Wiki de BDD . Estas son referencias iniciales para BDD y probablemente querrá buscar herramientas y marcos para ayudarlo. Lo importante a entender es que BDD es efectivamente TDD llevado a un nivel conceptual más alto. Le permite pensar en las pruebas como está pensando en las especificaciones, y probar en el mismo idioma que usa cuando escribe especificaciones. Los marcos generalmente se integran con otros marcos de pruebas unitarias, por lo que obtiene lo mejor de ambos mundos si decide que sus pruebas no necesariamente se beneficiarán de la sintaxis de BDD.
  • El artículo de desarrollo de software ágil de Wikipedia es una buena introducción sobre el desarrollo de software ágil, y proporciona una serie de referencias útiles y enlaces a artículos de algunas de las personas más respetadas de la comunidad de desarrollo.

Para mejorar la forma en que trabaja, debe permitirse ser completamente de mente abierta y estar dispuesto a salir de su zona de confort para aprender a mejorar las cosas que hace sin aferrarse a ciertos conceptos que puede encontrar son más cómodo para aferrarse. Hablando por experiencia personal, esto es probablemente lo más difícil de hacer o alentar a otros.

El cambio es difícil en el mejor de los casos, incluso si sientes que estás buscando activamente un cambio, por lo que el mejor consejo que realmente puedo darte es mirar las diversas metodologías ágiles que se han desarrollado a lo largo de los años para familiarizarte con las prácticas. que se consideran más importantes (p. ej., pruebas unitarias, integración continua, refactorización, etc.), y luego elija la metodología que parezca más cercana a lo que usted y su equipo se sentirán más cómodos. Una vez que haya tomado su decisión, ajuste las prácticas y su proceso de desarrollo para que se adapte a la forma en que su equipo preferiría trabajar, teniendo en cuenta esos principios lean y cómo desea trabajar para que su equipo pueda producir el mayor valor con el menos desperdicio. Finalmente,

Si cree que sus procesos simplemente necesitan ajustes, pero le preocupa que su cadena de herramientas no se ajuste a sus necesidades, entonces quizás busque mejoras allí. Como mínimo, un producto de integración de integración continua (como Continuum, Cruise Control o Hudson) y un sistema de seguimiento de problemas (como Jira o Redmine) deben ser una prioridad para ayudarlo a automatizar algunos de sus procesos de compilación y lanzamiento, y para mantener sus errores y solicitudes de funciones bajo control.

La realidad es que no importa cuán RAD sean sus procesos, si no invierte tiempo para hacer las cosas "correctas" para su equipo, sus problemas solo seguirán creciendo con el tiempo, y su percepción del tiempo disponible aumentará. reducir en consecuencia. Los grandes cambios generalmente están fuera de discusión cuando se encuentra bajo una fuerte presión de tiempo, pero trate de darse un pequeño "margen de maniobra" para establecer sistemas que lo ayuden a dar pequeños pasos hacia la visión de su equipo de una metodología ideal.

S.Robins
fuente
Me refería a nuestro equipo como equipo de desarrolladores "RAD" para enfatizar el hecho de que estamos en el negocio del "Desarrollo rápido de aplicaciones", donde los ciclos de desarrollo son extremadamente cortos. Por lo tanto, no tiene nada que ver con las herramientas RAD o IDE. Gracias por su respuesta.
PeterT
@PeterT: ¡Ah! Mis disculpas por el malentendido. Debo haber leído tu tercer párrafo y haber perdido el contexto. Editaré mi respuesta para adaptarla, sin embargo, el consejo en general sigue en contexto. :-)
S.Robins
2

Cada vez que escucho sobre defectos, mis primeras preguntas son sobre dónde se originan los defectos y dónde se detectan y eliminan. La eficiencia de eliminación de defectos es una buena forma de medir y rastrear esto. Al saber dónde se originan los defectos y trabajar para mejorar los procesos en esas fases, puede reducir el tiempo y el costo de un proyecto. Es bien sabido que es más barato reparar los defectos más cerca de su punto de inyección, por lo que una vez que sepa de dónde provienen los defectos, puede ver los cambios en las actividades para mejorar esas fases.

Una vez que tenga información sobre el origen de los defectos, puede ver exactamente qué técnicas y tecnologías desea aplicar. Las revisiones de los requisitos, el diseño y el código, las pruebas automatizadas, el análisis estático, la integración continua y las pruebas más exhaustivas impulsadas por el usuario pueden ser opciones que debe considerar, dependiendo de qué fases generan defectos.

Para ampliar su deseo de revisiones de código, también debe considerar diferentes niveles de revisiones de código en función de la prioridad y el riesgo de un módulo. Es posible que los módulos de bajo riesgo y baja prioridad no necesiten una revisión del código, o tal vez solo una simple verificación de escritorio, donde otro desarrollador solo lea el código por su cuenta y proporcione comentarios, funcionaría. Otras técnicas de revisión de código incluyen programación de pares, tutoriales, críticas e inspecciones con varios números de desarrolladores.

A los efectos de retroceder, trataría de automatizar ese proceso utilizando algún tipo de scripts para hacerlo más rápido y menos propenso a errores. En un mundo perfecto, me gustaría aumentar la calidad de los productos enviados de modo que no sea necesario retroceder, y puede lograrlo. Sin embargo, tener la capacidad podría ser una buena idea, pero que sea lo menos doloroso posible.

Thomas Owens
fuente
1

Como otros han señalado, agregar pruebas de regresión ayudará a evitar los mismos defectos que aparezcan en el futuro. Sin embargo, si encuentra nuevos defectos, puede ser el momento de agregar aserciones (también conocidas como contratos) al código que especifique las condiciones previas, las condiciones posteriores y los invariantes de las clases y métodos.

Por ejemplo, si tiene una clase en la que un método solo puede aceptar números entre 10 y 25 (esto se llama condición previa), agregaría una declaración de afirmación al comienzo del método. Cuando esta afirmación falla, el programa se bloqueará de inmediato y podrá seguir la cadena de métodos que condujeron a esa falla.

Python, PHP y otros lenguajes de programación se escriben dinámicamente y no agregan muchas condiciones a los métodos. Todo lo que se necesita para que algo funcione es que implemente un método particular. Sospecho que necesita más condiciones en sus métodos. Debe definir y probar para asegurarse de que un método realmente pueda funcionar en su entorno.

Para los programas C / C ++, descubrí que agregar aserciones para probar la asignación de memoria fue muy útil para reducir la cantidad de pérdidas de memoria en el programa.

Rudolf Olah
fuente
Bueno, estoy de acuerdo en que la verificación de afirmaciones / post / condiciones previas es una buena práctica de programación, y finalmente dará sus frutos, pero mi pregunta tenía como objetivo mejorar la calidad de los lanzamientos muy frecuentes, no la calidad del código en general.
PeterT
Pagará de inmediato porque tendrá que comenzar agregando afirmaciones / verificación de condición en cada versión para las nuevas características / correcciones de errores. Sería una gran tarea agregar afirmaciones a todo el proyecto de una sola vez; p
Rudolf Olah
Sin embargo, hay una cosa con las afirmaciones: ¿qué pasa si se equivoca? ¿Qué pasaría si pensáramos que el método solo debería aceptar números entre 10 y 25, pero en realidad está bien ampliar el rango a [0; 50] y solo se encontró después de que se lanzó un nuevo lanzamiento y estuvo en producción durante un día. Si un método bajo una pregunta es de bajo nivel y se usa en muchos lugares, no hay mucho que podamos hacer, sino volver a lanzarlo con una solución. Sin embargo, si no hubiéramos añadido la afirmación en el nivel de método a utilizar un bloque try-catch nivel más alto lugar que podría salirse con sólo una parte de la funcionalidad ....
PeterT
... no está disponible para que podamos comprarnos algo de tiempo para hacer un lanzamiento "apropiado" o llamarlo "programado" una semana después. Creo que entiendes mi punto. Gracias por tu comentario.
PeterT