Co oznacza jednoznaczność specyfikacji wymagań?
Kiedyś już rozważaliśmy, co standard IEEE 830 rozumie przez dobrze napisany SRS. Przeglądaliśmy również atrybuty dobrej specyfikacji wymagań według tego samego standardu, a nawet zastanawialiśmy się, czym jest "śledzenie" wymagań. Dzisiaj chciałbym pochylić się nad kolejnym atrybutem dobrego SRSa, nad jednoznacznością.
SRS jest jednoznaczny, jeśli każde opisane wymagania ma tylko jedną interpretację.
Atrybut ten jest o tyle istotny, że niejednoznacznie zapisane wymagania będą się na nas mściły od samego początku pracy nad oprogramowaniem, aż do samego końca. Niejednoznaczne wymagania spowodują, że klient może inaczej zrozumieć zapisane wymagania, inaczej zrozumie je architekt, jeszcze inaczej zaimplementują je programiści, a testerzy będą testować jeszcze coś innego. Problem jest o tyle ciężki do rozwiązania, że często pisząc wymagania nie zdajemy sobie sprawy, że coś może mieć więcej niż jedno znaczenie, dopiero zderzenie z innym punktem widzenia pomaga nam uzmysłowić sobie, że zapisane wymaganie można zinterpretować na kilka sposobów.
Niestety, jeśli używamy języka naturalnego do opisu wymagań, to skazujemy się automatycznie na niejednoznaczność, gdyż jest ona cechą charakterystyczną właśnie takiego podejścia.
Łatwiej zadbać o jednoznaczność korzystając z notacji przeznaczonych do opisu wymagań, które często w sposób automatyczny wskażą nam potencjalne problemy wieloznaczności. Niestety podejście to ma też swoje wady - wymaga ono poświęcenia czasu oraz wysiłku do nauki sprawnego posługiwania się daną notacją. W przypadku osób "technicznych" nie powinno stanowić to problemu, jednak dla naszego klienta może okazać się to barierą nie do przeskoczenia.
Możecie podzielić się swoimi "przygodami" wynikającymi z niejednoznaczności wymagań?
A najczęściej używana notacja to…
Patrząc przez ramię
Ile razy zastanawialiście się, w jaki sposób modelować Wasze wymagania? Która notacja będzie najlepsza? Który sposób modelowania powinienem\am wybrać? Ile razy zaglądaliście przez ramię koleżanki lub kolegi, żeby zobaczyć jak oni to robią? Czy nie fajnie by było spojrzeć przez ramię prawie 200 innych analityków i zobaczyć, z czego oni korzystają w swojej pracy z wymaganiami?
Ale jak to zrobić?
Na szczęście panowie Colin J. Neill oraz Phillip A. Laplante z Penn State University postanowili dowiedzieć się czegoś więcej na temat najczęściej stosowanych praktyk inżynierii wymagań. Stworzyli internetową ankietę, która składała się z 22 pytań i zaprosili do jej wypełnienia prawie 2000 osób (głównie absolwentów PennState University). Odpowiedzi udzieliły 194 osoby (m.in. z takich firm jak SAP, Boeing, Dupont, Simens Medical Systems) i odpowiedzi te były podstawą artykułu "Requirements Engineering: The State of the Practice", który ukazał się w 2003 roku.
A zwycięzcą jest...
Jako, że cały dokument jest dostępny tutaj, to nie będę rozwodził się nad poszczególnymi wnioskami, tylko przedstawię najciekawsze (moim zdaniem) wyniki, i tak:
- 60% osób biorących udział w ankiecie stosowało w jakimś stopniu prototypowanie.
- 35% respondentów powiedziało, że wykorzystują podejście kaskadowe.
- W projektach, które trwały dłużej niż dwa lata najpopularniejsze było podejście iteracyjne.
- 33% osób stwierdziło, że nie korzystają z żadnej metodologii
- 51% respondentów powiedziało, że stosują nieformalne sposoby zapisu wymagań, 27% sposoby półformalne, a 7% stosują notacje formalne.
- W 59% przypadków stosuje się inspekcje, jako sposób na podniesienie jakości wymagań.
- 52% osób stwierdziło, że w ich firmach za mało uwagi poświęca się na inżynierię wymagań.
- Ponad 50% osób wykorzystuje przypadki użycia i/lub scenariusze do zapisu wymagań.
Tak wyglądają wyniki badań po drugiej stronie oceanu, ciekaw jestem jak to wyglądałoby u nas? Bylibyście zainteresowani wzięciem udziału w takim badaniu? Dajcie znać w komentarzach lub mailowo.
Darmowy webinar o tworzeniu modeli przypadków użycia
Na blogu Bridging the Gap możecie się zarejestrować na darmowy webinar dotyczący tworzenia modeli przypadków użycia. Webinar jest zaplanowany na wtorek 04. maja na godzinę 18:00 EST, co oznacza 01:00 naszego czasu (będzie to już środa), (więc jeśli ktoś cierpi na bezsenność to) może warto skorzystać?
7 sposobów na zapewnienie porażki Twojemu projektowi
Jeśli chcesz, żeby Twój projekt zakończył się porażką zadbaj o następujące sprawy:
- Nie poświęcaj zbytniej uwagi i za dużo czasu ma wymagania
- Nie ustalaj priorytetów wymagań
- Nie słuchaj swojego klienta
- Używaj niezrozumiałych słów
- Nie używaj różnych modeli do reprezentowania wymagań
- Nie zarządzaj w żaden sposób swoimi wymaganiami
- Organizuj wiele bezproduktywnych spotkań
Znacie jeszcze jakieś inne gotowe sposoby na zapewnienie porażki projektu?
7 mitów na temat metod formalnych
Jakiś czas temu pisałem o tym, jakie metody powinniśmy stosować do różnych projektów, jedną z takich metod są podejścia formalne do zapisywania wymagań. Z badań wynika, że metody takie są mało popularne, jednym z powodów takiego stanu rzeczy są mity i przekonania, które wokół nich powstały. Artykuł "Seven Myths of Formal Methods" rozprawia się z siedmioma takimi mitami. Oto one:
Mit #1
Metody formalne zagwarantują, że oprogramowanie będzie idealne.
Niestety prawda jest taka, że nie ma żadnych metod, które mogą nam zagwarantować pewny sukces. Zwolennicy metod formalnych często przedstawiają je jako sposób na wszystkie bolączki projektów i zapewniają stuprocentowe powodzenie, a jako jedyny powód porażek przedstawiają niedoskonałość ludzi, którzy takie metody wykorzystują. Praktyka jednak pokazuje, że żadne mniej lub bardziej wyszukane nie są w stanie zagwarantować nam sukcesu.
Mit #2
Metody formalne sprawdzają się, bo umożliwiają udowodnienie, że oprogramowanie jest poprawne.
Weryfikacja poprawności jest tylko jednym z elementów metod formalnych i to tą najbardziej kosztowną, dlatego też bardzo często, jeśli system nie jest krytyczny, to ten element pomija się podczas pracy nad projektem.
Mit #3
Tylko bardzo krytyczne systemy mogą skorzystać z zalet notacji formalnych.
Oczywiście w przypadku systemów krytycznych zastosowanie notacji formalnych jest często koniecznością, nie oznacza to jednak, że pozostałe rodzaje systemów nie mogą skorzystać z zalet jakie niosą ze sobą podejścia formalne.
Mit #4
Metody formalne wymagają znajomości skomplikowanej matematyki.
Jak wiadomo większość metod formalnych wywodzi się z matematyki, a ta często postrzegana jest jako coś wielce skomplikowanego i trudnego do opanowania. Okazuje się jednak, że w praktyce metody formalne są stosunkowo proste i łatwe do przyswojenia.
Mit#5
Metody formalne zwiększają koszty wytwarzania oprogramowania.
Nawet jeśli tworzenie specyfikacji w notacji formalnej, lub też późniejsza implementacja kosztują więcej (a niekoniecznie musi tak być!), to na pewno faza utrzymania oprogramowanie jest później dużo niższa.
Mit #6
Formalne notacje są niezrozumiałe dla klientów.
Pomimo swojej matematycznej natury notacje formalne niosą ze sobą różne inne sposoby prezentowania informacji, które mogą być bardziej zrozumiałe dla klientów.
Mit #7
Nikt nie wykorzystuje metod formalnych w rzeczywistych projektach.
Często metody formalne wiąże się ze środowiskiem naukowym, jakoby tylko one mają odpowiednie zdolności do operowania formalizmami. Badania pokazują jednak, że metody formalne mogą być (i są!) z powodzeniem wykorzystywane w rzeczywistych projektach przemysłowych,
Po szczegóły rozprawienia się z powyższymi mitami zapraszam do lektury artykułu. Zamiast mitów autor artykułu proponuje następujące fakty:
- Notacje formalne pozwalają znaleźć błędy we wstępnym etapie tworzenia oprogramowania oraz pozwalają wyeliminować pewne klasy błędów.
- Formalizmy zmuszają do intensywnego przemyślenia koncepcji tworzonego systemu.
- Praktycznie dotworzenia każdego rodzaju oprogramowania można wykorzystać metody formalne.
- Notacje formalne bazują na specyfikacji matematycznej, która jest dużo prostsza do zrozumienia niż kod programu.
- Metody formalne mogą zmniejszyć koszty wytwarzania oprogramowania.
- Klienci mogą lepiej zrozumieć budowany system tworzony z wykorzystaniem notacji formalnych.
- Wiele rzeczywistych projektów przemysłowych wykosztuje formalizmy.
Jak pisać przypadki użycia?
Pisałem ostatnio o przypadkach użycia jako formie zapisu wymagań. Na końcu obiecałem, że napiszę również o kwestii jakości przypadków użycia. Zatem proszę bardzo.
Źródła wiedzy
Jeśli chcemy dowiedzieć się jak najwięcej o tym w jaki sposób zapisywać wymagania to najlepiej przyjrzeć się bliżej dwóm pozycjom książkowym: "Patterns for effective use cases" oraz "Writing effective use cases". Obie te książki w przyjazny sposób prezentują najlepsze praktyki zapisu wymagań zwracając uwagę zarówno na sam proces tworzenia specyfikacji wymagań jak i sposób zapisu poszczególnych elementów.
Podstawowe wskazówki
Na co powinniśmy zwrócić uwagę zapisując nasze wymagania w postaci przypadków użycia? Otóż:
- scenariusz główny powinien posiadać nie mniej niż 3 kroki i nie więcej niż 9 kroków. Same liczby są wartościami arbitralnymi, pozwalają jednak pamiętać z jednej strony o tym, żeby przypadek użycia nie był zbyt krótki, gdyż prawdopodobnie nie niesie on za sobą żadnej wartościowej informacji i należy się zastanowić, czy ten jeden lub dwa kroki nie można włączyć do innego przypadku użycia; z drugiej strony długi przypadek użycia może być trudny do ogarnięcia - czytelnikowi może być trudno skupić się na kilkunastu krokach scenariusza (pod koniec może już nie pamiętać co było na początku), a dodatkowo wyjątki i rozszerzenia do tak długiego scenariusza mogą być przytłaczające - kto z Was chciałby czytać przypadek użycia zajmujący kilka stron? Dodatkowym czynnikiem jest trudność z utrzymaniem tak długiego przypadku użycia - w momencie potrzeby zmiany jakiegoś wymagania to my będziemy musieli się przebić przez te długie linijki i zmienić odpowiedni fragment. Co można zrobić z za długim przypadkiem użycia? Należy zastanowić się, czy nie możemy podzielić go na kilka osobnych przypadków użycia lub wydzielić przypadek użycia wyższego poziomu.
- należy unikać opisu interfejsu użytkownika. Dlaczego? Ponieważ przypadek użycia w swoim założeniu powinien opisywać intencje aktora, a nie sposób w jaki wykonywane są akcje. Innymi słowy przypadek użycia powinien opisywać wymagania, a nie gotową implementację. Na opis interfejsu użytkownika powinno być wydzielone osobne miejsce w specyfikacji wymagań, bo czy istotne jest, że użytkownik w danym miejscu klika na link? albo na przycisk? Nie! a opis tych szczegółów powoduje, że przypadek użycia staje się dłuższy i trudniejszy do zmiany (szczególnie gdy okazuje się, że później ten "link" trzeba wszędzie zmienić na "przycisk").
- istotne jest, aby w każdym kroku jasno określony był aktor wykonujący akcję. Często autorowi przypadku użycia może wydawać się oczywiste, w jaki sposób jakaś interakcja się wykonuje, jednak dla czytelnika nie musi być już to takie oczywiste. Dla przykładu krok "Wiadomość jest wysyłana" może oznaczać, że Użytkownik (który?) wysyła wiadomość, albo, że to System wysyła wiadomość do użytkownika, albo może to dwa systemy się ze sobą komunikują i wysyłają między sobą wiadomości - tylko który z nich wysyła wiadomość w tym momencie? Jak widzicie jasne określenie aktora może być kluczowe dla zrozumienia wymagania, a przecież na tym zrozumieniu przez klienta, programistów, testerów (i pozostałe osoby związane z tworzeniem naszego oprogramowania) najbardziej nam zależy!
- warto jest zwrócić uwagę na prostotę używanego języka oraz na długość pojedynczych kroków. Pamiętajcie, że zależy nam na jednoznaczności zapisu, a każdy dodatkowy wyraz powoduje, że zdanie staje się bardziej skomplikowane i pozwala na dodatkowe możliwości interpretacji. Jeśli to możliwe starajcie się więc trzymań konstrukcji :
Podmiot + orzeczenie + dopełnienie
czyli np. "Administrator wysyła wiadomość do użytkowników premium", gdzie "Administrator" jest podmiotem, "wysyła" jest orzeczeniem", a "wiadomość do użytkowników premium" jest dopełnieniem. - spróbuj przechodzić od ogółu do szczegółu, czyli najpierw wypisz sobie wszystkie nazwy przypadków użycia, później zastanów się nad wszystkimi scenariuszami głównymi, żeby na końcu dopisać wszędzie sekcje wyjątków i rozszerzeń. Dlaczego warto stosować takie podejście? Pozwala nam ono lepiej ogarnąć całość specyfikacji i zaoszczędzić sporo energii, którą w przeciwnym przypadku wykorzystalibyśmy na początkowe szczegółowe opisywanie wymagań, które później będzie trzeba zmienić, bo ogólna koncepcja będzie inna, niż na początku nam się wydawało.
- w każdym przypadku należy skupiać się na pojedynczym celu aktora. Jeden przypadek użycia = jeden cel aktora. Jeśli zauważymy, że w danym przypadku użycia aktor osiąga kilka celi, to należy zastanowić się, czy nie lepiej byłoby podzielić dany przypadek użycia na kilka mniejszych. Dlaczego? Po pierwsze pojedynczy cel ułatwia ustalenie granicy między przypadkami użycia, co wpływa później na lepsze zrozumienie wymagań. Po drugie późniejsza weryfikacja takiego przypadku użycia jest łatwiejsza, gdyż sprawdzamy tylko jeden cel, a nie kilka.
- nazwa przypadku użycia powinna w jasny sposób określać, jaki konkretny cel osiąga aktor w danym przypadku użycia. Nazwy są tym elementem, który decyduje o tym w jaki sposób interpretujemy cały przypadek użycia, dlatego też istotne jest aby nazwy były jednoznaczne i trafnie określały, co przypadek użycia opisuje.
- poświęć dużo uwagi sekcji wyjątków i rozszerzeń. Zwykle jeśli dobrze określimy nazwę przypadku użycia czytelnik intuicyjnie będzie wiedział, jak powinien wyglądać scenariusz główny. Sprawa jest jednak trudniejsza w przypadku sytuacji wyjątkowych - jeśli nie opiszemy ich wyczerpująco, to okaże się, że programista nie zaimplementuje ich obsługi, co w konsekwencji może prowadzić do stworzenia systemu, z którego nie będzie można korzystać w sensowny sposób.
- przy zapisie wyjątków i rozszerzeń zapisuje warunki, które system może zweryfikować. Dlaczego? Wyobraź sobie przypadek użycia opisujący wypłatę pieniędzy z bankomatu. Czy jest sens zapisywać wyjątek "Klient odszedł od bankomatu"? Nie, gdyż system prawdopodobnie nie jest w stanie tego wykryć. Natomiast wyjątek "Klient nie odebrał gotówki w czasie 1 minuty" jest już łatwiejszy dla systemu do zweryfikowania, a co za tym idzie programiści mogą go zaimplementować, a testerzy odpowiednio przetestować.
- unikaj szczegółów technicznych. Jako informatyk, lub przynajmniej osoba dość mocno związana z branżą oprogramowania masz prawdopodobnie dużo szerszą wiedzę na temat technologii niż Twój klient, czemu by więc się tą wiedzą nie pochwalić? Niech klient wie, jaki jestem mądry! a co?! Ano to, że jeśli w przypadku użycia będziesz używał(a) języka technicznego, to klient większości tego nie zrozumie i dodatkowo czytanie takiej specyfikacji będzie dla niego bardzo uciążliwe. Pamiętaj, że przypadek użycia ma opisywać intencje aktora, a nie implementację systemu.
Przypadki użycia
Historia powstania przypadków użycia
Ostatnio zastanawialiśmy się, w jaki sposób można zapisać wymagania. Jednym z nieformalnych sposobów są przypadki użycia. Zostały one zaproponowane przez Ivara Jacobsona w latach 80-tych jako opis wymagań dla systemów stosowanych w branży telekomunikacyjnej. W latach 90-tych, gdy powstawały fundamenty notacji UML postanowiono włączyć pana Jacobsona do grona twórców UMLa i w ten sposób przypadki użycia znalazły swoje miejsce jako element tej właśnie notacji. Z jednej strony pozwoliło to przypadkom użycia zyskać na popularności i stać się jednym z popularniejszych sposobów zapisu wymagań (badania pokazują, że przypadki użycia i zapis scenariuszy jest wykorzystywany w ponad 50% projektów). Z drugiej strony jednak UML spowodował, że przypadki użycia zaczęły być kojarzone wyłącznie z diagramami, na których specyfikuje się aktorów oraz funkcje do jakich mają oni dostęp. Oczywiście diagramy są ważne, pozwalają one ogarnąć ogólną wizję funkcjonalności oraz zależności między przypadkami użycia. Przypadki użycia to jednak dużo więcej niż same diagramy - ich istotą są scenariusze interakcji między aktorami systemu.
Podstawowe elementy przypadków użycia
Tak jak wspomniałem powyżej głównym elementem przypadków użycia są scenariusze interakcji (zwane równieżscenariuszami głównymi), gdyż to one niosą za sobą największą wartość jeśli chodzi o wymagania. Co jeszcze w takim razie składa się na przypadek użycia? W podstawowej wersji poza scenariuszem podajemy:
- identyfikator pozwalający w jednoznaczny sposób odwoływać się do przypadku użycia,
- nazwę określającą czego dotyczy dany przypadek użycia,
- aktorów biorących udział w interakcji
- opis wyjątków oraz rozszerzeń dla scenariusza interakcji.
Z czego wynika ten ostatni element? Otóż w głównym scenariuszy podajemy pozytywny przebieg interakcji, czyli np. jeśli opisujemy zakup książki w sklepie internetowym to scenariusz główny kończy się zakupem książki (jest to tzw. "happy day scenario"). Co z przypadkami, gdy np. książki nie ma w naszym sklepie? Właśnie do takich sytuacji wykorzystywana jest sekcje wyjątków i rozszerzeń, w których możemy opisać sytuacje wyjątkowe (np. błędnie podane hasło przez użytkownika, błąd przy nawiązaniu połączenia zdalnego, itp.) oraz rozszerzenia naszego scenariusza głównego (np. gdy książki akurat nie ma w naszym sklepie, lub gdy nasz klient chce kupić więcej niż jedną książkę?).
Poniżej znajdziecie przykład przypadku użycia z wymienionymi wcześniej elementami:

Rozszerzony przypadek użycia
Poza podstawowymi elementami w przypadku użycia można zawszeń:
- wyzwalacze (ang. trigger) opisujące jakie zdarzenie może wywołać dany przypadek użycia
- warunki początkowe (ang. preconditions) określające jakie warunki muszą być spełnione, aby przypadek użycia mógł zostać wykonany
- warunki końcowe (ang. postconditions) mówiące o tym jakie warunki muszą być spełnione na końcu poprawnego wykonania przypadku użycia
- opis prezentujący skróconą wersję przypadku użycia
- wymagania dodatkowe określające wymagania, które nie zostały zawarte w scenariuszach, a są w jakiś sposób powiązane z przypadkiem użycia
- szkice ekranów prezentujące przykładowy wygląd systemu w danym kroku
- poza tym nazwisko autora przypadku użycia, datę utworzenia, datę ostatniej zmiany, wersję.
Poniżej znajdziecie nasz wcześniejszy przykład poszerzony o elementy dodatkowe:

Dlaczego przypadki użycia są fajne?
Jak widzimy przypadki użycia pisane są w języku naturalnym, co powoduje, że czytelnik nie potrzebuje specjalistycznej wiedzy, aby taki przypadek użycia zrozumieć. Dodatkowo z góry określona struktura ułatwia czytanie, gdyż każde wymagania zapisane jest w taki sam sposób. Pisanie takich przypadków również jest proste - każdy element wymagania ma swoje określone miejsce, więc dość prosto jest skupić się na każdym elemencie i opisać go osobno.
Czy to naprawdę jest takie proste?
Patrząc na powyższe przykłady może się wydawać, że w pisaniu przypadków użycia nie ma nic trudnego, gdyż korzystamy tutaj z języka naturalnego, który z łatwością pozwala nam wyrażań nasze myśli. Okazuje się, że z przypadkami użycia związana są pewne pułapki, o których należy pamiętać zapisując wymagania właśnie w taki sposób. Różne "zasadzki" oraz dobre praktyki opisane są m.in. w książkach pt. "Patterns for effective use cases" oraz "Writing effective use cases".
Jak zapisywać wymagania?
Skoro badania (np te lub te) pokazują, że wymagania sprawiają kłopoty, to powstaje naturalne pytanie w jaki sposób zapisywać wymagania tak aby miały one jak największą wartość? Pierwszym pytaniem jakie powinniśmy sobie zadań przy wyborze sposobu zapisu wymagań jest "kim jest nasz klient?". Dlaczego takie pytanie? To klient właśnie będzie specyfikował wymagania i to on musi je zatwierdzić. Innym klientem będzie kierownik apteki z wykształcenia farmaceuta, dla którego będziemy pisali stosunkowo prosty system do zarządzania zamówieniami leków, a innym inżynier lotów kosmicznych w NASA, dla którego będziemy pisali system kontroli dla najnowszego wahadłowca. Jakie różnice między tymi klientami są dla nas najważniejsze? Po pierwsze każdy z nich ma inny poziom wiedzy technicznej - aptekarz jest w stanie zrozumień język naturalny i zapewne po krótkim wprowadzeniu również podstawowe diagramy, natomiast notacje formalne (często matematyczne) mogą być dla niego zbyt trudne; inżynier z NASA natomiast bez trudu powinien poradzić sobie z notacjami formalnymi, jest to zapewne dla niego "chleb powszedni". Po drugie każdy z tych klientów ma inny poziom oczekiwań co do budowanego systemu - inżynier NASA oczekuje systemu o najwyższym stopniu precyzji, dokładności oraz niezawodności, dlatego trzeba się zastanowić nad sposobem zapisu wymagań, który pozwoli nam to zapewnić; aptekarz z kolei może nam pozwolić na większy margines dokładności. Musimy zatem zawsze zastanowić się dla kogo będziemy pisali oprogramowanie oraz jak krytyczny nasz system będzie. W przypadku mniej technicznych klientów i niekrytycznych systemów możemy pozwolić sobie na notację opartą na języku naturalnym, natomiast gdy mamy do stworzenia system o krytycznym znaczeniu wówczas warto zastanowić się nad notacją formalnych lub semi-formalnych, gdyż notacje te pozwalają nam na matematyczną weryfikację kompletności oraz poprawności wymagań.