Pierwsze kroki w naszej transformacji DevOps
5 min czytania

W drugim rozdziale tej serii – DevOps po zwycięstwo – omawiamy kluczowe początkowe kroki na drodze transformacji DevOps. Pierwsze kroki w każdej transformacji są często najtrudniejsze. W metodyce DevOps kluczem do osiągnięcia realnych postępów jest zidentyfikowanie właściwych działań początkowych – takich, które są zarówno skuteczne, jak i wykonalne.

Wiele organizacji popełnia błąd, ślepo wdrażając dobre praktyki bez uwzględnienia swoich unikalnych ograniczeń, co często prowadzi do frustracji i zmęczenia porażkami. Zamiast tego konieczne jest podejście bardziej strategiczne – takie, które identyfikuje wąskie gardła i systematycznie je usuwa.

Jak zidentyfikować pierwsze kroki?

Potężna zasada pomagająca ustalić, od czego zacząć, pochodzi z badań opublikowanych 30 lat temu w książce Cel. Doskonalenie procesu w praktyce (ang. The Goal: A Process of Ongoing Improvement) autorstwa Eliyahu M. Goldratta. Idea jest prosta: zidentyfikować główne wąskie gardło – czynnik ograniczający wydajność całego systemu. W naszym przypadku stało się to jasne, gdy zauważyliśmy piętrzącą się pracę w zespole deweloperskim. Zadania były rozpoczynane, ale nie kończone, a zaległości stale rosły.

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

  • Zespoły podejmowały się nowych zadań przed ukończeniem dotychczasowych.
  • Brakowało jasnych kryteriów ukończenia zadań – to, co programiści uznawali za „zrobione”, często różniło się od oczekiwań interesariuszy.
  • Przed oznaczeniem pracy jako ukończonej nie stosowano obiektywnych miar jakości, co prowadziło do defektów i konieczności poprawek.
  • Częste zmiany w składzie zespołów zakłócały ich stabilność, powodując obniżenie wydajności.

Tworzenie stabilnych zespołów

Jednym z pierwszych działań naprawczych była reorganizacja zespołów pod kątem spójności i skupienia. Zamiast traktować grupy osób jako doraźne grupy zadaniowe, utworzyliśmy stabilne, długoterminowe zespoły o jasno określonym zakresie odpowiedzialności.

Konfiguracja niektórych zespołów, takich jak grupy deweloperskie, była stosunkowo prosta. Jednak organizacja zespołów wsparcia – takich jak infrastruktura, zarządzanie projektami, zarządzanie produktem i analiza biznesowa – okazała się trudniejsza. Przeszliśmy przez kilka etapów, zanim znaleźliśmy odpowiednie połączenia.

Zgodnie z zasadą najpierw zespół (ang. team-first thinking) opisaną w publikacji Team Topologies autorstwa Matthew Skeltona i Manuela Paisa, podjęliśmy następujące kroki:

  • Utworzyliśmy małe, autonomiczne zespoły (liczące 4–7 członków), aby wspierać głęboką wiedzę dziedzinową i odpowiedzialność.
  • Wyeliminowano zależności między zespołami, zapewniając pełne zaangażowanie poszczególnych osób w jednym zespole.
  • Zmodyfikowano strukturę zespołów, ze szczególnym uwzględnieniem funkcji wspierających, takich jak infrastruktura i zarządzanie produktem, aby zoptymalizować przepływ pracy.

Wykorzystanie narzędzi do zapewnienia widoczności i zarządzania

Po ustrukturyzowaniu zespołów przeszliśmy na platformę Azure DevOps w celu zarządzania rejestrem prac i zadaniami. Zintegrowana platforma umożliwiła:

  • Lepszą widoczność prac, dzięki czemu zespoły mogły przejrzyście śledzić postępy.
  • Ustandaryzowane definicje „ukończenia”, aby ujednolicić oczekiwania we wszystkich działach.
  • Lepsze zarządzanie rejestrem prac, ograniczające rozrastanie się zakresu projektów i konflikty związane z priorytetami.

Wprowadzenie obiektywnych wskaźników jakości

Aby rozwiązać problem niejasnych miar jakości przed oznaczeniem zadań jako „gotowe do testów”, wdrożyliśmy narzędzie do statycznej analizy kodu, które zapewnia obiektywny wgląd w:

  • Pokrycie kodu testami
  • Luka w zabezpieczeniach
  • Zapachy kodu

Ulepszyliśmy również naszą definicję „ukończenia”, czyniąc kontrole jakości obowiązkowym krokiem przed oznaczeniem elementów pracy jako zakończonych.

Zarządzanie pracami w toku (WIP)

Jedną z najbardziej wpływowych zmian było monitorowanie i ograniczanie wartości pracy w toku (WIP). Wysoki wskaźnik WIP wskazywał na wąskie gardła, pozwalając nam aktywnie reagować w obszarach, gdzie praca napotykała opóźnienia.

To systemowe podejście, zakorzenione w publikacjach Cel oraz Topologie zespołów, stało się fundamentem ciągłego doskonalenia, ograniczając zależności i zwiększając odpowiedzialność.

Podczas naszej drogi transformacji DevOps jednym z najważniejszych wniosków było to, że po początkowych usprawnieniach głównym ograniczeniem dla płynności pracy stał się projekt oprogramowania – a konkretnie podatność naszego kodu na testowanie. Po wyeliminowaniu początkowych wąskich gardeł poprzez poprawę organizacji zespołów, zdefiniowanie „kryteriów ukończenia” (Definition of Done) i wdrożenie analizy kodu dostrzegliśmy, że praca gromadzi się w fazie testów. Kod tworzony przez zespoły scrumowe często czekał w kolejce na przetestowanie przez członków zespołu QA należących do tych samych zespołów scrumowych.

Rozwiązanie kolejnego problemu wąskiego gardła: luki w testach

Po usunięciu początkowych wąskich gardeł pojawiło się nowe ograniczenie – opóźnienia w testowaniu. Podczas gdy zadania programistyczne przebiegały sprawnie, testy stały się przeszkodą uniemożliwiającą szybsze wdrażanie nowych wersji. W trakcie analizy zidentyfikowaliśmy kluczowe wyzwania spowalniające ten proces:

  • Poleganie na testach manualnych: Większość testów była przeprowadzana ręcznie, co prowadziło do wolnych pętli zwrotnych i opóźnionego wykrywania usterek.
  • Zależność testów od interfejsu użytkownika (UI): Ponieważ elementy interfejsu były zazwyczaj kończone jako ostatnie, testy nie mogły rozpocząć się przed końcową fazą cyklu tworzenia oprogramowania.
  • 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ść na wczesnym etapie walidacji.

Przejście na podejście oparte na testowaniu

Aby przełamać to wąskie gardło, priorytetowo potraktowaliśmy testy jednostkowe i testy interfejsu API kosztem testów interfejsu użytkownika. Zmiana ta wymagała zasadniczych modyfikacji w sposobie myślenia programistów oraz w projektowaniu oprogramowania:

Usprawnienia w testowaniu interfejsów API

Aby testowanie interfejsów API było wydajne:

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

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

Wzmacnianie praktyk testów jednostkowych

Testowanie jednostkowe stanowiło większe wyzwanie:

  • Szybki postęp, a potem tzw. teatr pokrycia: Początkowo osiągnęliśmy wysoki poziom pokrycia kodu, jednak przeglądy kodu ujawniły, że wiele testów jednostkowych miało charakter powierzchowny i tworzono je wyłącznie po to, aby osiągnąć założone wskaźniki. Testy te nie sprawdzały istotnej funkcjonalności, nie uwzględniały scenariuszy błędów ani nie weryfikowały przypadków brzegowych.
  • Zmiana sposobu myślenia: Programisty musieli zrozumieć wartość testów jednostkowych – nie tylko pod kątem poprawy jakości kodu, ale także przyspieszenia rozwoju poprzez wczesne wykrywanie problemów.

Wyzwania związane z pisaniem kodu podlegającego testowaniu

Największą przeszkodą w skuteczny testowaniu jednostkowym był brak możliwości testowania w samej bazie kodu. Główne problemy obejmowały:

  • Duże, monolityczne funkcje.
  • Silnie powiązane komponenty.
  • Słabe oddzielenie poszczególnych kwestii.
  • Niewystarczająca abstrakcja.

Kwestie te utrudniały skuteczną izolację i testowanie poszczególnych elementów. Aby to rozwiązać, wykonaliśmy następujące czynności:

  1. Zapewnione wytyczne: Podzieliliśmy się najlepszymi praktykami dotyczącymi:
    • Wybór funkcji do testów jednostkowych.
    • Refaktoryzacja kodu w celu poprawy jego testowalności.
    • Projektowanie i używanie obiektów zastępczych (mocków) w celu ułatwienia testowania.
  2. Skupienie na stopniowych ulepszeniach: Zachęcano programistów do wprowadzania małych, znaczących zmian w celu poprawy testowalności w czasie.

Postępy, wyzwania i dalsza droga

W przypadku starszych produktów poprawa podatności na testy pozostawała powolnym procesem ze względu na ograniczenia architektoniczne. Działania te nie miały jednak na celu jedynie ulepszenia obecnego kodu – stanowiły inwestycję w przyszłość:

  • Programiści wykształcili lepsze nawyki, uwzględniając podatność na testy w nowym kodzie.
  • Zespoły stały się bardziej samorzutne, co zmniejszyło zależność od zewnętrznych działań w zakresie QA.
  • Organizacja unikała powtarzania dawnych błędów, dbając o to, by przyszłe produkty były łatwiejsze w utrzymaniu i rozwoju.

Jaki jest główny wnioski? DevOps nie polega na wdrażaniu narzędzi czy list kontrolnych. Chodzi o ciągłe ulepszanie przepływu pracy, eliminując jedno ograniczenie naraz.

W kolejnym rozdziale tej serii omówimy temat „Projektowania z myślą o testowaniu”. Przyjrzymy się bliżej temu, jak ulepszenie projektowania oprogramowania może pomóc w usunięciu ograniczeń testowych, umożliwiając szybsze uzyskiwanie informacji zwrotnych i wyższą jakość oprogramowania – najpierw w strukturach zespołów, potem w zarządzaniu przepływem pracy, a na końcu w obszarze testowalności – tworząc fundamenty pod zrównoważoną transformację DevOps.

Subskrybuj bloga Freyr

Polityka prywatności