Mono-repozitorii: vă rog, este necesar

Mono-repozitorii: vă rog, este necesar

Articolul este tradus pentru studenții cursului „Practicile și instrumentele DevOps” din proiectul educațional OTUS.

Trebuie să alegi un monorepository, pentru că comportamentul pe care acesta îl încurajează în echipele tale este transparența și responsabilitatea colectivă, mai ales pe măsură ce echipele cresc. Oricum va trebui să investești în instrumente, dar întotdeauna este mai bine când comportamentul implicit este cel pe care vrei să-l vezi în echipele tale.

De ce discutăm despre asta?

Matt Klein a scris un articol „Monorepos: Please don’t!”  (nota traductorului: traducerea pe Habrahabr „Monorepository: te rog, nu!”). Îmi place Matt, cred că este foarte inteligent și ar trebui să-i citești perspectiva. Inițial, el a publicat un sondaj pe Twitter:

Mono-repozitorii: vă rog, este necesar

Traducere:
În această zi de Anul Nou, voi argumenta cât de ridicole sunt monorepository-urile. Anul 2019 a început fără multe fapte. În spiritul acesta, vă ofer un sondaj. Cine sunt marii fani? Susținători:
— Monorepository
— Rust
— Sondaj greșit / și una și alta

Răspunsul meu a fost: „Sunt literalmente ambele aceste persoane”. În loc să discutăm despre cât de drog este Rust, haideți să vedem de ce cred că se înșală în legătură cu monorepository-urile. Puțin despre mine. Sunt director tehnic la Chef Software. Avem aproximativ 100 de ingineri, o bază de cod de aproximativ 11–12 ani și 4 produse principale. O parte din acest cod se află într-un repository poli (poziția mea de start), o parte în monorepository (poziția mea actuală).

Înainte să încep: fiecare argument pe care îl voi aduce aici se va aplica ambelor tipuri de repository. În opinia mea, nu există motive tehnice pentru care ar trebui să alegi un tip de repository sau altul. Poți face să funcționeze orice abordare. Sunt deschis să discut despre asta, dar nu mă interesează motivele tehnice artificiale pentru care unul este superior altuia.

Sunt de acord cu prima parte a punctului de vedere al lui Matt:

Pentru că la scară mare, un monorepository va rezolva toate aceleași probleme pe care le rezolvă și un repository poli, dar va provoca, de asemenea, o legătura puternică a codului tău și va necesita un efort incredibil pentru a crește scalabilitatea sistemului tău de control al versiunilor.

Veți trebuie să rezolvați probleme similare, indiferent dacă alegeți un monorepo sau un polirepo. Cum lansați versiunile? Care este abordarea dvs. pentru actualizări? Compatibilitate inversă? Dependențe încrucișate ale proiectelor? Ce stiluri arhitecturale sunt acceptabile? Cum gestionați infrastructura de construire și testare? Lista este nesfârșită. Și veți rezolva toate acestea pe măsură ce creșteți. Nu există brânză gratuită.

Cred că argumentul lui Matt este similar cu părerile împărtășite de mulți ingineri (și manageri) pe care îi respect. Vine din perspectiva unui inginer care lucrează la un component sau a unei echipe care lucrează la acesta. Ascultați lucruri precum:

  • Codul este greoi — nu am nevoie de tot acest gunoi.
  • Este mai greu de testat, deoarece trebuie să verific tot acest gunoi de care nu am nevoie.
  • Este mai complicat să lucrez cu dependențe externe.
  • Am nevoie de propriile mele sisteme virtuale de gestionare a versiunilor.

Cu siguranță, toate aceste puncte sunt valide. Acest lucru se întâmplă în ambele cazuri — în polirepo am gunoiul meu, pe lângă cel necesar pentru construire… S-ar putea să mai am nevoie și de alte lucruri. Așadar, «doar» creez unelte care fac checkout-ul întregului proiect. Sau creez un fals monorepo cu submodule. Am putea discuta toată ziua despre asta. Dar cred că argumentul lui Matt trece cu vederea motivul principal, pe care l-am întors destul de mult în favoarea monorepo-ului:

Îndeamnă la comunicare și evidențiază problemele.

Când împărțim repositoarele, de facto creăm o problemă de coordonare și transparență. Asta corespunde modului în care gândim despre echipe (în special modului în care gândesc membrii individuali): suntem responsabili pentru un anumit component. Lucrăm în izolare relativă. Granițele sunt fixate pe echipa mea și componenta(ele) la care lucrăm.

Pe măsură ce arhitectura devine mai complexă, o singură echipă nu poate gestiona totul singură. Foarte puțini ingineri păstrează întreaga sistemă în minte. Să presupunem că gestionezi componenta comună A, care este utilizată de echipele B, C și D. Echipa A face refactorizarea, îmbunătățește API-ul și schimbă, de asemenea, implementarea internă. Drept urmare, modificările devin incompatibile cu versiuni anterioare. Ce sfaturi i-ai oferi?

  • Găsește toate locurile unde este utilizat vechiul API.
  • Există locuri unde noul API nu poate fi utilizat?
  • Poți corecta și testa celelalte componente pentru a te asigura că nu se defectează?
  • Îți pot verifica aceste echipe modificările chiar acum?

Reține că aceste întrebări nu depind de tipul de depozit. Va trebui să găsești echipele B, C și D. Va trebui să vorbești cu ele, să afli timpul necesar, să înțelegi prioritățile lor. Sperăm că vei face acest lucru.

De fapt, nimeni nu își dorește să se ocupe de asta. Este mult mai puțin captivant decât pur și simplu să repari acel nenorocit de API. Totul este uman și complicat. Într-un depozit poli, poți face pur și simplu modificări, le dai spre revizuire celor care lucrează la această componentă (probabil nu B, C sau D) și să mergi mai departe. Echipele B, C și D pot rămâne momentan pe versiunea lor actuală. Se vor actualiza atunci când își vor da seama de genialitatea ta!

Într-un depozit monorepo, responsabilitatea se schimbă implicit. Echipa A își schimbă componenta și, dacă nu este atentă, sparge imediat B, C și D. Acest lucru face ca B, C și D să apară la ușa echipei A, mirându-se de ce echipa A a stricat compilarea. Acest lucru îi învață pe A că nu pot să ignore lista mea de mai sus. Trebuie să discute despre ceea ce urmează să facă. Pot B, C și D să progreseze? Dar dacă B și C pot, dar D a fost strâns legat de efectul secundar al comportamentului vechiului algorith?

Apoi trebuie să discutăm despre cum putem ieși din această situație:

  1. Să suportăm mai multe API-uri interne, în timp ce vechiul algoritm va fi marcat ca depreciat, până când D nu va mai putea să-l folosească.
  2. Să suportăm mai multe versiuni de lansare, una cu interfața veche, una cu cea nouă.
  3. Amânarea lansării modificărilor A până când simultan B, C și D pot să le accepte.

Să presupunem că am ales 1, câteva API. În acest caz, avem două bucăți de cod. Veche și nouă. Destul de convenabil în anumite situații. Revenim la vechiul cod, îl marcăm ca fiind învechit (deprecated) și stabilim un calendar pentru eliminarea acestuia împreună cu echipa D. Practic, este identic pentru poli și pentru monorepo.

Pentru lansarea mai multor versiuni, avem nevoie de un branch. Acum avem două componente - A1 și A2. Echipele B și C folosesc A2, iar D folosește A1. Trebuie să ne asigurăm că fiecare componentă este gata pentru lansare, deoarece, înainte ca D să poată avansa, pot fi necesare actualizări de securitate și remedieri pentru alte bug-uri. În polirepo, putem ascunde acest lucru într-un branch pe termen lung, care se simte bine. În monorepo, forțăm crearea codului într-un nou modul. Echipa D va trebui, de asemenea, să facă modificări la componenta „veche”. Toată lumea poate vedea costul pe care îl plătim aici - acum avem de două ori mai mult cod, și orice remedii pentru bug-uri aplicate la A1 și A2 trebuie aplicate pentru amândouă. Cu abordarea utilizării branch-urilor în polirepo, acest lucru este ascuns prin cherry-pick. Considerăm costul ca fiind mai mic, deoarece nu există duplicare. Din punct de vedere practic, costul este identic: veți crea, lansa și menține două baze de cod, în mare parte identice, până când veți putea elimina una dintre ele. Diferența este că, în monorepo, această durere este directă și vizibilă. Este și mai rău, și asta e bine.

În sfârșit, am ajuns la al treilea punct. Întârzierea lansării. Este posibil ca modificările aduse de A să îmbunătățească viața echipei A. Important, dar nu urgent. Putem oare pur și simplu să întârziem? În repositoarele de tip monorepo, noi încurajăm consolidarea artefactelor. Desigur, discutăm asta cu echipa D. Doar rămâneți la versiunea veche până ajungeți din urmă! Aceasta setează o mentalitate de frică. Echipa A continuă să lucreze la componenta lor, ignorând faptul că echipa D folosește o versiune din ce în ce mai învechită (este problema echipei D, sunt nepricepuți). Între timp, echipa D vorbește despre comportamentul imprudent al echipei A față de stabilitatea codului, dacă discută despre asta. Trec luni. În cele din urmă, echipa D decide să analizeze posibilitatea actualizării, dar modificările din A au devenit doar mai numeroase. Echipa A își amintește cu greu când și cum au stricat D. Actualizarea devine mai dureroasă și va necesita mai mult timp. Ceea ce îi trimite mai departe în josul listei de priorități. Până în ziua în care apare o problemă de securitate în A, care ne face să facem o ramificare. Echipa A trebuie să călătorească înapoi în timp, să găsească momentul în care D era stabil, să repare problema de acolo și să o pregătească pentru lansare. Aceasta este, de facto, alegerea pe care o fac oamenii și este, fără îndoială, cea mai proastă. Se pare că este bine atât pentru echipa A, cât și pentru D, cât timp putem să ne ignorăm unii pe alții.

În monorepo, a treia opțiune nu este cu adevărat o opțiune. Ești forțat să gestionezi situația în unul dintre cele două moduri. Trebuie să vezi costurile de a avea două ramuri de lansare. Să înveți să te protejezi de actualizări care rup compatibilitatea înapoi. Dar cel mai important: nu poți evita o conversație dificilă.

Din experiența mea, atunci când echipele devin mari, nu mai există posibilitatea de a ține în minte întregul sistem, iar aceasta este cea mai importantă parte. Trebuie să îmbunătățești vizibilitatea dezacordurilor din sistem. Trebuie să lucrezi activ pentru a determina echipele să își îndrepte atenția de la componentele lor și să se uite la munca celorlalte echipe și a consumatorilor.

Da, puteți crea instrumente care să încerce să rezolve problema polirepozitoriilor. Dar experiența mea în livrarea continuă și automatizare în întreprinderi mari îmi spune următoarele: comportamentul implicit, fără utilizarea unor instrumente suplimentare, este ceea ce te aștepți să vezi. Comportamentul implicit al polirepozitoriului este izolația, acesta fiind întregul punct. Comportamentul implicit al monorepozitoriului este responsabilitatea comună și transparența, acesta fiind întregul punct. În ambele cazuri, am de gând să creez un instrument care să atenueze colțurile ascuțite. Ca lider, voi alege monorepozitoul de fiecare dată, deoarece instrumentele ar trebui să întărească cultura pe care o doresc, iar cultura provine din decizii mici și din munca zilnică a echipei.

Numai utilizatorii înregistrați pot participa la sondaj. Conectați-vă, vă rugăm.

Cine sunt mai mari fani? Susținătorii:

  • Monorepository

  • Rust

  • Sondaj greșit / și una și alta

Au votat 33 de utilizatori. 13 utilizatori s-au abținut.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster