Monorepozytoria: proszę, muszę

Monorepozytoria: proszę, muszę

Tłumaczenie artykułu przygotowanego dla studentów kursu „Praktyki i narzędzia DevOps” w projekcie edukacyjnym OTUS.

Powinieneś wybrać monorepozytorium, ponieważ promowane przez nie zachowanie w Twoich zespołach to przejrzystość i wspólna odpowiedzialność, zwłaszcza w miarę rozwoju zespołów. Tak czy inaczej, będziesz musiał zainwestować w oprzyrządowanie, ale zawsze lepiej jest, jeśli domyślnym zachowaniem jest zachowanie, które chcesz w swoich poleceniach.

Dlaczego o tym mówimy?

Artykuł napisał Matt Klein „Monorepos: proszę, nie!”  (przypis tłumacza: tłumaczenie na temat Habré „Monorepozytoria: proszę nie”). Lubię Matta, uważam, że jest bardzo mądry i powinieneś poznać jego punkt widzenia. Pierwotnie zamieścił ankietę na Twitterze:

Monorepozytoria: proszę, muszę

Tłumaczenie:
W Nowy Rok będę się kłócił o to, jak absurdalne są monorepozytoria. Rok 2019 rozpoczął się spokojnie. W tym duchu proponuję Państwu ankietę. Kim są wielcy fanatycy? Zwolennicy:
- Monorepo
- Rdza
- Niepoprawna ankieta / jedno i drugie

Moja odpowiedź brzmiała: „Dosłownie jestem jedną i drugą osobą”. Zamiast rozmawiać o tym, że Rust jest lekiem, przyjrzyjmy się, dlaczego moim zdaniem myli się co do monorepozytorów. Trochę o sobie. Jestem dyrektorem technicznym w Chef Software. Mamy około 100 inżynierów, bazę kodu sięgającą około 11-12 lat i 4 główne produkty. Część tego kodu znajduje się w polirepozytorium (moja pozycja początkowa), część znajduje się w monorepozytorium (moja bieżąca pozycja).

Zanim zacznę: każdy argument, który tutaj przedstawię, będzie miał zastosowanie do obu rodzajów repozytoriów. Moim zdaniem nie ma technicznego powodu, dla którego powinieneś wybierać jeden typ repozytorium zamiast innego. Możesz zastosować dowolne podejście. Chętnie o tym porozmawiam, ale nie interesują mnie sztuczne, techniczne powody, dla których jedno jest lepsze od drugiego.

Zgadzam się z pierwszą częścią uwagi Matta:

Ponieważ na dużą skalę monorepozytorium rozwiąże te same problemy, które rozwiązuje polirepozytorium, ale jednocześnie zmusi Cię do ścisłego powiązania kodu i wymaga niesamowitych wysiłków, aby zwiększyć skalowalność systemu kontroli wersji.

Będziesz musiał rozwiązać te same problemy, niezależnie od tego, czy wybierzesz monorepozytorium, czy polirepozytorium. Jak publikujecie wydania? Jakie jest Twoje podejście do aktualizacji? Kompatybilność wsteczna? Zależności między projektami? Jakie style architektoniczne są dopuszczalne? Jak zarządzasz infrastrukturą kompilacji i testowania? Lista jest nieskończona. I rozwiążesz je wszystkie w miarę dorastania. Nie ma darmowego sera.

Myślę, że argument Matta jest podobny do poglądów podzielanych przez wielu inżynierów (i menedżerów), których szanuję. Dzieje się to z perspektywy inżyniera pracującego nad komponentem lub zespołu pracującego nad komponentem. Słyszysz takie rzeczy jak:

  • Baza kodu jest nieporęczna - nie potrzebuję tych wszystkich śmieci.
  • Trudniej jest przetestować, ponieważ muszę przetestować wszystkie te śmieci, których nie potrzebuję.
  • Trudniej jest pracować z zależnościami zewnętrznymi.
  • Potrzebuję własnych wirtualnych systemów kontroli wersji.

Oczywiście wszystkie te punkty są uzasadnione. Dzieje się tak w obu przypadkach - w polirepozytorium mam własne śmieci, oprócz tego potrzebnego do kompilacji... Być może będę potrzebował także innych śmieci. Dlatego „po prostu” tworzę narzędzia, które sprawdzają cały projekt. Lub tworzę fałszywe monorepozytorium z submodułami. Moglibyśmy tak chodzić cały dzień. Myślę jednak, że argument Matta pomija główny powód, który dość mocno przerzuciłem na korzyść monorepozytorium:

Prowokuje komunikację i pokazuje problemy

Kiedy rozdzielamy repozytoria, stwarzamy de facto problem koordynacji i przejrzystości. Odpowiada to sposobowi, w jaki myślimy o zespołach (zwłaszcza o tym, jak myślą o nich poszczególni członkowie): jesteśmy odpowiedzialni za określony komponent. Pracujemy we względnej izolacji. Granice mojego zespołu i komponentów, nad którymi pracujemy, są ustalone.

W miarę jak architektura staje się coraz bardziej złożona, jeden zespół nie jest już w stanie samodzielnie nią zarządzać. Bardzo niewielu inżynierów ma w głowie cały system. Załóżmy, że zarządzasz współdzielonym komponentem A używanym przez zespoły B, C i D. Zespół A refaktoryzuje, ulepsza interfejs API, a także zmienia wewnętrzną implementację. W rezultacie zmiany nie są kompatybilne wstecz. Jaką masz radę?

  • Znajdź wszystkie miejsca, w których używane jest stare API.
  • Czy są miejsca, w których nie można zastosować nowego API?
  • Czy możesz naprawić i przetestować inne komponenty, aby upewnić się, że się nie zepsują?
  • Czy te zespoły mogą teraz przetestować wprowadzone zmiany?

Należy pamiętać, że te pytania są niezależne od typu repozytorium. Będziesz musiał znaleźć zespoły B, C i D. Będziesz musiał z nimi porozmawiać, ustalić czas, zrozumieć ich priorytety. Przynajmniej mamy nadzieję, że to zrobisz.

Nikt tak naprawdę nie chce tego robić. To o wiele mniej zabawne niż naprawianie tego cholernego API. To wszystko jest ludzkie i brudne. W repozytorium możesz po prostu wprowadzić zmiany, przekazać je osobom pracującym nad tym komponentem (prawdopodobnie nie B, C lub D) do sprawdzenia i przejść dalej. Zespoły B, C i D mogą na razie pozostać przy obecnej wersji. Zostaną odnowione, gdy zdadzą sobie sprawę z Twojego geniuszu!

W przypadku monorepozytorium odpowiedzialność jest domyślnie przeniesiona. Zespół A zmienia swój element i, jeśli nie jest ostrożny, natychmiast psuje B, C i D. Prowadzi to do tego, że B, C i D pojawiają się pod drzwiami A i zastanawiają się, dlaczego Zespół A zepsuł montaż. To uczy A, że nie może pominąć mojej listy powyżej. Muszą porozmawiać o tym, co zamierzają zrobić. Czy B, C i D mogą się poruszać? Co jeśli B i C mogą, ale D było ściśle powiązane z efektem ubocznym zachowania starego algorytmu?

Następnie musimy porozmawiać o tym, jak wydostać się z tej sytuacji:

  1. Obsługa wielu wewnętrznych interfejsów API i oznaczy stary algorytm jako przestarzały, dopóki D nie przestanie go używać.
  2. Obsługa wielu wersji, jedna ze starym interfejsem, druga z nowym.
  3. Opóźnij wydanie zmian A, dopóki B, C i D nie będą mogły ich jednocześnie zaakceptować.

Załóżmy, że wybraliśmy 1, kilka interfejsów API. W tym przypadku mamy dwa fragmenty kodu. Stare i nowe. Całkiem wygodne w niektórych sytuacjach. Sprawdzamy ponownie stary kod, oznaczamy go jako przestarzały i uzgadniamy harmonogram usuwania z zespołem D. Zasadniczo identyczny dla repozytoriów Poly i Mono.

Aby wydać wiele wersji, potrzebujemy gałęzi. Teraz mamy dwa komponenty - A1 i A2. Zespoły B i C korzystają z A2, a D z A1. Potrzebujemy, aby każdy komponent był gotowy do wydania, ponieważ aktualizacje zabezpieczeń i inne poprawki błędów mogą być wymagane, zanim D będzie mógł działać dalej. W repozytorium możemy ukryć to w długowiecznej gałęzi, która jest dobra. W monorepozytorium wymuszamy utworzenie kodu w nowym module. Zespół D będzie nadal musiał wprowadzić zmiany w „starym” komponencie. Każdy może zobaczyć, ile tutaj płacimy — mamy teraz dwa razy więcej kodu, a wszelkie poprawki błędów dotyczące A1 i A2 muszą dotyczyć obu z nich. Dzięki podejściu rozgałęziającemu w repozytorium wielostronnym jest to ukryte za opcją cherry-pick. Uważamy, że koszt jest niższy, ponieważ nie dochodzi do powielania działań. Z praktycznego punktu widzenia koszt jest taki sam: zbudujesz, wypuścisz i utrzymasz dwie w dużej mierze identyczne bazy kodu, dopóki nie będziesz mógł usunąć jednej z nich. Różnica jest taka, że ​​przy monorepozytorium ból ten jest bezpośredni i widoczny. To jest jeszcze gorsze i to dobrze.

W końcu dotarliśmy do trzeciego punktu. Opóźnienie zwolnienia. Możliwe, że zmiany wprowadzone przez A poprawią życie Zespołu A. Ważne, ale nie pilne. Czy możemy po prostu zwlekać? W repozytorium wielostronnym wypychamy to, aby przypiąć artefakt. Oczywiście mówimy to Zespołowi D. Po prostu pozostań przy starej wersji, dopóki nie nadrobisz zaległości! To sprawia, że ​​odgrywasz rolę tchórza. Zespół A kontynuuje pracę nad swoim komponentem, ignorując fakt, że Zespół D używa coraz bardziej przestarzałej wersji (to problem Zespołu D, są głupi). Tymczasem Zespół D źle wypowiada się na temat nieostrożnego podejścia Zespołu A do stabilności kodu, jeśli w ogóle o tym mówi. Mijają miesiące. Wreszcie Zespół D postanawia przyjrzeć się możliwości aktualizacji, ale Zespół A ma tylko więcej zmian. Zespół A ledwo pamięta, kiedy i jak złamał D. Ulepszenie jest bardziej bolesne i potrwa dłużej. Co wysyła go dalej w dół stosu priorytetów. Aż do dnia, w którym wystąpi problem bezpieczeństwa w A, który zmusza nas do utworzenia oddziału. Zespół A musi cofnąć się w czasie, znaleźć punkt, w którym D był stabilny, naprawić tam problem i przygotować go do wydania. Jest to de facto wybór, którego ludzie dokonują i jest zdecydowanie najgorszy. Wydaje się, że jest to dobre zarówno dla Zespołu A, jak i Zespołu D, o ile możemy się ignorować.

W przypadku monorepozytorium trzecie tak naprawdę nie wchodzi w grę. Jesteś zmuszony poradzić sobie z tą sytuacją na jeden z dwóch sposobów. Musisz zobaczyć koszty posiadania dwóch gałęzi wydań. Dowiedz się, jak chronić się przed aktualizacjami naruszającymi kompatybilność wsteczną. Ale najważniejsze: nie możesz uniknąć trudnej rozmowy.

Z mojego doświadczenia wynika, że ​​gdy zespoły się rozrastają, nie da się już pamiętać o całym systemie, a to jest najważniejsze. Musisz poprawić widoczność niezgody w systemie. Musisz aktywnie pracować, aby zespoły odwróciły wzrok od swoich komponentów i spojrzały na pracę innych zespołów i konsumentów.

Tak, możesz stworzyć narzędzia, które będą próbowały rozwiązać problem polirepozytorium. Jednak moje doświadczenie w nauczaniu ciągłego dostarczania i automatyzacji w dużych przedsiębiorstwach mówi mi jedno: domyślne zachowanie bez użycia dodatkowych narzędzi jest zachowaniem, którego się spodziewasz. Domyślnym zachowaniem repozytorium jest izolacja i o to właśnie chodzi. Domyślnym zachowaniem monorepozytorium jest wspólna odpowiedzialność i przejrzystość, o to właśnie chodzi. W obu przypadkach stworzę narzędzie, które wygładzi ostre krawędzie. Jako lider za każdym razem wybiorę monorepozytorium, ponieważ narzędzia muszą wzmacniać kulturę, którą chcę, a kultura powstaje w wyniku drobnych decyzji i codziennej pracy zespołu.

W ankiecie mogą brać udział tylko zarejestrowani użytkownicy. Zaloguj się, Proszę.

Kim są najwięksi fanatycy? Zwolennicy:

  • Monorepo

  • Rdza

  • Niepoprawna ankieta / jedno i drugie

Głosowało 33 użytkowników. 13 użytkowników wstrzymało się od głosu.

Źródło: www.habr.com

Dodaj komentarz