sobota, lutego 11, 2017

O tym czemu branche są złe...

Jeszcze w poprzedniej firmie narysowałem taki "komiks":


Który oddaje mój stosunek do branchy ;-)

Czemu nie lubię branchy?

Bo sprzyjają konfliktom w czasie mergowania.

Jeśli wszyscy pracują  na wspólnym źródle, czyli wszystkie commit'y idą do wspólnej gałęzi to mamy tak, że co chwilę odbywa się integracja.

Gdy developer robi pull z repozytorium to ma prawie 100% szans, że wszystkie pliki jakie pobrał są w najnowszej wersji (znaczy, że nikt nie ma nowszej wersji zakiszonej na swojej lokalnej maszynie).
To nie jest pełne 100%, bo inni developerzy też pracują nad swoimi zmianami, stąd pewna niewielka grupa plików jest u nich w nowszych wersjach. Ale, że nie mając własnych branchy wszystkie commity muszą iść do głównej gałęzi, co nadal jeszcze niewiele daje, ale zwykle każdy developer robi przeciętnie 1 pusha do repo dziennie oddając kod, który "w miarę działa". Dzięki temu w większości plików mamy pewność, że ich nowsza wersja nie będzie się znacząco różniła od tego co pobraliśmy właśnie z repo.
Stąd z jednej strony mamy dość małe szanse by w danym czasie 2 developerów pracowało nad tym samym plikiem, jeśli jednak pracują i pojawi się konflikt to będzie on ze zmian z 1 dnia.

W przypadku branchy już tak dobrze nie jest.
Gdy developer robi pull z repozytorium dostaje najnowsze wersje plików, ale dość duża grupa plików ma nowsze wersje na innych branchach gdzie mogą się kumulować zmiany z kilku ostatnich tygodni.
Robienie upmergy z głównej gałęzi nie rozwiązuje problemu, bo nadal pobieramy tak tylko część zmian. Do tego ponieważ nasza gałąź ma już ileś tam dni to przy każdym upmerge'u mamy niezerowe prawdopodobieństwo konfliktu. Jego rozmiar jest tym większy im dłużej minęło od momentu gdy nasz gałąź dla danego pliku odpięła się od innej wersji tego pliku. Do tego zwykle w takim merge'u mamy dość dużo zmian.
W końcu gdy robimy naszego końcowego merge'a to znów mamy szansę na konflikt.

"Matematyka" do tego niby jest prosta, chociaż trudno to tak opisać.
Zakładając, że każdy developer pracuje codziennie z 1 plikiem mamy szansę, że dany plik zostanie dotknięty przez danego deva z prawdopodobieństwem P(plik dotknięty przez deva)=1/N gdzie N to liczba plików.
W takim przypadku konflikt, czyli P(konflikt)=P(prawdopodobieństwo dotknięcia pliku przez 2 devów)=(1/N)^2

Gdy mamy branche i każdy dev nadal dotyka 1 pliku dziennie to po M dniach kiszenia czegoś na branchu mamy zmienione M/N plików z repo (gdzie M to ilość dni kiszenia, a N nadal ilość plików w repo).
Trudniej tu stwierdzić jakie jest prawdopodobieństwo konfliktu bo przecież może ono zajść na dowolnym z M plików, ale załóżmy, że chodzi o konflikt z devem, który zrobi 1 zmianę na 1 pliku, wtedy P(konflikt na branchu)=M/N^2.
Czyli prawdopodobieństwo konfliktu na branchu jest przynajmniej M razy większe niż bez branchy.

Problemem tu nie są nawet same branche, a to, że branche oznaczają rzadszą integrację.

Stworzyłem programik w Pythonie, którego zadaniem jest zasymulowanie pracy zespołu 5 developerów, którzy pracują nad małym repo z 3000 plików i pracują albo bez branchy, przeprowadzając integrację codziennie przez robienie codziennie commit'ów kodu, który "w miarę działa", oraz tego samego zespołu który integruje się z branchy raz na 5, 10, 15, 20, 25 i 30 dni.
Pracowali przez 250 dni (czyli mniej więcej tyle ile jest dni roboczych w roku).


odstęp między commitamikonfliktów
10
54
109
1514
2019
2522
3029

Liczba konfliktów w przypadku commitów codziennie wyniosła 0, przy 5 dniowych branchach 4, przy 10 dniowych 9 i tak dalej.
Większe odstępy między commitami wyszły trochę lepiej niż wyszłyby w rzeczywistości bo po prostu 250 nie do końca się ładnie przez nie dzieli, stąd ich liczby konfliktów zostały trochę zaniżone.

Wyraźnie widać, że liczba konfliktów rośnie wraz z czasem kiszenia zmian na swoim branchu. Nawet upmerge tutaj nie pomagają, bo co najwyżej trochę zmniejsza odstępy między integracją.

Jedynym powodem stosowania branchy jaki widzę jest to, że łatwiej robić review zmian w przypadku branchy, bo widać zmiany w jednym kawałku. 
Z drugiej jednak strony, gdyby zastąpić duże inspekcje serią mniejszych i później jedną większą, która przegląda wszystkie zmiany to chyba każda z inspekcji byłaby prostsza, a i szansa wprowadzenia błędu mniejsza...

Jak kto ciekawy to kod programiku do symulacji jest tutaj.



Podobne postybeta
Trzy heurystyki developerskie, których wdrożenie uchroni Cię przed zawałem i pozwoli przebić balon zadufania ;-)
Projekty Informatyczne - Mity ;-)
OS X po 1.5 miesiąca... chyba wolę Ubuntu ;-)
Inercja i koło wielokrotnego wynajdywania, czyli radosne macki piekieł w kodzie [alem pojechał w tytule ;-)]
Dobór naturalny, albo my