Stratégie d'utilisation du contrôle de version sur un système modulaire

15

Supposons (pour simplifier) ​​que nous avons une application avec client et serveur; existe-t-il une meilleure idée d'utiliser un référentiel pour les deux ou une paire de référentiels distincts?

Les mélanger facilitera probablement le suivi des changements corrélés et maintiendra les branches corrélées (c'est-à-dire l'évolution du protocole), mais d'un autre côté, le développement individuel sera plus encombré ...

mbq
la source
Et quel est le problème avec l'utilisation de branches distinctes? Un développeur a seulement besoin que la branche sur laquelle il travaille actuellement soit ouverte localement, donc il ne verra même pas les éléments qui ne se trouvent que dans les autres branches de toute façon. Mais s'il doit entrer dans la succursale pour une raison quelconque, il le peut.
Spencer Rathbun
@SpencerRathbun - L'utilisation de branches distinctes comme celle-ci est une recette pour un désastre . Il serait vraiment difficile de partager des fichiers entre le serveur et le client, en particulier les interfaces et la documentation du système, etc. toute indication quant aux versions client et serveur qui fonctionneraient ensemble. Comparé à un référentiel monolithique (unique) ou à une répartition modulaire (multiple) du référentiel, vous obtenez en fait le pire des deux mondes .
Mark Booth
@MarkBooth Humm, je pensais aux sections de projet dans chaque branche, car il a indiqué qu'elles partageraient du code. Marquez simplement chaque section comme les branches appropriées, et vous êtes bon. Votre DVCS n'autorise-t-il pas un fichier / commit à avoir plusieurs balises?
Spencer Rathbun

Réponses:

12

Si vous utilisez git ou mercurial , vous voudrez peut-être regarder les sous - modules ou les sous - dépôts .

Le client, le serveur et leurs fichiers d'interface seraient dans leurs propres référentiels, mais seraient liés ensemble au niveau du super-référentiel . Cela vous permettrait d'effectuer une seule vérification au niveau supérieur et / gitou de hgvérifier la validation appropriée de chacun des sous-modules / sous-dépôts.

En ne s'engageant dans le super-référentiel que lorsque le client et le serveur étaient appropriés l'un à l'autre, le super-référentiel ne vous donnerait que la possibilité de vérifier un système fonctionnel - vous n'essaieriez donc jamais d'exécuter le nouveau client sur un ancien serveur ou vice-versa.

Les sous-modules / sous-dépôts vous offrent tous les avantages d'utiliser des référentiels séparés, ainsi que les avantages d'un référentiel monolithique unique, au détriment d'un peu plus de complexité.

Cette réponse n'est pas destinée à plaider gitou par hgrapport à d'autres SCM, il se trouve simplement que je ne connais ces SCM que suffisamment bien pour savoir que cette option existe. Je ne comprends pas comment svnfonctionnent les externes par exemple.

Mark Booth
la source
1
Maintenant, c'est une fonctionnalité intéressante. Je serais intéressé de voir quelques études de cas appropriées sur son utilisation, je n'en avais même pas entendu parler auparavant!
Ed James
Une chose similaire dans subversion est les définitions externes: svnbook.red-bean.com/en/1.0/ch07s03.html . Cependant, cela fonctionne d'une manière légèrement différente.
liori
1
@MarkBooth: oui, vous le pouvez. Sur cette page, vous pouvez voir les paramètres qui ressemblent à -r12345 - ceux qui définissent la révision que vous souhaitez obtenir. Et puisque la propriété svn: externals est versionnée comme n'importe quel fichier texte, vous pouvez avoir des valeurs différentes pour -r pour chaque révision. De plus, vous parcourez l'ancienne documentation 1.0. Les définitions externes ont été modifiées dans 1.5, et la version actuelle est 1.7. Voir: svnbook.red-bean.com/en/1.7/svn.advanced.externals.html
liori
6

Séparé!

En fait, j'aurais probablement trois référentiels, un pour le client et les bibliothèques client uniquement correspondantes, un pour le serveur (et les bibliothèques correspondantes) et un pour les bibliothèques partagées (incorporant les interfaces API qui exposent la fonctionnalité entre les deux , plus tout autre code partagé). Je pense que c'est vraiment la clé, le code partagé devrait aller dans un référentiel séparé. De cette façon, vous pouvez vous assurer que l'interopérabilité entre votre client et votre serveur est toujours à la même version ET est isolée de la conception de chacun de ses consommateurs.

Évidemment, cela n'est pas toujours possible, selon le cadre de communication particulier que vous utilisez, mais il y a probablement du code partagé qui dicte le format des objets de transfert de données ou les étapes de la négociation dans votre protocole personnalisé (ou un autre exemple) .

En supposant que vous avez une intégration continue et une configuration d'AQ assez décentes (une hypothèse assez large, d'après mon expérience, mais je vais néanmoins la faire. Si vous n'avez pas de service d'assurance qualité, vous devriez au moins obtenir un CI), vous ne devriez pas pas besoin d'utiliser le modèle de repo unique comme défense contre d'éventuelles erreurs de correspondance de code, soit votre serveur CI signalera l'interopérabilité de la bibliothèque, soit votre équipe QA détectera les erreurs d'exécution (ou, mieux encore, vos tests unitaires le feront).

Les avantages des référentiels fractionnés résident dans la possibilité de versionner séparément des parties distinctes d'un système. Vous voulez prendre une copie du serveur de la semaine dernière et l'exécuter avec le client de cette semaine, pour essayer de verrouiller la racine d'un problème de performances? Pas de soucis.

Ed James
la source
1

Dans Mercurial , ce schéma peut être utilisé, en utilisant ->pour désigner la relation subrepo:

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

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

Le produit a un sous-client, un serveur. Chacun de ces éléments a ses composants en tant que sous-dépôts, éventuellement au moins un sous-référentiel partagé entre les deux.

Le balisage devrait probablement se faire sur les deux premiers niveaux, pas en dessous.

Les validations sont effectuées au niveau des composants, les superpositions suivent efficacement les branches nommées et les versions du produit. Les branches / signets nommés sont généralement meilleurs que les branches clones pour la convivialité (c'est-à-dire la formabilité) et la compatibilité avec les sous-dépôts.

hg tend vers l'hypothèse que les superpositions sont le produit et les validations sont effectuées au niveau supérieur, mais cela ne fonctionne pas particulièrement bien lorsque plusieurs produits utilisent les mêmes composants. :-)

Je ne pense pas que ce schéma changera beaucoup s'il est passé à git, mais je ne l'ai pas encore essayé dans git.

Paul Nathan
la source
1

Il s'agit d'un problème de gestion de configuration, pas d'un problème de contrôle de révision. Comme toujours, un programmeur utilise un tournevis pour enfoncer un clou. Déterminez comment vous allez gérer vos configurations, le contrôle de révision prendra soin de lui-même.

mattnz
la source
1

L' approche la plus simple consiste à utiliser un référentiel unique, donc à moins que vous n'aimiez la complexité pour la complexité, cela devrait être le choix par défaut en l'absence d'arguments convaincants.

Le développement client et serveur sera-t-il assuré par différentes organisations? Y aura-t-il plusieurs implémentations du client (ou serveur)? Le client open source et l'implémentation du serveur sont-ils secrets? Si la réponse à toutes ces questions est "Non", alors quelque chose de plus complexe qu'un seul référentiel est susceptible de n'apporter que des inconvénients sans aucun avantage.

Si vous choisissez de maintenir des bases de code distinctes, vous aurez besoin de politiques claires sur la façon dont cela est administré, afin d'éviter les incompatibilités et l'enfer des dépendances. Après avoir travaillé sur les premiers hoquets, vous découvrirez peut-être que la chose la plus sûre est de toujours vérifier les deux référentiels ensemble, de les construire ensemble et de les déployer ensemble ... ce qui va évidemment à l'encontre de l'objectif de les séparer!

La modularité est une belle propriété, mais le fractionnement des référentiels n'est pas un outil pour y parvenir. Comme le paragraphe précédent l'indique, vous pouvez avoir des composants hautement couplés qui sont divisés sur plusieurs bases de code (indésirable), et de même, vous pouvez avoir des composants hautement modulaires dans la même base de code (souhaitable).

À plusieurs reprises, j'ai plaidé (avec succès) pour que mon équipe fusionne les référentiels git existants, car cela simplifiait le développement et le déploiement.

Todd Owen
la source
0

Oubliez le référentiel un instant. Comment organiseriez-vous les deux projets sur votre machine si vous ne partagiez avec personne? Comment le reste de l'équipe le ferait-il? Voudriez-vous...

  • Placer tous les fichiers source du client et du serveur dans le même répertoire?

  • Créer un répertoire de projet principal contenant des sous-répertoires pour le client et le serveur?

  • Gardez les deux projets complètement séparés?

Une fois que vous êtes parvenu à un consensus à ce sujet en tant qu'équipe, vous êtes prêt à archiver les projets dans votre référentiel de code. Tous les outils de contrôle des révisions auxquels je peux penser sont heureux de reproduire la structure de répertoires que vous aimez - ils ne se soucient pas du tout du fichier qui appartient à quel projet. Et la différence entre avoir un référentiel ou deux (ou six) n'est généralement pas si grande, à part des différences administratives mineures.

Par exemple, avec Subversion, la plus grande différence entre des référentiels séparés pour le client et le serveur et un référentiel combiné unique réside dans la façon dont les numéros de révision changent. Avec un référentiel unique, le numéro de version augmentera chaque fois que vous validerez du code sur le client ou le serveur. Avec des référentiels séparés, une validation sur le projet de serveur ne changera pas le numéro de révision de tête pour le client.

Caleb
la source