Wyobraźmy sobie taką oto sytuację: przez kilkanaście miesięcy rozwijamy oprogramowanie, za wszelką cenę dostarczając funkcjonalność wymaganą przez interesariuszy w narzuconych z góry terminach. Nie ma czasu na zadbanie o jakość strukturalną rozwiązania, przez co z wydania na wydanie ilość błędów rośnie, zwiększa się też trudność w ich rozwiązywaniu. Ponieważ często podejmujemy decyzje, by iść na skróty – wszak dotrzymanie terminów jest najważniejsze – dodawanie nowych funkcjonalności jest coraz trudniejsze, ponieważ potykamy się o narastający dług techniczny.

Wreszcie uderzamy w ścianę: ilość błędów i problemów, zarówno technicznych, jak i funkcjonalnych, jest tak duża, że większość czasu spędzamy na ich rozwiązywaniu. Rozwój oprogramowania zamiera, choć przecież praca Developerom płonie w rękach żywym ogniem.

Wygląda to znajomo, prawda? Praktycznie każdy w branży IT zna choć jeden podobny przypadek, większość zetknęła się z kilkoma, a niektórzy mieli pecha taką pełzającą katastrofę obserwować od środka.

Gdy już dojdziemy do muru, jedynym rozwiązaniem jest zmiana sposobu postępowania. Niezależnie od terminów, nacisków ze strony zarządu, presji interesariuszy czy prób ratowania się konsultantami, wcześniej czy później jasne staje się, że do wyboru są w zasadzie trzy opcje.

Toniemy…

Można nie zrobić nic i spokojnie poczekać na bankructwo firmy. Bez zmian w podejściu do wytwarzania oprogramowania jest ono w zasadzie nieuchronne. Dlaczego? Bo produkt jest tak źle wytworzony, że nawet próby rozwiązywania krytycznych błędów kończą się lawiną nowych zgłoszeń o problemach. Próby stabilizowania oprogramowania z wykorzystywaniem procesu, w którym dopuszczalne jest spawanie na krótko, byleby szybko dostarczyć jakiś kod oznaczają, że z dnia na dzień będzie coraz gorzej.

Wersja 2.0 nas uratuje!

Można podjąć śmiałą decyzję o stworzeniu produktu od nowa. Skoro wiemy, co nie wyszło nam w pierwszej wersji, jakoś ją połatajmy, aby zyskać czas na wytworzenie wersji kolejnej. Takiej, która będzie „napisana dobrze” (cudzysłów nieprzypadkowy). Gdy tylko będzie to możliwe, odetniemy balast, jakim stał się stary niemożliwy do dalszego rozwoju kod… tak przynajmniej nam się wydaje. Niestety, to podejście ma trzy ogromne wady.

Najbardziej oczywista: ryzykujemy, że braknie nam czasu, zanim dojdzie do katastrofy, tym bardziej że przez długi czas będziemy musieli gasić pożary w starym rozwiązaniu i jednocześnie próbować wytworzyć nowe, które go zastąpi. Cierpliwość klientów korzystających z oprogramowania może się skończyć, zanim zdołamy im dostarczyć wystarczająco dopracowaną wersję 2.0, a wtedy czeka nas potencjalne bankructwo.

Mniej oczywisty problem: może się zdarzyć, że wersje 1.0 i 2.0 będą używane jednocześnie, przez co na jakimś etapie będziemy mieć wszystkie problemy związane z utrzymaniem starego, źle napisanego rozwiązania, oraz z rozwojem nowego systemu, niedojrzałego i wciąż wymagającego dopracowania. W ekstremalnych przypadkach nie udaje się nigdy odciąć od starego oprogramowania, przez co sytuacja firmy może z dramatycznej zmienić się w katastrofalną (podwojone koszty utrzymania systemów i wciąż wysoka liczba nierozwiązanych błędów).

Często jednak się udaje, wytwarzamy wymarzoną wersję 2.0 i… tu pojawia się trzecie zagrożenie: jest ona napisana równie źle, jak ta poprzednia. Dlaczego? Cóż, decydując się na swoistą informatyczną ucieczkę do przodu przed problemami, najczęściej uciekamy też przed koniecznością zmierzenia się z przyczynami, przez które ugrzęźliśmy w długu technicznym. Jako że nowe oprogramowanie pisze się zawsze łatwiej, na początku praca nad nim idzie płynnie i bezproblemowo, bo doskonale wiemy, co próbujemy zbudować. Tylko że mniej lub bardziej świadomie replikujemy wiele z błędnych decyzji, nasz proces wciąż nie zapobiega prowizorkom i irracjonalnym oszczędnościom… a presja czasu rośnie, im dłużej tę wersję 2.0 piszemy. Skoro trzeba się spieszyć, nie dbamy o jakość i wracamy do punktu wyjścia.

Świadomy maintenance

Trzecim rozwiązaniem jest zracjonalizowanie procesu wytwarzania oprogramowania tak, by zyskać czas na redukcję długu technicznego. Im bardziej się pod nim zakopaliśmy, tym większe spowolnienie rozwoju nas czeka – bo więcej błędów trzeba będzie rozwiązać. Być może wiele iteracji (o ile posługujemy się w ogóle procesem zakładającym pracę iteracyjną) poświęcić trzeba będzie na maintenance.

Aby to podejście miało sens, konieczne jest zagwarantowanie, że dług techniczny nie będzie powiększany. Nawet jeśli musimy zawołać „wszystkie ręce na pokład!” i zająć się tylko rozwiązywaniem błędów, nie możemy przy tym niczego robić szybko i byle jak. W przeciwnym razie będziemy dreptać w miejscu (coś naprawimy, ale co innego przestanie działać), albo wręcz będziemy kontynuować degradację rozwiązania.

Kanban kołem ratunkowym?

Wiele firm szukających sposobu na ocalenie marnego produktu zwraca się w stronę metod zwinnych. Kierują się przekonaniem, że Agile pozwoli robić więcej i szybciej niż taki na przykład Waterfall. Jest to połowiczna prawda, bo istotą Agile jest zaprzestanie robienia rzeczy niepotrzebnych i optymalizacja procesu tak, by pracując w tym samym tempie osiągać więcej, niekoniecznie produkując dwa razy tyle.

Dość szybko okazuje się, że próba rozwiązywania błędów przy pomocy metody Scrum jest zadaniem dość karkołomnym. Nie można przewidzieć, kiedy i jakie błędy zostaną zgłoszone – jak więc planować Sprinty? Priorytety zmienić mogą się w dowolnej chwili – jak więc zapewnić stabilność w iteracji?

Dlatego dla wielu osób to nie metody Agile, ale Kanban jest sposobem na powadzenie sobie z pracami utrzymaniowymi. Nie wymaga on definiowania iteracji o stałej długości, tak jak na przykład Scrum, planowanie może odbywać się w sposób ciągły, można ewolucyjnie usprawniać proces od punktu początkowego, jakim jest stan obecny.

I to wszystko jest prawdą, należy wszakże zadać sobie pytanie: co chcemy osiągnąć? Ponieważ w zależności od odpowiedzi na nie, być może Kanban będzie złym wyborem.

Trudne decyzje

Dla przypomnienia: Kaban posiada wbudowane mechanizmy pozwalające na ewolucyjne usprawnianie procesu obsługi zleceń, ale nie jest metodą produktową, tylko strategią optymalizacji procesów. Nie jest więc wprost nastawiony na poszukiwanie najlepszych rozwiązań potrzeb biznesowych. Wszystko zależy od procesu, na który strategia kanbanowa jest nakładana.

Aby rozwijać produkt w Kanbanie za pomocą własnego procesu (czyli nie korzystając ze zdefiniowanych metod zwinnych, takich jak Scrum), trzeba samodzielnie zadbać o to, by stosowany proces wyposażony był we wszystkie potrzebne do tego elementy. Tak użyty Kanban wymaga dużej dyscypliny, bez której łatwo można zatrzymać się na szklanym suficie, gdy tylko pojawi się poczucie, że jest już dostatecznie dobrze i dalsze usprawnienia nie są pilnie potrzebne. A to zwykle oznacza, że w praktyce nie pojawiają się wcale.

Może pojawić się pokusa, by rozdzielić rozwój produktu od rozwiązywania błędów: użyć Scruma do „prac rozwojowych”, a w jakimś prostym procesie, z wykorzystaniem Kanbana, obsługiwać problemy zgłaszane przez użytkowników. W rzeczywistości ten rozwój będzie naprawdę iluzoryczny (stąd cudzysłów w poprzednim zdaniu), a w najlepszym razie organizacja zdoła co najwyżej zatrzymać powolną degradację produktu. Dlaczego?

W tym modelu działania nie pojawi się realna potrzeba zmiany sposobu, w jaki rozwijany jest produkt. Zamiast usprawnić produkt, wyspecjalizujemy się w rozwiązywaniu błędów. Z pomocą Kanbana udoskonalimy procedury ich obsługi i skrócimy czas reakcji, co spowoduje, że będziemy bardzo sprawnie radzić sobie ze skutkami niskiej jakości, ale produkt pozostanie marny. Do tego dwie różne grupy Developerów będą zajmować się jednym produktem, stawiając sobie często rozbieżne cele i niekoniecznie potrafiąc ustalić wspólny zestaw praktyk, które skutkowały spójnym podejściem do kwestii jakości.

Wracając do pytania, które wcześniej zadałem: co jest celem dla firmy, która chce uratować produkt, nim dług techniczny pociągnie go wraz z firmą na dno? Odpowiedź jest trywialna: poprawienie jakości produktu i nauczenie się, jak o nią dbać długoterminowo, bo tylko w ten sposób można zatrzymać nadchodzącą katastrofę i odwrócić niepokojące tendencje.

Jeśli rzeczywiście chcemy udoskonalić sam produkt, powinniśmy skorzystać ze Scruma mimo wszystkich trudności, jakie potężna ilość zgłaszanych problemów spowoduje w każdym Sprincie. I jednocześnie możemy użyć Kanbana jako strategii zarządzania przepływem pracy w ramach iteracji.

Scrum a maintenance

Tym, czego desperacko potrzebujemy, jest mechanizm wymuszający jakość strukturalną produktu – bez niej o jakości funkcjonalnej ciężko mówić.

W Scrumie stosowana jest Definicja Ukończenia, która określa, jaki produkt spełnia w ogóle kryteria technicznej używalności i nadaje się wydania. Poprzez świadome ustawienie Definicji na takim poziomie, który jest osiągalny przez Developerów, a jednocześnie wymusza poprawę jakości, uruchomimy powolny, ale skuteczny proces wygrzebywania się z błota, w jakim tkwimy.

Kolejną przyczyną, dla której Scrum jest dobrym wyborem w opisanej sytuacji, jest orientacja tej metody na rozwój produktu. Tym bardziej że sposobem na rozwiązanie problemów z oprogramowaniem nie zawsze jest naprawianie kodu, ale – nieoczywista rzecz – czasami lepszym pomysłem jest usuwanie niepotrzebnych funkcjonalności z produktu. To wymaga zaangażowania interesariuszy, aby świadomie taką decyzję podjąć. Scrum ma mechanizmy, które temu służą.

Oczywiście Scrum, zwłaszcza w połączeniu z Kanbanem, pozwala doskonalić procesy, narzędzia i komunikację – więc nic nie tracimy, decydując się na wybór tej metody.

Trzeba przy tym dobrać właściwą długość iteracji, bo nie mogą one być zbyt długie. Jeśli Sprinty trwałyby miesiąc lub np. trzy tygodnie, konieczne stanie się rezerwowanie sporej ilości czasu na obsługę błędów, jakie zgłaszają użytkownicy produktu. Nie będą oni bowiem skłonni oczekiwać na rozwiązania przez kilka tygodni. To automatycznie spowoduje, że tylko część każdego Sprintu użyta zostanie do wykonania planowanych działań, a to nie będzie sprzyjać podnoszeniu jakości (lub chociaż utrzymywaniu jej na akceptowalnym poziomie). Developerzy mogą miotać się między realizacją elementów Backlogu Produktu i rozwiązywaniem losowo pojawiających się błędów.

Natomiast tygodniowe iteracje (albo i krótsze, bo nikt nie mówi, że ich długość musi być wielokrotnością tygodni) pozwolą na zapewnienie wystarczającej reaktywności procesu przy jednoczesnym zachowaniu możliwości planowania działań. Wystarczy zarezerwować nieco czasu na krytyczne błędy (których zapewne nie będzie aż tak wiele), a o pracy nad pozostałymi Zespół zdecydować może w uporządkowany sposób w trakcie najbliższego Planowania Sprintu.

Dlaczego warto ratować produkt z użyciem Scruma?

Przede wszystkim dlatego, że w opisanej na samym początku tragicznej sytuacji wciąż musimy pamiętać, co jest celem. Nie jest nim wyłącznie opanowanie pożaru, bo wtedy katastrofa wróci z hukiem za jakiś czas. Celem jest doprowadzenie do takiej sytuacji, by po wygaszeniu ognia (czyli ustabilizowaniu rozwiązania) potrafić dalej go rozwijać bez tworzenia nowego długu technicznego.

Jeśli Zespół i organizacja nauczy się korzystać ze Scruma w taki sposób, by dbać o jakość strukturalną rozwiązań, będzie bez trudu w stanie kontynuować rozwój produktu przy pomocy tej metody. To da zmianę w procesie, który pozwoli utrzymywać akceptowalny poziom jakości albo wręcz będzie sprzyjał jej podnoszeniu. Co więcej, nie nastąpi rozdzielenie odpowiedzialności wśród Developerów na tych, co rozwijają oprogramowanie i tych, co naprawiają produkt, ponieważ usuwanie długu technicznego przeprowadzą te same Zespoły, które produkt rozwijają. Nauczą się, dlaczego warto zapobiegać jego gromadzeniu się.