Na niedawno zakończonej konferencji beIT organizowanej na Politechnice Gdańskiej przez Wydział Elektrotechniki, Telekomunikacji i Informatyki, wygłosiłem referat zatytułowany Filozofia czyli Aplikacja jako element biznesowej rzeczywistości (a nie gra komputerowa). Przesłanie tej prezentacji to:

Oprogramowanie bardzo często zastępuje konstrukcje rzeczywiste takie jak zegarek, kartoteka, biblioteka, księgi handlowe, programator pralki i wiele innych rzeczy. Dlatego analiza powinna polegać na zrozumieniu i udokumentowaniu mechanizmu działania “tego czegoś” a nie jedynie na spisaniu zewnętrznych oznak tego działania i zarządzanie tym spisem.

Referat miał lekkie podłoże filozoficzne :).

Ten artykuł nie będzie jednak powtórzeniem referatu (wyżej link do pobrania). Do jego napisania skłoniło mnie jedno z pytań z sali:

“Stosujemy TDD, czy to nie wystarczy? Po co więc robić to o czym Pan mówi?”

Otóż odpowiedź brzmiała: TDD nie zastępuje opisu mechanizmu działania. Innymi słowy: sam zestaw testów bardzo często nie stanowi żadnej informacji o tym co ma powstać.

Niedawno pisałem:

Mechanizm jednak to nie zawsze tylko same reguły, bardzo często (praktycznie zawsze dla nietrywialnych systemów) powinien powstać diagram pokazujący wewnętrzną budowę (architekturę) systemu, zestaw komponentów odpowiedzialnych za logikę realizowania tych reguł (a jedną z nich jest np. ?treść dokumentów musi być zapamiętywana z możliwością przywołania jej w dowolnym momencie?). Taki diagram nazywa się Model dziedziny. Jak go tworzyć pisałem nap. w artykule Model dziedziny jako wymaganie. (Źródło: Model To Mechanizm | | Jarosław Żeliński IT-Consulting)

A teraz jako przykład przytoczę dość złożony komponent wielu systemów (pogrubienie moje):

Jak działa scoring w Banku. Klient zainteresowany uzyskaniem kredytu wypełnia wniosek kredytowy dla wybranego produktu kredytowego. Dane z wniosku rejestrowane są w systemie informatycznym, który wspomaga proces obsługi wniosków kredytowych w Banku. Podczas przetwarzania wniosku następuje weryfikacja danych oraz zapytanie o automatyczną rekomendację kredytową kierowaną do silnika decyzyjnego. Silnik decyzyjny wykonuje zdefiniowany w postaci reguł przetwarzania algorytm scoringowy: gromadzi dodatkowe informacje z dostępnych źródeł (np. Biuro Informacji Kredytowej SA, bazy niesolidnych klientów oraz dowodów zastrzeżonych ? MIG BR, MIG DZ), wyznacza wskaźniki, określa przydział do klas ryzyka oraz wylicza ocenę punktową w oparciu o karty scoringowe. (Źródło: Scoring – metoda oceny wiarygodności kredytowej – ERP-view.pl – ERP, CRM, MRP, Business Intelligence, MRP)

Odpowiadając na pytanie o TDD powiem tak: nie da się “jednoznacznie zamówić” Systemu scoringowego, podając jedynie partię danych wejściowych i spodziewanych danych wyjściowych. Testy można opracować znając mechanizm działania tego systemu, tworzymy wtedy reprezentatywny zestaw testów “pokrywający cały kod”, o ile znamy strukturę tego kodu (projekt). Sam kod nie musi istnieć w momencie projektowania tych testów, ale opracowany mechanizm tak, bo jak już pisałem “model dziedziny to struktura kodu realizującego logikę biznesową wraz z metodami”.

Można tu powiedzieć, że nie każdy system to złożoność systemu scoringowego. To prawda, ale to co nazywamy biznesem to reguły biznesowe, mechanizm działania organizacji, a ten nigdy nie jest trywialny. Reguły udzielania upustów, reguły przydzielania kredytów kupieckich, reguły nagradzania w systemach lojalnościowych, reguły rozliczania kosztów i wiele, wiele innych w prawie każdej firmie, organizacji czy instytucji publicznej.

Prawdopodobieństwo tego, że powstanie “poprawne” oprogramowanie tylko na podstawie zapisu  szeregu “zewnętrznych obserwacji” (bo czym są wymagania jako zapis burz mózgów, ankiet, wywiadów, itp.?) jest tym bardziej bliskie zeru im bardziej organizacja ma złożony mechanizm działania (czyli większość).

Zjawisko to jest znane już od dziesiątków lat:

Problemy, w których rozwiązaniu mają pomóc budowane złożone systemy są zwykle ?problemami złośliwymi? (Rittel i Webber, 1973). ?Problem złośliwy? to taki skomplikowany problem, w którym jest tak wiele powiązanych ze sobą bytów, że nie istnieje jego ostateczna specyfikacja. Prawdziwy charakter problemu objawia się dopiero w miarę opracowywania rozwiązania.

Dlatego rozwiązanie nietrywialnego problemu nie polega na specyfikowaniu tego co znamy, a na podjęciu próby zaprojektowania rozwiązania. Tym projektem nie jest jednak “opis reakcji systsemu na bodźce”  (czarna skrzynka). Projektem jest opisany (jednoznacznie udokumentowany) mechanizm działania rozwiązania (biała skrzynka).

Dlatego wymagania specyfikujemy skutecznie poprzez projekt produktu a nie poprzez listę cech produktu. Zamówienie dla developera powinno zawierać projekt a nie wizualizację efektu końcowego, dokładnie tak jak w branży budowlanej, elektronicznej czy nawet mechanicznej (nawet wykonawca wału korbowego dostaje rysunki techniczne a nie rozwlekłą prośbę o fajny wał do samochodu).

Zilustrować to można tak:

Wymagania

  1. Wymagania biznesowe zgłasza biznes, są one formą opisu i konsekwencją problemu biznesowego, wymagania wobec rozwiązania to ustalony zakres projektu.
  2. Jeżeli jest to projekt z obszaru inżynierii oprogramowania, ma powstać oprogramowanie opisane z użyciem Przypadków użycia i Modelu dziedziny.
  3. Jak przejść od wymagań biznesowych do Przypadków użycia i modelu dziedziny i kto ma tego dokonać?

Kto ma opracować to ostatnie? Programista? A na jakiej podstawie, skoro “nie zna tego biznesu” (to programista a nie analityk biznesowy)? Czy same przypadki użycia opisują reguły (mechanizm działania) działania systsemu scoringowego czy systemu upustów w promocji (to jedna liczba, wartość upustu, na fakturze)? Nie. Czy da się na bazie partii testów (czyli skończonej, ale z reguły niezupełnej liście bodziec-odpowiedź) stworzyć cokolwiek? Mało kiedy. Oznacza to, że wymagania zebrane tylko jako przypadki użycia “mało kiedy” dają szansę na powstanie oprogramowania “za pierwszym razem”, tu prototypów nie jest nigdy przewidywalna. To dlatego metody zwane zwinnymi, bazujące wyłącznie na user story i prototypach, nadają się do problemów prostych. Kompletnie nie sprawdzają się w przypadkach złożonych systemów, rozumianych jako złożone mechanizmy. Te ostatnie trzeba nie raz “od zera” odkryć i opisać.

Paradygmat i metody obiektowe

Kluczem metod obiektowych (i paradygmatu obiektowego) jest hermetyzacja. Oznacza to, że złożoność obiektu “z zewnątrz” nie jest znana nigdy, nie ma znaczenia wielkość obiektu (mała klasa czy mega-komponent), na zewnątrz postrzegany jest wyłącznie jako interfejs. Rozważania na początku pokazały, że odpowiedzi na bodźce to oczekiwane (wymagane) cechy rozwiązania, które jednak nie determinują jego mechanizmu.

Oprogramowanie pomagające w nauce tabliczki mnożenia do 100, może zawierać statyczną tablicę znaną z ostatnich stron starych zeszytów, a może to być mechanizm będący implementacją algorytmu mnożenia. Po pierwsze zestaw testów, jak widać, nie determinuje żadnej z tych metod implementacji. Po drugie specyfikacja w pierwszym wypadku będzie “duża” (kosztowna), w drugim bardzo prosta. Po trzecie rozwijanie (tabliczka mnożenia do 1000) oprogramowania w wersji z tablicą statyczną będzie znacznie droższe niż pierwotne wytworzenie wersji z mnożeniem do 100. W drugim przypadku będzie polegało wyłącznie na zdjęciu blokady mnożenia liczb większych niż 10.

Tak więc co z tym TDD? Popatrzmy na to jak jest definiowane:

Co to jest Test Driven Development

Test Driven Development, czyli TDD, to technika tworzenia oprogramowania sterowana przez testy. Tworzenie kodu składa się z wielokrotnie wykonywanych trzech głównych kroków:

  1. Stworzenie testu jednostkowego, który powinien być możliwie najprostszy, aby uniknąć możliwości popełnienia błędu w samym teście. Test ma sprawdzać funkcjonalność, która będzie implementowana w kroku 2.
  2. Implementacja funkcjonalności ? tworzymy funkcjonalność, którą chcemy zaimplementować. Funkcjonalność ta powinna spełniać założenia testu jednostkowego, a wykonanie testu jednostkowego powinno kończyć się sukcesem.
  3. Refaktoryzacja, czyli porządki w stworzonej funkcjonalności. Ma to na celu uporządkowanie kodu, tak aby spełnione były standardy. Czynności wykonywane w tym kroku nie mogą zmienić wyniku testów.

Źródło: Test Driven Development

Pod pojęciem funkcjonalność tu rozumiany jest “oczekiwany efekt”, bo test nie jest niczym innym. Czy testy to są (zastępują) projekt wewnętrznej logiki? W przypadkach trywialnych pewnie tak, tam gdzie logika jest prosta lub nie występuje (przypadki użycia typu CRUD), albo tam gdzie “logika” jest “powszechnie znana” zna ją także programista (np. sposób działania zegara).

Jednak system o nietrywialnej logice działania, nie da się wyspecyfikować w postaci skończonej (lub rozsądnie krótkiej) listy bodziec-efekt (np. przykładowych partii gry w szachy). W jednej ze swoich książek Martin Fowler napisał, że żadna ilość godzin filmu znad stołu bilardowego, jako wymaganie, nie da w efekcie nawet namiastki dobrej gry w bilarda. Ale schemat stołu, wymiary kul, kija oraz prawa fizyki rządzące ruchem kul, pozwolą na napisanie wręcz doskonałej symulacyjnej gry. Taki opis to właśnie model dziedziny gry w szachy, dokładny opis mechanizmu tego co dzieje się na stole bilardowym.

Ostatnie pytanie brzmiało: Jak przejść od wymagań biznesowych do Przypadków użycia i modelu dziedziny i kto ma  tego dokonać?

Odpowiedź na to pytanie zawiera pewien artykuł, napisany w 2014 roku na nieco inny temat:

…rolą analityka biznesowego nie jest spisanie przebiegu dziesiątek wywiadów i setek indywidualnych wymagań. Nie mają większego sensu dokumenty na dwa, trzy tysiące stron (nikt ich nie czyta!). Rolą analityka biznesowego jest przeanalizowanie dostępnych dokumentów, informacji, i stworzenie opisu mechanizmu działania organizacji oraz opisu rozwiązania, narzędzia mogącego usprawnić działanie organizacji. Opisu zawierającego reguły biznesowe, przetwarzane informacje (wzory dokumentów) oraz listą usług jakie ma świadczyć planowana do wdrożenia aplikacja wraz z opisem tego, jak te usługi mają być realizowane (umiejętności, które można zautomatyzować).  Sens mają więc zwięzłe opisy i modele mechanizmów działania organizacji oraz opisy tego jakie informacje i jak mają być przetwarzane z uwzględnieniem tego, że część tych prac nadal będą wykonywali ludzie. Takie jak reguły gry w szachy: ważne są dwie strony opisu reguł gry a nie setki stron opisów przykładowych partii. (Źródło: Warsztaty Analityczne ? Czyli Malowanie Trawy | | Jarosław Żeliński IT-Consulting)

Tak więc robimy to tak, jak w innych dziedzinach inżynierii: analizujemy, projektujemy i zlecamy wykonanie (implementację).

Na zakończenie

Kim jest, członkiem którego zespołu jest (powinien być) projektant? Przewrotnie odpowiem, że praktyka pokazuje, że – z powodu ryzyka projektowego – wykonawca nie powinien sam sobie stawiać wymagań. To dlatego złożone i ryzykowne projekty mają wydzieloną rolę analityka projektanta, nie jest to członek zespołu biznesu ani developera bo obie te strony mają sprzeczne interesy (zakres i koszt). W branży budowlanej jest to Biuro Projektowe (tu architekt), trzeci niezależna rola, poza inwestorem i wykonawcą (z uwagi na ryzyko, prawo budowlane zabrania łączenia jakiejkolwiek z tych trzech ról). W metodykach takich jak SCRUM, jest to Product Owner, i z powyższego powodu nie jest dobrze gdy jest to “człowiek developera”.

Jarosław Żeliński

Jarosław Żeliński: Od roku 1991 roku, nieprzerwanie, realizuje projekty z zakresu analiz i projektowania systemów, dla urzędów, firm i organizacji. Od 1998 roku prowadzi samodzielne studia i prace badawcze z obszaru analizy systemowej i modelowania (modele jako przedmiot badań: ORCID). Od 2005 roku, jako wykładowca akademicki wizytujący (nieetatowy), prowadzi wykłady i laboratoria (ontologie i modelowanie systemów informacyjnych, aktualnie w Wyższej Szkole Informatyki Stosowanej i Zarządzania pod auspicjami Polskiej Akademii Nauk w Warszawie.) Oświadczenia: moje badania i publikacje nie mają finansowania z zewnątrz, jako ich autor deklaruję brak konfliktu interesów. Prawa autorskie: Zgodnie z art. 25 ust. 1 pkt. 1) lit. b) ustawy o prawie autorskim i prawach pokrewnych zastrzegam, że dalsze rozpowszechnianie artykułów publikowanych w niniejszym serwisie jest zabronione bez indywidualnej zgody autora (patrz Polityki Strony). Konsultacje: wszelka pomoc i wyjaśnienia dotyczące treści artykułów autora bloga udzielana jest wyłącznie w ramach płatnych konsultacji.

Ten post ma 3 komentarzy

  1. Szympans u steru

    Bardzo ciekawie opisane.
    W przypadku TDD można też znaleźć i trywialny przypadek, którego TDD nie obsłuży prawidłowo a przynajmniej nie da nam jednoznacznej odpowiedzi na temat tego jaki System należy wybrać.

    Przypuśćmy, że mamy do zaprojektowania samochód, którego jedynym warunkiem jest osiągnięcie 100km/h w 9 sekund.
    Test jaki zaprojektujemy jest prosty, startujemy samochodem, włączamy stoper i wyłączamy po osiągnięciu 100km/h.

    Prosty test, który zaliczy zarówno Opel Astra z silnikiem 1.4 jak i Ferrari, z tym że Ferrari zrobi to na wstecznym. I tak oto używając jedynie TDD możemy z czystym sumieniem zaproponować odbiorcy zakup Ferrari 488 GTB za milion. Pytanie czy to na pewno ten samochód jaki Klient potrzebuje?


    Poruszyłeś jeszcze jedną ciekawą kwestię, która często gdzieś umyka. Developer czy człowiek z biznesu robiący za analityka. Ten pierwszy na zasadzie “Idź Krzysiu pilnuj, żeby nam nie wcisnęli za dużo do zrobienia”, ten drugi na zasadzie “Halinka idź, dasz radę, lubisz przecież analizę”

    Co prawda często jest to wynikiem ograniczeń budżetowych i zatrudniania – zwłaszcza w korporacjach – yes manów, którzy zrobią wszystko. Przeważnie wystarczy jednak jeden rzut oka na dokumentację żeby wiedzieć czy analityk chociaż przechodził koło niej.
    Nikomu nie ujmując wiedzy czy ambicji, analizę wymagań najlepiej zostawić podmiotom zewnętrznym nie związanym z biznesem czy developerem. Przy naprawdę dużych i ciekawych rozwiązaniach – moim zdaniem – dobrze jeśli wydzieli się także niezwiązaną z projektem i firmą osobę odpowiedzialną za napisanie scenariuszy testowych.

  2. Jaroslaw Zelinski

    Uwagi w drugiej części są bardzo niepopularne gdyż wdrożenie ich praktycznie całkowicie eliminuje lobbing jednej i drugiej strony, który najczęściej psuje projekt poprzez wymuszanie nielogicznych wymagań, które dają jakieś korzyści lobbującemu. 😉

  3. Pawel Zubkiewicz

    Witam Jarku,
    Muszę przyznać, że to chyba jeden z Twoich najlepszych artykułów na blogu! Sądząc po pytaniach to na konferencji była “praca u podstaw” dlatego tym bardziej ważne jest promowanie elementarnej wiedzy. Szczególnie przypadł mi do gustu przykład z tabliczką mnożenia, osobiście w głowie od razu zaświtała mi “funkcja w matematyce” czyli ogólny zapis (wzór) zamiast szeregu specyficznych przypadków usiłujących “opisać” zjawisko.

    Pytanie o TDD dla mnie trochę chybione, pewnie osobie pytającej chodziło o to, że mają user stories też… ale to nie ważne. Istotne jest to, że same wymagania w postaci kryteriów (pobudzenie i rezultat) BEZ analizy nie wystarczają i niestety to jest największa bolączka metodyki Agile. O tym nie napisałeś wprost,choć domyślam się z jakich względów 🙂

    Do Szympans u steru: pracując w TDD raczej małe jest prawdopodobieństwo, że zbudujesz Ferrari (bardziej rozbudowany produkt) niż Opla (mniej skomplikowany) wcześniej. Udoskonalasz produkt tak długo aż spełni kryteria, najwczęściej LINIOWO udoskonalasz, czyli w pierwszej próbie samochód jedzie 10km/h, w drugiej 23 i tak dalej… aż osiągniesz 100km/h (przejdzie test).

Możliwość dodawania komentarzy nie jest dostępna.