Estrategia para usar el control de versiones en un sistema modular

15

Supongamos (por simplicidad) que tenemos una aplicación con cliente y servidor; ¿Hay una mejor idea para usar un repositorio para ambos o un par de repositorios separados?

Mezclarlos probablemente hará que sea más fácil rastrear los cambios correlacionados y mantener ramas correlacionadas (es decir, la evolución del protocolo), pero por otro lado hará que el desarrollo individual sea más desordenado ...

mbq
fuente
¿Y qué hay de malo en usar ramas separadas? Un desarrollador solo necesita tener la sucursal en la que está trabajando actualmente abierta localmente, por lo que de todos modos ni siquiera verá las cosas que solo están en las otras sucursales. Pero, si necesita ingresar a la sucursal por alguna razón, puede hacerlo.
Spencer Rathbun
@SpencerRathbun: el uso de ramas separadas como esta es una receta para el desastre . Sería realmente difícil compartir archivos entre el servidor y el cliente, especialmente las interfaces y la documentación del sistema, etc. Con un DVCS requeriría que clone todos los compromisos del cliente y el servidor, incluso si solo quisiera uno, y no le daría cualquier pista sobre qué versiones de cliente y servidor funcionarían juntas. En comparación con un repositorio monolítico (único) o un desglose modular (múltiple) del repositorio, en realidad obtienes lo peor de ambos mundos .
Mark Booth
@ MarkBooth Humm, estaba pensando en las secciones del proyecto en cada sucursal, ya que él indicó que compartirán el código. Simplemente etiquete cada sección como las ramas apropiadas, y estará bien. ¿Su DVCS no permite que un archivo / commit tenga múltiples etiquetas?
Spencer Rathbun

Respuestas:

12

Si está utilizando git o mercurial , es posible que desee ver submódulos o subrepositorios .

El cliente, el servidor y sus archivos de interfaz estarían en sus propios repositorios, pero estarían unidos en el nivel del superrepositorio . Esto le permitiría hacer un pago en el nivel superior gito hgverificar el compromiso apropiado de cada uno de los submódulos / subrepositorios.

Al comprometerse solo con el súper repositorio cuando el cliente y el servidor eran apropiados entre sí, el súper repositorio solo le daría la opción de verificar un sistema en funcionamiento, por lo que nunca intentaría ejecutar el nuevo cliente contra un viejo servidor o viceversa.

Los submódulos / subrepositorios le brindan todas las ventajas de usar repositorios separados, junto con las ventajas de un único repositorio monolítico, a expensas de un poco de complejidad adicional.

Esta respuesta no tiene la intención de abogar gito hgsobre otros SCM, simplemente sucede que solo conozco estos SCM lo suficientemente bien como para saber que esta opción existe. No entiendo cómo svnfuncionan los externos, por ejemplo.

Mark Booth
fuente
1
Ahora que es una característica interesante. Me interesaría ver algunos estudios de caso adecuados sobre su uso, ¡ni siquiera había oído hablar de él antes!
Ed James
Algo similar en subversion son las definiciones externas: svnbook.red-bean.com/en/1.0/ch07s03.html . Sin embargo, funciona de una manera ligeramente diferente.
liori
1
@ MarkBooth: sí, puedes. En esa página puede ver los parámetros que se parecen a -r12345, que definen qué revisión desea obtener. Y dado que la propiedad svn: externals está versionada como cualquier archivo de texto, puede tener diferentes valores para -r para cada revisión. Además, está explorando la documentación antigua 1.0. Las definiciones externas se cambiaron en 1.5, y la versión actual es 1.7. Ver: svnbook.red-bean.com/en/1.7/svn.advanced.externals.html
liori
6

¡Separar!

De hecho, probablemente tendría tres repositorios, uno para el Cliente y las bibliotecas correspondientes solo para clientes, una para el Servidor (y las bibliotecas correspondientes) y otra para las bibliotecas compartidas (que incorporan las interfaces API que exponen la funcionalidad entre los dos , más cualquier otro código compartido). Creo que esa es realmente la clave, el código compartido debe ir a un repositorio separado propio. De esa manera, puede asegurarse de que la interoperabilidad entre su cliente y servidor esté siempre en la misma versión Y esté aislada del diseño de cada uno de sus consumidores.

Obviamente, esto no siempre es posible, dependiendo del marco de comunicación particular que esté utilizando, pero es probable que haya código compartido que dicte el formato de los objetos de transferencia de datos o los pasos del protocolo de enlace en su protocolo personalizado (o algún otro ejemplo) .

Suponiendo que tiene una integración continua y una configuración de control de calidad bastante decentes (una suposición bastante grande, en mi experiencia, pero que haré de todos modos. Si no tiene un departamento de control de calidad, al menos debería obtener algo de CI) no debería No es necesario utilizar el patrón de repositorio único como defensa contra posibles errores de coincidencia de código, ya sea que su servidor CI detecte la interoperabilidad de la biblioteca o que su equipo de control de calidad detecte errores de tiempo de ejecución (o, mejor aún, sus Pruebas de unidad).

Los beneficios de los repositorios divididos radican en la capacidad de versionar por separado partes separadas de un sistema. ¿Desea tomar una copia del Servidor de la semana pasada y ejecutarla con el Cliente de esta semana para intentar bloquear la raíz de un problema de rendimiento? Sin preocupaciones.

Ed James
fuente
1

En Mercurial , este esquema se puede usar ->para denotar la relación de subrepo:

product -> client -|-> (many components)
                   |->  shared component A

        -> server -|-> (many components)
                   |->  shared component A

El producto tiene subrepos cliente, servidor. Cada uno de ellos tiene sus componentes como subrepos, posiblemente al menos un subrepo compartido entre los dos.

El etiquetado probablemente debería hacerse en los dos primeros niveles, no por debajo de eso.

Los compromisos se realizan en el nivel de componente, los superrepos hacen un seguimiento efectivo de las ramas y versiones del producto. Las ramas / marcadores con nombre suelen ser mejores que las ramas clonadas para la usabilidad (es decir, la capacidad de entrenamiento) y la compatibilidad con subrepos.

hg tiende a asumir que los superrepos son el producto, y las confirmaciones se realizan en el nivel superior, pero eso no funciona particularmente bien cuando varios productos usan los mismos componentes. :-)

No creo que este esquema cambie mucho si se hace la transición a git, pero aún no lo he probado en git.

Paul Nathan
fuente
1

Este es un problema de administración de configuración, no un problema de control de revisión. Como siempre, un programador con un destornillador para clavar un clavo. Determine cómo administrará sus configuraciones, el control de revisión se encargará de sí mismo.

Mattnz
fuente
1

El enfoque más simple es usar un único repositorio, por lo que, a menos que le guste la complejidad por el bien de la complejidad, esa debería ser la opción predeterminada en ausencia de argumentos convincentes de lo contrario.

¿El desarrollo del cliente y del servidor será llevado a cabo por diferentes organizaciones? ¿Habrá múltiples implementaciones del cliente (o servidor)? ¿El cliente es de código abierto y la implementación del servidor es secreta? Si la respuesta a todas estas preguntas es "No", entonces cualquier cosa más compleja que un solo repositorio puede traer inconvenientes sin ningún beneficio.

Si elige mantener bases de código separadas, necesitará políticas claras sobre cómo se administra esto, para evitar incompatibilidades y dependencia de infierno. Después de superar los primeros inconvenientes, puede terminar descubriendo que lo más seguro es siempre revisar ambos repositorios juntos, construirlos juntos y desplegarlos juntos ... ¡lo que obviamente anula el propósito de separarlos!

La modularidad es una buena propiedad, pero dividir los repositorios no es una herramienta para lograrlo. Como implica el párrafo anterior, puede tener componentes altamente acoplados que se dividen en múltiples bases de código (indeseable), y del mismo modo puede tener componentes altamente modulares dentro de la misma base de código (deseable).

En más de una ocasión, he abogado (con éxito) para que mi equipo combine los repositorios git existentes, porque simplificó el desarrollo y la implementación.

Todd Owen
fuente
0

Olvídate del repositorio por un momento. ¿Cómo organizaría los dos proyectos en su máquina si no estuviera compartiendo con nadie? ¿Cómo lo haría el resto del equipo? ¿Podrías ...

  • ¿Poner todos los archivos de origen para el cliente y el servidor en el mismo directorio?

  • ¿Crear un directorio principal del proyecto que contenga subdirectorios para el cliente y el servidor?

  • ¿Mantener los dos proyectos completamente separados?

Una vez que llegue a un consenso sobre eso como equipo, estará listo para verificar los proyectos en su repositorio de código. Todas las herramientas de control de revisiones que se me ocurren están felices de reproducir cualquier estructura de directorio que desee, no les importa un poco qué archivo pertenece a qué proyecto. Y la diferencia entre tener un repositorio o dos (o seis) generalmente no es tan grande, aparte de pequeñas diferencias administrativas.

Por ejemplo, con Subversion, la mayor diferencia entre repositorios separados para el cliente y el servidor y un único repositorio combinado está en la forma en que cambian los números de revisión. Con un repositorio único, el número de versión aumentará cada vez que confirme el código al cliente o al servidor. Con repositorios separados, una confirmación para el proyecto del servidor no cambiará el número de revisión principal para el cliente.

Caleb
fuente