version-control refactoring branch feature-branch

version control - ¿Es compatible usar “ramas de características” con la refactorización?



version-control refactoring (4)

Ramas de características es cuando cada característica se desarrolla en su propia rama y solo se fusiona con la línea principal cuando se ha probado y está lista para ser enviada. Esto permite al propietario del producto elegir las características que se incluyen en un envío dado y la característica de "estacionamiento" que están escritas en parte si se recibe un trabajo más importante (por ejemplo, un cliente llama al MD para quejarse).

La " refactorización " está transformando el código para mejorar su diseño a fin de reducir el costo del cambio. Sin hacer esto continuamente, tiendes a obtener bases de código más feas, por lo que es más difícil escribir pruebas.

En la vida real, siempre hay clientes que han vendido nuevas funciones y, debido a la política, todos los clientes tienen que ver que se está avanzando en "su" grupo de características. Por lo tanto, es muy raro que haya un momento sin muchas funciones a medio terminar en las ramas.

Si se ha realizado alguna refactorización, la fusión en las "ramas de características" se vuelve mucho más difícil, si no imposible.

¿Tenemos que renunciar a poder hacer refactorización?

Consulte también " ¿Cómo maneja la tensión entre la refactorización y la necesidad de fusionarse ?"


Las ramas de las características ciertamente hacen que la refactorización sea mucho más difícil. También hacen que las cosas como la integración y la implementación continuas sean más difíciles, ya que se está incrementando la cantidad de flujos de desarrollo paralelos que se deben construir y probar. También está obviando el principio central de la "integración continua": que todos están trabajando en la misma base de código e integrando "continuamente" sus cambios con el resto de los cambios del equipo. Normalmente, cuando las ramas de características están en uso, la rama de características no se construye o prueba continuamente, por lo que la primera vez que el código de "rama de características" se ejecuta en el proceso de creación / prueba / implementación de producción es cuando se "hace" y se combina en el maletero Esto puede introducir una gran cantidad de problemas en una etapa tardía y crítica de su proceso de desarrollo.

Sostengo la opinión controvertida de que debe evitar las sucursales de funciones a (casi) todos los costos . El costo de la fusión es muy alto, y (quizás más importante) el costo de oportunidad de no "integrarse continuamente" en una base de código compartido es aún mayor.

En su escenario, ¿está seguro de que necesita una rama de características separada para las características de cada cliente? ¿Podría en su lugar desarrollar esas características en el troncal pero dejarlas deshabilitadas hasta que estén listas? Por lo general, creo que es mejor desarrollar "características" de esta manera: insértelas en el troncal incluso si no están listas para la producción, pero déjelas fuera de la aplicación hasta que estén listas. Esta práctica también lo alienta a mantener sus componentes bien protegidos y protegidos detrás de interfaces bien diseñadas. El enfoque de "rama de características" le da la excusa para realizar cambios radicales en la base del código para implementar la nueva característica.


Me gusta esta tesis provocadora (''renunciar a la refactorización''), porque enriquece la discusión :)

Estoy de acuerdo en que hay que tener mucho cuidado con una refactorización más grande cuando se tienen muchas líneas de código paralelas, ya que los conflictos pueden aumentar mucho el trabajo de integración e incluso provocar la introducción de errores de regresión durante la fusión.

Debido a esto con el problema de la refactorización frente a las características, hay muchas compensaciones. Por eso decido caso por caso:

  • En las ramas de características solo hago refactorizaciones si preparan mi característica para que sea más fácil de implementar. Siempre trato de centrarme solo en la característica. Las ramas deben diferir del tronco / línea principal al menos como sea posible.
  • Tomando el revés, a veces incluso tengo ramas de refactorización, donde hago refactorizaciones más grandes (revertir varios pasos es muy fácil y no distraigo a mis colegas de tronco). Por supuesto, le diré a mi equipo, que estoy haciendo esta refactorización e intentaré planear hacerlo durante un ciclo de desarrollo de limpieza (llámelo sprint si lo desea).
  • Si su política mencionada es una gran cosa, entonces resumiría los esfuerzos de refactorización internamente y los agregaría a la estimación. En mi opinión, los clientes a medio plazo verán un progreso más rápido cuando tengan una mejor calidad de código. Lo más probable es que no entiendan la refactorización (lo cual tiene sentido, porque esto está fuera de su alcance ...), así que les oculto esto
  • Lo que nunca haría es refactorizar una rama de lanzamiento, cuyo objetivo es la estabilidad. Sólo se permiten correcciones de errores allí.

Como resumen planearía mis refactorizaciones dependiendo de la línea de código:

  • característica-rama: solo las más pequeñas (si "ayudan" a mi característica)
  • rama de refactorización: para las más grandes, donde el objetivo de refactorización no está completamente claro (a menudo las llamo "refactorizaciones de garabatos")
  • troncal / línea principal: está bien, pero tengo que comunicarme con los desarrolladores en las sucursales de características para no crear una pesadilla de integración.
  • rama de lanzamiento: nunca jamás

Parte del problema es que la mayoría de las herramientas de combinación son demasiado estúpidas para entender cualquier refactorización. Un simple cambio de nombre de un método debe combinarse como un cambio de nombre del método, no como una edición de 101 líneas de código. Por lo tanto, por ejemplo, las llamadas adicionales al método en otra rama se deben atender automáticamente.

Ahora hay algunas mejores herramientas de fusión (por ejemplo, SemanticMerge ) que se basan en el análisis de idioma, diseñadas para tratar con el código que se ha movido y modificado. JetBrains (la creación de ReShaper) acaba de publicar un blog sobre esto.

A lo largo de los años ha habido mucha research sobre esto, por fin algunos productos están llegando al mercado.


Refactorización y fusión son los dos temas combinados en los que se centra Plastic SCM . De hecho, hay dos áreas importantes para enfocar: una es tratar (durante la fusión) con los archivos que se han codicesoftware.blogspot.com/2010/08/… . La buena noticia aquí es que todos los SCM "new age" te permitirán hacerlo correctamente (Plastic, Git, Hg) mientras que los antiguos simplemente fallan (SVN, Perforce e incluso los más antiguos).

La otra parte es tratar con código refactorizado dentro del mismo archivo: ya sabes, mueves tu código y otro desarrollador lo modifica en paralelo. Es un problema más difícil, pero también nos centramos en él con el nuevo conjunto de herramientas de combinación / diferencia. Encuentra la información de xdiff aquí y la de xmerge (fusión cruzada) here . Una buena discusión sobre cómo encontrar el código movido aquí (comparado con "más allá de la comparación").

Si bien la "fusión de directorios" o el problema de fusión de estructuras es un problema central (ya sea que el sistema lo haga o no), el segundo es más un problema de herramientas (qué tan buenas son sus herramientas de combinación y diferencia de tres vías). Puedes tener Git y Hg gratis para resolver el primer problema (e incluso Plastic SCM ahora también es gratis).