ĂversĂ€ttningen av artikeln förbereddes för studenter i kursen i utbildningsprojektet OTUS.
Du bör vÀlja monorepo eftersom det beteende som det frÀmjar i dina team Àr transparens och kollektivt ansvar, sÀrskilt nÀr team vÀxer. I vilket fall som helst mÄste du investera i verktyg, men det Àr alltid bÀttre nÀr standardbeteendet Àr det beteende du vill se i dina team.
Varför pratar vi om detta?
Matt Klein skrev en artikel â (övers. anm.: översĂ€ttning pĂ„ HabrĂ© ). Jag gillar Matt, jag tycker att han Ă€r mycket smart, och du bör lĂ€sa hans Ă„sikt. Ursprungligen publicerade han en omröstning pĂ„ Twitter:
ĂversĂ€ttning:
PĂ„ denna nyĂ„rsdag skulle jag argumentera för hur absurda monorepositorier Ă€r. Ă
r 2019 började obemÀrkt. I den andan föreslÄr jag en omröstning. Vem Àr stora entusiaster? FöresprÄkare:
â Monorepo
â Rust
â Felaktig omröstning / bĂ„da
Mitt svar var: «Jag Ă€r bokstavligen bĂ„da dessa personer». IstĂ€llet för att prata om hur Rust Ă€r en drog, lĂ„t oss gĂ„ igenom varför jag tycker att han har fel om monorepositorier. Lite om mig sjĂ€lv. Jag Ă€r teknisk chef för Chef Software. Vi har cirka 100 ingenjörer, en kodbas som Ă€r omkring 11â12 Ă„r gammal och 4 huvudprodukter. Del av denna kod ligger i polyrepo (min startposition), del i monorepo (min nuvarande position).
Innan jag börjar: varje argument jag tar upp hÀr kommer att tillÀmpas pÄ bÄda typerna av repositorier. Enligt min mening finns det ingen teknisk anledning till varför du bör vÀlja den ena eller den andra typen av repository. Du kan fÄ vilket tillvÀgagÄngssÀtt som helst att fungera. Jag Àr glad att diskutera detta, men jag Àr inte intresserad av konstgjorda tekniska anledningar till att det ena övergÄr det andra.
Jag hÄller med om den första delen av Matts synpunkt:
För pÄ stor skala kommer ett monorepo att hantera alla de samma problemen som ett polyrepo, men samtidigt utmana dig till en starkare sammankoppling av din kod och krÀva otroliga insatser för att öka skalbarheten av ditt versionskontrollsystem.
Oavsett om du vĂ€ljer en monorepo eller polyrepo kommer du att stĂ€llas inför samma problem. Hur slĂ€pper ni nya versioner? Vad Ă€r er strategi för uppdateringar? BakĂ„tkompatibilitet? Ămsesidiga beroenden mellan projekt? Vilka arkitekturstilar Ă€r acceptabla? Hur hanterar ni er bygg- och testinfrastruktur? Listan kan göras oĂ€ndlig. Och ni kommer att behöva lösa dem alla i takt med att ni vĂ€xer. Ingen gratis ost finns.
Jag tror att Matts argument liknar Äsikter som delas av mÄnga ingenjörer (och chefer) som jag respekterar. Det kommer frÄn perspektivet hos en ingenjör som arbetar med en komponent eller ett team som arbetar med en komponent. Du hör saker som:
- Koden Ă€r otymplig â jag behöver inte allt det hĂ€r skrĂ€pet.
- Det Àr svÄrare att testa eftersom jag mÄste kolla allt det hÀr skrÀpet som jag inte behöver.
- Det Àr svÄrare att arbeta med externa beroenden.
- Jag behöver mina egna versionshanteringssystem.
SjĂ€lvklart Ă€r alla dessa punkter berĂ€ttigade. Det Ă€r fallet i bĂ„da scenarierna â i en polyrepo har jag mitt skrĂ€p, förutom det som behövs för byggandet⊠Jag kan behöva Ă€nnu mer skrĂ€p. SĂ„ jag "bara" skapar verktyg som checkoutar hela projektet. Eller sĂ„ skapar jag ett falskt monorepo med submoduler. Vi skulle kunna diskutera detta hela dagen. Men jag tror att Matts argument missar den grundlĂ€ggande anledningen till varför jag starkt föresprĂ„kar monorepo:
Det frÀmjar kommunikation och visar pÄ problem.
NÀr vi delar upp repository skapar vi de facto en koordinerings- och transparensproblematik. Det matchar hur vi tÀnker pÄ team (sÀrskilt hur enskilda deltagare tÀnker pÄ dem): vi Àr ansvariga för en viss komponent. Vi arbetar relativt isolerat. GrÀnserna faststÀlls kring mitt team och de komponenter vi arbetar med.
NÀr arkitekturen blir mer komplex kan ett team inte lÀngre hantera den ensamt. Mycket fÄ ingenjörer har hela systemet i huvudet. Anta att du hanterar en gemensam komponent A som anvÀnds av team B, C och D. Team A refaktorerar, förbÀttrar API:et och Àndrar den interna implementationen. Som resultat blir förÀndringarna bakÄtkompatibla. Vilket rÄd skulle du ge?
- Identifiera alla platser dÀr det gamla API:et anvÀnds.
- Finns det platser dÀr det nya API:et inte kan anvÀndas?
- Kan ni fixa och testa andra komponenter för att sÀkerstÀlla att de inte gÄr sönder?
- Kan dessa team kontrollera era förÀndringar just nu?
Observera att dessa frÄgor inte beror pÄ typ av lager. Ni behöver hitta team B, C och D. Ni mÄste prata med dem, ta reda pÄ deras tidsramar och förstÄ deras prioriteringar. à tminstone hoppas vi att ni gör det.
Ingen vill faktiskt göra detta. Det Àr mycket mindre spÀnnande Àn att bara fixa det förbannade API:et. Allt detta Àr mÀnskligt och komplicerat. I ett polerat lager kan ni helt enkelt göra Àndringar, ge dem för granskning till dem som arbetar med den hÀr komponenten (förmodligen inte B, C eller D) och gÄ vidare. Team B, C och D kan förbli pÄ sin nuvarande version för tillfÀllet. De kommer att uppdatera sig sjÀlva nÀr de inser er genialitet!
I ett monolager förÀndras ansvaret per automatik. Team A Àndrar sin komponent och om de inte Àr försiktiga bryter de omedelbart B, C och D. Detta leder till att B, C och D dyker upp vid dörren hos A och undrar varför team A har brutit bygget. Detta lÀr A att de inte kan hoppa över min lista ovan. De mÄste prata om vad de planerar att göra. Kan B, C och D gÄ vidare? Vad hÀnder om B och C kan, men D Àr djupt kopplad till sideffekterna av det gamla algoritmens beteende?
Vi mÄste sedan prata om hur vi ska ta oss ur denna situation:
- Stödja flera interna API:er, dÀr den gamla algoritmen markeras som förÄldrad tills D kan sluta anvÀnda den.
- Stödja flera versionsutgÄvor, en med det gamla grÀnssnittet, en med det nya.
- Fördröja lanseringen av förÀndringarna i A tills B, C och D samtidigt kan ta emot dem.
Anta att vi har valt 1, flera API:er. I sÄ fall har vi tvÄ bitar av kod. Den gamla och den nya. Ganska praktiskt i vissa situationer. Vi ÄterstÀller den gamla koden, markerar den som förÄldrad (deprecated) och samordnar en tidsplan för dess borttagning med team D. I praktiken Àr det identiskt för bÄde poly- och monorepo.
För att slĂ€ppa flera versioner behöver vi en gren. Nu har vi tvĂ„ komponenter â A1 och A2. Team B och C anvĂ€nder A2, medan D anvĂ€nder A1. Vi behöver att varje komponent Ă€r redo för release, för innan D kan gĂ„ vidare kan sĂ€kerhetsuppdateringar och andra buggfixar krĂ€vas. I poly-repon kan vi dölja detta i en lĂ„nglivad gren, som kĂ€nns bra. I monorepo tvingar vi att skapa kod i en ny modul. Team D mĂ„ste fortfarande göra Ă€ndringar i den "gamla" komponenten. Alla kan se kostnaden vi betalar hĂ€r â vi har nu dubbelt sĂ„ mycket kod, och alla buggfixar som tillĂ€mpas pĂ„ A1 och A2 mĂ„ste tillĂ€mpas pĂ„ bĂ„da. Med grensystemet i poly-repo Ă€r detta dolt bakom cherry-pick. Vi ser kostnaden som mindre, för dĂ€r sker ingen duplicering. Ur praktisk synvinkel Ă€r kostnaden densamma: du kommer att skapa, slĂ€ppa och underhĂ„lla tvĂ„ i huvudsak identiska kodbaser tills du kan ta bort en av dem. Skillnaden Ă€r att smĂ€rtan i monorepo Ă€r direkt och synlig. Det Ă€r Ă€nnu vĂ€rre, och det Ă€r bra.
Ăntligen har vi kommit till den tredje punkten. Förseningen av lanseringen. Det Ă€r möjligt att de Ă€ndringar som team A gör kommer att förbĂ€ttra livet för team A. Viktigt, men inte brĂ„dskande. Kan vi bara fördröja det? I monorepot pushar vi detta för att befĂ€sta artefakten. SjĂ€lvklart pratar vi om det med team D. HĂ„ll bara kvar vid den gamla versionen tills ni hinner ikapp! Detta sĂ€tter tonen för en fegare instĂ€llning. Team A fortsĂ€tter att arbeta med sin komponent, och ignorerar det faktum att team D anvĂ€nder en allt mer förĂ„ldrad version (det Ă€r team D:s problem, de Ă€r dumma). Under tiden pratar team D negativt om team A:s nonchalanta instĂ€llning till kodens stabilitet, om de ens nĂ€mner det. MĂ„nader gĂ„r. Till slut bestĂ€mmer sig team D för att se pĂ„ möjligheten att uppdatera, men Ă€ndringarna i A har bara blivit fler. Team A minns knappt nĂ€r och hur de bröt D. Uppdateringen blir mer smĂ€rtsam och tar lĂ€ngre tid. Detta sĂ€tter det lĂ€ngre ner pĂ„ prioriteringslistan. Tills den dagen dĂ„ vi fĂ„r ett sĂ€kerhetsproblem i A som tvingar oss att göra en branch. Team A mĂ„ste gĂ„ tillbaka i tiden, hitta den punkt dĂ„ D var stabilt, fixa problemet dĂ€r och göra det redo för lansering. Detta Ă€r ett de facto-val som mĂ€nniskor gör, och det Ă€r definitivt det sĂ€msta. Det verkar vara bra för bĂ„de team A och D, sĂ„ lĂ€nge vi kan ignorera varandra.
I monorepot Àr det verkligen inte ett alternativ. Du Àr tvungen att hantera situationen pÄ tvÄ sÀtt. Du behöver se kostnaderna för att ha tvÄ release-grenar. LÀra dig att skydda dig mot uppdateringar som bryter bakÄtkompatibiliteten. Men det viktigaste Àr: du kan inte undvika en svÄr konversation.
Enligt min erfarenhet, nÀr teamen blir stora, finns det inte lÀngre möjlighet att hÄlla hela systemet i huvudet, och det Àr den viktigaste delen. Du mÄste förbÀttra synligheten för motsÀttningarna i systemet. Du mÄste aktivt arbeta för att fÄ teamen att titta bort frÄn sina komponenter och se pÄ arbetet hos andra team och konsumenter.
Ja, du kan skapa verktyg som försöker lösa problemet med polymorf repon. Men min erfarenhet av kontinuerlig leverans och automatisering pÄ stora företag sÀger mig följande: standardbeteendet utan att anvÀnda extra verktyg Àr det beteende du förvÀntar dig att se. Standardbeteendet för polymorfa repon Àr isolering, det Àr hela poÀngen. Standardbeteendet för monorepo Àr gemensamt ansvar och transparens, det Àr hela poÀngen. I bÄda fallen planerar jag att skapa ett verktyg som gör det enklare. Som ledare kommer jag alltid att vÀlja monorepo, eftersom verktyg bör stÀrka den kultur jag vill ha, och kulturen kommer frÄn smÄ beslut och dagligt arbete frÄn teamet.
Endast registrerade anvÀndare kan delta i omröstningen. , tack.
Vem Àr mer fanatisk? AnhÀngare:
Monorepo
Rust
Felaktig omröstning / bÄda
33 anvÀndare röstade. 13 anvÀnde sig av avhÄllsamhet.
KĂ€lla: habr.com
