La traduction de l'article est préparée pour les étudiants du cours dans le projet éducatif OTUS.
Vous devez opter pour un monorepo, car le comportement qu'il favorise au sein de vos équipes est la transparence et la responsabilité collective, surtout lorsqu'il s'agit de l'expansion des équipes. 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 voir dans vos équipes.
Pourquoi en parlons-nous ?
Matt Klein a écrit un article (note du traducteur : traduction sur Habré ). J'aime Matt, je pense qu'il est très intelligent, et vous devriez lire son point de vue. Il a d'abord publié un sondage sur Twitter :
Traduction :
En ce jour de nouvel an, je vais débattre sur l'absurdité des monorepos. L'année 2019 a commencé discrètement. Dans cet esprit, je vous propose un sondage. Qui sont les grands fanatiques ? Les partisans :
— Monorepo
— Rust
— Sondage incorrect / les deux
Ma réponse était : « Je suis littéralement ces deux personnes ». Au lieu de discuter de la façon dont Rust est une drogue, voyons pourquoi je pense qu'il a tort au sujet des monorepos. Un peu sur moi. Je suis directeur technique de Chef Software. Nous avons environ 100 ingénieurs, une base de code de près de 11 à 12 ans et 4 produits principaux. Une partie de ce code se trouve dans un polyrepo (ma position de départ), et une autre dans un monorepo (ma position actuelle).
Avant de commencer : chaque argument que j'expose ici sera applicable aux dépôts des deux types. À mon avis, il n'y a pas de raisons techniques qui justifient le choix de l'un ou l'autre type de dépôt. Vous pouvez faire fonctionner n'importe quelle approche. Je suis heureux d'en parler, mais je ne suis pas intéressé par des raisons techniques artificielles qui privilégieraient l'un sur l'autre.
Je suis d'accord avec la première partie du point de vue de Matt :
Parce qu'à grande échelle, un monorepo résoudra exactement les mêmes problèmes qu'un polyrepo, tout en vous incitant à avoir une forte cohésion dans votre code et nécessitant d'incroyables efforts pour augmenter la scalabilité de votre système de contrôle de version.
Vous devrez résoudre les mêmes problèmes, que vous choisissiez un monorépertoire ou un polyrépertoire. Comment publiez-vous des versions ? Quelle est votre approche des mises à jour ? La compatibilité descendante ? Les dépendances croisées des projets ? Quels styles architecturaux sont acceptables ? Comment gérez-vous votre infrastructure de construction et de test ? La liste est infinie. Et vous les résoudrez toutes au fur et à mesure de votre croissance. Il n'y a pas de fromage gratuit.
Je pense que l'argument de Matt ressemble à des points de vue partagés par de nombreux ingénieurs (et managers) que je respecte. Cela vient du point de vue d'un ingénieur travaillant sur un composant, ou d'une équipe travaillant sur un composant. Vous entendez des choses comme :
- La base de code est encombrante - je n'ai pas besoin de tout ce gâchis.
- C'est plus difficile à tester, car je dois vérifier tout ce gâchis dont je n'ai pas besoin.
- C'est plus compliqué de travailler avec des dépendances externes.
- J'ai besoin de mes propres systèmes de contrôle de version virtuels.
Sans aucun doute, tous ces points sont valables. C'est vrai dans les deux cas - dans un polyrépertoire, j'ai mon propre gâchis, en plus de celui nécessaire pour la construction... Je peux aussi avoir besoin d'un autre gâchis. Donc, je crée « simplement » des outils qui permettent de faire le checkout de l'ensemble du projet. Ou je crée un faux monorépertoire avec des sous-modules. Nous pourrions en discuter toute la journée. Mais je pense que l'argument de Matt omet la raison principale, pour laquelle j'ai assez fortement basculé en faveur du monorépertoire :
Il provoque la communication et met en lumière les problèmes
Lorsque nous séparons les dépôts, nous créons de facto un problème de coordination et de transparence. Cela correspond à la façon dont nous pensons aux équipes (surtout à la façon dont les membres perçoivent leur travail) : nous sommes responsables d'un certain composant. Nous travaillons en relative isolation. Les frontières sont fixées autour de mon équipe et du ou des composants 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 peuvent garder l'ensemble du système en tête. Supposons que vous gériez un composant commun A, utilisé par les équipes B, C et D. L'équipe A refactore, améliore l'API et modifie également l'implémentation interne. En conséquence, ces changements ne sont pas rétrocompatibles. Quel conseil donneriez-vous?
- Identifier tous les endroits où l'ancien API est utilisé.
- Y a-t-il des cas où le nouvel API ne peut pas être utilisé?
- Pouvez-vous corriger et tester d'autres composants pour vous assurer qu'ils ne seront pas cassés?
- Ces équipes peuvent-elles vérifier vos modifications dès maintenant?
Notez que ces questions ne dépendent pas du type de dépôt. Vous devrez trouver les équipes B, C et D. Vous devrez leur parler, comprendre leur emploi du temps et leurs priorités. Du moins, nous espérons que vous le ferez.
En réalité, personne ne veut faire cela. C'est beaucoup moins excitant que de simplement corriger cet API. Tout cela est humain et compliqué. Dans un dépôt polyglot, vous pouvez simplement apporter des modifications, soumettre pour révision à ceux qui travaillent sur ce composant (probablement pas B, C ou D) et passer à autre chose. Pendant ce temps, les équipes B, C et D peuvent rester sur leur version actuelle. Elles mettront à jour une fois qu'elles auront réalisé votre génie!
Dans un dépôt monorepo, la responsabilité passe par défaut. L'équipe A change son composant et, si elle n'est pas prudente, casse immédiatement B, C et D. Cela conduit B, C et D à frapper à la porte de A, se demandant pourquoi l'équipe A a cassé la build. Cela enseigne à A qu'elle ne peut pas ignorer ma liste ci-dessus. Elles doivent parler de ce qu'elles envisagent de faire. B, C et D peuvent-ils avancer? Que se passe-t-il si B et C peuvent, mais que D était étroitement lié à l'effet secondaire du vieux comportement de l'algorithme?
Nous devons ensuite parler de la manière dont nous allons sortir de cette situation :
- Support de plusieurs API internes, l'ancien algorithme étant marqué comme obsolète jusqu'à ce que D puisse cesser de l'utiliser.
- Support de plusieurs versions de version, une avec l'interface ancienne, une avec la nouvelle.
- Retarder le déploiement des modifications A jusqu'à ce que B, C et D puissent les accepter simultanément.
Supposons que nous ayons choisi 1, plusieurs API. Dans ce cas, nous avons deux morceaux de code. Ancien et nouveau. Assez pratique dans certaines situations. Nous réintégrons l'ancien code, le marquons comme obsolète (deprecated) et convenons d'un calendrier pour sa suppression avec l'équipe D. Essentiellement identique pour le poly et le mono dépôt.
Pour la sortie de plusieurs versions, nous avons besoin d'une branche. Maintenant, nous avons deux composants — A1 et A2. Les équipes B et C utilisent A2, tandis que D utilise A1. Nous devons nous assurer que chaque composant est prêt pour la sortie, car avant que D puisse avancer, des mises à jour de sécurité et des corrections d'autres bogues peuvent être nécessaires. Dans le poly dépôt, nous pouvons cacher cela dans une branche à long terme qui fonctionne bien. Dans le mono dépôt, nous sommes contraints de créer du code dans un nouveau module. L'équipe D devra toujours apporter des modifications à l'ancien composant. Tout le monde peut voir le coût que nous payons ici — nous avons maintenant le double du code, et toutes les corrections de bogues appliquées à A1 et A2 doivent être appliquées à tous les deux. Avec l'approche de l'utilisation des branches dans le poly dépôt, cela est caché derrière le cherry-pick. Nous considérons le coût comme moindre car il n'y a pas de duplication. D'un point de vue pratique, le coût est le même : vous allez créer, publier et maintenir deux bases de code essentiellement identiques jusqu'à ce que vous puissiez en supprimer une. La différence est que dans le mono dépôt, cette douleur est directe et visible. C'est encore pire, et c'est bien.
Enfin, nous en sommes au troisième point. Le retard dans la publication. 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 attendre? Dans le monoréférentiel, nous nous dirigeons vers la consolidation de l'artefact. Bien sûr, nous en parlons à l'équipe D. Restez simplement sur l'ancienne version, jusqu'à ce que vous soyez à jour! Cela crée une atmosphère de jeu de cache-cache. 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 idiots). Pendant ce temps, l'équipe D parle mal de l'attitude imprudente de l'équipe A à l'égard de la stabilité du code, s'ils en parlent même. Les mois passent. Enfin, l'équipe D décide de considérer la possibilité d'une mise à jour, mais les changements dans A ne font qu'augmenter. L'équipe A peine se souvient quand et comment ils ont cassé D. La mise à jour sera plus douloureuse et prendra plus de temps. Ce qui l'envoie plus bas dans la liste des priorités. Jusqu'au jour où nous aurons un problème de sécurité dans A, ce qui nous oblige à faire une branche. L'équipe A doit revenir en arrière, trouver le moment où D était stable, corriger le problème et le préparer pour la publication. C'est un choix de facto que font les gens, et c'est sans aucun doute le pire. On dirait que c'est bien pour les équipes A et D, tant que nous pouvons nous ignorer.
Dans un monoréférentiel, le troisième n'est vraiment pas une option. Vous devez gérer la situation de l'une des deux manières. Vous devez comprendre les coûts d'avoir deux branches de publication. Apprendre à vous protéger contre les mises à jour qui cassent la rétrocompatibilité. Mais surtout : vous ne pouvez pas éviter une conversation difficile.
D'après mon expérience, lorsque les équipes deviennent grandes, il n'est plus possible de garder en tête l'ensemble du système, et c'est la partie la plus importante. Vous devez améliorer la visibilité des divergences dans le système. Vous devez travailler activement pour amener les équipes à détourner leur attention de leurs composants et à se concentrer sur le travail des autres équipes et des consommateurs.
Oui, vous pouvez créer des outils qui tenteront de résoudre le problème des polirépôts. Mais mon expérience de l'apprentissage entre livraison continue (continuous delivery) et de l'automatisation dans les grandes entreprises me dit ceci : le comportement par défaut sans outils supplémentaires est celui que vous vous attendez à voir. Le comportement par défaut d'un polirépôt est l'isolation, c'est tout son sens. Le comportement d'un monorépôt est une responsabilité collective et de la transparence, c'est tout son sens. Dans les deux cas, je vais créer un outil qui permettra d'adoucir les angles. En tant que responsable, je choisirai un monorépôt à chaque fois, car les outils doivent renforcer la culture que je souhaite, et la culture découle des petites décisions et du travail quotidien de l'équipe.
Seuls les utilisateurs enregistrés peuvent participer au sondage. , s'il vous plaît.
Qui sont les plus grands fanatiques ? Les partisans :
Monorepo
Rust
Sondage incorrect / les deux
33 utilisateurs ont voté. 13 utilisateurs se sont abstenus.
Source : habr.com
