Monodepozitele: vă rog, trebuie

Monodepozitele: vă rog, trebuie

Traducerea articolului pregătit pentru cursanții „Practici și instrumente DevOps” în proiectul educațional OTUS.

Ar trebui să alegeți un monodepozitar, deoarece comportamentul pe care îl promovează în echipele dvs. este transparența și responsabilitatea partajată, mai ales pe măsură ce echipele cresc. Oricum, va trebui să investiți în instrumente, dar este întotdeauna mai bine dacă comportamentul implicit este comportamentul pe care îl doriți în comenzile dvs.

De ce vorbim despre asta?

Matt Klein a scris articolul "Monorepos: Te rog nu!"  (nota traducătorului: traducere pe Habré „Monorepozitoare: vă rugăm să nu faceți”). Îmi place Matt, cred că este foarte inteligent și ar trebui să-i citești punctul de vedere. El a postat inițial sondajul pe Twitter:

Monodepozitele: vă rog, trebuie

Traducere:
În această zi de Anul Nou, o să mă cert despre cât de ridicole sunt monodepozitele. 2019 a început liniștit. În spiritul acestui lucru, vă propun un sondaj. Cine sunt marii fanatici? Suporteri:
- Monorepo
- Rugină
- Sondaj incorect / ambele

Răspunsul meu a fost: „Sunt literalmente amândoi”. În loc să vorbim despre felul în care Rust este un medicament, să vedem de ce cred că greșește în privința monorepozitoriilor. Un pic despre tine. Sunt directorul tehnic al 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 polirepository (poziția mea de pornire), altele se află într-un monorepozitiv (poziția mea curentă).

Înainte de a începe: fiecare argument pe care îl fac aici se va aplica ambelor tipuri de depozite. În opinia mea, nu există niciun motiv tehnic pentru care ar trebui să alegeți un tip de depozit în locul altuia. Puteți face ca orice abordare să funcționeze. Mă bucur să vorbesc despre asta, dar nu mă interesează motivele tehnice artificiale pentru care unul este superior altuia.

Sunt de acord cu prima parte a punctului lui Matt:

Pentru că la scară, un monorepository va rezolva toate aceleași probleme pe care le rezolvă un polirepository, dar, în același timp, vă va forța să vă cuplați strâns codul și va necesita eforturi incredibile pentru a crește scalabilitatea sistemului dvs. de control al versiunilor.

Va trebui să rezolvi aceleași probleme, indiferent dacă alegi un monodepozitar sau un polirepository. Cum eliberezi lansări? Care este abordarea dvs. cu privire la actualizări? Compatibilitate inversă? Dependențe încrucișate de proiect? Ce stiluri arhitecturale sunt acceptabile? Cum vă gestionați infrastructura de construcție și testare? Lista este nesfârșită. Și le vei rezolva pe toate pe măsură ce vei crește. Nu există brânză gratuită.

Cred că argumentul lui Matt este similar cu opiniile împărtășite de mulți ingineri (și manageri) pe care îi respect. Acest lucru se întâmplă din perspectiva inginerului care lucrează la componentă sau a echipei care lucrează la componentă. Auzi lucruri precum:

  • Baza de cod este voluminoasă - nu am nevoie de toate aceste vechituri.
  • Este mai greu de testat pentru că trebuie să testez toate aceste nedorite de care nu am nevoie.
  • Este mai dificil să lucrezi cu dependențe externe.
  • Am nevoie de propriile mele sisteme virtuale de control al versiunilor.

Desigur, toate aceste puncte sunt justificate. Acest lucru se întâmplă în ambele cazuri - în polirepository am propriul meu junk, pe lângă cel necesar pentru build... s-ar putea să am nevoie și de alte junk-uri. Așa că „pur și simplu” creez instrumente care verifică întregul proiect. Sau creez un monodepozitiv fals cu submodule. Ne-am putea plimba prin asta toată ziua. Dar cred că argumentul lui Matt ratează motivul principal, pe care l-am răsturnat destul de mult în favoarea monorepozitoriului:

Provoacă comunicare și arată probleme

Când separăm depozitele, creăm o problemă de coordonare și transparență de facto. Aceasta corespunde modului în care gândim echipele (în special felul în care gândesc membrii individuali despre ele): suntem responsabili pentru o anumită componentă. Lucrăm în relativă izolare. Granițele sunt fixate pentru echipa mea și componentele la care lucrăm.

Pe măsură ce arhitectura devine mai complexă, o singură echipă nu o mai poate gestiona singură. Foarte puțini ingineri au întregul sistem în cap. Să presupunem că gestionați o componentă partajată A care este utilizată de echipele B, C și D. Echipa A refactorizează, îmbunătățește API-ul și, de asemenea, modifică implementarea internă. Ca urmare, modificările nu sunt compatibile cu invers. Ce sfaturi ai?

  • Găsiți toate locurile în care este folosit vechiul API.
  • Există locuri în care noul API nu poate fi utilizat?
  • Puteți repara și testa alte componente pentru a vă asigura că nu se sparg?
  • Aceste echipe vă pot testa modificările chiar acum?

Vă rugăm să rețineți că aceste întrebări sunt independente de tipul de depozit. Va trebui să găsiți echipele B, C și D. Va trebui să vorbiți cu ei, să aflați timpul, să le înțelegeți prioritățile. Cel puțin sperăm să o faci.

Nimeni nu vrea cu adevărat să facă asta. Acest lucru este mult mai puțin distractiv decât simpla remediere a naibii de API. Totul este uman și dezordonat. Într-un polyrepository, puteți pur și simplu să faceți modificări, să le oferiți oamenilor care lucrează la acea componentă (probabil nu B, C sau D) pentru revizuire și să continuați. Echipele B, C și D pot rămâne doar cu versiunea lor actuală pentru moment. Vor fi reînnoiți când își vor da seama de geniul tău!

Într-un singur depozit, responsabilitatea este transferată în mod 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 lui A, întrebându-se de ce Echipa A a spart ansamblul. Acest lucru îl învață pe A că nu pot sări peste lista mea de mai sus. Trebuie să vorbească despre ceea ce vor face. B, C și D se pot mișca? Ce se întâmplă dacă B și C pot, dar D a fost strâns legat de un efect secundar al comportamentului vechiului algoritm?

Apoi trebuie să vorbim despre cum vom ieși din această situație:

  1. Suport pentru mai multe API-uri interne și va marca vechiul algoritm ca fiind depreciat până când D va înceta să-l mai folosească.
  2. Suport pentru versiuni multiple, una cu interfața veche, una cu cea nouă.
  3. Întârzie lansarea modificărilor lui A până când B, C și D o pot accepta simultan.

Să presupunem că am selectat 1, mai multe API-uri. În acest caz avem două bucăți de cod. Vechi și nou. Destul de convenabil în unele situații. Verificăm din nou codul vechi, îl marcăm ca depreciat și cădem de acord cu echipa D asupra unui program de eliminare În esență identic pentru depozitele poli și mono.

Pentru a lansa mai multe versiuni, avem nevoie de o ramură. Acum avem două componente - A1 și A2. Echipele B și C folosesc A2 și D folosesc A1. Avem nevoie ca fiecare componentă să fie pregătită pentru lansare, deoarece pot fi necesare actualizări de securitate și alte remedieri de erori înainte ca D să poată merge mai departe. Într-un polidepozitar, putem ascunde acest lucru într-o ramură cu viață lungă, care se simte bine. Într-un monorepozitiv, forțăm ca codul să fie creat într-un modul nou. Echipa D va trebui în continuare 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 remediere a erorilor care se aplică pentru A1 și A2 trebuie să se aplice pentru ambele. Odată cu abordarea ramificată într-un polidepozit, acest lucru este ascuns în spatele cherry-pick. Considerăm că costul este mai mic deoarece nu există dublare. Din punct de vedere practic, costul este același: veți construi, elibera și menține două baze de cod în mare parte identice până când veți putea șterge una dintre ele. Diferența este că cu un monorepozitiv această durere este directă și vizibilă. Acest lucru este și mai rău, și asta e bine.

În sfârșit, am ajuns la al treilea punct. Întârziere de eliberare. Este posibil ca modificările făcute de A să îmbunătățească viața echipei A. Importante, dar nu urgente. Putem doar să amânăm? Într-un polidepozitiv, împingem acest lucru pentru a fixa artefactul. Bineînțeles că îi spunem acest lucru echipei D. Rămâneți doar la versiunea veche până când ajungeți din urmă! Asta te face să te joci lașul. Echipa A continuă să lucreze la componenta lor, ignorând faptul că Echipa D folosește o versiune din ce în ce mai depășită (asta e problema echipei D, sunt proști). Între timp, Echipa D vorbește prost despre atitudinea neglijentă a echipei A față de stabilitatea codului, dacă vorbesc deloc despre asta. Trec lunile. În cele din urmă, Echipa D decide să se uite la posibilitatea de actualizare, dar A are doar mai multe modificări. Echipa A abia își amintește când sau cum a rupt D. Upgrade-ul este mai dureros și va dura mai mult. Ceea ce îl trimite mai jos în stiva prioritară. Până în ziua în care avem o problemă de securitate în A care ne obligă să facem o ramură. Echipa A trebuie să se întoarcă în timp, să găsească un punct în care D a fost stabil, să remedieze problema acolo și să o pregătească pentru lansare. Aceasta este alegerea de facto pe care o fac oamenii și este de departe cea mai proastă. Pare să fie bine atât pentru echipa A, cât și pentru echipa D, atâta timp cât ne putem ignora unul pe celălalt.

Într-un monorepozitiv, al treilea nu este într-adevăr o opțiune. Ești forțat să faci față situației într-unul din două moduri. Trebuie să vedeți costurile pentru a avea două ramuri de lansare. Învață să te protejezi de actualizările care încalcă compatibilitatea anterioară. Dar cel mai important: nu poți evita să ai o conversație dificilă.

Din experiența mea, atunci când echipele devin mari, nu mai este posibil să ținem cont de întregul sistem și aceasta este partea cea mai importantă. Trebuie să îmbunătățiți vizibilitatea discordiei în sistem. Trebuie să lucrați în mod activ pentru a determina echipele să nu privească de la componentele lor și să privească munca altor echipe și consumatori.

Da, puteți crea instrumente care încearcă să rezolve problema polirepository. Dar experiența mea de predare a livrării continue și automatizării în întreprinderi mari îmi spune acest lucru: comportamentul implicit fără utilizarea unor instrumente suplimentare este comportamentul pe care vă așteptați să îl vedeți. Comportamentul implicit al unui polirepository este izolarea, acesta este scopul. Comportamentul implicit al unui monodepozitar este responsabilitatea și transparența împărtășită, acesta este esențialul. În ambele cazuri, voi crea un instrument care va netezi marginile aspre. Ca lider, voi alege de fiecare dată un monodepozitar, deoarece instrumentele trebuie să întărească cultura pe care mi-o doresc, iar cultura provine din decizii minuscule și din munca zilnică a echipei.

Numai utilizatorii înregistrați pot participa la sondaj. Loghează-te, Vă rog.

Cine sunt cei mai mari fanatici? Suporteri:

  • Monorepo

  • Rugină

  • Sondaj incorect / ambele

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

Sursa: www.habr.com

Adauga un comentariu