Pregunta

Nuestra política al entregar una nueva versión es crear una sucursal en nuestro VCS y administrarla a nuestro equipo de control de calidad. Cuando este último da luz verde, etiquetamos y lanzamos nuestro producto. La rama se mantiene para recibir (solo) correcciones de errores para que podamos crear versiones técnicas. Esas correcciones de errores se fusionan posteriormente en el tronco.

Durante este tiempo, el tronco ve el trabajo principal de desarrollo y está potencialmente sujeto a cambios de refactorización.

El problema es que hay una tensión entre la necesidad de tener un tronco estable (de modo que la combinación de correcciones de errores tenga éxito, por lo general no puede si el código, por ejemplo, se extrajo a otro método o se transfirió a otro). clase) y la necesidad de refactorizarlo al introducir nuevas características.

La política en nuestro lugar es no realizar ninguna refactorización antes de que haya pasado suficiente tiempo y la rama sea lo suficientemente estable. Cuando este es el caso, uno puede comenzar a hacer cambios de refactorización en el tronco, y las correcciones de errores se deben confirmar manualmente tanto en el tronco como en la rama.

Pero esto significa que los desarrolladores deben esperar bastante tiempo antes de realizar cualquier cambio de refactorización en el tronco, ya que esto podría romper la fusión posterior de la rama al tronco. Y tener que trasladar manualmente los errores de la rama al tronco es doloroso. Me parece que esto dificulta el desarrollo ...

¿Cómo manejas esta tensión?

Gracias.

¿Fue útil?

Solución

Este es un problema práctico real. Empeora si tiene varias versiones que necesita admitir y se ha ramificado para cada una. Peor aún si también tienes una rama de I + D genuina.

Mi preferencia era permitir que el troncal principal procediera a su velocidad normal y no aferrarse porque en un entorno donde los tiempos de lanzamiento eran importantes comercialmente, nunca podría argumentar que deberíamos permitir que el código se estabilice (" qué , quiere decir que lo lanzó en un estado inestable? ").

La clave era asegurarse de que las pruebas unitarias que se crearon para las correcciones de errores se transfirieron cuando el error se migró a la rama principal. Si los cambios en su nuevo código son realmente solo una re-factorización, entonces las pruebas anteriores deberían funcionar igual de bien. Si sus cambios son tales que ya no son válidos, entonces no puede simplemente portar su reparación en cualquier caso y necesitará que alguien piense detenidamente sobre la solución en la nueva secuencia de código.

Después de varios años manejando este tipo de problema, llegué a la conclusión de que probablemente necesite 4 flujos de código como mínimo para proporcionar soporte y cobertura adecuados, y una colección de procesos bastante rigurosos para administrar el código entre ellos. Es un poco como el problema de poder dibujar cualquier mapa en 4 colores.

Nunca encontré ninguna literatura realmente buena sobre este tema. Inevitablemente, estará vinculado a su estrategia de lanzamiento y los acuerdos de nivel de servicio que firme con sus clientes.

Anexo: También debo mencionar que fue necesario escribir la fusión de la rama como hitos específicos en el calendario de lanzamiento de la rama principal. No subestime la cantidad de trabajo que podría implicar unir sus sucursales si tiene una colección de desarrolladores que trabajan arduamente y que hacen su trabajo implementando las características.

Otros consejos

Donde trabajo, creamos ramas de trabajo temporales y de corta duración (menos de un día, unas pocas semanas) para cada cambio no trivial (adición de características o corrección de errores). El tronco es estable y (idealmente) potencialmente liberable todo el tiempo; solo los elementos hechos se fusionan en él. Todo lo comprometido desde el tronco se fusiona en las ramas de trabajo todos los días; Esto puede ser en gran parte automatizado (usamos Hudson, Ant y Subversion). (Este último punto porque, por lo general, es mejor resolver cualquier conflicto más pronto que tarde, por supuesto).

El modelo actual que utilizamos fue influenciado en gran medida por un excelente artículo ( que he conectado antes ) por Henrik Kniberg: Control de versiones para Equipos Agile Múltiples .

(En nuestro caso, tenemos dos equipos scrum trabajando en una base de código, pero he llegado a pensar que este modelo puede ser beneficioso incluso con un equipo).

Hay un poco de sobrecarga sobre la ramificación y fusión adicionales, pero no demasiado, realmente, una vez que te acostumbras y mejoras con las herramientas (por ejemplo, svn merge --reintegrate es útil) . Y no, no creo una rama temporal siempre, por ejemplo, para refactorizaciones más pequeñas y de bajo riesgo (no relacionadas con los elementos principales actualmente en trabajo) que se pueden completar fácilmente con una confirmación al tronco.

También mantenemos una rama de versión anterior en la que se corrigen errores críticos de vez en cuando. Es cierto que puede haber trabajo de fusión manual (a veces tedioso) si alguna parte particular del código ha evolucionado significativamente en el tronco en comparación con la rama. (Con suerte, esto se convierte en un problema menor a medida que avanzamos hacia la liberación continua de incrementos desde el tronco (internamente) y permitiendo que el marketing y la gestión de productos decidan cuándo quieren hacer una versión externa.

No estoy seguro de si esto responde a su pregunta directamente, o si puede aplicar esto en su entorno (con el equipo de control de calidad separado y todos), pero al menos puedo decir que la tensión que describe no existe para nosotros y somos libres de refactorizarnos siempre. Buena suerte!

Creo que la tensión se puede manejar agregando los siguientes ingredientes a su proceso de desarrollo:

  1. Integración continua
  2. Pruebas funcionales automatizadas (supongo que ya cuenta con pruebas unitarias)
  3. Entrega automatizada

Con la integración continua, cada compromiso implica una compilación en la que se ejecutan todas las pruebas de unidad y se alarma si algo sale mal. Empiezas a trabajar más con head y eres menos propenso a ramificar la base del código.

Con las pruebas funcionales automatizadas, puede probar su aplicación con solo hacer clic en el botón. En general, dado que estas pruebas toman más tiempo, se realizan todas las noches. Con esto, el papel clásico de las versiones comienza a perder importancia. Usted no toma la decisión sobre cuándo lanzar según la versión y su vencimiento, es más una decisión comercial. Si ha implementado pruebas de unidad y funcionales y su equipo está enviando el código probado, el jefe siempre debe estar en un estado que pueda ser liberado. Los errores se descubren, se solucionan y se distribuyen continuamente, pero este no es un proceso más cíclico, es el continuo.

Probablemente tengas dos tipos de detractores, ya que esto implica cambiar algunas prácticas arraigadas. Primero, el cambio de paradigma de la entrega continua parece contra-intuitivo para los gerentes. & # 8220; Aren & # 8217; t arriesgamos a enviar un error mayor? & # 8221; Si analiza las distribuciones de Linux o Windows, esto es exactamente lo que están haciendo: impulsar los lanzamientos hacia los clientes. Y dado que cuenta con un conjunto de pruebas automatizadas, los peligros disminuyen aún más.

A continuación, equipo o departamento de control de calidad. (Algunos dirían que el problema es su existencia en sí mismo). En general, serán aversivos a la automatización de las pruebas. Significa aprender una herramienta nueva ya veces complicada. Aquí, lo mejor es predicar haciéndolo. Nuestro equipo de desarrollo comenzó a trabajar en integraciones continuas y al mismo tiempo escribiendo el conjunto de pruebas funcionales con Selenium . Cuando el equipo de control de calidad vio la herramienta en acción, fue difícil oponerse a su implementación.

Finalmente, la conclusión es que el proceso que describí no es tan simple como agregar 3 ingredientes a su proceso de desarrollo. Implica un cambio profundo en la forma de desarrollar software.

Tal vez Git (u otro DVCS) es mejor para manejar las combinaciones con el código actualizado gracias al hecho de que (realmente) administran los cambios en lugar de solo comparar archivos ... Como Joel dice :

  

Con el control de versión distribuido, las combinaciones son fáciles y funcionan bien. Por lo tanto, puede tener una rama estable y una rama de desarrollo, o crear sucursales de larga duración para su equipo de control de calidad donde se evalúan las cosas antes de la implementación, o puede crear sucursales de corta duración para probar nuevas ideas y ver cómo funcionan.

No lo he intentado todavía, aunque ...

Donde trabajo, seguimos con la refactorización en la rama principal. Si las fusiones se vuelven complicadas, solo tienen que ser tratadas de manera ad-hoc, todas son factibles, pero ocasionalmente toman un poco de tiempo.

Tal vez nuestro problema proviene del hecho de que tenemos sucursales que deben tener una vida bastante larga (hasta 18 meses), y hay muchas soluciones que deben hacerse contra ellas.

Asegurarse de que solo nos bifurcamos desde un código extremadamente estable probablemente ayudaría, pero no será tan fácil ... :(

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top