web-dev-qa-db-fra.com

Devrais-je stocker le code généré dans le contrôle de source

C'est un débat auquel je participe. J'aimerais avoir plus d'opinions et de points de vue.

Certaines classes sont générées pendant la construction pour gérer les opérations de base de données (dans Ce cas spécifique, avec SubSonic, mais je ne pense pas que ce soit très important pour la question). La génération est définie comme une étape de pré-génération dans Visual Studio. Ainsi, chaque fois qu'un développeur (ou le processus de construction officiel) exécute une construction, ces classes sont générées, puis compilées dans le projet.

Certaines personnes affirment maintenant que l'enregistrement de ces classes dans le contrôle de source pourrait être source de confusion, au cas où le code obtenu ne correspond pas à ce qui aurait été généré dans votre propre environnement.

J'aimerais avoir un moyen de retracer l'historique du code, même s'il est généralement traité comme une boîte noire.

Des arguments ou des contre-arguments?


UPDATE: J'ai posé cette question car je croyais vraiment qu'il y avait une réponse définitive. En regardant toutes les réponses, je pourrais dire avec un haut niveau de certitude, qu’il n’existe pas de telle réponse. La décision doit être prise en fonction de plusieurs paramètres. La lecture des réponses ci-dessous pourrait fournir un très bon guide pour les types de questions que vous devriez vous poser lorsque vous devez décider de cette question.

Je ne choisirai pas de réponse acceptée à ce stade pour les raisons mentionnées ci-dessus.

94
Ron Harlev

L'enregistrer dans le contrôle de source représente plus de problèmes qu'il n'en vaut la peine. 

Vous devez faire un commit à chaque fois que vous construisez un build pour que ce soit une valeur.

Généralement, nous laissons le code généré (idl, jaxb, etc.) en dehors du contrôle de source où je travaille et cela n'a jamais été un problème

47
Glen

Chaque fois que je souhaite afficher les modifications apportées à une arborescence de sources sur mon dépôt personnel, tous les "fichiers générés" apparaissent comme ayant changé et doivent être validés.

Je préférerais avoir une liste plus claire de modifications qui incluent uniquement les mises à jour réelles effectuées, et non les modifications générées automatiquement.

Laissez-les de côté, puis après la construction, ajoutez un "ignorer" sur chacun des fichiers générés.

30
Kieveli

Mettez-le dans le contrôle du code source. L'avantage de disposer de l'historique de tout ce que vous écrivez pour les futurs développeurs l'emporte sur la douleur mineure liée à la reconstruction occasionnelle après une synchronisation. 

27
JaredPar

Regardez-le de cette façon: vérifiez-vous vos fichiers d’objets dans le contrôle de source? Les fichiers source générés sont des artefacts de construction, tout comme les fichiers objets, les bibliothèques et les exécutables. Ils devraient être traités de la même façon. La plupart diront que vous ne devriez pas vérifier les fichiers d'objet générés et les exécutables dans le contrôle de source. Les mêmes arguments s'appliquent aux sources générées.

Si vous devez consulter la version historique d'un fichier généré, vous pouvez la synchroniser avec la version historique de ses sources et la reconstruire.

Vérifier les fichiers générés de toute sorte dans le contrôle de code source est analogue à la dénormalisation de la base de données. Il y a à l'occasion / des raisons de le faire (généralement pour des performances), mais cela ne doit être fait qu'avec beaucoup de précaution, car il devient beaucoup plus difficile de maintenir l'exactitude et la cohérence une fois les données dénormalisées.

24

Je dirais que vous devriez éviter d'ajouter du code généré (ou d'autres artefacts) au contrôle de code source. Si le code généré est le même pour l'entrée donnée, vous pouvez simplement vérifier les versions que vous souhaitez comparer et générer le code à des fins de comparaison.

19
FeatureCreep

J'appelle le principe DRY. Si vous avez déjà dans le référentiel les "fichiers source" utilisés pour générer ces fichiers de code au moment de la construction, il n'est pas nécessaire que le même code soit validé "deux fois". 

En outre, vous pourriez éviter certains problèmes de cette manière si, par exemple, la génération de code devait être interrompue un jour.

16
John Smith

Je ne pense vraiment pas que vous devriez les enregistrer.

Sûrement tout changement dans le code généré sera soit du bruit - changements entre environnements, ou changements résultant de quelque chose d'autre - par exemple. un changement dans votre base de données. Si les scripts de création de votre base de données (ou toute autre dépendance) sont dans le contrôle de source, pourquoi avez-vous également besoin des scripts générés?

14
thatismatt

Non, pour trois raisons.

  1. Le code source est tout ce qui est nécessaire et suffisant pour reproduire un instantané de votre application à un moment actuel ou précédent - rien de plus, rien de moins. Cela implique en partie qu'une personne est responsable de tout ce qui est enregistré. Généralement, je suis heureux d'être responsable du code que j'écris, mais pas du code généré à la suite de ce que j'écris.

  2. Je ne veux pas que quelqu'un soit tenté d'essayer de raccourcir une compilation à partir de sources primaires en utilisant un code intermédiaire qui peut ne pas être actuel (et plus important encore pour lequel je ne veux pas accepter la responsabilité). Et c'est trop tentant pour certaines personnes de se laisser entraîner dans un processus sans signification sur les conflits de débogage dans le code intermédiaire basé sur des versions partielles.

  3. Une fois que c'est sous contrôle de code source, j'accepte la responsabilité de. être là, b. il est courant, et c. il peut être intégralement intégré à tout le reste. Cela inclut de l'enlever quand je ne l'utilise plus. Moins il y a de responsabilités, mieux c'est.

13
dkretz

La règle générale est non , mais si la génération du code prend du temps (à cause de l'accès à la base de données, des services Web, etc.), vous voudrez peut-être enregistrer une version mise en cache dans le contrôle de code source et éviter à tout le monde. 

Vos outils doivent également en être conscients et gérer l'extraction du contrôle de code source si nécessaire. Trop d'outils décident d'extraire du contrôle de source sans aucune raison.
Un bon outil utilisera la version mise en cache sans le toucher (ni modifier les pas de temps sur le fichier). 

Aussi, vous devez mettre un grand avertissement dans le code généré pour que les personnes ne modifient pas le fichier, un avertissement au sommet ne suffit pas, vous devez le répéter toutes les douze lignes.

8
Shay Erlichmen

Nous ne stockons pas non plus le code de base de données généré: puisqu'il est généré, vous pouvez l'obtenir à volonté, à n'importe quelle version, à partir des fichiers sources. Stocker ce serait comme stocker du bytecode ou autre.

Maintenant, vous devez vous assurer que le générateur de code utilisé dans une version donnée est disponible! Les nouvelles versions peuvent générer un code différent ...

6
PhiLho

Laisser de côté.

Si vous archivez des fichiers générés, vous faites quelque chose de mal. Ce qui ne va pas peut différer, il se peut que votre processus de construction soit inefficace, ou quelque chose d'autre, mais je ne le vois pas - jamais étant une bonne idée. L’historique doit être associé aux fichiers source et non aux fichiers générés.

Cela crée simplement un mal de tête pour les personnes qui finissent par essayer de résoudre les différences, trouvent les fichiers qui ne sont plus générés par la construction, puis les suppriment, etc.

Un monde de souffrance attend ceux qui archivent les fichiers générés!

5
rich

Il existe un cas particulier dans lequel vous souhaitez archiver vos fichiers générés: il peut être nécessaire de créer sur des systèmes où les outils utilisés pour générer les autres fichiers ne sont pas disponibles. L'exemple classique, avec lequel je travaille, est le code Lex et Yacc. Parce que nous développons un système d'exécution qui doit être construit et exécuté sur une grande variété de plateformes et d'architectures, nous ne pouvons compter que sur les systèmes cibles pour disposer de compilateurs C et C++, et non des outils nécessaires pour générer le code lexing/parsing de la définition de notre interface. traducteur. Ainsi, lorsque nous changeons nos grammaires, nous archivons le code généré.

4
Phil Miller

arriver un peu en retard ... quand même ...

Souhaitez-vous mettre le fichier intermédiaire du compilateur dans le contrôle de version source? Dans le cas de la génération de code, par définition, le code source est l’entrée du générateur, alors que le code généré peut être considéré comme un fichier intermédiaire entre la "vraie" source et l’application construite.

Je dirais donc: ne mettez pas le code généré sous contrôle de version, mais le générateur et son entrée.

Concrètement, je travaille avec un générateur de code que j'ai écrit: Je n'ai jamais eu à maintenir le code source généré sous contrôle de version. Je dirais même que depuis que le générateur a atteint un certain niveau de maturité, je n'ai pas eu à observer le contenu du code généré bien que l'entrée (par exemple la description du modèle) ait changé.

4
dilig0

Dans certains projets, j'ajoute du code généré au contrôle de code source, mais cela dépend vraiment. Mon principe de base est que si le code généré est une partie intrinsèque du compilateur, je ne l'ajouterai pas. Si le code généré provient d'un outil externe, tel que SubSonic dans ce cas, j'ajouterais un contrôle de source. Si vous mettez périodiquement à niveau le composant, je souhaite connaître les modifications apportées au source généré en cas de problèmes.

En ce qui concerne le code généré devant être archivé, le pire des cas est de différencier manuellement les fichiers et de les restaurer si nécessaire. Si vous utilisez svn, vous pouvez ajouter un hook de pré-validation dans svn pour refuser une validation si le fichier n'a pas vraiment changé.

3
Ryan

Il existe de bons arguments pour et contre présentés ici. Pour mémoire, je construis le système de génération T4 dans Visual Studio et notre option prête à l'emploi par défaut entraîne l'enregistrement du code généré. travailler un peu plus fort si vous préférez ne pas vous enregistrer.

Pour moi, l’important est de différencier la sortie générée lorsque l’entrée ou le générateur lui-même est mis à jour.

Si votre sortie n'est pas archivée, vous devez créer une copie de tout le code généré avant de mettre à niveau un générateur ou de modifier une entrée afin de pouvoir la comparer à la sortie de la nouvelle version. Je pense que c'est un processus assez fastidieux, mais avec une sortie contrôlée, il est simple de faire la différence entre la nouvelle sortie et le référentiel.

À ce stade, il est raisonnable de demander "Pourquoi vous souciez-vous des changements dans le code généré?" (Surtout par rapport au code objet.) Je crois qu’il existe plusieurs raisons principales qui relèvent de l’état actuel de la technique plutôt que de tout problème inhérent.

  1. Vous créez un code manuscrit qui se lie étroitement au code généré. Ce n’est pas le cas dans l’ensemble avec les fichiers obj de nos jours. Lorsque le code généré change, il est malheureusement assez souvent nécessaire que certains codes manuscrits changent pour correspondre. Les gens n'observent souvent pas un degré élevé de compatibilité avec les points d'extensibilité dans le code généré.

  2. Le code généré change simplement son comportement. Cela ne serait pas toléré par un compilateur, mais en réalité, un générateur de code au niveau de l’application cible un domaine de problème différent avec une gamme plus large de solutions acceptables. Il est important de voir si vos hypothèses sur le comportement précédent sont maintenant brisées.

  3. Vous ne faites pas confiance à 100% à la sortie de votre générateur de version en version. Les outils de génération ont beaucoup de valeur même s'ils ne sont pas conçus et maintenus avec la rigueur du vendeur de votre compilateur. La version 1.0 était peut-être parfaitement stable pour votre application, mais peut-être que la 1.1 présente quelques problèmes pour votre cas d'utilisation maintenant. Sinon, vous modifiez les valeurs d'entrée et constatez que vous exercez un nouvel élément du générateur que vous n'aviez pas utilisé auparavant - vous risquez d'être surpris par les résultats.

La plupart de ces facteurs dépendent de la maturité des outils: la plupart des générateurs de code d'applications métier ne sont pas aussi avancés que ceux des compilateurs ou même des outils de niveau Lex/yacc depuis des années.

2
GarethJ

La réponse correcte est "ça dépend". Cela dépend des besoins du client. Si vous pouvez restaurer le code d’une version particulière et résister aux audits externes qui en sont dépourvus, alors vous n’êtes pas encore sur des bases solides. En tant que développeurs, nous devons prendre en compte non seulement le «bruit», la douleur et l'espace disque, mais aussi le fait que nous sommes chargés de générer de la propriété intellectuelle, ce qui peut avoir des conséquences juridiques. Seriez-vous en mesure de prouver à un juge que vous êtes en mesure de régénérer un site Web exactement comme le voyait son client il y a deux ans?

Je ne vous suggère pas de sauvegarder ou de ne pas sauvegarder de fichiers gén'd, quelle que soit la manière dont vous décidez si vous n'impliquez pas les experts en la matière dans la décision que vous avez probablement tort.

Mes deux centimes. 

2
James Fleming

Le travail de gestion de la configuration (dont le contrôle de version ne constitue qu’une partie) consiste à pouvoir effectuer les tâches suivantes:

  • Sachez quelles modifications et corrections de bugs ont été apportées à chaque version livrée.
  • Être capable de reproduire exactement n'importe quelle version livrée, à partir du code source original. Le code généré automatiquement ne compte pas comme "code source", quelle que soit la langue.

Le premier garantit que lorsque vous indiquez au client ou à l'utilisateur final "le bogue que vous avez signalé la semaine dernière est corrigé et que la nouvelle fonctionnalité a été ajoutée", ils ne reviennent pas deux heures plus tard et disent "non, ce n'est pas le cas". Cela garantit également qu'ils ne disent pas "Pourquoi fait-il X? Nous n'avons jamais demandé X".

La seconde signifie que lorsque le client ou l'utilisateur final rapporte un bogue dans une version que vous avez publiée il y a un an, vous pouvez y revenir, reproduire le bogue, le corriger et prouver que c'était votre correctif qui a éliminé le bogue plutôt que de le supprimer. quelques perturbations du compilateur et autres correctifs.

Cela signifie que votre compilateur, vos bibliothèques, etc. doivent également faire partie de CM.

Alors maintenant, pour répondre à votre question: si vous pouvez faire tout ce qui précède, vous n’aurez pas besoin d’enregistrer de représentations intermédiaires, car vous êtes certain d’obtenir la même réponse. Si vous ne pouvez pas faire tout ce qui précède, alors tous les paris sont ouverts, car vous ne pouvez jamais garantir de faire la même chose deux fois et d'obtenir la même réponse. Vous pouvez donc également placer tous vos fichiers .o sous contrôle de version.

2
Paul Johnson

Les deux côtés ont des arguments valables et raisonnables, et il est difficile de s'entendre sur quelque chose de commun. Les systèmes de contrôle de version (VCS) suivent les fichiers Que les développeurs y ont placés et supposent que les fichiers contenus dans VCS sont créés à la main par les développeurs. Les développeurs sont intéressés par l'historique Et changent révision des fichiers. Cette hypothèse égalise les deux concepts: "Je souhaite obtenir ce fichier lorsque je passe à la caisse". et "Je suis intéressé par le changement de ce fichier."

Maintenant, les arguments des deux côtés pourraient être reformulés comme suit:

  • "Je veux obtenir tous ces fichiers générés lorsque je passe à la caisse, car je ne dispose pas de l'outil pour les générer sur cette machine."
  • "Je ne devrais pas les mettre dans VCS, car le changement de ce fichier ne m'intéresse pas."

Heureusement, il semble que les deux exigences ne soient pas fondamentalement contradictoires. Avec une certaine extension des VCS actuels, il devrait être possible d’avoir Les deux. En d'autres termes, c'est un faux dilemme. Si nous y réfléchissons un moment, il n’est pas difficile de comprendre que le problème découle de l’hypothèse de départ des VCS. Les VCS Doivent distinguer les fichiers, créés à la main par les développeurs, des fichiers qui ne sont pas créés à la main par les développeurs, mais qui se trouvent simplement dans De ce VCS. Pour la première catégorie de fichiers, que nous appelons généralement les fichiers sources (code), les VCS ont déjà fait un excellent travail. Pour cette dernière catégorie, les VCS n’ont pas encore , À ma connaissance.

Résumé

Je prendrai git comme exemple pour illustrer ce que je veux dire.

  • git status ne doit pas afficher les fichiers générés par défaut.
  • git commit devrait inclure les fichiers générés sous forme d'instantané.
  • git diff ne doit pas afficher les fichiers générés par défaut.

PS

Les crochets Git peuvent être utilisés comme solution de contournement, mais ce serait bien si git le supportait de manière native. gitignore ne répond pas à notre exigence, car les fichiers ignorés ne seront pas enregistrés dans les VCS .enter code here

2
Albert Netymk

Ça dépend vraiment. En fin de compte, l’objectif est de pouvoir reproduire ce que vous aviez au besoin. Si vous pouvez régénérer vos fichiers binaires exactement, il n’est pas nécessaire de les stocker. mais vous devez vous rappeler que pour recréer votre contenu, vous aurez probablement besoin de la configuration exacte avec laquelle vous l'avez fait en premier lieu, ce qui signifie non seulement votre code source, mais également votre environnement de construction, votre IDE, voire même d'autres bibliothèques. , générateurs ou autres, dans la configuration exacte (versions) que vous avez utilisée. 

Des problèmes se posaient dans les projets lorsque nous avions mis à niveau notre environnement de génération vers des versions plus récentes, voire vers un autre fournisseur, où nous ne pouvions pas recréer les fichiers binaires exacts que nous possédions auparavant. C'est très pénible lorsque les fichiers binaires à déployer dépendent d'un type de hachage, en particulier dans un environnement sécurisé, et que les fichiers recréés diffèrent d'une manière ou d'une autre en raison des mises à niveau du compilateur ou autres.

Alors, voulez-vous stocker le code généré: je dirais non. Les fichiers binaires ou les produits livrables publiés, y compris les outils avec lesquels vous les avez reproduits, seraient stockés. Et puis, il n’est pas nécessaire de les stocker dans le contrôle de source, faites juste une bonne sauvegarde de ces fichiers.

2
nojevive

Je dirais que oui, vous voulez le placer sous contrôle de source. Du point de vue de la gestion de la configuration, TOUT est utilisé pour produire une version logicielle qui doit être contrôlée pour pouvoir être recréée. Je comprends que le code généré peut être facilement recréé, mais on peut dire que ce n’est pas la même chose puisque la date et l’horodatage seront différents entre les deux versions. Dans certains domaines tels que le gouvernement, il faut souvent beaucoup de temps.

1
Mark

I (regretfully) wind up putting a lot of derived sources under source control because I work remotely with people who either can't be bothered to set up a proper build environment or who don't have the skills to set it up so that the derived sources are built exactly right. (And when it comes to Gnu autotools, I am one of those people myself! I can't work with three different systems each of which works with a different version of autotools—and only that version.)

Ce type de difficulté s’applique probablement davantage aux projets à temps partiel, volontaires et à code source ouvert qu'aux projets rémunérés dans lesquels la personne qui paie les factures peut exiger un environnement de construction uniforme.

Lorsque vous faites cela, vous vous engagez à créer les fichiers dérivés uniquement sur un site ou uniquement sur des sites correctement configurés. Vos fichiers Makefiles (ou autre) doivent être configurés de manière à indiquer où ils s'exécutent et doivent refuser de redéfinir les sources à moins qu'ils ne sachent qu'ils s'exécutent sur un site de construction sûr.

1
Norman Ramsey

Absolument avoir le code généré dans le contrôle de source, pour de nombreuses raisons. Je réitère ce que beaucoup de gens ont déjà dit, mais certaines des raisons pour lesquelles je le ferais sont

  1. Avec les fichiers de code dans le contrôle de source, vous pourrez potentiellement compiler le code sans utiliser l'étape de pré-génération de Visual Studio.
  2. Lorsque vous effectuez une comparaison complète entre deux versions, il serait utile de savoir si le code généré a changé entre ces deux balises, sans avoir à le vérifier manuellement.
  3. Si le générateur de code change lui-même, vous devez vous assurer que les modifications apportées au code généré sont modifiées de manière appropriée. C'est-à-dire que si votre générateur change, mais que la sortie ne soit pas supposée changer, alors quand vous allez valider votre code, il n'y aura aucune différence entre ce qui a été généré précédemment et ce qui est dans le code généré maintenant.
1
Joe Enos

En général, le code généré n'a pas besoin d'être stocké dans le contrôle de source car l'historique de révision de ce code peut être suivi par l'historique de révision du code qui l'a généré!

Cependant, il semble que l'OP utilise le code généré en tant que couche d'accès aux données de l'application au lieu de l'écrire manuellement. Dans ce cas, je modifierais le processus de génération et engagerais le code dans le contrôle de code source, car il s'agit d'un composant essentiel du code d'exécution. Cela supprime également la dépendance vis-à-vis de l'outil de génération de code du processus de génération dans le cas où les développeurs doivent utiliser une version différente de l'outil pour différentes branches.

Il semble que le code n'ait besoin d'être généré qu'une seule fois au lieu de chaque construction. Lorsqu'un développeur doit ajouter/supprimer/modifier la manière dont un objet accède à la base de données, le code doit être généré à nouveau, tout comme les modifications manuelles. Cela accélère le processus de construction, permet d’optimiser manuellement la couche d’accès aux données et de conserver l’historique de la couche d’accès aux données de manière simple.

1
benson

Je plaiderais pour. Si vous utilisez un processus d'intégration continue qui extrait le code, modifie le numéro de version, construit le logiciel puis le teste, il est alors plus simple et plus facile de simplement inclure ce code dans votre référentiel.

De plus, cela fait partie intégrante de chaque "instantané" que vous prenez de votre référentiel logiciel. Si cela fait partie du logiciel, alors cela devrait faire partie du référentiel.

1
womp

S'il fait partie du code source, il doit être placé dans le contrôle de source, peu importe qui le génère ou non. Vous voulez que votre contrôle de source reflète l'état actuel de votre système sans avoir à le régénérer.

0
mezoid

On dirait qu'il y a des opinions très fortes et convaincantes des deux côtés. Je recommanderais de lire toutes les réponses les plus votées, puis de décider quels arguments s’appliquent à votre cas particulier.

UPDATE: J'ai posé cette question car je croyais vraiment qu'il y avait une réponse définitive. En regardant toutes les réponses, je pourrais dire avec un haut niveau de certitude, qu’il n’existe pas de telle réponse. La décision doit être prise en fonction de plusieurs paramètres. La lecture des autres réponses pourrait fournir de très bonnes indications sur les types de questions que vous devriez vous poser lorsque vous devez décider de cette question.

0
Ron Harlev

Je laisserais les fichiers générés out d'un arbre source, mais le placerais dans in un arbre de construction séparé.

par exemple. le flux de travail est

  1. archiver/extraire/modifier/fusionner la source normalement (sans fichiers générés)
  2. Aux occasions appropriées, consultez l’arbre source dans un arbre de construction propre
  3. Après une construction, archivez tous les fichiers "importants" (fichiers source "réels", exécutables + fichier source généré) qui doivent être présents à des fins d'audit/de réglementation. Cela vous donne un historique de tous les codes générés appropriés + les exécutables + quels que soient les incréments temporels liés aux éditions/tests d'instantanés, etc., et découplés du développement quotidien.

Il existe probablement de bonnes méthodes dans Subversion/Mercurial/Git/etc pour relier l’historique des fichiers source réels aux deux endroits.

0
Jason S