Kategorie
Software Development

User Story – przewodnik

User Story to ciekawy i ważny temat w środowisku projektów IT. Nie od dziś wiadomo, że jakość i zadowolenie z naszych aplikacji bardzo często zależy od jakości wymagań, jakie przyjdzie nam zebrać podczas analizy.

Zmierzmy się z tym tematem. Lecimy!

Junior Java Developer Handbook

User Story … czyli co?

Żeby w prosty sposób zdefiniować, czym jest User Story, można powiedzieć, że jest to po prostu opis funkcjonalności systemu. Z założenia ta funkcjonalność ma pewną wartość dla właściciela produktu, który rozwijamy.

Istotną częścią naszej definicji będzie określenie trzech cech, jakie User Story powinno spełniać, żeby można mówić o jego dobry zdefiniowaniu. Tymi cechami są:

  • Opis pisemny naszej historii, który pozwoli nam się zorientować, czego dotyczy.
  • Rozmowa pogłębiająca nasze zrozumienie historii.
  • Zdefiniowanie testów jako kryterium akceptacji, mówiących o tym, że dana historia jest zakończona.

Widzimy tutaj zasadę 3C Rona Jeffriesa (ang. Card Conversation Confirmation). Jeśli wczytamy się w esencję tej zasady, to przekonamy się, że pierwszy element listy, czyli sam opis User Story, nie jest tym najważniejszym.

Wynika to z faktu, że na etapie pierwszego opisu User Story, np. w formie prostego zdania, bardzo wiele elementów wymagania jest jeszcze niezdefiniowane.

Rozmowa o User Story jest właśnie tym elementem, który pozwoli nam na głębsze zrozumienie problemu. To tutaj nastąpi dyskusja, wymiana myśli, wspólne rysowanie na tablicy (często zdalnej). To tutaj następuje moment, kiedy krystalizuje się nasze wymaganie.

Tę krystalizację User Story następnie jesteśmy w stanie zapisać w formie testów. Testy stanowią element dokumentujący. To właśnie one określają, kiedy nasze wymaganie zostaje poprawnie zaimplementowane i działa zgodnie z wymaganiami. Bardzo często, jeśli używamy Scruma, mówimy tutaj o Definition of Done.

Konwencje

Przyjęło się, że User Story zapisujemy w konwencji:

Jako <użytkownik> chcę <potrzeba>, żeby <uzasadnienie>.

Musimy pamiętać, że jest to tylko konwencja, a User Story możemy również spotkać w postaci innego zapisu i innej kolejności występowania elementów.

Bardzo często w praktyce spotkasz się również z brakiem uzasadnienia. Często jest on po prostu oczywiste i w rzeczywistości nie wniesie za wiele. Ale czasem może być inaczej. I warto na to zwrócić uwagę, czy wszyscy rozumieją dane wymaganie w ten sam sposób.

Mamy User Story, ale i tak nam nie idzie …

Bardzo często możemy spotkać zespoły developerskie, które pomimo „stosowania” User Story cały czas mają duże problemy z jakością, dostarczaniem na czas oraz ze zrozumieniem wymagań.

Często okazuje się, że User Story wprowadzono jako cudowny element magii, który miał rozwiązać wszystkie problemy związane z definiowaniem wymagań.

Jednak tak się nie stało, a wymagania pozostały w takiej samej, złej formie, jak wcześniej.

I teraz pojawia się pytanie, dlaczego tak się dzieje?

Moje doświadczenie jest takie, że najczęściej w takich przypadkach słowo „User Story” było zastępstwem. Zmieniała się formalna konwencja nazywania wymagań. Zaczynały to być „User Story”, ale nic więcej się nie zmieniało. Cały czas zespół developerski bazował na czymś w rodzaju:

US Użytkownik może zaplanować podróż w plannerze.

I na przykład zespół w takiej sytuacji dokonywał estymacji. Jedna osoba mówiła 50 dni pracy, inna że 10, a inna, że w zasadzie nie wie. Bo nikt nie widział, co tak naprawdę kryje się pod tym krótkim opisem, ani nikt o tym wymaganiu nie rozmawiał. Bo nikt nigdy nie zastanowił się, co ono oznacza. Nikt nie wiedział, co to za planner, jak z niego korzystać, etc.

Takie niby wymaganie trafiało do Sprintu i oczywiście nie było kończone. Bo nie zadano sobie pytań, jak duże to zadanie jest, jak powinno wyglądać i co właściwie znaczy, że zostało ukończone.

INVEST na ratunek

Metoda kryjąca się pod mnemonikiem INVEST jest jedną z podstaw, która pozwala nam przybliżyć nasze wymagania do dobrze zdefiniowanych User Story.

INVEST określa dla nas cechy, które potrzebne są do stwierdzenia, że cała historia jest zdefiniowana w sensowny sposób. A oznacza:

  • niezależność (ang. Independent),
  • negocjowalność (ang. Negotiable)
  • wartość (ang. Valuable to users or customers),
  • estymowalność (ang. Estimatable),
  • małą wielkość (ang. Small),
  • testowalność (ang. Testable).

Wraz z Twoim doświadczeniem będzie rosło automatyczne skanowanie historii właśnie pod względem tych kryteriów. Wynika to z tego, że z czasem dużo lepiej będziesz umiał przełożyć poszczególne wymagania na realny kawałek kodu aplikacji. A tym samym dużo szybciej będziesz czuł, że jedno wymaganie jest zdefiniowane w klarowny sposób, a inne już nie bardzo. Również bardzo często od razu będziesz wiedział, że dana historia jest nielogiczna, jest bardzo powiązana z innymi historiami, a przez to nie da się jej zrealizować samodzielnie. Takie naturalne zrozumienie tych cech prędzej, czy później, w sobie wyrobisz.

Przykłady zastosowania INVEST

Niezależność

Jako przykład niech posłuży zamówienie w sklepie internetowym, za które klient musi zapłacić. Poniżej przykłady historii użytkownika:

US-1 Jako klient mogę opłacić przesyłkę za pomocą karty kredytowej Visa.

US-2 Jako klient mogę opłacić przesyłkę za pomocą karty kredytowej Master Card.

US-3 Jako klient mogę opłacić przesyłkę za pomocą karty kredytowej American Express.

Przechodząc do estymacji. Developerzy mogą oszacować różnie. Jeden oceni, że zrealizowanie pierwszej historii to 7 SP (Story Points). Każda następna to 2 SP. I mamy zależność bardzo wyraźnie widoczną. Należy się jej pozbyć. Są na to takie sposoby:

  1. Można zebrać te historie w jedną większą i realizować jako całość.
  2. Można poszukać innego miejsca podziału historii, gdyby podejście z punktu 1. nie było możliwe.

Z pierwszym sposobem należy uważać. Może nam wyjść za duża historia, którą będzie ciężko zrealizować zespołowi w ramach jednego Sprintu. Stosuj ją więc z rozwagą.

W drugim przypadku, szukamy innej drogi. Zwykle podział możliwy jest w kilku miejscach. Szukamy tego, który pozwoli nam dostarczyć cały czas wartość dla produktu, np.:

US-1 Jako klient mogę opłacić przesyłkę za pomocą karty kredytowej Visa.

US-2 Jako klient mogę również opłacić przesyłkę za pomocą karty kredytowej Master Card oraz American Express.

Bądźmy też tutaj pragmatyczni. Pierwsza historia powinna znaleźć się w pierwszej iteracji, a druga w drugiej. Tak, żeby nie blokować nam zadań w Sprincie.

Negocjowalność

Weźmy raz jeszcze jako przykład nasz sklep internetowy i inną postać wcześniejszych historii:

US Jako klient mogę opłacić przesyłkę za pomocą karty kredytowej.
Notatka: Rozważyć obsługę kart kredytowych Visa, Master Card, American Express oraz Diners Club.

Notatka pozwala na łatwiejsze wejście w proces uszczegółowienia takiej historii w momencie brania jej do iteracji. Zespół developerski prowadzi ciągły dialog z właścicielem produktu. Być może musi wybrać jeden typ kart, które są przetwarzane przez jedną, konkretną bramkę. Tu właśnie mamy bardzo widoczną fazę rozmowy pogłębiającej temat. Tutaj szukamy zrozumienia i zapewnienia wartości.

Dla odmiany spójrzmy na historię użytkownika, która jest zbyt szczegółowa. 

US Jako klient mogę opłacić przesyłkę za pomocą karty kredytowej.
Notatka: Rozważyć obsługę kart kredytowych Visa, Master Card, American Express oraz Diners Club. Dla płatności powyżej 2000 zł należy wpisać identyfikator karty z jej odwrotu. System pokazuje na podstawie dwóch pierwszych cyfr nr karty, jaki to typ karty. System musi również pamiętać nr karty do ewentualnego późniejszego jej użycia, jak również powinien zapamiętać datę ważności karty.

Nadmiar informacji sprawia, że rośnie prawdopodobieństwo postrzegania tej historii w kontekście szczegółów implementacyjnych. Długie historie, z psychologicznego punktu widzenia, mogą też zostać postrzegane jako takie, w których już wszystko zostało powiedziane i nie warto już o nich wracać.

Nic bardziej mylnego. Utworzenie takiego opisu zbyt wcześnie przed realizacji historii często będzie zwykłą stratą czasu. Wymagania odnośnie działania systemu bardzo często zmieniają się z dnia na dzień. Naszą rolą jest za nimi nadążać bez marnowania sił na próbę zdefiniowania wszystkiego od razu.

Dlatego zapamiętaj:

  • Opis historii to tylko zapis, największa wartość to rozmowa z potencjalnym użytkownikiem.
  • W notatkach nie twórz wizji działania. Zapisz, co jeszcze trzeba zbadać.
  • Szczegóły zbieraj w postaci testów, które mają potwierdzić zakończenie realizacji danej historii.

Wartościowość dla klienta lub dla użytkowników

Rozważmy następującą historię:

US System stosuje konfigurację pobieraną z korporacyjnego HashiCorp Consul.

Użytkownik końcowy nie jest specjalnie zainteresowany taką historią. Szczerze mówiąc zwykle go to nie interesuje i nie ma dla niego żadnego znaczenia. Prawda jest taka, że użytkownicy chcą używać oprogramowania. Sposób jego zbudowania ich już jednak nie obchodzi. Ono ma po prostu działać.

Z drugiej jednak strony takie wymaganie może zostać postawione przez klienta, który oczekuje produktu, który będzie zgodny z jego architekturą IT. Podobnie jest w przypadku takich historii:

US Zespół będzie dokumentował system zgodnie z normą ISO 9001.

US Oprogramowanie będzie wytwarzane przez zespół deweloperski zgodnie ze Scrumem.

Zwracajmy zatem uwagę na wartość historii. Na ich wartość oraz na to, dla kogo ta wartość ma być budowana.

Tutaj warto pamiętać o jednym – User Story nie może być tylko wartościowe dla developera. Nie on będzie (zwykle) odbiorcą końcowym aplikacji.

Dla przykładu kilka historii:

US Wszystkie operacje odczytu muszą być wspierane przez in-memory data grid Hazelcast.

US REST API będzie wystawiane przez bibliotekę spring-mvc.

Gdzie jest wartość dla użytkownika. Spróbujmy popatrzeć z jego strony. Dla właściciela biznesowego bardziej liczyć się będzie np. to, ilu użytkowników bez problemu obsłuży system:

US System obsłuży do 100 jednoczesnych użytkowników realizujących zadania na jednej licencji connectora do bazy danych.

Estymowalność

Wiedza o wielkości historyjki jest kluczowa z punktu widzenia planowania iteracji, jak również całego produktu. Bez niej wszelkie plany są z góry skazane na porażkę.

Tworząc historię należy zwrócić szczególną uwagę na to, co czyni jej estymacje niemożliwą:

  1. Deweloperzy nie mają odpowiedniej wiedzy domenowej.
  2. Deweloperzy nie mają odpowiedniej wiedzy technologicznej.
  3. Historia jest po prostu za duża do realnej estymacji.

W przypadku braku wiedzy domenowej kluczowy jest etap konwersacji z użytkownikiem. Ten etap pozwala na doprecyzowanie opowieści i zebranie odpowiednich testów.

Technologia też może być problemem. Dla przykładu zintegrowanie oprogramowania Java ze specyficznym protokołem komunikacyjnym w branży telekomunikacyjnej często będzie wymagać podjęcia najpierw działań w celu poznania tej drugiej technologii i dopiero później próby estymacji właściwej historyjki.

Zbyt duże historie wymagają dekompozycji. Powód jest tutaj prozaiczny – całkiem dobrze estymujemy małe, skończone elementy, z dużymi, bardziej abstrakcyjnymi blokami radzimy sobie słabiej.

Mała wielkość

Duże historie są problemem. Ale również te za małe są często po prostu za małe.

Przykład za dużej historii to:

US Użytkownik może zaplanować podróż.

Taka historia jest ważna w systemie rezerwacji rejsów. W jej realizację zaangażowanych jest jednak bardzo wiele różnych funkcji, np. wyszukiwanie rejsu, zajęcie kajuty, płatność.

Zbyt duże historie nazwyamy epikami. Należy je podzielić na mniejsze.

Możemy też znaleźć przykłady zbyt małych historii:

US W informacji o godzinie lotu korzystamy z pogrubionej czcionki.

Tutaj mamy historię, która jest malutka. Trudno ją nawet estymować, bo front-end developer zrobi ją między jednym łykiem kawy a drugim.

Testowalność

Kiedy możemy stwierdzić zakończenie realizacji User Story? Kiedy jest ten punkt, w którym możemy powiedzieć, że jest ona skończona? Odpowiedź jest bardzo prosta – wtedy i tylko wtedy, gdy pozytywnie zakończy się weryfikacja zawartych w niej testów.

Problem z niemożliwością przetestowania danej historii najczęściej związany jest z wpisywaniem jako historii wymagań niefunkcjonalnych, które rzeczywiście dotyczą wytwarzanego oprogramowania, ale nie jego realnych funkcjonalności, np.:

US System musi być łatwy w obsłudze.

Zamiast zapisywać wymagania funkcjonalnego jako historii użytkownika lepiej oznaczyć takie wymaganie jako ograniczenie (ang. constraint). I jest to ograniczenie systemowe. Nie jest to element wymagań funkcjonalnych.

Uważaj jednak na takie ograniczenia:

  • System musi być ergonomiczny.
  • Musi działać na wszystkich przeglądarkach.
  • IE 11 jest priorytetem (front-end developerzy darzą ten przypadek szczególnym uczuciem 🙂 ).
  • Nowy system musi wykorzystywać naszą starą bazę danych.
  • System obsłuży 100 jednoczesnych transakcji.

Zawsze, jak pojawi się ogólna lista wymagań niefukcjonalnych, to staraj się je uszczegółowić.

Dyskusje o ergonomiczności mogą rozwalić każdy projekt. Zamiast zostawiać takie ogólne terminy zacznijcie tworzyć np. makiety wraz z użytkownikami.

Zawsze staraj się dojść do potrzebnego poziomu szczegółow.

A wracając do testowalności User Story. Jak mogłoby wyglądać dobrze zdefiniowany ten aspekt:

US Jako zalogowany użytkownik sklepu internetowego chciałbym aktywować bon podarunkowy
TESTS
– Otrzymałem wcześniej kod bonu podarunkowego.
– Wprowadzam kod bonu podarunkowego w panelu klienta w sekcji z bonami.
– Kwota bonu zostaje dodana do mojego salda na zakupy, jeśli kod jest ważny. Otrzymuję komunikat XYZ.
– Kwota bonu nie zostaje dodana do mojego salda na zakupu, jeśli kod nie jest już ważny. komunikat ZYX.

Testy stają się z punktu widzenia użytkownika scenariuszami. Dzięki takiemu podejściu oprogramowanie zyska dużo wyższą jakość.

Tutaj też należy pamiętać, że testy są emanacją scenariusza biznesowego. Jeśli np. dodanie kwoty do salda oznacza w rzeczywistość konieczność komunikacji z kontekstem (ang. bounded context) dedykowanym dla sald, to tutaj w testach tego nie będziemy uwzględniać.

Zapamiętaj – User Story opisuje biznesowe wymagania. Integracje, szczegóły techniczne, wewnętrzna komunikacja to rola scenariusza domenowego.

Gdzie leży odpowiedzialność?

Kiedy przychodzi o wytwarzania oprogramowania, zawsze pojawia się temat odpowiedzialności. Bo kto ostatecznie będzie odpowiadał za tworzenie wymagań.

Tutaj należy uwzględnić zawsze dwie perspektywy. Weźmy pod uwagę Scrum.

Z jednej strony będzie to zespół developerski. To on pomaga właścicielowi produktu w przygotowywaniu wysokiej jakości wymagań. Dzięki zastosowaniu 3C i kryteriów INVEST rozmowa o wymaganiach dużo łatwiej prowadzić będzie do jakościowych User Story.

Z powyższych zdań wynika również, że ta odpowiedzialność leży też po stronie właściciela produktu. To on ma tworzyć wymagania. To on powinien rozumieć 3C i INVEST. I to on musi brać czynny udział w rozmowach z zespołem.

Bardzo często zapomina się o tym. Rolę towarzysza rozmów o wymaganiach zaczyna pełnić analityk, który po pewnym czasie staje się swoistym proxy dla właściciela produktu. To duży błąd.

Błąd jest tym bardziej widoczny w projektach, gdzie na początku właściciel produktu jest realnie zaangażowany w prace zespołu, a potem nagle gdzieś znika. Wtedy zespół czuje to najbardziej i automatycznie przekłada się na spadek jakości.

Dlatego zapamiętaj, odpowiedzialność leży i po stronie właściciela produktu i jego wizji systemy. Ale również i po stronie zespołu developerskiego, który musi go wspierać na etapie tworzenia realnych wymagań.

Krótko o dzieleniu User Story

Złożoność jest kluczem

Duże historie, czyli epiki, można rozważać w dwóch aspektach.

Aspekt pierwszy, koncepcyjnie prostszy, dotyczy historii, które zawierają w sobie wiele mniejszych historii (ang. compound user story).

Aspekt drugi, jest trudniejszy. W tym przypadku mamy do czynienia z historiami, które ze swej natury są złożone, trudne i skomplikowane (ang. complex user story).

Compound User Story

W tej kategorii znajdziemy niezwykle popularne wymagania dotyczące zarządzania czymś.

US Jako administrator systemu mogę zarządzać użytkownikami.

Kiedy jesteśmy na samym początku zbierania wymagań, to takie historie będą się zdarzały. To normalne. Nie mamy jeszcze pełnej wiedzy odnośnie zachowania systemu. W ten sposób oznaczamy sobie obszary, które nas interesują. Musimy wziąć jednak pod uwagę, że w istocie może nam chodzić np. o tym konkretnym przypadku może oznaczać to takie zagadnienia:

  • dodawanie konta użytkowników z ich danymi,
  • aktywowanie konta użytkowników,
  • blokowanie konta użytkowników,
  • anonimizację danych użytkownika po wygaśnięciu umowy.

Każdy z powyższych punktów będzie mógł stanowić podstawę do oddzielnego User Story. I każdy będzie mógł trafić do realizacji w odpowiednim czasie.

Pamiętajmy przy tym, żeby nie zejść zbyt nisko w naszym podziale. Niezbyt trafne będą w tym przypadku historie:

US Jako administrator chcę w formularzu tworzenia nowego konta wypełniać imię i nazwisko

Treść tego przykładu będzie raczej testem w User Story dotyczącym zakładania nowego konta w systemie.

Stosujemy tutaj zwykle dwa podejścia do dzielenia większych historii:

  1. Względem wykonywanych operacji, np. tworzenie, usuwanie, modyfikacja, aktywacja, blokowanie, etc.
  2. Alternatywnie względem przetwarzania rodzaju danych, np. użytkownik dodaje dane o lokalizacji preferowanego paczkomatu, użytkownik modyfikuje dane adresowe, etc.

Widzimy, że oba podejścia są bardzo zbliżone, w obu występują czasowniki. Które podejście wybierzemy zależy od tego, w którym łatwiej jest się nam komunikować z zespołem i właścicielem produktu.

Complex User Story

W przypadku złożonych, trudnych koncepcyjnie historii stosujemy inne podejście. Skomplikowane problemy są bardzo często trudne do podziału.

Zawsze jednak możemy naszą pracę starać się rozbić na mniejsze fragmenty. Możemy zacząć od rozbicia problemu na dwa, które przyniosą wartość:

  1. Pierwsza historia to zbadanie tematu i zdobycie odpowiedniej wiedzy do jego implementacji. Dzięki temu możemy lepiej poznać zagadnienie, a czasem nawet zrezygnować z jego dalszego wdrażania w systemie.
  2. Druga historia to implementacja funkcji w oparciu o zdobytą wiedzę.

Stosując to podejście dobrą praktyką jest również umieszczenie pierwszej historii w pierwszym Sprincie, a drugiej w kolejnym. Tak, żeby zachować spójność w ramach iteracji.

Wracając do podobnego przykładu z kartami kredytowymi:

US Jako klient sklepu będę mógł opłacić zamówienie kartą kredytową.

Dla zespołu, który nigdy nie realizował płatności kartami to zagadnienie będzie skomplikowane. Temat wydaje się prosty. Jednak jeśli miałeś już do czynienia z bramkami płatności, to dobrze wiesz, że rozwiązania te są usiane sytuacjami wyjątkowymi.

Dużo łatwiej dla zespoły developerskiego będzie podzielenie tej historii na kilka mniejszych:

US Zbadanie rozwiązań płatności kartą kredytową w sklepie
TESTS Opis scenariuszy integracji z bramkami dla kart Visa i Mastercard.

US Jako klient sklepu mogę opłacić zamówienie kartą kredytową Visa.
TESTS

Podsumowanie dla Ciebie

Na tym etapie musisz wiedzieć, że User Story są bardzo popularnym narzędziem do tworzenia wymagań.

Musisz też zapamiętać, że sam pisemny zapis tematu User Story to tylko początek. Jest to wstęp do rozmowy. A rozmowa ta doprowadzi Cię dalej, do zrozumienia sedna zagadnienia.

Zwracaj uwagę na obecność kryteriów akceptacji, w postaci testów. To dzięki nim będziesz wiedział, że skończyłeś pracę.

Do tworzenia historii warto stosować metodę INVEST. Jest to szczególnie pomocna metoda na początku, kiedy dopiero uczysz się pracy w zespole i pomagasz właścicielowi produktu w tworzeniu wymagań.

I na koniec! Bardzo Ci dziękuję, że dotarłeś do końca. I jeśli tu jesteś, to wiem, że ten artykuł jest dla Ciebie wartościowy. Przeczytanie ponad 2,8 tys. słów coś znaczy. Dlatego prośba do Ciebie. Przekaż ten artykuł swoim znajomym, wrzuć na Face’a i oznacz mnie w swoim poście. Dla mnie to super sygnał, że robię dobrą robotę 💪💪💪

4 1 vote
Article Rating
Subscribe
Powiadom o
guest
0 komentarzy
Inline Feedbacks
View all comments