Pierwsze Kroki w Naszej Transformacji DevOps
5 min czytania

W drugim rozdziale tej serii – „DevOps dla zwycięstwa” – badamy kluczowe początkowe kroki podróży transformacji DevOps. Pierwsze kroki w każdej podróży transformacyjnej są często najtrudniejsze. W DevOps, zidentyfikowanie właściwych początkowych kroków – tych, które są zarówno skuteczne, jak i osiągalne – jest kluczem do osiągnięcia znaczącego postępu.

Wiele organizacji popełnia błąd, ślepo wdrażając najlepsze praktyki bez uwzględnienia ich unikalnych ograniczeń, co często prowadzi do frustracji i zniechęcenia niepowodzeniami. Zamiast tego, wymagane jest bardziej strategiczne podejście – takie, które identyfikuje wąskie gardła i systematycznie je eliminuje.

Jak zidentyfikować pierwsze kroki?

Potężna zasada określająca, od czego zacząć, pochodzi z badań opublikowanych 30 lat temu w książce Cel: Proces ciągłego doskonalenia autorstwa Eliyahu M. Goldratta. Idea jest prosta: zidentyfikować główne wąskie gardło – czynnik ograniczający wydajność systemu. W naszym przypadku stało się to jasne, gdy zobaczyliśmy, jak praca piętrzy się w zespole deweloperskim. Zadania były rozpoczynane, ale nie kończone, a zaległości stale rosły.

Aby odkryć główne przyczyny, zorganizowaliśmy szczegółowe sesje z zespołami deweloperskimi, liderami technicznymi i menedżerami produktu. Dyskusje te ujawniły kilka kluczowych problemów:

  • Zespoły podejmowały się nowych zadań, zanim ukończyły te już istniejące.
  • Nie istniały jasne kryteria ukończenia zadań – to, co deweloperzy uważali za „ukończone”, często różniło się od oczekiwań interesariuszy.
  • Nie było obiektywnych miar jakości przed uznaniem pracy za zakończoną, co prowadziło do wad i konieczności poprawek.
  • Częste zmiany przydziałów zakłócały stabilność zespołu, powodując nieefektywność.

Tworzenie stabilnych zespołów.

Jednym z pierwszych środków naprawczych była restrukturyzacja zespołów w celu zapewnienia spójności i koncentracji. Zamiast traktować grupy osób jako doraźne zespoły zadaniowe, utworzyliśmy stabilne, długoterminowe zespoły z jasno określonymi zakresami odpowiedzialności.

Tworzenie niektórych zespołów, takich jak zespoły deweloperskie, było stosunkowo proste. Jednak organizowanie zespołów wsparcia – takich jak infrastruktura, zarządzanie projektami, zarządzanie produktami i analiza biznesowa – okazało się trudniejsze. Przeszliśmy przez kilka iteracji, aby znaleźć właściwe kombinacje.

Zgodnie z zasadą myślenia zorientowanego na zespół opisaną w książce Team Topologies autorstwa Matthew Skeltona i Manuela Paisa, my:

  • Stworzono małe, autonomiczne zespoły (4–7 członków) w celu promowania głębokiej wiedzy specjalistycznej i odpowiedzialności.
  • Wyeliminowano zależności między zespołami poprzez zapewnienie, że osoby były w pełni przydzielone do jednego zespołu.
  • Powtarzano prace nad strukturami zespołów, zwłaszcza w przypadku funkcji wsparcia, takich jak infrastruktura i zarządzanie produktem, w celu optymalizacji przepływu.

Wykorzystanie narzędzi dla widoczności i zarządzania

Po ustrukturyzowaniu zespołów przeszliśmy na Azure DevOps do zarządzania backlogiem i pracą. Zunifikowana platforma umożliwiła:

  • Lepsza widoczność pracy , aby zespoły mogły śledzić postępy w sposób przejrzysty.
  • Ustandaryzowane definicje “zakończenia” aby ujednolicić oczekiwania we wszystkich działach.
  • Ulepszone zarządzanie zaległościami, ograniczające rozszerzanie zakresu i konflikty priorytetów.

Egzekwowanie obiektywnych wskaźników jakości

Aby rozwiązać problem niejasnych miar jakości przed oznaczeniem zadań jako “gotowe do testowania”, zintegrowaliśmy narzędzie do statycznej analizy kodu, dostarczające obiektywnych informacji na temat:

  • Pokrycie kodu
  • Luki w zabezpieczeniach.
  • Podejrzane fragmenty kodu

Udoskonaliliśmy również naszą definicję „ukończenia”, aby kontrole jakości stały się obowiązkowym krokiem przed oznaczeniem zadań jako zakończone.

Zarządzanie pracami w toku (WIP)

Jedną z najbardziej znaczących zmian było monitorowanie i ograniczanie pracy w toku (WIP). Wysokie WIP wskazywało na wąskie gardła, co pozwoliło nam proaktywnie reagować na obszary, w których praca utykała.

To systematyczne podejście, zakorzenione w The Goal i Team Topologies, położyło podwaliny pod ciągłe doskonalenie, zmniejszając zależności i poprawiając odpowiedzialność.

W naszej podróży transformacji DevOps, jednym z najważniejszych odkryć było to, że po początkowych usprawnieniach, głównym ograniczeniem przepływu stało się projektowanie oprogramowania – a konkretnie, testowalność naszego kodu. Po usunięciu początkowych wąskich gardeł poprzez poprawę organizacji zespołu, zdefiniowanie „Definicji Ukończenia” i wdrożenie analizy kodu, zauważyliśmy, że praca kumulowała się w fazie testowania. Kod opracowany przez zespoły scrumowe często czekał w kolejce na testowanie przez członków QA w tych samych zespołach scrumowych.

Rozwiązanie kolejnego wąskiego gardła: Luka w testowaniu

Po usunięciu początkowych wąskich gardeł pojawiło się nowe ograniczenie – opóźnienia w testowaniu. Podczas gdy zadania rozwojowe postępowały sprawnie, testowanie stało się przeszkodą, uniemożliwiającą szybsze wydania. Po zbadaniu zidentyfikowaliśmy kluczowe wyzwania spowalniające proces:

  • Poleganie na testach manualnych: Większość testów była wykonywana manualnie, co prowadziło do powolnych pętli informacji zwrotnej i opóźnionego wykrywania defektów.
  • Zależność od interfejsu użytkownika w testowaniu: Ponieważ komponenty interfejsu użytkownika były zazwyczaj kończone jako ostatnie, testowanie mogło rozpocząć się dopiero pod koniec cyklu rozwoju.
  • Brak proaktywnej automatyzacji: Zautomatyzowane testy, takie jak testy interfejsu użytkownika oparte na Selenium, były pisane dopiero po testach manualnych, co ograniczało ich skuteczność we wczesnej fazie walidacji.

Przejście na Podejścia Oparte na Testach

Aby przełamać to wąskie gardło, priorytetyzowaliśmy testy jednostkowe i testy API nad testami interfejsu użytkownika. Ta zmiana wymagała fundamentalnych zmian w sposobie myślenia o rozwoju i projektowaniu oprogramowania:

Usprawnienia w testowaniu APIs

Aby testowanie API było efektywne:

  1. Dobrze zdefiniowane APIs: APIs musiały być proste, dobrze udokumentowane i dostępne na wczesnym etapie rozwoju, aby testerzy mogli proaktywnie tworzyć przypadki testowe.
  2. Unikanie bazy danych jako punktu integracji:
    • Wykorzystywanie baz danych jako punktu integracji między zespołami tworzyło zależności, które spowalniały testowanie.
    • Tworzenie przypadków testowych wymagało konfigurowania baz danych ze złożonymi danymi, co wydłużało czas konfiguracji i ograniczało możliwość testowania wielu scenariuszy.
    • Przechodząc na integrację opartą na API (głównie REST przez HTTP, a ostatnio GraphQL), znacznie zmniejszyliśmy opóźnienia i złożoności spowodowane zależnościami od baz danych.

Ta zmiana umożliwiła szybszy postęp w automatyzacji przypadków testowych dla APIs, pokazując, że skupienie się na projektowaniu API-first poprawiło zarówno testowalność, jak i wydajność.

Wzmacnianie Praktyk Testowania Jednostkowego

Testowanie jednostkowe stanowiło większe wyzwanie:

  • Szybki postęp, a następnie pozorna zgodność: Początkowo osiągnęliśmy wysoki poziom pokrycia kodu, ale przeglądy kodu wykazały, że wiele testów jednostkowych było powierzchownych, napisanych tylko po to, aby spełnić cele pokrycia. Testy te nie sprawdzały istotnej funkcjonalności, nie obejmowały scenariuszy awarii ani nie walidowały przypadków brzegowych.
  • Zmiana sposobu myślenia: Deweloperzy musieli zrozumieć wartość testów jednostkowych – nie tylko dla poprawy jakości kodu, ale także dla przyspieszenia rozwoju poprzez wczesne wykrywanie problemów.

Wyzwania w pisaniu testowalnego kodu

Największą przeszkodą w skutecznym testowaniu jednostkowym był brak testowalności w samym kodzie. Kluczowe problemy obejmowały:

  • Duże, monolityczne funkcje.
  • Ściśle powiązane komponenty.
  • Słabe rozdzielenie odpowiedzialności.
  • Niewystarczająca abstrakcja.

Te problemy utrudniały skuteczne izolowanie i testowanie poszczególnych jednostek. Aby temu zaradzić, my:

  1. Udzieliliśmy wytycznych.: Podzieliliśmy się najlepszymi praktykami w zakresie:
    • Wybieranie funkcji do testowania jednostkowego.
    • Refaktoryzacja kodu w celu poprawy testowalności.
    • Projektowanie i używanie makiet w celu ułatwienia testowania.
  2. Skupienie na stopniowych ulepszeniach: Zachęcano deweloperów do wprowadzania małych, znaczących zmian, aby z czasem poprawić testowalność.

Postępy, wyzwania i perspektywy na przyszłość

W przypadku starszych produktów, poprawa testowalności pozostawała powolnym procesem ze względu na ograniczenia architektoniczne. Jednak te działania nie miały na celu jedynie ulepszenia istniejącego kodu – były one inwestycją w przyszłość:

  • Deweloperzy wypracowali lepsze nawyki, wdrażając testowalność w nowe bazy kodu.
  • Zespoły stały się bardziej samodzielne, zmniejszając zależność od zewnętrznych działań QA.
  • Organizacja unikała powtarzania błędów z przeszłości, zapewniając, że przyszłe produkty były łatwiejsze w utrzymaniu i rozwoju.

Kluczowy wniosek? DevOps nie polega na wdrażaniu narzędzi czy list kontrolnych. Chodzi o ciągłe usprawnianie przepływu pracy, eliminując jedno ograniczenie po drugim.

W kolejnym rozdziale tej serii przyjrzymy się zagadnieniu „Projektowania pod kątem testowalności”. Zagłębimy się w to, jak ulepszanie projektowania oprogramowania może eliminować ograniczenia testowania, umożliwiając szybsze pętle informacji zwrotnej i wyższą jakość oprogramowania – najpierw w strukturach zespołowych, następnie w zarządzaniu przepływem pracy, a na końcu w testowalności – kładziemy podwaliny pod zrównoważoną transformację DevOps.

Subskrybuj blog Freyr

Polityka prywatności