figure
22 listopada 2019

Jak szybko i skutecznie zbudować profesjonalny zespół programistyczny w kilku krokach – studium przypadku

Obecne trendy w tworzeniu i dostarczaniu dedykowanego oprogramowania dla firm mocno poszły w kierunku modelu opartego o outsourcing. Jest to bardzo wygodne rozwiązanie, gdyż klient (firma zamawiająca) nie musi utrzymywać całego działu programistów. Zamiast tego może skorzystać z usługi outsourcingu IT i wynająć specjalistów i ekspertów, którzy w profesjonalny sposób dostarczą gotowy produkt. W tym rozwiązaniu odpada problem inwestycji w kształcenie własnych programistów, testerów, analityków czy nawet IT managerów. Jest to wygodne i elastyczne podejście. Korzyści są oczywiste, a dowodem na to jest stale rosnące zapotrzebowanie na outsourcing specjalistów z branży IT oraz nowo powstające software house’y.

A gdyby zrobić inaczej niż wszyscy? Czy tworzenie działu odpowiedzialnego za dostarczanie oprogramowania w firmie, która z IT ma niewiele wspólnego ma sens i szansę powodzenia? Pewnie tak, przecież zawsze można zatrudnić wykwalifikowane osoby, które wypracują wszystkie procesy i zbudują zespół. OK, to teraz podnieśmy poprzeczkę. Co jeśli podejmiemy decyzję o budowie zespołu tylko i wyłącznie w oparciu o pracowników, którzy bardzo dobrze znają biznes własnej firmy, ale z programowaniem i branżą IT nie mieli wcześniej do czynienia? Na dodatek celem jest stworzenie od podstaw i wdrożenie systemu do zarządzania produkcją w przeciągu kilku miesięcy. Czy to brzmi jak szalony plan? Być może, ale w tym wpisie chcę pokazać, że czasem właśnie w tym szaleństwie jest metoda. Zapraszam do lektury studium przypadku pewnej firmy, która zdecydowała się pójść tą drogą i wyszkolić swój własny zespół programistów.

Zacznijmy od przedstawienia profilu firmy klienta. Jest to duża organizacja działająca w branży motoryzacyjnej, mająca oddziały w kilkunastu krajach. Do głównych obszarów jej działalności należy produkcja elementów wyposażenia aut. W jednym ze swoich oddziałów firma wdrożyła system do monitoringu, kontrolowania i planowania produkcji. Jest to system napisany i utrzymywany przez jednego (!) z pracowników – pasjonatę i samouka w dziedzinie programowania. System działa bardzo dobrze, ale został napisany bez użycia jakichkolwiek wzorców architektonicznych, dobrych praktyk programowania czy nawet bez użycia systemu kontroli wersji! Aby móc go sensownie rozwijać i wdrażać w kolejnych zakładach produkcyjnych należało napisać go od nowa w profesjonalny sposób z użyciem najlepszych technik i narzędzi. Z taką potrzebą klient zwrócił się do Transition Technologies PSC. Pomogliśmy mu w ciągu około 8 miesięcy zrealizować cel jakim było napisanie odpowiedniego systemu i jednocześnie przekazanie wiedzy know-how dotyczącej całego procesu wytwarzania oprogramowania. Warto podkreślić, że praca z klientem odbywała się niemal 100% zdalnie. W dalszej części artykułu skupię się na opisaniu, jak w tak krótkim czasie możliwe było wyszkolenie 4 developerów od poziomu praktycznie zerowego do solidnych juniorów, a w przypadku jednej osoby -nawet regular developera.

Krok 1 – szkolenia i warsztaty

Pierwszym oczywistym krokiem jest nauka podstaw niezbędnych do rozpoczęcia pracy. Projekt miał powstać w technologii .NET Core, do zarządzania projektem wybraliśmy Jirę, a kod źródłowy miał być trzymany i zarządzany przez Bitbucket. Do zapewnienia Continuous Integration zaproponowaliśmy Jenkinsa. W pierwszej kolejności rozpoczęliśmy cykl szkoleń z powyższych tematów. W ciągu jednego tygodnia zaaplikowaliśmy solidny zastrzyk wiedzy organizując następujące szkolenia:
• Jira user training,
• Git developer training,
• BitBucket developer training,
• Visual Studio training,
• Development process workshop,
• Jenkins developer training.

Każde z nich musiało być prowadzone od podstaw i trwało do 8 godzin, a więc było tylko wprowadzeniem w temat. Aby poznać głębiej te zagadnienia, zespół przez 3-4 tygodnie miał szkolić się dalej we własnym zakresie z ukierunkowaniem głównie na: C#, ASP.NET MVC Core, Entity Framework Core, JavaScript i jQuery (tak, stare dobre jQuery – uznałem, że nowoczesne frameworki js-owe miałyby zbyt wysoki próg wejścia dla zupełnie początkujących). Znaczącą rolę odegrał tu dostęp do platformy zawierającej dużą bazę dobrej jakości szkoleń online. Dodatkowo warto wspomnieć, że w ramach nauki własnej, tuż przed rozpoczęciem prac nad właściwym projektem, część programistów pracowała samodzielnie nad własnymi projektami rozwojowymi, a następnie projekty te były poddane rewizji. Dzięki temu pierwsze uwagi odnoszące się do rozpoczęcia programowania można było zgłosić jeszcze na tych tzw. demo projektach i dana osoba wchodząc na właściwy projekt była już bogatsza o doświadczenia zebrane podczas realizacji demo projektu.

Na dalszym etapie projektu organizowaliśmy mniej więcej co dwa miesiące 2-3 dniowe warsztaty on-site u klienta. To był moment, w którym mogliśmy dokładnie wytłumaczyć i przeszkolić osoby biorące udział w projekcie z potrzebnego w danej chwili tematu. Dużo wygodniej jest odpowiedzieć na wszystkie nurtujące pytania i przekazać niezbędne informacje w trakcie spotkania w cztery oczy, mając do dyspozycji rzutnik czy też tablicę, na której można pewne rzeczy rozrysować i pochylić się nad trudniejszym zagadnieniem.

Krok 2 – kontrolowanie, mentoring, konsultacje

Kiedy rozpoczęliśmy pierwszy sprint i wystartowaliśmy z pracą nad właściwym projektem, mój czteroosobowy zespół programistów poruszał się jeszcze po nowopoznanych zagadnieniach jak we mgle. Jednego nie można było im odmówić – ambicji i chęci do nauki. Nie było czasu na wyszkolenie ich na odpowiednio wysokim poziomie i dopiero wówczas rozpoczęcie projektu. Musieliśmy zacząć działać tu i teraz. Na szczęście wszyscy znali i akceptowali ryzyko wynikające z tego, że zespół dopiero się uczy. Na mnie spoczywał obowiązek trzymania całego projektu w ryzach. Dla klienta najważniejsze było, aby stworzyć produkt wysokiej jakości , nawet kosztem opóźnienia w realizacji zadań. Wykorzystałem do tego wszelkie dostępne narzędzia ułatwiające mi pracę. Dzięki Jirze, która była naszym jedynym źródłem prawdy o projekcie („one source of truth”), w każdym momencie łatwo można było sprawdzić aktualny status prac i zidentyfikować problemy.

Dzięki pull requestom z Bitbucketa, każde zadanie czy naprawiony błąd musiał przejść przez moje code review zanim zostało to zmergowane do głównego brancha. Początkowo, co zrozumiałe, uwag było bardzo dużo. Głównie były to zastrzeżenia dotyczące nie tylko samego kodu, ale również niewłaściwej pracy z gitem. Okazało się na przykład, że jak ktoś pracował równolegle nad kilkoma zadaniami i miał kilka feature branchy, to jak trzeba było nanieść poprawkę na jeden z nich, poprawka lądowała najpierw na branchu, na którym aktualnie pracowali, a potem była ręcznie kopiowana i nanoszona na wszystkie pozostałe branche. Powodowało to, że na jednym feature branchu znajdował się kod, który powinien znajdować się na zupełnie innym. Skutkowało to wieloma merge konfliktami. Benefity związane z separacją kodu i pracą branch per task stały się w pełni zrozumiałe dopiero po ponownym szkoleniu z gita skupiającym się już tylko na tych obszarach, z którymi faktycznie były problemy. O ile nie spodziewałem się wcześniej trudności z poprawną pracą z gitem, to byłem niemalże pewien problemów ze zrozumieniem i właściwą implementacją zadań zgodnie z zaproponowaną architekturą oraz dobrymi zasadami, takimi jak SOLID. Wiedziałem, że te zagadnienia mogą być faktycznie trudne do przyswojenia dla zespołu nie mającego doświadczenia. Skupiłem się więc na przeszkoleniu wszystkich z tego czym jest SOLID, pokazaniu na prostych przykładach, jak należy pisać kod z użyciem tych praktyk i dlaczego jest to tak ważne. Poza tym, zależało mi na zaimplementowaniu jednego z pierwszych user story, wymagającego przejścia przez wszystkie warstwy systemu i pokazanie tego jako wzorcowy przykład. Wszystkie pozostałe błędy starałem się korygować na bieżąco podczas code review, które na początku również wyglądało nietypowo. Dlaczego? Pewnie się domyślacie, że błędów było wiele. Szalenie istotne było, aby moje uwagi były rzeczowe i konstruktywne oraz aby za ich pomocą przekazać, dlaczego coś jest zrobione źle, jak może być zrobione lepiej i dlaczego inne rozwiązanie jest skuteczniejsze. Często wymagało to dodatkowej rozmowy ze współdzieleniem ekranu, aby doprecyzować sens danej uwagi i upewnić się, że została ona dobrze zrozumiana. Takie podejście miało na celu naukę i eliminację podobnych błędów w przyszłości. Ponadto budowało dobrą relację z programistą, bo uwagi nie były odbierane jako czepianie się lub złośliwość, a bardziej jako chęć przekazania mojej wiedzy i doświadczenia (na zasadzie – zobacz, jak zrobisz to inaczej, to wtedy będzie lepiej, z takiego a takiego powodu). I poprzez taką systematyczną, mozolną pracę zespół w szybkim tempie nabierał doświadczenia. I to w najlepszy możliwy sposób, bo ucząc się na własnych błędach. Sami empirycznie doświadczali, dlaczego w wielu przypadkach powtarzanie kodu jest złe, mieszanie odpowiedzialności przynosi złe efekty, dlaczego konwencje nazewnicze mają znaczenie, po co w zasadzie są testy jednostkowe, na napisanie których trzeba poświęcić tyle czasu itp.

Jak w każdym projekcie, czasami trzeba było się pochylić nad jakimś trudniejszym zagadnieniem i wymyśleć dobry sposób na jego zrealizowanie. Tego typu sprawy najczęściej były planowane jako temat do dyskusji podczas warsztatów on-site u klienta. Mogliśmy usiąść wspólnie w jednym pomieszczeniu i swobodnie zrobić burzę mózgów, po której wyłaniał się zarys, a następnie szczegóły rozwiązania. Było to też niezwykle budujące i rozwijające dla programistów. Nauczyło ich jak szukać rozwiązań dla kluczowych i skomplikowanych wymagań biznesowych tak, by mieć na uwadze również wydajność, skalowalność czy bezpieczeństwo całego systemu. Angażując się w ten proces, uczyli się koncentrować uwagę nie tylko na omawianym problemie, ale również na analizowaniu jego wpływu na system jako całość.

Taka praca przynosiła wymierne korzyści. Postęp był widoczny chociażby na spotkaniach Sprint Retrospective. Developerzy mówili czego nowego się nauczyli w danym sprincie. Oprócz tego widać było jak kolejne propozycje usprawnień projektowych z naszego rejestru lessons learned były wdrażane i jak wpływało to na jakość i wydajność pracy mierzoną przez raporty burndown i velocity. Widać było również, że jest coraz mniej uwag z code review, a pull requesty są szybciej mergowane.

Krok 3 – przygotowanie do samodzielnej pracy

Ostatnim krokiem było przygotowanie członków zespołu do pracy jako samodzielnych programistów, którzy znają, rozumieją i stosują podstawowe techniki i wzorce programowania w .NET. Powinni umieć rozwiązać (lub wyszukać narzędzia pomocne do rozwiązania) większości typowych problemów programistycznych. Ważne jest również, aby potrafili zidentyfikować błędy w kodzie innego programisty robiąc code review.

Proces wejścia na ten poziom odbywał się stopniowo. Najpierw, kiedy widać było, że programista popełnia coraz mniej poważnych błędów, sam je zauważa i potrzebuje pomocy jedynie przy trudniejszych zadaniach, przyznawaliśmy mu rolę reviewera. Od tej pory mógł robić code review innym, akceptować pull requesty, ale wymagały one dodatkowego sprawdzenia przez drugiego reviewera (tzw. double check). Uczyło go to innego spojrzenia, bo od tej pory nie tylko jego kod podlegał sprawdzeniu, ale sam miał szansę spojrzeć krytycznie na kod pisany przez zespół i zgłosić błędy innym autorom. Dodatkowo, przy tzw. double checku mógł jeszcze raz spojrzeć na pull requesta i zobaczyć, jakie ewentualne inne błędy zgłosił drugi reviewer, których on sam nie wychwycił. W ocenie pomagał przygotowany wcześniej dokument wypunktowujący zasady poprawnego kodowania w projekcie, tzw. developer guide. Kiedy programista zrobił sporą ilość code review i ich jakość była zadowalająca, stawał się niezależnym reviewerem. Od tej pory jego akceptacja pull requesta skutkowała zmergowaniem go do docelowego brancha.

W ten sposób doszliśmy do etapu, gdzie zespół był już na poziomie solidnych junior developerów, a w przypadku przynajmniej jednego z nich był to już poziom regular developera. Dzięki czemu zespół nie wymagał już dalszego stałego mentoringu, kontroli i nauki. Mógł rozwijać się dalej samodzielnie. Na wypadek zaistnienia poważnych problemów wymagających do ich rozwiązania dużej wiedzy i doświadczenia, klient pozostawił sobie jedynie w kontrakcie furtkę na konsultacje i szkolenia w opcjonalnym i niewielkim wymiarze czasowym.

Podsumowanie

Czy tego rodzaju eksperyment polegający na zbudowaniu zespołu w oparciu o osoby bez doświadczenia i bez niezbędnej wiedzy na temat programowania zakończył się sukcesem? Jak najbardziej! Projekt został zrealizowany zgodnie z założeniami. Bardzo dobrze przeszedł pierwsze testy bezpieczeństwa, które wykryły tylko jeden poważny incydent. W momencie zakończenia współpracy i mojej roli w projekcie, software był przygotowywany do wdrożenia produkcyjnego. Wiadomo, że pełna ocena jakości projektu i to, czy okaże się on sukcesem czy nie, będzie możliwa dopiero po pewnym czasie działania na produkcji. Chciałbym jednak podkreślić, że w tym wszystkim równie ważne jak zrealizowanie samego projektu, było uzyskanie przez firmę kompetencji i wiedzy know-how związanej z tworzeniem oprogramowania. Dzięki temu, klient może budować i rozwijać dalej te kompetencje poszerzając zespół o kolejnych specjalistów, nie tylko już programistów, ale również testerów, analityków czy devopsów.

Jak podobał ci się ten post?

Kliknij na gwiazdkę, aby ocenić!

Średnia ocena: / 5. Liczba głosów:

Zostaw komentarz (0 komentarzy)

Napisz opinię…
W przypadku naruszenia Regulaminu Twój wpis zostanie usunięty.
Twoje imię i nazwisko

    Kontakt

    Transition Technologies PSC Sp. z o.o.
    Polska, Łódź 90-361, ul. Piotrkowska 276
    NIP 729-271-23-88

    tel.: +48 42 664 97 20
    fax: +48 42 664 97 30

    contact@ttpsc.com