Pozory porządku – Historie z placu boju
Pracując jako developer i biorąc udział w kolejnych projektach zbieramy w końcu zestaw historii, które teraz nas śmieszą ale kiedyś rwaliśmy sobie przez to włosy z głowy. Ponieważ mi też powoli zbierają się tego typu zeznania to postanowiłem spisać je dla potomności.
Kolejność losowa, zależnie od tego co mi się akurat przypomni. Z oczywistych powodów nie mogę podawać nazw firm. A nazwisk i tak nie pamiętam zwykle.
Dzisiejszy przypadek jest w miarę świeży. Sprzed maksymalnie kilku miesięcy.
Side quest
Ponieważ pracuję dla firmy outsourcingowej to naturalną koleją rzeczy mamy wielu klientów równolegle. I trafiła się taka sytuacja, że jeden z klientów miał problem z wydajnością aplikacji. I z tego powodu poszukiwana była osoba, która wspomoże rozwiązanie problemu. Zachęcony wyzwaniem (i woreczkiem cebul na koncie) postanowiłem dołożyć sobie na 2 tygodnie dodatkowe 2 godziny pracy dziennie.
Ułatwieniem było to, że w projekt byli już zaangażowani koledzy, z którymi wcześniej pracowałem. Wprowadzili mnie oni w temat. Dostałem dostęp do repozytorium i wspólnie skonfigurowaliśmy projekt.
Od początku pod górkę
Już od początku były schody bo pierwszym problemem była baza danych. Aplikacja była desktopowa i wymagała zainstalowania lokalnej bazy danych Postgresql. Nie brzmi skomplikowanie jednak potrzebna byłą konkretna wersja, z konkretnym zestawem uprawnień i co do piksela dokładnie skonfigurowaną bazą i tabelami. Część rzeczy była załatwiana skryptem. Ale to też wymagało żeby foldery w dokładnie każdym miejscu były idealnie tak samo ułożone. Tak samo pliki z danymi musiały być w konkretnym katalogu na dysku systemowym. Ogólnie samo uruchomienie bazy danych tak żeby zawierała dane testowe zajęło nam około godziny i mniej więcej dwóch reinstalacji i kilku restartów komputera.
Potem nie było dużo łatwiej bo sama aplikacja w najnowszej wersji nie miała jeszcze gotowego instalatora. A ponownie wymagała żeby wszystko było przygotowane od linijki. Było trochę problemów z licencjami i kontami testowymi (aplikacja sprzedawana użytkownikom na płycie). Ale jakoś poszło. Po kilku godzinach udało się ją uruchomić.
Uporządkowany chaos
Najciekawiej się zrobiło kiedy doszliśmy do kodu źródłowego. I to jest właściwie meritum tego tekstu.
Pierwsza rzecz jaka mnie uderzyła, mimo, że zostałem o niej uprzedzony, to liczba projektów w solucji. Aplikacja miała coś koło TRZYSTU projektów. Dla Visual Studio był to taki szok, że chłopaki napisali swój skrypt do przebudowywania całości bo wykonanie Rebuild powodowało, że Visual Studio tracił kontakt ze światem. Mimo włączonej kompilacji na wszystkich rdzeniach.
I tutaj się robi ciekawie. Bo te wszystkie projekty i to co się w nich znajdowało wyglądało jakby ktoś zasadę pojedynczej odpowiedzialności wziął sobie BARDZO MOCNO do serca. Każdy z tych projektów to było zwykle maksymalnie kilka klas. Co więcej przechodząc przez te klasy okazywało się, że wiele z nich jedyne co robi to wywołuje metody z innych klas, z innych projektów.
W ten sposób patrząc na pojedyncze pliki miało się wrażenie, że jest to super kod. Wszystko w miarę krótkie (poza pojedynczymi wyjątkami). Nazwy jasne. Tylko kiedy próbowałem debugować aplikację to miałem wrażenie, że kręcę się w kółko. Dodawałem breakpoint i przechodząc przez kolejne linie lądowałem w kolejnych projektach. Jestem wręcz pewien, że w jednej takiej rundzie przechodziłem kilkukrotnie przez te same miejsca. Ale nie wiem, bo sporo rzeczy było napisane w ten sposób, że miały bardzo podobne nazwy i albo były jedną z kilku implementacji wywoływanych w zależności od kontekstu albo były kolejnymi etapami procesu. Gdzie nazwa kolejnych fragmentów różniła się jednym słowem w nazwie klasy, ale wszystkie one miały bardzo podobne interfejsy i strukturę.
Dochodziło do tego, że modyfikowałem jakiś fragment. Przechodziłem do innych plików i nagle trafiałem na fragment, który wyglądał identycznie tylko nie był zmieniony. Czułem się jak ktoś kto postradał zmysły. Bo już nie wiedziałem co zmieniłem, a co nie.
Siatka połączeń
I cała ta idea bardzo małych projektów może i by miała sens. Bo faktycznie można w ten sposób ekstremalnie rozdzielać odpowiedzialności. Tylko, że w tym przypadku żadnego podziału nie było! Klasy z różnych projektów zależały od siebie bardzo mocno. Do tego razem korzystały z interfejsów z jeszcze innych projektów, a ich wywołania były w kolejnych projektach, które znowu się łączyły.
W ten sposób kod, który na poziomie metody był wypieszczony zaczynał odkrywać swoje mroczne sekrety im wyżej się patrzyło. Każda warstwa sama w sobie bardzo ładnie się prezentowała. Ale potem widok ich wszystkich poskładanych razem sprawiał wrażenie tego pudełka, do którego wrzucamy wszystkie kable, które „kiedyś się przydadzą”. To już jest jedna masa, którą się przygarnia w całości albo wcale.
Miejsce gdzie całość była w ogóle uruchamiana odkryłem chyba dopiero po 2 albo 3 dniach debugowania kodu…
Dokumentacja? 1000% normy
Skoro projekt był tak „dopieszczony” to i kwestia udokumentowania go musiała stać na najwyższym poziomie.
Nooo powiedzmy, że tak było.
Sprawa wyglądała w ten sposób, że klient początkowo wymagał żeby nawet prywatne metody miały pełną dokumentację w postaci komentarzy (dokumentacja w postaci znaczników umieszczonych w specjalnych komentarzach zaczynających się od /// ). Na szczęście ten pomysł został w końcu wybity z głowy.
Jednak i tak otwierając dowolną klasę stosunek zielonego fontu komentarzy do fontu kodu to było spokojnie 10:1. Niekiedy naprawdę musiałem spędzić chwilę czasu żeby odnaleźć jakieś pole klasy pomiędzy komentarzami. Ale były one dokładne, zawierające wszystkie potrzebne informacje itd. Tylko, że powodowały, że kod wyglądał jakby był jednym wielkim komentarzem.
Koszmar.
Dodatkowo dla klienta jedynym kryterium było to czy kod ma wystarczająco dużo komentarzy i czy każda litera w nazwie się zgadza. Kompletnie nie interesowało go to czy całość wali się jak wieża pod którą ktoś zrobił podkop. Ważne, że cegły były czyste.
Podsumowanie
Ostatecznie niewiele udało mi się zrobić bo z tych 2 tygodni po 2 godziny dziennie mniej więcej połowę czasu poświęciłem na szukanie klas w kodzie i uruchamianie aplikacji, która budowała się i startowała około 15 minut. Jeden z procesów faktycznie mocno przyspieszył kiedy zastosowałem hashmapę zamiast zwykłego przeszukiwania zbioru kilkunastu tysięcy punktów w pętli. Parę prób zakończyło się fiaskiem bo aplikacja nie była gotowa na zrównoleglanie. Pod koniec doszedłem do tego, że jakieś 70% czasu uruchamiania (jakieś 2-3 minuty) zabierała inicjalizacja zewnętrznego frameworka, na którym to wszystko stało, a resztę procesu ograniczała zewnętrzna biblioteka, dla której nie było żadnej alternatywy i sama też od wielu lat niewiele miała zmieniane.
Czy nie polecam takiego doświadczenia? Chyba paradoksalnie polecam. Ale na krótko. Tak jak to wyglądało u mnie. 2-3 tygodnie poprzerzucania obornika i uciekamy. A doświadczenie zostaje.
Jeżeli chcecie więcej takich wpisów to zostawcie komentarz albo lajka pod linkiem do tego tekstu na Facebooku :)
Ciekawy wpis, historie z placu boju są zawsze interesujące ale dopiero jak się na nie popatrzy z perspektywy czasu, gdy stres i kurz opadnie :)
Pozdrawiam, Mateusz.