Actualmente tenemos una rama maestra para nuestra aplicación PHP en un repositorio compartido. Tenemos más de 500 clientes suscriptores de nuestro software, la mayoría de los cuales tienen personalización para diferentes propósitos, cada uno en una sucursal separada. La personalización podría ser un nombre de campo de texto diferente, una función o módulo totalmente nuevo, o nuevas tablas / columnas en la base de datos.
El desafío al que nos enfrentamos es que a medida que mantenemos estos cientos de sucursales personalizadas y distribuimos a los clientes, de vez en cuando brindamos nuevas funciones y actualizamos nuestra sucursal maestra, y nos gustaría impulsar los cambios de la sucursal maestra a las sucursales personalizadas para actualizar ellos a la última versión.
Desafortunadamente, esto a menudo resulta en muchos conflictos en el código personalizado, y pasamos muchas horas revisando cada rama para resolver todos los conflictos. Esto es muy ineficiente, y hemos descubierto que los errores no son infrecuentes al resolver estos conflictos.
Estoy buscando una manera más eficiente de mantener nuestras sucursales de lanzamiento de clientes actualizadas con la sucursal maestra, lo que resultará en menos esfuerzo durante la fusión.
fuente
Respuestas:
Estás abusando completamente de las ramas! Debe tener la personalización impulsada por la flexibilidad en su aplicación, no por la flexibilidad en el control de su versión (que, como ha descubierto, no está destinada / diseñada para este tipo de uso).
Por ejemplo, haga que las etiquetas de campo de texto provengan de un archivo de texto, no se codifiquen en su aplicación (así es como funciona la internacionalización). Si algunos clientes tienen características diferentes, haga que su aplicación sea modular , con límites internos estrictos regidos por API estrictas y estables, para que las características se puedan conectar según sea necesario.
La infraestructura central y las características compartidas solo deben almacenarse, mantenerse y probarse una vez .
Deberías haber hecho esto desde el principio. Si ya tiene quinientas variantes de producto (!), Arreglar esto será un gran trabajo ... pero no más que un mantenimiento continuo.
fuente
Tener 500 clientes es un buen problema, si hubiera pasado el tiempo por adelantado para evitar este problema con las sucursales, es posible que nunca haya podido seguir operando durante el tiempo suficiente para obtener clientes.
En primer lugar, espero que cobre a sus clientes lo suficiente como para cubrir TODOS los costos de mantener sus versiones personalizadas. Supongo que los clientes esperan obtener nuevas versiones sin tener que pagar para que sus personalizaciones se realicen nuevamente. Comenzaría por encontrar todos los archivos que son iguales en el 95% de sus sucursales. Ese 95% es la parte estable de su aplicación.
Luego, encuentre todos los archivos que solo tienen unas pocas líneas diferentes entre las ramas; intente introducir un sistema de configuración de modo que se puedan eliminar estas diferencias. Entonces, por ejemplo, en lugar de tener cientos de archivos con etiquetas de campo de texto que son diferentes, tiene 1 archivo de configuración que puede anular cualquier etiqueta de texto. (Esto no tiene que hacerse de una vez, solo configure la etiqueta de un campo de texto la primera vez que un cliente quiera cambiarla).
Luego pase a los problemas más difíciles utilizando el patrón de Estrategia, la inyección de dependencia, etc.
Considere almacenar json en la base de datos en lugar de agregar columnas para los propios campos del cliente; esto puede funcionar para usted si no necesita buscar estos campos con SQL.
Cada vez que verifique un archivo en una rama, DEBE diferenciarlo con main y justificar cada cambio, incluido el espacio en blanco. Muchos cambios no serán necesarios y se pueden eliminar antes del registro. Esto puede deberse a que un desarrollador tenga diferentes configuraciones en su editor para la forma en que se formatea el código.
Su objetivo es pasar primero de 500 sucursales con muchos archivos que son diferentes, a la mayoría de las sucursales que solo tienen unos pocos archivos que son diferentes. Sin dejar de ganar suficiente dinero para vivir.
Es posible que aún tenga 500 sucursales en muchos años, pero si son mucho más fáciles de administrar, entonces ha ganado.
Basado en el comentario de br3w5:
Solo haga lo anterior después de haber obtenido el grano fácil, y siga primero con algunas clases.
fuente
En el futuro, haga las preguntas de la prueba de Joel en su entrevista. Sería más probable que no entrasen en un choque de trenes.
Este es un, ah, cómo diremos ... realmente, muy mal problema tener. La "tasa de interés" de esta deuda técnica será muy, muy alta. Puede que no sea recuperable ...
¿Cuán integrados con el "núcleo" están estos cambios personalizados? ¿Puede convertirlos en su propia biblioteca y tener un solo "núcleo" y que cada cliente específico tenga su propio "complemento"?
¿O son todas estas configuraciones muy menores?
Creo que la solución es una combinación de:
Ninguno de los dos será trivial, ya que si terminó aquí con más de 500 clientes, es probable que no haya hecho una distinción real en esto. Espero que sus cambios al separar esto va a ser una tarea muy lenta.
También sospecho que tendrá problemas importantes para separar y clasificar fácilmente todo el código específico de su cliente.
Si la mayoría de sus cambios son específicamente diferencias de redacción, sugiero leer preguntas como esta sobre la localización del idioma. Ya sea que esté haciendo múltiples idiomas por completo o solo un subconjunto, la solución es la misma. Esto es específicamente PHP y localización.
fuente
Este es uno de los peores antipatrones que puedes usar con cualquier VCS.
El enfoque correcto aquí es convertir el código personalizado en algo impulsado por la configuración, y luego cada cliente puede tener su propia configuración, ya sea codificada en un archivo de configuración, o en una base de datos u otra ubicación. Puede habilitar o deshabilitar funciones completas, personalizar el aspecto de las respuestas, etc.
Esto le permite mantener una rama maestra con su código de producción.
fuente
if(getFeature(FEATURE_X).isEnabled())
todo.El propósito de las sucursales es explorar una posible vía de desarrollo sin arriesgarse a romper la estabilidad de la sucursal principal. Eventualmente deberían fusionarse de nuevo en un momento adecuado, o descartarse si conducen a un callejón sin salida. Lo que tienes no son tanto ramas, sino más bien 500 tenedores del mismo proyecto y tratar de aplicar los conjuntos de cambios vitales a todos ellos es una tarea sísifo.
En cambio, lo que debe hacer es tener su código central en vivo en su propio repositorio, con los puntos de entrada necesarios para modificar el comportamiento a través de la configuración e inyectar el comportamiento según lo permitan las dependencias invertidas .
Las diferentes configuraciones que tiene para los clientes pueden simplemente distinguirse entre sí por un estado configurado externamente (por ejemplo, una base de datos) o, si es necesario, vivir como repositorios separados, que agregan el núcleo como un submódulo.
fuente
Todas las cosas importantes han sido propuestas por buenas respuestas aquí. Me gustaría agregar mis cinco peniques como sugerencia de proceso.
Me gustaría sugerirle que resuelva este problema a largo o mediano plazo y que adopte su política sobre cómo desarrollar el código. Intenta convertirte en un equipo de aprendizaje flexible. Si alguien permitió tener 500 repos en lugar de hacer que el software sea configurable, entonces es hora de preguntarse cómo ha trabajado hasta ahora y lo hará a partir de ahora.
Lo que significa:
Esto de ninguna manera pretende crear una atmósfera de mala presión en su equipo. Prefiero que aclare estos puntos primero y, donde sea que sienta el apoyo, organícelo junto con su equipo. Invita a personas amigables a la mesa para mejorar toda tu experiencia.
Luego, intente establecer una ventana de tiempo a largo plazo, donde cocine esta cosa en una pequeña llama. Sugerencia: intente fusionar al menos dos repositorios cada semana, y elimine al menos uno . Puede aprender que a menudo, puede fusionar más de dos ramas, a medida que adquiere rutina y supervisión. De esa manera, en un año puede manejar las peores (¿las más caras?) Sucursales, y en dos años puede reducir este problema para tener un software claramente mejor. Pero no espere más, ya que al final nadie "tendrá tiempo" para esto, pero usted es quien no lo permitirá más, ya que es el arquitecto del software.
Así es como trataría de manejarlo si estuviera en tu posición. Sin embargo, no sé cómo su equipo va a aceptar tales cosas, cómo el software realmente lo permite, cómo se le brinda soporte y qué es lo que aún tiene que aprender. Usted es el arquitecto de software, simplemente hágalo :-)
fuente
En contraste con todos los que no lo dicen, asumamos una necesidad comercial real.
(por ejemplo, entregable es el código fuente, los clientes son de la misma línea de negocios y, por lo tanto, competidores entre sí, y su modelo de negocio promete mantener sus secretos en secreto)
Además, supongamos que su empresa tiene las herramientas para mantener todas las sucursales, es decir, mano de obra (digamos 100 desarrolladores dedicados a la fusión, suponiendo un retraso de lanzamiento de 5 días; o 10 desarrolladores suponiendo que el retraso de lanzamiento de 50 días está bien), o tal prueba impresionante automatizado que se funde automatizados están verdaderamente a prueba tanto a las especificaciones del núcleo y la especificación de extensión en cada rama, y por lo tanto sólo los cambios que no se funden "limpiamente" requieren la intervención humana. Si sus clientes pagan no solo por las personalizaciones sino también por el mantenimiento de las mismas, este puede ser un modelo comercial válido.
Mi pregunta (y negativa) es: ¿tiene una persona dedicada responsable de la entrega a cada cliente? Si usted es, digamos, una compañía de 10,000 personas, puede ser el caso.
Esto podría ser manejado por la arquitectura de complementos en algunos casos, digamos que su núcleo es troncal, los complementos podrían mantenerse en troncal o ramas, y la configuración para cada cliente es un archivo con un nombre único o se mantiene en la rama del cliente.
Los complementos pueden cargarse en tiempo de ejecución o incorporarse en tiempo de compilación.
Realmente muchos proyectos se hacen así, fundamentalmente el mismo problema aún se aplica: los cambios básicos simples son triviales para integrar, los cambios de conflicto deben revertirse o se necesitan cambios para muchos complementos.
Hay casos en que los complementos no son lo suficientemente buenos, es decir, cuando se deben ajustar tantas partes internas del núcleo que el recuento de la interfaz del complemento se vuelve demasiado grande para manejar.
Idealmente, esto se manejaría mediante programación orientada a aspectos , donde el enlace troncal es el código central y las ramas son aspectos (es decir, código adicional e instrucciones sobre cómo conectar los extras al núcleo)
Un ejemplo simple, puede especificar que la costumbre
foo
se ejecute antes o después del núcleoklass.foo
o que la reemplace, o que la envuelva y pueda cambiar la entrada o la salida.Hay un montón de bibliotecas para eso, sin embargo, el problema de los conflictos de fusión no desaparece: AOP maneja las fusiones limpias y los conflictos aún necesitan la intervención humana.
Finalmente, este negocio realmente tiene que preocuparse por el mantenimiento de la sucursal , a saber, ¿la característica X específica del cliente es tan común que es más barato moverla al núcleo, a pesar de que no todos los clientes pagan por ella?
fuente
No está resolviendo la causa raíz de la enfermedad al observar el síntoma. El uso de un enfoque de 'gestión de código' es sintomático, pero no resolverá las cosas a largo plazo. La causa raíz es la falta de capacidades, características y sus extensiones y variaciones de producto 'bien administradas'.
Su código 'personalizado' no representa más que extensiones de las características y capacidades del producto y cambios en el campo de datos en otros.
Cuán extensas serán las características personalizadas, qué tan diferentes, qué contextualmente similares o no jugarán mucho en la "desinfección" de la base de código de su producto.
Más allá de cómo codifica y versiona, este es un lugar donde la gestión del producto, la arquitectura del producto y la arquitectura de datos entran en juego. Seriamente.
Porque, al final del día, el código no es más que su oferta de negocios y características / servicios de productos a sus clientes. Eso es lo que le pagan a su empresa.
Obtener un mejor manejo de esto debe provenir del punto de vista de 'capacidades' y no del punto de vista del código.
Usted, su empresa y su producto no pueden ser todo para todos. Ahora que tiene una base de ingresos decente de 500 clientes, es hora de productivizar en lo que pretende ser.
Y si ofrece varias cosas, tendría sentido modularizar las capacidades de su producto de manera organizada.
¿Qué tan amplios y profundos serán sus productos? O bien, esto conducirá a problemas de 'calidad de servicio' y 'dilución y fragmentación del producto' a medida que avance la línea.
¿ Serás un CRM o ERP o procesamiento / despacho de pedidos o Microsoft Excel?
Sus extensiones existentes deben acumularse y armonizarse, de la misma manera que un gran software atrae y fusiona productos adquiridos de una startup.
Necesitará contar con una sólida persona de administración de productos y arquitectura de datos que asigne lo siguiente:
..para crear una hoja de ruta de asimilación y armonización de todos estos hilos / ramas de productos sueltos en el gran contexto de su aplicación principal.
PD: Conéctate conmigo, conozco a una persona que puede ayudarte a solucionar esto :)
fuente
Me identifico con esto. He tomado muchos proyectos. De hecho, el 90% de nuestro trabajo de desarrollo está arreglando tales cosas. No todos son perfectos, por lo que te sugiero que uses el control de versiones de la manera correcta y dónde estás, si es posible, puedes hacer lo siguiente.
Personalmente importé un repositorio de GitHub con 40 sucursales a Bitbucket y creé 40 repositorios. Solo tomó cuatro horas. Estas fueron las variaciones del tema de WordPress , así que empujar y tirar fue rápido.
Hay muchas razones para "no hacerlo bien la primera vez", y creo que aquellos que las aceptan rápidamente y continúan con "hacerlo bien esta vez" siempre tendrán éxito.
fuente