Cuándo separar un proyecto en múltiples subproyectos

30

Me gustaría saber si tiene sentido dividir el proyecto en el que estoy trabajando en dos repositorios en lugar de uno.

Por lo que puedo decir:

  • Frontend se escribirá en html + js
  • Backend en .net
  • El backend no depende del frontend y el frontend no depende del backend
  • El frontend utilizará una API de descanso implementada en el backend.
  • El frontend podría estar alojado en cualquier servidor http estático.

A partir de ahora, el repositorio tiene esta estructura:

raíz:

  • Interfaz/*
  • backend / *

Creo que es un error mantener ambos proyectos en el mismo repositorio. Dado que ambos proyectos no tienen dependencias entre sí, deben pertenecer a repositorios individuales y, si es necesario, a un repositorio principal que tenga submódulos.

Me han dicho que no tiene sentido y que no obtendremos ningún beneficio al hacerlo.

Estos son algunos de mis argumentos:

  • Tenemos dos módulos que no dependen entre sí.
  • Tener el historial de origen de ambos proyectos a largo plazo puede complicar las cosas (intente buscar en el historial algo en la interfaz mientras tiene la mitad de las confirmaciones que no están relacionadas con el error que está buscando)
  • Conflicto y fusión (Esto no debería suceder, pero tener a alguien empujando al backend obligará a otro desarrollador a hacer cambios en el backend para impulsar los cambios frontend).
  • Un desarrollador puede trabajar solo en el backend, pero siempre tendrá que tirar de la interfaz o al revés.
  • A la larga, cuándo será el momento de la implementación. De alguna manera, la interfaz podría implementarse en múltiples servidores estáticos mientras se tiene un servidor de fondo. En todos los casos, las personas se verán obligadas a clonar todo el backend con él o a crear un script personalizado para enviar a todos los servidores solo el front-end o eliminar el back-end. Es más fácil empujar / jalar solo el frontend o backend que ambos si solo se necesita uno
  • Contraargumento (una persona puede trabajar en ambos proyectos), cree un tercer repositorio con submódulo y desarrolle con él. El historial se mantiene separado en módulos individuales y siempre se pueden crear etiquetas donde la versión de backend / frontend realmente funciona en sincronía. Tener ambos frontend / backend juntos en un repositorio no significa que trabajarán juntos. Es solo fusionar la historia en un gran repositorio.
  • Tener frontend / backend como submódulos facilitará las cosas si desea agregar un profesional independiente al proyecto. En algunos casos, realmente no desea dar acceso completo a la base de código. Tener un gran módulo hará las cosas más difíciles si desea restringir lo que los "extraños" pueden ver / editar.
  • Introducción y corrección de errores, inserté un nuevo error en la interfaz. Entonces alguien arregla un error en el backend Con un repositorio, retroceder antes del nuevo error también revertirá el backend, lo que podría dificultar la reparación. Tendría que clonar el backend en una carpeta diferente para que el backend funcione mientras se soluciona el error en la interfaz ... luego tratar de reactivar las cosas ... Tener dos repositorios será sencillo porque mover el HEAD de un repositorio ganó No cambies el otro. Y probar contra diferentes versiones de backend será indoloro.

¿Puede alguien darme más argumentos para convencerlos o al menos decirme por qué no tiene sentido (más complicado) dividir el proyecto en dos submódulos? El proyecto es nuevo y la base de código tiene un par de días de antigüedad, por lo que no es demasiado pronto para solucionarlo.

Loïc Faure-Lacroix
fuente

Respuestas:

23

En mi empresa, utilizamos un repositorio SVN separado para cada componente del sistema. Puedo decirte que se vuelve extremadamente frustrante. Nuestro proceso de construcción tiene muchas capas de abstracción.

Hacemos esto con Java, por lo que tenemos un proceso de compilación pesado con compilación javac, compilación de enlaces JibX, validación XML, etc.

Para su sitio, puede que no sea un gran problema si realmente no lo "construye" (como PHP vainilla).

Desventajas de dividir un producto en múltiples repositorios

  1. Gestión de compilación: no puedo simplemente extraer el código, ejecutar un script de compilación autónomo y tener un producto ejecutable / instalable / implementable. Necesito un sistema de compilación externo que salga a múltiples repositorios, ejecute múltiples scripts de compilación internos y luego ensamble los artefactos.
  2. Seguimiento de cambios: ver quién cambió qué, cuándo y por qué. Si una corrección de error en el frontend requiere un cambio de back-end, ahora hay 2 caminos divergentes para que pueda consultar más adelante.
  3. Administración: ¿realmente desea duplicar la cantidad de cuentas de usuario, políticas de contraseña, etc. que deben administrarse?
  4. Fusionar: es probable que las nuevas funciones cambien mucho código. Al dividir su proyecto en múltiples repositorios, está multiplicando la cantidad de fusiones necesarias.
  5. Creación de bifurcación: el mismo trato con la bifurcación, para crear una bifurcación, ahora debe crear una bifurcación en cada repositorio.
  6. Etiquetado: después de una prueba exitosa de su código, desea etiquetar una versión para su lanzamiento. Ahora tiene varias etiquetas para crear, una en cada repositorio.
  7. Difícil de encontrar algo: tal vez el frontend / backend es sencillo, pero se convierte en una pendiente resbaladiza. Si se divide en suficientes módulos, los desarrolladores pueden tener que investigar dónde reside una parte del código en el control de código fuente.

Mi caso es un poco extremo ya que nuestro producto se divide en 14 repositorios diferentes y cada repositorio se divide en 4-8 módulos. Si mal no recuerdo, tenemos alrededor de 80 o algunos "paquetes" que deben ser revisados ​​individualmente y luego ensamblados.

Su caso con solo backend / frontend puede ser menos complicado, pero aún así desaconsejo.

Los ejemplos extremos pueden ser argumentos convincentes a favor o en contra de casi cualquier cosa :)

Criterios que usaría para decidir

Consideraría dividir un producto en múltiples repositorios de código fuente después de considerar los siguientes factores:

  1. Compilación: ¿los resultados de la compilación de cada componente se combinan para formar un producto? Como combinar archivos .class de un grupo de componentes en una serie de archivos .jar o .war.
  2. Implementación: ¿terminas con componentes que se implementan juntos como una unidad o unidades diferentes que van a diferentes servidores? Por ejemplo, los scripts de base de datos van a su servidor de base de datos, mientras que javascript va a su servidor web.
  3. Co-cambio - ¿Tienden a cambiar con frecuencia o juntos? En su caso, pueden cambiar por separado, pero aún con frecuencia.
  4. Frecuencia de ramificación / fusión: si todos se registran en el tronco y las ramas son raros, es posible que pueda salirse con la suya. Si frecuentemente se ramifica y fusiona, esto puede convertirse en una pesadilla.
  5. Agilidad: si necesita desarrollar, probar, liberar e implementar un cambio en cualquier momento (probablemente con SaaS), ¿puede hacerlo sin pasar un tiempo precioso haciendo malabarismos con las ramas y repositorios?

Sus argumentos

Tampoco estoy de acuerdo con la mayoría de sus argumentos para esta división. No los discutiré a todos porque esta respuesta larga se hará aún más larga, pero algunos que se destacan:

Tenemos dos módulos que no dependen entre sí.

Disparates. Si te quitas el backend, ¿funcionará tu interfaz? Es lo que pensaba.

Tener el historial de origen de ambos proyectos a largo plazo puede complicar las cosas (intente buscar en el historial algo en la interfaz mientras tiene la mitad de las confirmaciones que no están relacionadas con el error que está buscando)

Si la raíz de su proyecto se divide en frontend / y backend /, puede ver el historial de esas jerarquías de forma independiente.

Conflicto y fusión (Esto no debería suceder, pero tener a alguien empujando hacia el backend obligará a otro desarrollador a realizar cambios en el backend para impulsar los cambios en la interfaz). alrededor.

Dividir su proyecto en diferentes repositorios no resuelve esto. Un conflicto frontend y un conflicto de back-end todavía te dejan con 2 conflictos, ya sea 1 repositorio por 2 conflictos o 2 repositorios por 1 conflicto. Alguien todavía necesita resolverlos.

Si la preocupación es que 2 repos significa que un desarrollador frontend puede fusionar el código frontend mientras que un desarrollador backend fusiona el código backend, aún puede hacerlo con un único repositorio usando SVN. SVN puede fusionarse en cualquier nivel. ¿Tal vez eso es una limitación git o mercurial (etiquetó ambos, así que no está seguro de qué SCM usa)?

Por otra parte

Dicho todo esto, he visto casos en los que funciona dividir un proyecto en múltiples módulos o repositorios. Incluso lo defendí una vez para un proyecto en particular donde integramos Solr en nuestro producto. Por supuesto, Solr se ejecuta en servidores separados, solo cambia cuando un conjunto de cambios está relacionado con la búsqueda (nuestro producto hace mucho más que buscar), tiene un proceso de compilación separado y no hay artefactos de código o artefactos de construcción compartidos.

Brandon
fuente
Moderación en todas las cosas, como solía decir mi madre ...
William Payne
A partir de mi escritura, estoy escribiendo la interfaz sin backend. Emulo el backend con archivos json, y probablemente incluso podría emular completamente con indexedDB en el navegador. Entonces, sí, el backend es solo un servidor que sirve a json. Podría ser reemplazado por cualquier cosa siempre que los datos recibidos se ajusten a la API. Ambos proyectos utilizan un sistema de construcción diferente. En resumen, es más o menos como tener un sitio web y una aplicación móvil de Android. Agregar la aplicación móvil dentro del repositorio del servidor web.
Loïc Faure-Lacroix
Además, si no estaba claro, el backend y la interfaz no son interfaces de usuario / administrador. Pero el frontend es solo una interfaz ajax y el backend sirve json. Los usuarios y roles se manejan de manera diferente y la interfaz de administración estará en la interfaz. La idea es mantener ambas partes aisladas y evitar que el html generado por javascript cargue el html generado por el servidor. El servidor solo debe servir json o xml.
Loïc Faure-Lacroix
1
Entonces no tiene problemas de compilación o implementación, por lo que puede estar bien. Pero una vez más, si realiza un cambio importante, es posible que deba cambiar la API, que afecta tanto al front-end como al back-end y, por lo tanto, se bifurcará dos veces, se fusionará dos veces, se etiquetará dos veces, etc. Pero siempre que permanezca solo dos veces y no No se convierta en 3 ... 4 ... 12 ... 20, probablemente no sea una mala idea.
Brandon
Incluso si la API cambia, con el control de versiones adecuado, podría ser posible crear versiones de sucursal para cada interfaz que admita una versión de API. El backend debería tener cierta compatibilidad "hacia atrás" y mantener la API antigua funcionando el mayor tiempo posible.
Loïc Faure-Lacroix
3

Algunos de sus argumentos son válidos y otros no.

Tenemos dos módulos que no dependen entre sí.

Eso en realidad no es del todo cierto. Para poder comunicarse, tanto el front-end como el back-end deben tener una interfaz común (descripción). Eso lo convierte en un argumento débil a favor de tener ambos en un repositorio común. Pero solo un argumento débil, ya que no hace mucha diferencia.

Tener el historial de origen de ambos proyectos a largo plazo puede complicar las cosas (intente buscar en el historial algo en la interfaz mientras tiene la mitad de las confirmaciones que no están relacionadas con el error que está buscando)

Este es un argumento falso. Si desea consultar cómo se solucionó un error en particular, busque en el rastreador de errores para el cual commit contiene la corrección. Y si desea saber cómo evolucionó un código en particular, mire el historial de un solo archivo (o como mucho un puñado). En cualquier caso, tener otros archivos, posiblemente de otros módulos, en el repositorio no debería complicar las cosas de ninguna manera.

Conflicto y fusión (Esto no debería suceder, pero tener a alguien empujando al backend obligará a otro desarrollador a hacer cambios en el backend para impulsar los cambios frontend).

Este es un argumento falso. No conozco ningún VCS (medio decente) en el que necesite sincronizar todo el repositorio antes de poder confirmar / enviar sus cambios. Como máximo, debe sincronizar las carpetas que contienen los archivos modificados (y a menudo solo los archivos mismos).

Un desarrollador puede trabajar solo en el backend, pero siempre tendrá que tirar del backend o al revés.

Este es el mismo argumento falso que el anterior.

A la larga, cuándo será el momento de la implementación. De alguna manera, la interfaz podría implementarse en múltiples servidores estáticos mientras se tiene un servidor de fondo. En todos los casos, las personas se verán obligadas a clonar todo el backend con él o a crear un script personalizado para enviar a todos los servidores solo el front-end o eliminar el back-end. Es más fácil empujar / jalar solo el frontend o backend que ambos si solo se necesita uno

Dependiendo de cómo las personas imaginen que se realizará el despliegue, esto puede ser un argumento válido. Si la implementación se realizará desempacando un archivo zip / tarbal en el servidor, no importa cómo estén organizados sus repositorios. Si la implementación se realizará al retirar (parte de) un repositorio en el servidor, entonces puede ser una buena idea usar repositorios separados para los módulos que se implementan por separado.

Contraargumento (una persona puede trabajar en ambos proyectos), cree un tercer repositorio con submódulo y desarrolle con él. El historial se mantiene separado en módulos individuales y siempre se pueden crear etiquetas donde la versión de backend / frontend realmente funciona en sincronía. Tener ambos frontend / backend juntos en un repositorio no significa que trabajarán juntos. Es solo fusionar la historia en un gran repositorio.

Este es un argumento válido, pero no es tan fuerte.

Tener frontend / backend como submódulos facilitará las cosas si desea agregar un profesional independiente al proyecto. En algunos casos, realmente no desea dar acceso completo a la base de código. Tener un gran módulo hará las cosas más difíciles si desea restringir lo que los "extraños" pueden ver / editar.

Este es un argumento válido.

Introducción y corrección de errores, inserté un nuevo error en la interfaz. Entonces alguien arregla un error en el backend Con un repositorio, retroceder antes del nuevo error también revertirá el backend, lo que podría dificultar la reparación.

Es un argumento falso, porque significaría que después de dos correcciones de errores en un módulo, no podrá revertir el primero. Cualquier VCS medio decente le permitirá revertir casi cualquier confirmación anterior (aunque a menudo significará que realiza una nueva confirmación que revierte esos cambios, a veces incluso para la parte superior de HEAD).

Tendría que clonar el backend en una carpeta diferente para que el backend funcione mientras se soluciona el error en la interfaz ... luego tratar de reactivar las cosas ... Tener dos repositorios será sencillo porque mover el HEAD de un repositorio ganó No cambies el otro. Y probar contra diferentes versiones de backend será indoloro.

Este es realmente un buen argumento. Tener dos repositorios hace que sea más fácil probar los escenarios en los que los front-end y back-end desplegados pueden estar (ligeramente) fuera de sincronización.

Bart van Ingen Schenau
fuente
Para ser sincero, la mayoría de los argumentos falsos se pueden resolver con ramas. Rama para frontend y rama para backend. Maestro para la sincronización. Pero de alguna manera, manejar una rama como esa está complicando las cosas que tener dos repositorios.
Loïc Faure-Lacroix
1
@Sybiam: En realidad, son argumentos falsos, porque no resaltan un problema que podría existir con el uso de un único repositorio, incluso si todos los cambios se realizan solo en trunk / main.
Bart van Ingen Schenau
Creo que tus críticas son válidas. Simplemente no creo que ese sea el punto de la pregunta.
sylvanaar
2

Esta publicación es un poco antigua pero me gustaría contribuir. Si bien su back-end no sabe realmente sobre el front-end, el front-end necesita tener solicitudes que coincidan con la API del back-end. Si considera su back-end como una API REST, podría definir un archivo de interfaz como una interfaz YAML swagger. Ahora hay realmente 3 proyectos, que puede dividir individualmente en diferentes repositorios como mejor le parezca:

  • Definición de API
  • Back-end
  • Interfaz

La definición de API es una dependencia en los otros dos proyectos, digamos que estaba usando Maven como una herramienta de inyección de dependencia. Entonces depende de cuán estrictamente desee hacer el control de versiones. Puede aumentar la versión del proyecto de definición de API cada vez que realice un cambio para asegurarse de que los proyectos estén siempre en un estado compatible pero requiera más sobrecarga, o puede usar algo como INSTANTÁNEAS en maven, y solo realice el control de versiones una vez que están contentos con la interfaz que es menos costosa pero a menudo puede tener incompatibilidades. Pero siempre que aplique la definición de API en su front-end y back-end, estará bien dividiendo los proyectos en diferentes repositorios.

Estos problemas tienen más que ver con la gestión de dependencias. Incluso si los proyectos no están divididos y están en el mismo repositorio, es bastante fácil que el sitio web se coloque en un estado en el que el front-end y el back-end no estén sincronizados. Realmente, la única forma de detener esto es definir realmente el contrato entre los dos, pero desea hacerlo de una manera que no acople las implementaciones del front-end y el back-end, al igual que codificaría una interfaz en su lugar de una implementación en programación OO.

Además, para manejar de manera preventiva la crítica de que esto crea una sobrecarga de mantener este archivo de interfaz, swagger, por ejemplo, incluso puede producir códigos auxiliares para diferentes lenguajes de programación y marcos como JAX-RS. Para que pueda producir una interfaz en la tecnología elegida y luego implementar esta interfaz. También agrega documentación muy agradable a su back-end, lo que facilita a los desarrolladores front-end hacer su trabajo.

Snickers3192
fuente