Monodépôts : s'il vous plaît, devez

Monodépôts : s'il vous plaît, devez

Traduction de l'article préparé pour les étudiants du cours "Pratiques et outils DevOps" dans le projet pédagogique OTUS.

Vous devez choisir un monoréférentiel car le comportement qu'il favorise au sein de vos équipes est la transparence et la responsabilité partagée, d'autant plus que les équipes grandissent. Quoi qu'il en soit, vous devrez investir dans des outils, mais il est toujours préférable que le comportement par défaut soit celui que vous souhaitez dans vos commandes.

Pourquoi parle-t-on de cela ?

Matt Klein a écrit l'article "Monorepos : s'il vous plaît, ne le faites pas !"  (ndlr : traduction sur Habré « Monodépôts : s’il vous plaît, ne le faites pas »). J'aime Matt, je pense qu'il est très intelligent et vous devriez lire son point de vue. Il a initialement publié le sondage sur Twitter :

Monodépôts : s'il vous plaît, devez

Traduction:
Ce jour du Nouvel An, je vais expliquer à quel point les monodépôts sont ridicules. L’année 2019 a commencé tranquillement. Dans cet esprit, je vous propose une enquête. Qui sont les grands fanatiques ? Partisans:
- Monorepo
- Calme
- Sondage incorrect/les deux

Ma réponse a été : « Je suis littéralement ces deux personnes. » Au lieu de dire que Rust est une drogue, voyons pourquoi je pense qu'il se trompe à propos des monodépôts. Un peu de vous. Je suis le CTO de Chef Software. Nous avons environ 100 ingénieurs, une base de code datant d'environ 11 à 12 ans et 4 produits principaux. Une partie de ce code est dans un polydépôt (ma position de départ), une partie est dans un monodépôt (ma position actuelle).

Avant de commencer : tous les arguments que je avance ici s'appliqueront aux deux types de référentiels. À mon avis, il n’y a aucune raison technique pour laquelle vous devriez choisir un type de référentiel plutôt qu’un autre. Vous pouvez faire fonctionner n’importe quelle approche. Je suis heureux d'en parler, mais je ne m'intéresse pas aux raisons techniques artificielles pour lesquelles l'un est supérieur à l'autre.

Je suis d'accord avec la première partie du point de Matt :

Parce qu'à grande échelle, un monodépôt résoudra tous les mêmes problèmes qu'un polydépôt, mais en même temps vous obligeant à coupler étroitement votre code et nécessitant des efforts incroyables pour augmenter l'évolutivité de votre système de contrôle de version.

Vous devrez résoudre les mêmes problèmes que vous choisissiez un mono-dépôt ou un poly-dépôt. Comment publiez-vous les versions ? Quelle est votre approche des mises à jour ? Rétrocompatibilité? Dépendances croisées entre projets ? Quels styles architecturaux sont acceptables ? Comment gérez-vous votre infrastructure de build et de test ? La liste est interminable. Et vous les résoudrez tous au fur et à mesure de votre croissance. Il n'y a pas de fromage gratuit.

Je pense que l'argument de Matt est similaire aux opinions partagées par de nombreux ingénieurs (et managers) que je respecte. Cela se produit du point de vue de l’ingénieur travaillant sur le composant ou de l’équipe travaillant sur le composant. Vous entendez des choses comme :

  • La base de code est volumineuse – je n’ai pas besoin de toutes ces cochonneries.
  • C'est plus difficile à tester parce que je dois tester toutes ces cochonneries dont je n'ai pas besoin.
  • Il est plus difficile de travailler avec des dépendances externes.
  • J'ai besoin de mes propres systèmes de contrôle de version virtuel.

Bien entendu, tous ces points sont justifiés. Cela se produit dans les deux cas - dans le polydépôt, j'ai mes propres fichiers indésirables, en plus de ceux nécessaires à la construction... Je peux aussi avoir besoin d'autres fichiers indésirables. Je crée donc « simplement » des outils qui vérifient l’ensemble du projet. Ou je crée un faux monodépôt avec des sous-modules. On pourrait s'y promener toute la journée. Mais je pense que l'argument de Matt passe à côté de la raison principale, que j'ai largement inversée en faveur du mono-dépôt :

Cela provoque la communication et montre des problèmes

Lorsque nous séparons les référentiels, nous créons de facto un problème de coordination et de transparence. Cela correspond à la façon dont nous pensons aux équipes (en particulier la façon dont les membres individuels les perçoivent) : nous sommes responsables d'une certaine composante. Nous travaillons dans un isolement relatif. Les limites sont fixées sur mon équipe et le(s) composant(s) sur lesquels nous travaillons.

À mesure que l’architecture devient plus complexe, une équipe ne peut plus la gérer seule. Très peu d’ingénieurs ont l’intégralité du système en tête. Supposons que vous gérez un composant partagé A utilisé par les équipes B, C et D. L'équipe A est en train de refactoriser, d'améliorer l'API et de modifier également l'implémentation interne. Par conséquent, les modifications ne sont pas rétrocompatibles. Quels conseils avez-vous ?

  • Recherchez tous les endroits où l'ancienne API est utilisée.
  • Y a-t-il des endroits où la nouvelle API ne peut pas être utilisée ?
  • Pouvez-vous réparer et tester d’autres composants pour vous assurer qu’ils ne se cassent pas ?
  • Ces équipes peuvent-elles tester vos modifications dès maintenant ?

Veuillez noter que ces questions sont indépendantes du type de référentiel. Vous devrez trouver les équipes B, C et D. Vous devrez leur parler, connaître l'heure, comprendre leurs priorités. Du moins, nous espérons que vous le ferez.

Personne ne veut vraiment faire ça. C'est beaucoup moins amusant que de simplement réparer cette foutue API. Tout est humain et désordonné. Dans un polydépôt, vous pouvez simplement apporter des modifications, les transmettre aux personnes travaillant sur ce composant (probablement pas B, C ou D) pour révision, et passer à autre chose. Les équipes B, C et D peuvent simplement conserver leur version actuelle pour le moment. Ils se renouvelleront lorsqu'ils réaliseront votre génie !

Dans un monodépôt, la responsabilité est transférée par défaut. L'équipe A change de composant et, si elle ne fait pas attention, casse immédiatement B, C et D. Cela amène B, C et D à se présenter à la porte de A, se demandant pourquoi l'équipe A a cassé l'assemblage. Cela apprend à A qu'il ne peut pas ignorer ma liste ci-dessus. Ils doivent parler de ce qu'ils vont faire. B, C et D peuvent-ils bouger ? Et si B et C le pouvaient, mais que D était étroitement lié à un effet secondaire du comportement de l'ancien algorithme ?

Ensuite, nous devons parler de la manière dont nous allons sortir de cette situation :

  1. Prise en charge de plusieurs API internes et marquera l'ancien algorithme comme obsolète jusqu'à ce que D puisse cesser de l'utiliser.
  2. Prise en charge de plusieurs versions, une avec l'ancienne interface, une avec la nouvelle.
  3. Retardez la publication des modifications de A jusqu'à ce que B, C et D puissent les accepter simultanément.

Disons que nous avons sélectionné 1 ou plusieurs API. Dans ce cas, nous avons deux morceaux de code. Vieux et nouveau. Assez pratique dans certaines situations. Nous réintégrons l'ancien code, le marquons comme obsolète et convenons d'un calendrier de suppression avec l'équipe D. Essentiellement identique pour les référentiels poly et mono.

Pour publier plusieurs versions, nous avons besoin d'une branche. Nous avons maintenant deux composants : A1 et A2. Les équipes B et C utilisent A2 et D utilise A1. Nous avons besoin que chaque composant soit prêt à être publié, car des mises à jour de sécurité et d'autres corrections de bogues peuvent être nécessaires avant que D puisse avancer. Dans un polydépôt, nous pouvons cacher cela dans une branche de longue durée qui fait du bien. Dans un monodépôt, on force la création du code dans un nouveau module. L'équipe D devra encore apporter des modifications à "l'ancien" composant. Tout le monde peut voir le coût que nous payons ici : nous avons maintenant deux fois plus de code, et toutes les corrections de bugs qui s'appliquent à A1 et A2 doivent s'appliquer aux deux. Avec l'approche de branchement dans un polydépôt, cela est caché derrière le choix. Nous considérons que le coût est moindre car il n’y a pas de dédoublement. D'un point de vue pratique, le coût est le même : vous allez créer, publier et maintenir deux bases de code largement identiques jusqu'à ce que vous puissiez en supprimer une. La différence est qu’avec un monoréférentiel, cette douleur est directe et visible. C'est encore pire, et c'est bien.

Finalement, nous arrivons au troisième point. Retard de sortie. Il est possible que les changements apportés par A améliorent la vie de l’équipe A. Important, mais pas urgent. Pouvons-nous simplement retarder ? Dans un polydépôt, nous poussons ceci pour épingler l'artefact. Bien sûr, nous le disons à l'équipe D. Restez simplement sur l'ancienne version jusqu'à ce que vous ayez rattrapé votre retard ! Cela vous prépare à jouer le lâche. L'équipe A continue de travailler sur son composant, ignorant le fait que l'équipe D utilise une version de plus en plus obsolète (c'est le problème de l'équipe D, ils sont stupides). Pendant ce temps, l'équipe D parle mal de l'attitude négligente de l'équipe A envers la stabilité du code, si elle en parle. Les mois passent. Finalement, l'équipe D décide d'examiner la possibilité d'une mise à jour, mais A n'a que d'autres changements. L'équipe A se souvient à peine quand et comment elle a cassé D. La mise à niveau est plus pénible et prendra plus de temps. Ce qui l'envoie plus bas dans la pile prioritaire. Jusqu'au jour où nous avons un problème de sécurité en A qui nous oblige à faire un branchement. L'équipe A doit remonter le temps, trouver un moment où D était stable, résoudre le problème à cet endroit et le préparer à la sortie. C’est le choix de facto que font les gens, et c’est de loin le pire. Cela semble être bon pour l’équipe A et l’équipe D tant que nous pouvons nous ignorer.

Dans un monodépôt, le troisième n’est vraiment pas une option. Vous êtes obligé de gérer la situation de deux manières. Vous devez voir les coûts liés à la présence de deux branches de version. Apprenez à vous protéger des mises à jour qui rompent la compatibilité ascendante. Mais le plus important: vous ne pouvez pas éviter d'avoir une conversation difficile.

D'après mon expérience, lorsque les équipes grandissent, il n'est plus possible de garder l'ensemble du système à l'esprit, et c'est la partie la plus importante. Vous devez améliorer la visibilité de la discorde dans le système. Vous devez travailler activement pour amener les équipes à détourner le regard de leurs composants et à examiner le travail des autres équipes et des consommateurs.

Oui, vous pouvez créer des outils qui tentent de résoudre le problème du polydépôt. Mais mon expérience dans l’enseignement de la livraison continue et de l’automatisation dans les grandes entreprises me dit ceci : le comportement par défaut sans utilisation d’outils supplémentaires est le comportement que vous vous attendez à voir. Le comportement par défaut d'un polydépôt est l'isolation, c'est tout l'intérêt. Le comportement par défaut d'un monodépôt est la responsabilité partagée et la transparence, c'est tout l'intérêt. Dans les deux cas, je vais créer un outil qui lissera les aspérités. En tant que leader, je choisirai à chaque fois un mono-dépôt car les outils doivent renforcer la culture que je souhaite, et la culture vient de petites décisions et du travail quotidien de l'équipe.

Seuls les utilisateurs enregistrés peuvent participer à l'enquête. se connecters'il te plait.

Qui sont les plus grands fanatiques ? Partisans:

  • Monorepo

  • Calme

  • Sondage incorrect/les deux

33 utilisateurs ont voté. 13 utilisateurs se sont abstenus.

Source: habr.com

Ajouter un commentaire