De vertaling van het artikel is voorbereid voor studenten van de cursus in het onderwijproject OTUS.
Je zou voor een monorepository moeten kiezen, omdat het gedrag dat het in je teams bevordert transparantie en collectieve verantwoordelijkheid is, vooral bij het groeien van teams. Hoe dan ook, je zult moeten investeren in gereedschap, maar het is altijd beter wanneer het standaardgedrag is wat je wilt zien in je teams.
Waarom praten we hierover?
Matt Klein schreef een artikel (opmerking van de vertaler: vertaling op Habra) ). Ik vind Matt leuk, ik denk dat hij erg slim is, en je moet zijn standpunt lezen. Oorspronkelijk publiceerde hij een enquête op Twitter:
Vertaling:
Op deze nieuwjaarsdag zal ik betogen hoe belachelijk monorepositories zijn. 2019 is onopgemerkt begonnen. In die geest bied ik je een enquête aan. Wie zijn de grote fans? Voorstanders:
— Monorepository
— Rust
— Incorrecte enquête / beide
Mijn antwoord was: «Ik ben letterlijk beide van deze mensen». In plaats van te praten over hoe Rust een verslaving is, laten we bespreken waarom ik denk dat hij het bij monorepositories mis heeft. Een beetje over mij. Ik ben technisch directeur bij Chef Software. We hebben ongeveer 100 ingenieurs, een codebasis van ongeveer 11–12 jaar oud en 4 hoofdproducten. Een deel van die code bevindt zich in een polyrepository (mijn startpositie), een deel in een monorepository (mijn huidige positie).
Voordat ik begin: elk argument dat ik hier aandraag, geldt voor beide soorten repositories. Naar mijn mening zijn er geen technische redenen om de ene of de andere repository te kiezen. Je kunt elke aanpak doen werken. Ik praat daar graag over, maar ik ben niet geïnteresseerd in kunstmatige technische redenen waarom de een beter zou zijn dan de ander.
Ik ben het eens met het eerste deel van Matts standpunt:
Omdat een monorepository op grote schaal al dezelfde problemen zal oplossen als een polyrepository, maar je tegelijkertijd uitnodigt tot sterke verbondenheid van je code en ongelooflijke inspanningen vereist om de schaalbaarheid van je versiebeheersysteem te vergroten.
U staat voor dezelfde problemen, of u nu voor een monorepository of een polyrepository kiest. Hoe publiceert u releases? Wat is uw aanpak voor updates? Achterwaartse compatibiliteit? Kruisafhankelijkheden tussen projecten? Welke architecturale stijlen zijn acceptabel? Hoe beheert u uw build- en testinfrastructuur? De lijst is eindeloos. En u zult ze allemaal oplossen naarmate u groeit. Er is geen gratis kaas.
Ik denk dat het argument van Matt vergelijkbaar is met de opvattingen die veel ingenieurs (en managers) delen die ik respecteer. Dit komt vanuit het perspectief van een ingenieur die aan een component werkt, of een team dat aan een component werkt. U hoort zaken als:
- De codebase is omvangrijk — ik heb al die rommel niet nodig.
- Het is moeilijker te testen, omdat ik al die rommel moet controleren die ik niet nodig heb.
- Het is moeilijker om met externe afhankelijkheden te werken.
- Ik heb mijn eigen virtuele versiebeheersystemen nodig.
Zeker, al deze punten zijn gerechtvaardigd. Dit geldt in beide gevallen — in een polyrepository heb ik mijn rommel, naast wat nodig is voor de build... Ik heb mogelijk nog meer rommel nodig. Daarom creëer ik "simpelweg" tools die de hele projectcheckout uitvoeren. Of ik maak een nep monorepository met submodules. We zouden hier de hele dag omheen kunnen draaien. Maar ik denk dat het argument van Matt de belangrijkste reden overslaat die ik sterk heb omgedraaid in het voordeel van een monorepository:
Het stimuleert communicatie en laat problemen zien.
Wanneer we repositories scheiden, creëren we de facto een probleem van coördinatie en transparantie. Dit komt overeen met hoe we over teams denken (vooral hoe individuele leden over hen denken): we zijn verantwoordelijk voor een bepaalde component. We werken in relatieve isolatie. De grenzen zijn vastgesteld op mijn team en de component(-en) waaraan we werken.
Bij het complexer maken van de architectuur kan één team het niet langer alleen beheren. Heel weinig ingenieurs houden het volledige systeem in hun hoofd. Stel dat u een gemeenschappelijk component A beheert dat door teams B, C en D wordt gebruikt. Team A voert refactoring uit, verbetert de API en wijzigt de interne implementatie. Hierdoor zijn de wijzigingen niet meer compatibel met eerdere versies. Welk advies zou u geven?
- Vind alle plekken waar de oude API wordt gebruikt.
- Zijn er plekken waar de nieuwe API niet kan worden gebruikt?
- Kunt u andere componenten aanpassen en testen om er zeker van te zijn dat ze niet kapot gaan?
- Kunnen deze teams uw wijzigingen nu controleren?
Houd er rekening mee dat deze vragen niet afhankelijk zijn van het type repository. U moet teams B, C en D vinden. U moet met hen praten, hun tijdlijn begrijpen en hun prioriteiten leren kennen. Tenminste, we hopen dat u dat doet.
Eigenlijk wil niemand zich hiermee bezighouden. Het is veel minder spannend dan gewoon die verdomde API te repareren. Dit is allemaal menselijk en ingewikkeld. In een polirepository kunt u eenvoudig wijzigingen aanbrengen, deze ter beoordeling geven aan degenen die aan die component werken (waarschijnlijk niet B, C of D) en verder gaan. Teams B, C en D kunnen voorlopig gewoon op hun huidige versie blijven. Ze zullen bijwerken zodra ze uw genialiteit beseffen!
In een monorepository verschuift de verantwoordelijkheid standaard. Team A wijzigt zijn component en, als ze niet voorzichtig zijn, breken ze onmiddellijk B, C en D. Dit zorgt ervoor dat B, C en D aan de deur van A verschijnen, zich afvragend waarom team A de build heeft gebroken. Dit leert A dat ze mijn bovenstaande lijst niet kunnen negeren. Ze moeten praten over wat ze van plan zijn te doen. Kunnen B, C en D vooruit? Wat als B en C dat kunnen, maar D nauw verbonden is met het bijeffect van het gedrag van het oude algoritme?
Dan moeten we praten over hoe we uit deze situatie komen:
- Ondersteuning voor meerdere interne API's, waarbij het oude algoritme als verouderd wordt gemarkeerd totdat D het niet meer kan gebruiken.
- Ondersteuning voor meerdere versies van releases, één met de oude interface, één met de nieuwe.
- Uitgestelde release van wijzigingen A totdat B, C en D tegelijkertijd deze kunnen accepteren.
Stel dat we 1 kiezen, verschillende API's. In dit geval hebben we twee stukken code. Een oude en een nieuwe. Dit is in sommige situaties behoorlijk handig. We zetten de oude code terug, markeren deze als verouderd (deprecated) en stemmen de planning voor de verwijdering ervan af met team D. In wezen is dit identiek voor poly en mono-repositories.
Voor de release van verschillende versies hebben we een branch nodig. Nu hebben we twee componenten - A1 en A2. Teams B en C gebruiken A2, terwijl D A1 gebruikt. We moeten ervoor zorgen dat elk component release-klaar is, want voordat D verder kan, kunnen er beveiligingsupdates en andere bugfixes nodig zijn. In de poly-repository kunnen we dit verbergen in een langlevende branch, wat goed aanvoelt. In de mono-repository forceren we een code creatie in een nieuwe module. Team D zal nog steeds wijzigingen moeten aanbrengen in de 'oude' component. Iedereen kan de kosten zien die we hier dragen - we hebben nu tweemaal zoveel code, en eventuele bugfixes die op A1 en A2 worden toegepast, moeten voor hen beiden worden toegepast. Met de takkenbenadering in de poly-repository is dit verborgen achter cherry-pick. We beschouwen de kosten als lager, omdat er geen duplicatie is. Vanuit praktisch oogpunt zijn de kosten hetzelfde: je zult twee in wezen identieke codebases bouwen, uitbrengen en onderhouden totdat je er een kunt verwijderen. Het verschil is dat deze pijn in de mono-repository direct en in het zicht is. Dit is nog erger, en dat is goed.
Eindelijk zijn we aangekomen bij het derde punt: de uitstel van de release. Het kan zijn dat de wijzigingen aangebracht door A het leven van team A verbeteren. Belangrijk, maar niet urgent. Kunnen we het gewoon uitstellen? In de monorepo duwen we dit om het artefact vast te leggen. Natuurlijk spreken we hierover met team D. Blijf gewoon op de oude versie totdat je bij bent! Dit creëert een situatie van angst. Team A blijft werken aan hun component, zonder rekening te houden met het feit dat team D een steeds verouderde versie gebruikt (dat is het probleem van team D, ze zijn dom). Ondertussen praat team D slecht over de onvoorzichtige houding van team A ten aanzien van de stabiliteit van de code, als ze er überhaupt over praten. Maanden verstrijken. Uiteindelijk besluit team D om te bekijken of een update mogelijk is, maar de wijzigingen in A zijn alleen maar toegenomen. Team A herinnert zich nauwelijks wanneer en hoe ze D hebben gebroken. Het updaten is nu pijnlijker en zal meer tijd kosten. Wat het verder naar beneden duwt op de prioriteitenlijst. Tot de dag dat we een beveiligingsprobleem in A tegenkomen, wat ons dwingt om een branch te maken. Team A moet terug in de tijd reizen, het moment vinden waarop D stabiel was, het probleem daar oplossen en het klaar maken voor release. Dit is de facto de keuze die mensen maken, en het is zeker de slechtste. Het lijkt goed te zijn voor zowel team A als D, zolang we elkaar kunnen negeren.
In de monorepo is de derde echt geen optie. Je moet omgaan met de situatie op een van de twee manieren. Je moet de kosten zien van het hebben van twee release branches. Leren jezelf te beschermen tegen updates die de achterwaartse compatibiliteit breken. Maar het belangrijkste: je kunt de moeilijke conversatie niet vermijden.
Uit mijn ervaring, wanneer teams groter worden, is het niet meer mogelijk om het hele systeem in gedachten te houden, en dat is het belangrijkste. Je moet de zichtbaarheid van meningsverschillen in het systeem verbeteren. Je moet actief werken om teams te helpen hun aandacht van hun componenten af te halen en te kijken naar het werk van andere teams en de consumenten.
Ja, je kunt tools creëren die proberen het probleem van poly-repositories op te lossen. Maar mijn ervaring met continue levering en automatisering in grote ondernemingen vertelt me het volgende: het standaardgedrag zonder extra tools is het gedrag dat je verwacht te zien. Het standaardgedrag van een poly-repository is isolatie, dat is de essentie. Het standaardgedrag van een monorepository is gedeelde verantwoordelijkheid en transparantie, dat is de essentie. In beide gevallen ben ik van plan een tool te creëren die de scherpe hoeken verzacht. Als leider zal ik elke keer voor een monorepository kiezen, omdat tools de cultuur moeten versterken die ik wil, en cultuur komt voort uit kleine beslissingen en het dagelijkse werk van het team.
Alleen geregistreerde gebruikers kunnen deelnemen aan de enquête. , alstublieft.
Wie zijn de grotere fanatici? Voorstanders:
Monorepository
Rust
Incorrecte enquête / beide
33 gebruikers stemden. 13 gebruikers onthielden zich.
Bron: habr.com
