Stratégie de branchement et de version pour les bibliothèques partagées


12

Ces messages semblent liés, mais mon cerveau commence à fondre, essayant d'y réfléchir: P

Mon employeur vient de commencer à utiliser le contrôle de code source, principalement parce qu'avant d'embaucher plus de développeurs, le «référentiel» était le disque dur du seul développeur, qui travaille principalement à domicile. Tout le code .NET qu'il avait écrit a été vérifié en masse , et il y a beaucoup de fonctionnalités dupliquées (lire: copier-coller). En ce moment, notre système SCM est une sauvegarde glorifiée.

Je voudrais extraire une partie du code dupliqué dans des bibliothèques partagées. Je laisse le dépôt d'origine seul pour ne rien casser - nous pouvons déplacer et / ou refactoriser le code existant au fur et à mesure des besoins. J'ai donc mis en place un dépôt uniquement pour le nouveau code, y compris les bibliothèques.

Mon problème tourne autour de la version des bibliothèques sans nous refléter dans un processus excessif: ayant reconnu que nous avons besoin d'une approche plus cohérente, avec plus de développeurs écrivant tous du code très similaire, la direction et les autres développeurs sont ouverts à la réorganisation des choses, mais ce ne sera probablement pas le cas descendez bien si la solution commence à affecter la productivité.

La solution idéale dans mon esprit obsessionnel est de construire les bibliothèques séparément, chaque projet dépendant étant construit contre des versions compatibles délibérément choisies. De cette façon, nous savons exactement quels clients ont quelles versions de quelles bibliothèques, peuvent reproduire de manière plus fiable les bogues, maintenir des branches de publication indépendantes pour les produits et les bibliothèques, et ne pas casser les projets les uns des autres lors du changement de code partagé.

Cela rend cependant la mise à jour des bibliothèques fastidieuse, en particulier pour le développeur qui travaille à domicile. Je m'attends à ce que les bibliothèques changent rapidement, au moins au début alors que nous (enfin) rassemblons les bits communs. Il est tout à fait possible que j'y réfléchisse complètement et nous serions bien de tout construire en fonction des commits de bibliothèque les plus récents, mais j'aimerais au moins être prêt pour le jour où nous déciderons que certains composants doivent être indépendamment versionnés et distribué. Le fait que certaines bibliothèques devront être installées dans le GAC rend le contrôle de version particulièrement important.

Alors ma question est: qu'est-ce qui me manque? J'ai l'impression d'avoir fixé une solution et j'essaie maintenant de trouver des variantes qui faciliteront les changements. Quels types de stratégies avez-vous utilisés pour résoudre ce genre de problème auparavant? Je me rends compte que cette question est partout; Je ferai de mon mieux pour nettoyer et clarifier tout point d'incertitude.

Et autant que j'aimerais utiliser Mercurial, nous avons déjà dépensé de l'argent sur un SCM commercial centralisé (Vault) et la commutation n'est pas une option. En outre, je pense que le problème ici va plus loin que le choix de l'outil de contrôle de version.


le coût fixe est irrécupérable
alternative le

Réponses:


1

Je salue votre initiative. Cela devrait générer un certain nombre d'avantages pour l'organisation lors de sa mise en œuvre. Je déplacerais le code plutôt que de le copier. La possession de copies entraînera probablement des modifications incompatibles qui devront être résolues.

Il y aura une certaine douleur à mesure que les bibliothèques seront développées et stabilisées. Une fois cela fait, les avantages arriveront. N'oubliez pas que les interfaces avec la bibliothèque sont essentiellement un contrat avec les projets travaillant avec le contrat. Vous pouvez avoir l'avantage de supprimer les anciennes interfaces car vous pourrez déterminer si elles sont utilisées.

Alors que les bibliothèques se stabilisent, l'obtention de nouvelles bibliothèques devrait probablement faire partie du processus de mise à jour du code. Vous pouvez planifier des validations de modifications de bibliothèque. L'annonce du déplacement du code peut aider à réduire les modifications conflictuelles.

Les bibliothèques devraient être traitées comme des projets distincts et stabilisées dès que possible. Une fois stabilisées (en particulier les interfaces), il devrait être plus facile d'intégrer les modifications à d'autres projets. Les nouvelles bibliothèques devraient fonctionner avec l'ancien code. Balisez les versions de bibliothèque stables avec leur propre ID de version. Essayez de traiter les bibliothèques comme vous le feriez pour des bibliothèques tierces.


6

Le code partagé entre les projets doit être traité comme un projet sur lui-même. Ils doivent être traités avec la même rigueur que les bibliothèques tierces. Il n'y a pas d'autre chemin.

Si vous ne pouvez pas amener votre groupe à adopter une stratégie pour le code partagé, vous pouvez l'adopter vous-même à l'aide d'outils de gestion de code source modernes comme Mercurial ou GIT, même si le SCM que votre entreprise n'utilisera pas officiellement n'est pas non plus. Avec un peu de soin, deux SCM peuvent utiliser le même répertoire de travail simplement en disant à l'un d'ignorer les fichiers internes de l'autre. Vous utiliseriez un SCM pour gérer le quotidien et celui de l'entreprise pour l'intégrer.

Quoi qu'il en soit, vous devez être responsable du moment de mettre à jour votre répertoire de travail avec les modifications que d'autres projets ont apportées au code partagé. Cela ne devrait se produire que lorsque vous êtes prêt à faire face aux incompatibilités qui peuvent survenir; sinon, votre travail peut devenir instable au-delà de ce qui est réalisable.


4

Si vous avez la possibilité de les décomposer en projets de "module" séparés, je choisirais cette approche. Une chose à craindre est le couplage de code. Vous créeriez une séparation des préoccupations en les dissociant , ce qui est une bonne pratique.

Quelques avantages:

  1. Débogage plus simple de chaque module.
  2. Cycles de construction plus rapides (pas de reconstruction des bibliothèques qui n'ont pas changé)
  3. Une fois que quelque chose fonctionne, vous êtes moins susceptible de le casser en changeant une autre zone en dehors de ce module (pas 100%, mais vous réduisez les chances).
  4. Il est plus facile de diviser les tâches si ce n'est pas un gros gâchis interdépendant.
  5. Distribution plus rapide de petits morceaux lorsque vous corrigez une bibliothèque (une grande raison pour laquelle vous avez des fichiers .dll / .so).

J'ai une question sur cette partie:

"La solution idéale dans mon esprit obsessionnel est de construire les bibliothèques séparément, chaque projet dépendant étant construit contre des versions compatibles délibérément choisies."

Reliez-vous statiquement l'ensemble du projet? Si c'est le cas, cela conduirait à: 6. Réduction de la surcharge de code inutile.

Quelques points négatifs:

  1. Si le projet est petit, vous ajoutez simplement de la complexité là où elle n'est pas nécessaire.
  2. Brancher de nombreux modules peut devenir un problème de maintenance pour les très gros projets. Je ne connais pas "Vault", donc je ne sais pas si leurs opérations de branchement sont bonnes ou mauvaises.

C'est du code C #, c'est donc un "non" à la liaison statique dans son sens habituel. Vault est comme Subversion, pré-1.5: PI attendu si ardemment pour le suivi de fusion dans svn, pensant que j'étais dans le ciel quand il est enfin arrivé. Ensuite, j'ai trouvé DVCS.
shambulator

1

À l'heure actuelle, il semble que vous ayez une base de code intégrée en une seule cible. Vous n'avez probablement pas plus de cinq développeurs. Je ne vois pas vraiment l'utilité de trop séparer les bibliothèques. Vous changeriez votre flux de travail de code -> compiler -> exécuter en code -> compiler -> copier DLL -> compiler -> exécuter ... ick.

Certaines entreprises (Google et Amazon) ont une infrastructure de développement suffisante pour qu'il soit assez facile de faire construire de nombreuses bibliothèques distinctes séparément. L'infrastructure pour le rendre indolore implique un moyen de spécifier les versions de bibliothèque qui vivent dans votre SCM (que vous avez probablement), un moyen de spécifier les versions de dépendance qui vivent dans votre SCM, un serveur de construction qui peut le comprendre et tout compiler correctement et un moyen de récupérer les artefacts de génération appropriés à partir de votre serveur de génération et de votre espace de travail local. Je doute que vous ayez cela.

Sans cette infrastructure, je séparerais le projet lorsque l'une des conditions suivantes s'applique:

  • Vous avez plusieurs produits ou applications distinctes selon cette bibliothèque
  • Vous travaillez exclusivement sur ces bibliothèques pendant plusieurs jours à la fois
  • La fonctionnalité de la bibliothèque est extrêmement distincte de tout ce qui concerne l'entreprise (par exemple, les enveloppes autour des API spécifiques à la plate-forme)
  • Les temps de construction pour le projet combiné deviennent trop grands

Je m'inquiéterais de construire cette infrastructure lorsque vous avez beaucoup de projets et que certains ont des développeurs dédiés et des cycles de publication indépendants.

Qu'est - ce que vous pouvez et devez faire est maintenant mis en place un serveur de build pour fiable, reproductible construit et assurez - vous que vous pouvez trouver la révision source d'un exécutable donné. Vous semblez utiliser .NET; il est assez simple de configurer CruiseControl.NET pour insérer une chaîne de version, y compris le numéro de révision.

Une fois que vous avez un serveur de génération, la séparation d'une bibliothèque consistera à peu près à la déplacer dans Vault, à ajouter une autre cible dans CC.NET et à copier la DLL résultante dans le dossier de bibliothèque de votre projet principal et à la valider. Plus facile du côté SCM que le développement au jour le jour.


1

Mercurial a une fonctionnalité appelée sous-dépôts. J'ai récemment lu ce blog de Kiln expliquant comment ils fonctionnent.

Fondamentalement, vous liez votre projet à une révision spécifique d'un référentiel de bibliothèque. Vous pouvez mettre à jour la bibliothèque autant que vous le souhaitez sans interrompre les projets dépendants. Lorsque vous êtes prêt, vous pouvez intégrer les nouvelles fonctionnalités de la bibliothèque dans votre projet et gérer toute casse. Différents projets peuvent être liés à différentes révisions de la bibliothèque, ils ne doivent donc pas tous être synchronisés et utiliser la même révision de bibliothèque.

Peut-être que Vault a une fonctionnalité similaire.


1

Nous avons ajouté un fichier de métadonnées à chaque module dans SC qui indique le nom de tous les autres modules dont il dépend. Un produit aura un deuxième fichier de métadonnées indiquant quelle version de chaque module dépendant est requise pour le produit. De plus, un outil permet d'analyser les fichiers de métadonnées, de vérifier tous les modules requis et de générer un projet pour notre IDE.

Cela garantit que nos versions sont toujours reproductibles et que les fichiers d'en-tête corrects sont toujours partagés entre les composants. Une autre complexité peut être ajoutée au fur et à mesure que le besoin se développe. Nous avons des outils qui peuvent désormais générer des rapports sur les différences entre deux versions d'un produit, en spécifiant les fichiers source qui ont changé, les commentaires d'archivage, les commentaires de version, les auteurs, sur tous les modules indépendants de SC. Nous obtenons une quantité phénoménale de réutilisation de notre base de code.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.