Słyszałem ostatnio jakże prawdziwą tezę: programowanie to 95% frustracji, że nie działa i 5% nieposkromionej dumy, że działa.
Jak już działa, to czasem zafascynowani chwilą wrzucamy nasz kod na środowisko produkcyjne i po chwili, po jakimś czasie, a może i później, przychodzi do nas ktoś z zespołu, szef albo klient i mówi nam: „Nie działa – twoja wina!”. Można próbować się bronić standardowym „U mnie działa” albo „To nie bug – to feature”, niestety takie hasła rzadko przynoszą pożądany efekt. Prawda jest taka, że bardzo często nie my tak naprawdę jesteśmy odpowiedzialni za błędy pojawiające się w trakcie życia projektu. W tym miejscu chciałbym przekazać kilka sprawdzonych metod, które pozwolą Wam skutecznie odpierać zarzuty.
1. Uporządkowany proces wytwórczy
Wszyscy pracujemy w jakiejś metodyce. Czy to stygmatyzowany Waterfall, czy wychwalany pod niebiosa Agile, czy wszystkie pozostałe wariacje na ich temat. I to jest dobre. Złe natomiast jest to, że często bardziej mówimy, że mamy metodykę, niż ją stosujemy. Obserwuję ogrom projektów prowadzonych w nazywanym przeze mnie Chaos Driven Delopment. Charakterystyczne dla tych projektów jest to, że każdy może być bohaterem, bo im więcej pracujesz, tym większy Twój wkład w projekt… Brzmi jak szybka droga do wypalenia? Dla mnie tak. Co ważniejsze, chaotyczny proces wytwórczy nie daje nam możliwości obrony. Natomiast uporządkowany pozwala odpowiadać tak:
„Dlaczego to nie jest zrobione?” – „Bo nie było w Backlogu”. Zadania w tej sytuacji realizowane są nie dlatego, bo ktoś powiedział, że zrealizowane mają być, ale dlatego, że istnieje ustrukturyzowany plan wytwórczy. Dzięki temu zadania zwykle są przemyślane i samo to powoduje szybsze dostarczenie najbardziej pożądanych funkcjonalności.
Dalej: „Dlaczego to nie jest zrobione?” – „Bo nie było w Backlogu”. Zadbanie o kompletny opis da nam możliwość obrony, ale przede wszystkim pozwoli nam wykonać zadanie zgodnie z wymaganiami klienta. Takie sytuacje można mnożyć dalej, dlatego warto zaprzyjaźnić się z dokumentacją zadań, niezależnie czy jest prowadzona w narzędziu dedykowanym jak Azure DevOps, Jira, czy jest prowadzona w arkuszu kalkulacyjnym.
2. Wiele zespołów – który winny?
Zwykle jest tak, że największą winę w oczach biznesu czy klienta ponosi warstwa wizualna. Naturalnym jest, że jak ktoś nietechniczny widzi błąd w aplikacji udostępniającej interfejs użytkownikowi, załóżmy mobilnej, oskarża o błąd właśnie twórcę tej aplikacji. My jednak wiemy, że na to, co zobaczy użytkownik składa się wiele warstw infrastruktury, która tworzona jest przez wiele zespołów. Zespół bazodanowców wprowadził zmianę w tabeli i modele się nie mapują? Zespół API zmienił proces rejestracji? Zespół sieciowców podmienił certyfikaty?
Jeśli pozostałe zespoły nie zdążyły zareagować na taką zmianę, klient dowie się o tym przez błąd w aplikacji mobilnej. Jeśli więc jesteś członkiem zespołu, który jest najbliżej klienta, możesz wykonać pracę, które uchronią Twoje dobre imię. Wiadomym jest, że piszemy testy. Pokrycie testami jest niejednokrotnie warunkiem uzyskania przepustki do repozytorium kodu. Natomiast testy, które szczególnie pomogą nam ustrzec się przed zmianami w infrastrukturze, na które nie mamy wpływu, to testy integracyjne, czyli takie, które wykonywane są w celu wykrycia błędów w komunikacji między komponentami oraz w interfejsach. Przetestowanie warstwy integrującej przed każdą zmianą jakiegokolwiek z komponentów naszej infrastruktury spowoduje, że nikt nie będzie w stanie podłożyć nam (w łatwy sposób) przysłowiowej bomby. Jeśli jeszcze wepniemy nasze testy w dobrze skonfigurowany proces Continuous Integration/Continuous Delivery, będziemy mogli spać spokojnie.
3. Repozytorium kodu prawdę ci powie
Mam wrażenie, że my technicy nieprzyzwoicie lubimy znajdować winnych: widziałeś głupotę w kodzie? Blame! I od razu widać ostatniego modyfikującego linię kodu, od razu można się pośmiać… Niestety, nawet najpopularniejszy obecnie GIT zrobi psikusa niedoświadczonemu użytkownikowi. Historię wprowadzających zmiany w GIT można nadpisać swoim nazwiskiem w bardzo prosty sposób. Nie jest to miejsce, w którym chciałbym robić wykłady z obsługi GITa, ale jeśli już przyszło Wam z nim pracować, zwróćcie uwagę na dobre praktyki wykorzystania komendy rebase, w szczególności jeśli zdarzają się sytuacje, w których pracujecie w więcej niż jedną osobę na jednym branchu bazowym. Zagadnienie związane z utrzymaniem prawidłowej historii w GIT jest dość popularne i proste zapytanie do wujka Googla pozwoli Wam zgłębić temat, a naprawdę warto, żeby ktoś nie śmiał się z Was, kiedy to nie Wasza wina.
4. Code Review
Wydaje się to być naturalne, że każdy kod wchodzący na produkcję powinien zostać przeczytany i zaakceptowany przez innego członka zespołu – uprawnionego do takiej czynności. W kontekście obrony przed oskarżeniami może nie jest to najbardziej koleżeński sposób – zrzucanie winy na osobę, która zaakceptowała Pull Request, ale sam fakt zadbania przez nas o to, żeby PR został sprawdzony, spowoduje, że prawdopodobieństwo popełnienia przez nas błędu znacznie spadnie.
5. Testuj sam siebie
Zespoły wytwarzające oprogramowanie zwykle w swoich szeregach mają dedykowanego testera. Nie zwalnia nas to jednak z myślenia o kodzie jako o działającej funkcjonalności, która przy okazji nie psuje dwóch innych. Oprócz sprawdzenia działania naszego kodu ręcznie, warto zadbać o pomoc automatyzacji przez zastosowanie testów jednostkowych, a w szczególności sprawdzonych praktyk wytwarzania oprogramowania wraz z testowaniem implementacji – TDD, czy nawet testowaniem całych funkcjonalności – BDD. Pozwoli to również innym członkom pracy. O wszystkie z tych elementów możemy zadbać sami. Wejście w nawyk korzystania z nich na porządku dziennym uczyni z Was programistów bardziej efektywnych – zarówno w kontekście pracy zespołowej, jak i w rezultacie, przez polepszenie swoich umiejętności, finansowym, czego serdecznie Wam życzę.