version-control code-generation

version control - ¿Debo almacenar el código generado en el control de código fuente?



version-control code-generation (27)

Absolutamente tiene el código generado en el control de la fuente, por muchas razones. Reitero lo que mucha gente ya ha dicho, pero algunas razones por las que lo haría son

  1. Con los archivos de código en control de código fuente, posiblemente podrá compilar el código sin usar su paso previo a la compilación de Visual Studio.
  2. Cuando haga una comparación completa entre dos versiones, sería bueno saber si el código generado cambió entre esas dos etiquetas, sin tener que verificarlo manualmente.
  3. Si el propio generador de códigos cambia, entonces querrá asegurarse de que los cambios en el código generado cambien de manera apropiada. es decir, si su generador cambia, pero no se supone que la salida cambie, cuando vaya a comprometer su código, no habrá diferencias entre lo que se generó previamente y lo que está en el código generado ahora.

Este es un debate en el que participo. Me gustaría obtener más opiniones y puntos de vista.

Tenemos algunas clases que se generan en el tiempo de compilación para manejar operaciones DB (en este caso específico, con SubSonic, pero no creo que sea muy importante para la pregunta). La generación se establece como un paso previo a la compilación en Visual Studio. Entonces, cada vez que un desarrollador (o el proceso de compilación oficial) ejecuta una compilación, estas clases se generan y luego se compilan en el proyecto.

Ahora algunas personas afirman que tener estas clases guardadas en el control de la fuente podría causar confusión, en caso de que el código que obtenga no coincida con lo que se habría generado en su propio entorno.

Me gustaría tener una forma de rastrear el historial del código, incluso si generalmente se trata como un recuadro negro.

¿Algún argumento o contra argumento?

ACTUALIZACIÓN: Hice esta pregunta ya que realmente creía que hay una respuesta definitiva. Mirando todas las respuestas, podría decir con alto nivel de certeza, que no hay tal respuesta. La decisión debe tomarse en base a más de un parámetro. Leer las respuestas a continuación podría proporcionar una muy buena guía para los tipos de preguntas que debería hacerse al decidir sobre este tema.

No seleccionaré una respuesta aceptada en este momento por los motivos mencionados anteriormente.


Ambas partes tienen argumentos válidos y razonables, y es difícil ponerse de acuerdo sobre algo común. Version Control Systems (VCS) rastrea los archivos que los desarrolladores colocaron en él, y asumen que los archivos dentro de VCS están hechos a mano por los desarrolladores, y los desarrolladores están interesados ​​en el historial y el cambio entre cualquier revisión de los archivos. Esta suposición iguala los dos conceptos: "Quiero obtener este archivo cuando finalice la compra". y "Estoy interesado en el cambio de este archivo".

Ahora, los argumentos de ambos lados podrían reformularse así:

  • "Quiero obtener todos estos archivos generados cuando finalizo la compra, porque no tengo la herramienta para generarlos en esta máquina".
  • "No debería ponerlos en VCS, ya que no estoy interesado en el cambio de este archivo".

Afortunadamente, parece que los dos requisitos no están en conflicto fundamentalmente. Con alguna extensión de los VCS actuales, debería ser posible tener ambos. En otras palabras, es un dilema falso. Si reflexionamos un rato, no es difícil darse cuenta de que el problema se deriva de la suposición de que los VCS tienen. Los VCS deben distinguir los archivos, que están hechos a mano por los desarrolladores, de archivos que no están hechos a mano por los desarrolladores, sino que simplemente están dentro de este VCS. Para la primera categoría de archivos, que llamamos archivos de código fuente (normalmente), los VCS han hecho un gran trabajo ahora. Para la última categoría, VCSs aún no han tenido ese concepto, hasta donde yo sé.

Resumen

Tomaré git como un ejemplo para ilustrar lo que quiero decir.

  • git status no debe mostrar los archivos generados por defecto.
  • git commit debe incluir los archivos generados como instantánea.
  • git diff no debe mostrar los archivos generados por defecto.

PD

Los ganchos Git podrían usarse como una solución alternativa, pero sería genial si git lo admite de forma nativa. gitignore no cumple con nuestros requisitos, ya que los archivos ignorados no entrarán en VCS. enter code here


Cada vez que deseo mostrar los cambios en un árbol fuente en mi repositorio personal, todos los ''archivos generados'' aparecerán como modificados y deben enviarse.

Preferiría tener una lista más limpia de modificaciones que solo incluya las actualizaciones reales que se realizaron y no los cambios autogenerados.

Déjelos fuera, y luego después de una compilación, agregue un "ignorar" en cada uno de los archivos generados.


Déjalo afuera.

Si está registrando archivos generados, está haciendo algo mal. Lo que está mal puede diferir, puede ser que tu proceso de compilación sea ineficiente o algo diferente, pero no veo que sea una buena idea. La historia debe estar asociada a los archivos fuente, no a los generados.

Simplemente crea un dolor de cabeza para las personas que luego terminan tratando de resolver las diferencias, encuentran los archivos que ya no son generados por la compilación y luego los eliminan, etc.

¡Un mundo de dolor espera a aquellos que registran los archivos generados!


Dejaría los archivos generados de un árbol fuente, pero los colocaría en un árbol de construcción separado.

por ejemplo, el flujo de trabajo es

  1. checkin / out / modify / merge source normalmente (sin los archivos generados)
  2. En ocasiones apropiadas, revisa el árbol de fuentes en un árbol de construcción limpio
  3. Después de una compilación, compruebe todos los archivos "importantes" (archivos fuente "reales", ejecutables + archivo fuente generado) que deben estar presentes para fines de auditoría / reglamentación. Esto le proporciona un historial de todos los códigos + ejecutables generados de manera apropiada, o lo que sea, en incrementos de tiempo relacionados con lanzamientos / instantáneas de prueba, etc. y desacoplados del desarrollo diario.

Probablemente haya buenas maneras en Subversion / Mercurial / Git / etc para unir el historial de los archivos fuente reales en ambos lugares.


El trabajo de gestión de configuración (cuyo control de versión es solo una parte) es poder hacer lo siguiente:

  • Conozca los cambios y las correcciones de errores en cada compilación entregada.
  • Ser capaz de reproducir exactamente cualquier construcción entregada, empezando por el código fuente original. El código generado automáticamente no cuenta como "código fuente" independientemente del idioma.

El primero se asegura de que cuando le diga al cliente o usuario final que "el error que informó la semana pasada sea corregido y que se haya agregado la nueva característica", no vuelvan dos horas después y diga "no, no es así". También se asegura de que no digan "¿Por qué está haciendo X? Nunca pedimos X".

El segundo significa que cuando el cliente o usuario final informa un error en alguna versión que emitió hace un año puede volver a esa versión, reproducir el error, arreglarlo y demostrar que fue su solución la que eliminó el error en lugar de alguna perturbación del compilador y otras correcciones.

Esto significa que su compilador, bibliotecas, etc. también deben ser parte de CM.

Así que ahora para responder a su pregunta: si puede hacer todo lo anterior, entonces no necesita registrar ninguna representación intermedia, porque de todos modos tiene la garantía de obtener la misma respuesta. Si no puede hacer todo lo anterior, todas las apuestas se cancelan porque nunca puede garantizar que haga lo mismo dos veces y obtenga la misma respuesta. Así que también podría poner todos sus archivos .o bajo control de versión también.


En algunos proyectos agrego código generado al control de fuente, pero realmente depende. Mi guía básica es si el código generado es una parte intrínseca del compilador, entonces no lo agregaré. Si el código generado proviene de una herramienta externa, como SubSonic en este caso, agregaría if al control de fuente. Si actualiza periódicamente el componente, entonces quiero saber los cambios en la fuente generada en caso de que aparezcan errores o problemas.

En cuanto al código generado que debe registrarse, el peor escenario posible es diferenciar manualmente los archivos y revertir los archivos si es necesario. Si está utilizando svn, puede agregar un enlace precompromiso en svn para denegar una confirmación si el archivo realmente no ha cambiado.


En general, el código generado no necesita almacenarse en el control de fuente porque el historial de revisión de este código puede ser rastreado por el historial de revisión del código que lo generó.

Sin embargo, parece que OP está utilizando el código generado como la capa de acceso a datos de la aplicación en lugar de escribir uno manualmente. En este caso, cambiaría el proceso de compilación y comprometería el código con el control de origen porque es un componente crítico del código de tiempo de ejecución. Esto también elimina la dependencia de la herramienta de generación de código del proceso de compilación en caso de que los desarrolladores necesiten usar una versión diferente de la herramienta para diferentes ramas.

Parece que el código solo debe generarse una vez en lugar de cada compilación. Cuando un desarrollador necesita agregar / eliminar / cambiar la forma en que un objeto accede a la base de datos, el código debe generarse nuevamente, al igual que hacer modificaciones manuales. Esto acelera el proceso de compilación, permite optimizaciones manuales en la capa de acceso a datos, y el historial de la capa de acceso a datos se conserva de manera simple.


Hay buenos argumentos a favor y en contra presentados aquí. Para que conste, construyo el sistema de generación T4 en Visual Studio y nuestra opción predeterminada lista para usar hace que se registre el código generado. Tienes que trabajar un poco más si no deseas realizar el check-in.

Para mí, la consideración clave es diferir la salida generada cuando se actualiza la entrada o el generador.

Si no tiene su salida registrada, entonces debe tomar una copia de todo el código generado antes de actualizar un generador o modificar la entrada para poder compararlo con el resultado de la nueva versión. Creo que este es un proceso bastante tedioso, pero con salida registrada, es una simple cuestión de diferir la nueva salida contra el repositorio.

En este punto, es razonable preguntar "¿Por qué te importan los cambios en el código generado?" (Especialmente en comparación con el código objeto.) Creo que hay algunas razones clave, que se reducen al estado actual de la técnica en lugar de cualquier problema inherente.

  1. Elaboras un código escrito a mano que se acopla estrechamente con el código generado. Ese no es el caso en general con archivos obj en estos días. Cuando el código generado cambia, es muy a menudo el caso que algunos códigos escritos a mano deben cambiar para coincidir. La gente a menudo no observa un alto grado de compatibilidad hacia atrás con los puntos de extensibilidad en el código generado.

  2. El código generado simplemente cambia su comportamiento. No toleraría esto por parte de un compilador, pero para ser justos, un generador de código de nivel de aplicación está apuntando a un campo de problema diferente con una gama más amplia de soluciones aceptables. Es importante ver si las suposiciones que hizo sobre el comportamiento anterior ahora están rotas.

  3. Simplemente no confías al 100% en la salida de tu generador de una versión a otra. Las herramientas de generador tienen mucho valor, incluso si no están construidas y mantenidas con el rigor de su proveedor de compiladores. La versión 1.0 podría haber sido perfectamente estable para su aplicación, pero tal vez 1.1 tiene algunas fallas técnicas para su caso de uso ahora. De forma alternativa, puede cambiar los valores de entrada y descubrir que está ejercitando una nueva pieza del generador que no había usado antes; es posible que se sorprenda por los resultados.

Básicamente, todas estas cosas se reducen a la madurez de la herramienta: la mayoría de los generadores de códigos de aplicaciones comerciales no se acercan al nivel que los compiladores o incluso las herramientas lex / yacc han tenido durante años.


Hay un caso especial en el que desea verificar los archivos generados: cuando es posible que necesite construir en sistemas donde las herramientas utilizadas para generar los otros archivos no están disponibles. El ejemplo clásico de esto, y con el que trabajo, es el código Lex y Yacc. Debido a que desarrollamos un sistema de tiempo de ejecución que tiene que construir y ejecutar en una gran variedad de plataformas y arquitecturas, solo podemos confiar en que los sistemas de destino tengan compiladores C y C ++, no las herramientas necesarias para generar el código lexing / analizador para nuestra definición de interfaz traductor. Por lo tanto, cuando cambiamos nuestras gramáticas, verificamos el código generado para analizarlo.


La regla general es no , pero si lleva tiempo generar el código (debido al acceso a bases de datos, servicios web, etc.), es posible que desee guardar una versión almacenada en caché en el control de código fuente y ahorrarle a todos la molestia.

Sus herramientas también deben ser conscientes de esto y controlar el control de origen cuando sea necesario; demasiadas herramientas deciden retirarlo del control de origen sin ningún motivo.
Una buena herramienta usará la versión en caché sin tocarla (ni modificará los pasos de tiempo en el archivo).

También debe colocar una gran advertencia dentro del código generado para que las personas no modifiquen el archivo, una advertencia en la parte superior no es suficiente, debe repetirlo cada docena de líneas.


La respuesta correcta es "Depende". Depende de cuáles sean las necesidades del cliente. Si puede retrotraer el código a un lanzamiento en particular y hacer frente a cualquier auditoría externa sin él, entonces todavía no está en terreno firme. Como desarrolladores, debemos considerar no solo el "ruido", el dolor y el espacio en disco, sino también el hecho de que tenemos la función de generar propiedad intelectual y de que puede haber ramificaciones legales. ¿Sería capaz de demostrarle a un juez que puede regenerar un sitio web exactamente como lo vio un cliente hace dos años?

No estoy sugiriendo que guarde o no guarde los archivos generados, cualquiera que sea la forma en que decida si no está involucrando a los Expertos en el tema de la decisión, probablemente esté equivocado.

Mis dos centavos.


Mírelo de esta manera: ¿verifica sus archivos objeto en control de fuente? Los archivos fuente generados son artefactos de compilación al igual que los archivos de objetos, bibliotecas y ejecutables. Deberían ser tratados de la misma manera. La mayoría argumentaría que no debería verificar los archivos de objetos generados y los ejecutables en el control de código fuente. Los mismos argumentos se aplican a la fuente generada.

Si necesita ver la versión histórica de un archivo generado, puede sincronizar con la versión histórica de sus fuentes y reconstruir.

Verificar los archivos generados de cualquier tipo en el control de la fuente es análogo a la desnormalización de la base de datos. En ocasiones, hay razones para hacerlo (por lo general, para el rendimiento), pero esto debe hacerse con gran cuidado, ya que se vuelve mucho más difícil mantener la corrección y la coherencia una vez que los datos se desnormalizan.


No, por tres razones.

  1. El código fuente es todo lo necesario y suficiente para reproducir una instantánea de su aplicación a partir de un momento actual o anterior, nada más y nada menos. Parte de lo que esto implica es que alguien es responsable de todo lo registrado. En general, me complace ser responsable del código que escribo, pero no del código que se genera como consecuencia de lo que escribo.

  2. No quiero que alguien tenga la tentación de intentar atajar una compilación a partir de fuentes primarias mediante el uso de un código intermedio que puede o no ser actual (y más importante que no quiero aceptar la responsabilidad). Y tampoco es así. tentador para algunas personas quedar atrapados en un proceso sin sentido sobre la depuración de conflictos en el código intermedio basado en compilaciones parciales.

  3. Una vez que está en control de la fuente, acepto la responsabilidad de a. está allí, b. siendo actual, y c. es confiablemente integrable con todo lo demás allí. Eso incluye eliminarlo cuando ya no lo estoy usando. Mientras menos de esa responsabilidad, mejor.


Parece que hay opiniones muy fuertes y convincentes en ambos lados. Recomiendo leer todas las respuestas más votadas, y luego decidir qué argumentos se aplican a su caso específico.

ACTUALIZACIÓN: Hice esta pregunta ya que realmente creía que hay una respuesta definitiva. Mirando todas las respuestas, podría decir con alto nivel de certeza, que no hay tal respuesta. La decisión debe tomarse en base a más de un parámetro. Leer las otras respuestas podría proporcionar una muy buena guía para los tipos de preguntas que debería hacerse al decidir sobre este tema.


Ponlo en control de código fuente. La ventaja de tener el historial de todo lo que escribe disponible para futuros desarrolladores supera el pequeño inconveniente de reconstruir ocasionalmente después de una sincronización.


Realmente depende. En última instancia, el objetivo es poder reproducir lo que tenía si fuera necesario. Si puede regenerar sus binarios exactamente, no hay necesidad de almacenarlos. pero necesitas recordar que para recrear tus cosas probablemente necesitarás la configuración exacta con la que lo hiciste, y eso no solo significa tu código fuente, sino también tu entorno de construcción, tu IDE, tal vez incluso otras bibliotecas , generadores o cosas así, en la configuración exacta (versiones) que ha utilizado.

Me he encontrado con problemas en los proyectos donde actualizamos nuestro entorno de compilación a versiones más nuevas o incluso a otros proveedores, donde no pudimos volver a crear los binarios exactos que teníamos antes. Esto es un verdadero dolor cuando los binarios que se deplyed dependen de un tipo de hash, especialmente en un entorno seguro, y los archivos recreados de alguna manera difieren debido a las actualizaciones del compilador o lo que sea.

Entonces, ¿guardarías el código generado? Yo diría que no. Los binarios o entregables que se lanzan, incluidas las herramientas con las que los reprodujo, los almacenaría. Y luego, no hay necesidad de almacenarlos en el control de fuente, solo haga una buena copia de seguridad de esos archivos.


Realmente no creo que debas verificarlos.

Seguramente cualquier cambio en el código generado va a ser ruido: cambios entre entornos o cambios como resultado de otra cosa, por ejemplo, un cambio en su base de datos. Si los scripts de creación de su base de datos (o cualquier otra dependencia) están en control de fuente, ¿por qué necesita los scripts generados también?


Si es parte del código fuente, entonces debe ponerse en control de fuente sin importar quién o qué lo genera. Desea que su control de origen refleje el estado actual de su sistema sin tener que volver a generarlo.


Tampoco almacenamos código de base de datos generado: dado que se genera, puede obtenerlo a voluntad en cualquier versión dada de los archivos fuente. Almacenarlo sería como almacenar bytecode o tal.

¡Ahora necesita asegurarse de que el generador de código utilizado en una versión determinada esté disponible! Las versiones más nuevas pueden generar código diferente ...


Yo (lamentablemente) termino poniendo un montón de fuentes derivadas bajo el control de la fuente porque trabajo de forma remota con personas que no pueden molestarse en establecer un entorno de construcción adecuado o que no tienen las habilidades para configurarlo de modo que el las fuentes derivadas se construyen exactamente bien. (Y cuando se trata de Gnu autotools, ¡yo mismo soy una de esas personas! No puedo trabajar con tres sistemas diferentes, cada uno de los cuales funciona con una versión diferente de autotools, y solo esa versión).

Este tipo de dificultad probablemente se aplica más a proyectos de código abierto de voluntarios a tiempo parcial que a proyectos pagados en los que la persona que paga las facturas puede insistir en un entorno de construcción uniforme.

Cuando haces esto, básicamente te comprometes a construir los archivos derivados solo en un sitio, o solo en sitios configurados correctamente. Tus Makefiles (o lo que sea) deberían configurarse para darse cuenta de dónde se están ejecutando y deberían negarse a volver a derivar las fuentes a menos que sepan que se están ejecutando en un sitio de compilación seguro.


Yo diría que debes evitar agregar cualquier código generado (u otros artefactos) al control de fuente. Si el código generado es el mismo para la entrada dada, entonces usted podría simplemente verificar las versiones que desea diferir y generar el código para la comparación.


Yo diría que sí, que quiere ponerlo bajo control de fuente. Desde el punto de vista de la gestión de la configuración, TODO lo que se utiliza para generar una compilación de software debe controlarse para poder recrearlo. Entiendo que el código generado se puede recrear fácilmente, pero se puede argumentar que no es el mismo ya que la fecha / marcas de tiempo serán diferentes entre las dos compilaciones. En algunas áreas, como el gobierno, requieren muchas veces esto es lo que se hace.


Yo discutiría por. Si está utilizando un proceso de integración continua que verifica el código, modifica el número de compilación, crea el software y luego lo prueba, entonces es más simple y fácil tener ese código como parte de su repositorio.

Además, forma parte de cada "instantánea" que toma de su repositorio de software. Si es parte del software, entonces debe ser parte del repositorio.


Yo llamo al principio SECO. Si ya tiene los "archivos de origen" en el repositorio que se utilizan para generar estos archivos de código en tiempo de compilación, no es necesario que el mismo código se haya "comprometido" dos veces.

Además, puede evitar algunos problemas de esta manera si, por ejemplo, la generación de código se rompe algún día.


llegando un poco tarde ... de todos modos ...

¿Pondría el archivo intermedio del compilador en el control de la versión de origen? En caso de generación de código, por definición, el código fuente es la entrada del generador, mientras que el código generado puede considerarse como archivos intermedios entre la fuente "real" y la aplicación construida.

Entonces diría: no coloque el código generado bajo control de versión, sino el generador y su entrada.

Concretamente, trabajo con un generador de código que escribí: nunca tuve que mantener el código fuente generado bajo control de versión. Incluso diría que, dado que el generador alcanzó cierto nivel de madurez, no tuve que observar el contenido del código generado, aunque la entrada (por ejemplo, la descripción del modelo) cambió.


Guardarlo en control de fuente es más problemas de lo que vale.

Debes hacer un commit cada vez que hagas una construcción para que tenga algún valor.

En general, dejamos el código generado (idl, jaxb cosas, etc.) fuera del control de fuente donde trabajo y nunca ha sido un problema