Programowanie systematyczne – rozdział pierwszy: systemy kontroli wersji

https://xpil.eu/rH2YP

Programista ze mnie jak z koziej dupy saksofon. Kiedyś, dawno temu, miałem aspiracje zostania Prawdziwym Programistą, jednak wskutek różnych życiowych wydarzeń ("różne życiowe wydarzenia" brzmi o niebo lepiej niż "lenistwo" prawda?) zboczyłem w stronę analityki na dużych zbiorach danych i obecnie nie programuję w niczym poza SQL-em (który właściwie nawet nie jest językiem programowania. Ale nie w tym rzecz).

Większość miejsc, w których pracowałem, to były firmy produkujące coś całkiem niekomputerowego (jak np. gacie, jedzenie, wiedzę bądź dług publiczny). Zaledwie dwa razy w życiu pracowałem dla firm stricte komputerowych, sprzedających software (bądź usługi na nim oparte). A tylko raz trafiła mi się firma na tyle duża, żeby trzeba było w niej używać systemu kontroli wersji.

(Dalszy ciąg będzie opowiadał o tym, czym jest / nie jest system kontroli wersji i w jaki sposób. Jeżeli jesteś w temacie, nie trać czasu - zajrzyj sobie na Dilbert.com albo na xkcd.com, albo idź na spacer...)

Systemy kontroli wersji kodu źródłowego są, z jakichś tajemniczych powodów, wyłączone z programu nauczania szkół wyższych. Nawet tych o profilach wysoce technicznych. Studiowałem na dwóch uczelniach, ale o kontroli wersji dowiedziałem się dopiero jak musiałem tego zacząć używać w pracy. "Hit the ground running" jak mawiają tubylcy.

Wyobraźmy sobie, że dwóch różnych ludków pracujących w dziale IT jakiejś firmy, pracuje wspólnie nad projektem wymagającym napisania kodu. Niezależnie od tego czy jest to kod w C, Javie, Pythonie czy SQL-u, prędzej czy później dojdzie do sytuacji, że obydwaj otworzą ten sam plik z kodem i zaczną wprowadzać do niego zmiany. W efekcie, ten, który zapisze plik jako drugi, zapewne nadpisze zmiany wprowadzone przez tego pierwszego, powodując zamieszanie i straty.

Co więc zrobić?

Ano, przy dwóch programistach to jescze pół biedy. Można wytyczyć ścisłą granicę, żeby sobie nawzajem nie wchodzili w drogę. Mogą się spotykać raz dziennie i mówić, nad czym będą pracować. Mogą skopiować sobie cały kod źródłowy lokalnie, wprowadzać modyfikacje i na koniec wrzucić całość z powrotem na wspólny katalog sieciowy, uważając na daty / wielkości plików (opcję synchronizacji katalogów ma większość porządnych menadżerów plików, np. Total Commander). Rozwiązań jest kilka, lepszych lub gorszych, wszystkie zadziałają przy odrobinie pomyślunku.

Co jednak jeżeli liczba współpracujących przy projekcie osób tworzących kod będzie więcej? 5? 50? 1000?

Niektóre rozwiązania informatyczne mają dziesiątki milionów linii kodu i żeby się połapać w tym co kto zmienił, potrzebne jest wysoce wyspecjalizowane oprogramowanie, zwane właśnie systemem kontroli wersji.

Nie chcę się rozpisywać zbyt szczegółowo na temat różnych systemów kontroli wersji. Opowiem tylko ogólnie jak to działa i postaram się zainteresować tematem - jak ktoś łyknie bakcyla, niech sobie dalej zgłębia zagadnienie we własnym zakresie 😉

Zacznijmy od tego, jak taki system kontroli wersji działa.

(Zamiast pisać cały czas "system kontroli wersji" będę używał skrótu VCS - od Version Control System)

Na ogół centralnym punktem VCS jest serwer przechowujący kod. Programista ma możliwość pobrania plików z kodem z serwera, może następnie modyfikować te pliki lokalnie, na koniec wysyła je z powrotem na serwer.

A co jeżeli kilku programistów wyśle na serwer dwie różniące się od siebie wersje tego samego pliku? Ano, powstaje konflikt, który trzeba rozwiązać. Większość porządnych VCS-ów ma wbudowany system rozwiązywania konfliktów, który w znacznym stopniu skraca czas potrzebny na ujednolicenie wersji.

Innym podejściem jest zablokowanie pliku w momencie, jeżeli został on pobrany do edycji przez jednego programistę. Dopóki nie wyśle on z powrotem pliku na serwer, pozostali użytkownicy VCS mogą czytać taki plik, ale nie mają możliwości wysyłania żadnych modyfikacji. Takie podejście zapewnia brak konfliktów (nigdy nie ma dwóch wersji tego samego pliku), ale z kolei prowadzi często do sytuacji, kiedy ktoś pobierze/zablokuje plik, zapomni o tym, wyjedzie na urlop i reszta musi czekać dwa tygodnie na odblokowanie tego jednego pliku. Da się to obejść (na ogół poprzez kontakt z administratorem VCS-u, który może taki plik odblokować ad-hoc), ale wprowadza to opóźnienia i zamieszanie do procesu.

Zaawansowane VCS-y na ogół wykonują kopię lokalną całego modułu (podzbioru powiązanych tematycznie plików należących do danego projektu) albo nawet całego projektu, następnie umożliwiają edycję lokalną wielu plików, a na koniec odesłanie całości na serwer, który wykona operację synchronizacji tych plików z wersją na serwerze, a w przypadku zaistnienia konfliktów uruchomi narzędzie do ich rozwiązywania.

Niektóre VCS-y potrafią zasugerować rozwiązanie konfliktu automatycznie. Weźmy następujący przykład:

O godzinie 8:00 jeden z plików na serwerze VCS zawiera następujący kod:

-----------------------
USE MyDB
GO
UPDATE dbo.T1 SET a=a+1 WHERE c=5
UPDATE dbo.T2 SET x=7 WHERE x>7
GO
-----------------------

O godzinie 9:00 pan Adam pobiera ten plik z serwera i zmienia go (u siebie, lokalnie) o tak:

-----------------------
USE MyDB
GO
UPDATE dbo.T1 SET a=a+1 WHERE c=15
UPDATE dbo.T2 SET x=7 WHERE x>7
GO
-----------------------

O godzinie 9:05 pan Bartosz pobiera ten sam plik z serwera i dokonuje następującej modyfikacji:

-----------------------
USE MyDB
GO
UPDATE dbo.T1 SET a=a+1 WHERE c=5
UPDATE dbo.T2 SET x=7 WHERE x>7
GO
DROP TABLE tmp.T1
GO
-----------------------

O godzinie 10:00 pan Bartosz odsyła swoją wersję pliku na VCS. VCS przesuwa aktualną wersję pliku do archiwum a następnie umieszcza wersję pana Bartosza jako najbardziej aktualną.
O godzinie 11:00 pan Adam wysyła na serwer swoją wersję pliku. I tu zaczynają się schody. Serwer "wie", że wersja pana Adama jest zmodyfikowaną wersją pobraną z serwera PRZED tym, kiedy pan Bartosz wgrał swoją wersję. Ponadto, serwer "widzi", że wersja pana Adama różni się od wersji pana Bartosza.

I co teraz?

Cóż, to już zależy od tego, jak sprytne jest oprogramowanie serwera. W najprostszym przypadku, serwer odrzuci plik pana Adama z komunikatem o konflikcie wersji. Pan Adam wówczas może pobrać świeżą wersję pliku z VCS (tą ze zmianami pana Bartosza) i wprowadzić swoje zmiany od nowa. W naszym przypadku to tylko jedna cyferka, więc nie ma za wiele do roboty - czasem jednak bywa tak, że obydwaj panowie wprowadzili więcej zmian i takie rozwiązanie jest czasochłonne dla pana Adama (w bardziej złożonych przypadkach musi on zapewne skontaktować się z panem Bartoszem, przedyskutować zmiany itd).

Najpopularniejszym podejściem jest wyświetlenie panu Adamowi obydwu wersji plików, z podświetlonymi na kolorowo różnicami. Jeżeli pan Adam orientuje się w temacie, może poprzez ^C - ^V przekleić odpowiednie fragmenty między wersjami i sprawa załatwiona.

Najbardziej zaawansowane narzędzia do usuwania konfliktów wersji potrafią automatycznie zaproponować nową wersję kodu, zawierającą zmiany obydwu panów. W naszym przypadku sytuacja jest dość prosta, ponieważ pan Adam zmienił linię numer 4 (i nic ponadto) a pan Bartosz dodał 3 linie na końcu (i nic ponadto). Łatwo jest więc połączyć te dwie modyfikacje w jedną i wygenerować (automatycznie) kod, który zawiera wszystkie zamiany:

-----------------------
USE MyDB
GO
UPDATE dbo.T1 SET a=a+1 WHERE c=15
UPDATE dbo.T2 SET x=7 WHERE x>7
GO
DROP TABLE tmp.T1
GO
-----------------------

W bardziej skomplikowanych sytuacjach, kiedy zmiany z wielu źródeł dotyczą tych samych linii / bloków kodu, bądź też są na tyle duże, że oprogramowanie "nie radzi" sobie z ich poprawną analizą, kończy się zazwyczaj wyświetleniem panu Adamowi obydwu wersji plików i pozostawienie mu decyzji na znalezienie wspólnego mianownika.

Za jakiś czas postaram się napisać trochę więcej o organizacji kodu w dużym przedsiębiorstwie. Temat jest ciekawy (może nie dla wszystkich... ale dla mnie jest, a to MÓJ blog!) i niebanalny.

Na koniec stary ale zawsze aktualny cytat:

"Programowanie to wyścig pomiędzy programistami, usiłującymi stworzyć większe, lepsze i bardziej idioto-odporne programy, a Wszechświatem tworzącym co raz większych i lepszych idiotów. Jak na razie Wszechświat wygrywa."

W oryginale:

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning."
-- Rich Cook

https://xpil.eu/rH2YP

1 Comment

Leave a Comment

Komentarze mile widziane.

Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]

Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.