czwartek, 13 maja 2010

Behaviour-Driven Development

Tak sobie ostatnio pomyślałem, że wyjechałem z tym Tumblerem bez przybliżenia najpierw o co w nim chodzi. To znaczy wyjaśniłem (mam nadzieję) o co w NIM chodzi, ale nie pisałem nigdy o samej idei na której on bazuje, czyli BDD. Samo hasło pewnie większość z Was słyszała, ale ciekawy jestem jaki procent wie o co w tym chodzi (nic, i tak się nie dowiem).

No więc BDD wywodzi się od Dana North'a (kiedyś z Thoughtworks, teraz nie wiem), który doszedł do wniosku, że jest jakaś dziura między tym co zwykle programiści myślą o projekcie, który robią, a tym czego oczekuje biznes. Główny problem jest taki, że każda z tych grup mówi innym językiem - biznes zasuwa wyłącznie o pieniądzach, a programiści chcą mieć wszystko wyłożone w javie. No więc Dan wpadł na pomysł jak to połączyć.
Po pierwsze trzeba się uporać z językiem - nie ma sensu, żeby każdy nazywał rzeczy po swojemu, więc Dan doszedł do wniosku, że skoro nas klient nas Paaaannnnnn to wszędzie należy używać tej nomenklatury (tak, to to samo co Ubiquitous Language w DDD).
Po drugie biznes(meni) patrzy na system z punktu widzenia jego użycia, a programiści z punktu widzenia... frameworków? Języka? Czy czegoś podobnego. Mówiąc w skrócie biznes patrzy z zewnątrz do wewnątrz a programiści odwrotnie.
No więc Dan wpadł na pomysł, żeby zbliżyć te wizje do siebie przez zmuszenie programistów do tego, żeby myśleli po angielsku, a więc za pomocą rzeczowników i czasowników a nie instancji i metod. Konkretnie chodziło mu o to, żeby wyrażać testy jako przykłady (coding by example) wyrażane w języku naturalnym (angielskim, bo: primo - polska fleksja nie nadaje się do parsowania, secundo - Dan nie włada polszczyzną). Idealnie powinno być tak, że nieprogramiści (tak, to jednak pewnie grubo ponad 99% ludzkości) są w stanie to przeczytać i zrozumieć. Tu wchodzimy na grząski grunt DSLi, którymi nie chcę się dziś zajmować, bo jest późno, a i tak już dużo napisałem.
Wracając do tematu, Dan wymyślił dość zwięzły i krótki zapis, który jest zrozumiały dla innych (no..., że nie tylko dla nas), a przy okazji jest parsowalny i da się przerobić łatwo na coś zrozumiałego dla maszyn. Zapis Dana jest następujący (ukradłem ten tekst ze strony Dana, więc mu nie mówcie):


Title (one line describing the story)
Narrative:
As a [role]
I want [feature]
So that [benefit]
Acceptance Criteria: (presented as Scenarios)
Scenario 1: Title
Given [context]
  And [some more context]...
When  [event]
Then  [outcome]
  And [another outcome]...
Scenario 2: ...
Story to coś a'la User Story w zwinnych metodykach, czyli jakaś funcjonalność. Narrative to znów znany ze zwinnych metodyk zwrocik (oj, zdrobnienie - wyszło, żem Warszawiak) "Jako KTOŚTAM chciałbym COŚTAM żeby COŚ SIĘ STAŁO". Do tego dochodzi Scenario, czyli konkretny przykład stosowania funkcjonalności, w formie znanej z wykładów Szczepana Fabera:
Given  ...
When ...
Then ...
Czyli prosty zapis tego co dane jest na wejściu, operacji, i jej wyniku.
Takie zdania powinien być w stanie nam dostarczyć każdy analityk (no dobra, tak naprawdę, to biznes powinien siedzieć nad tym z programistą, w końcu customer on-site...) A my z tych zdań budujemy szybko sobie testy, które prowadzą (młodzież powiedziałaby drajwują, ale ja jestem stary) zarówno zakres funkcjonalny tworzonej aplikacji, jak i w pewnym stopniu design - przynajmniej API.

Podsumowując - chodzi o to, by mieć wspólny zapis dla przykładów, które prowadzą development, oraz by te przykłady były wybierane (przez biznes) na podstawie ich wartości dla systemu. Realizacja tego pomysłu powoduje, że cały development jest prowadzony de facto przez interfejsy użytkownika, bo to jest to, o czym biznes myśli i co jest sobie w stanie wyobrazić (i dobrze!)

Do tego w BDD jest cała podszewka lingwistyczno-psychologiczna (powinienem pojechać tu hipotezą Sapir'a-Whorf'a ale na to jest zdecydowanie za późno....), która mówi o tym, że programiści lepiej myślą o kodzie jeśli rozumieją i wyrażają go po ludzku.

No i na koniec wisienka na torcie: oczywiście przykłady to tak naprawdę testy. Same przykłady to już dużo, bo pozwalają myśleć o kodzie z punktu widzenia jego użycia. Ale skoro przykłady opracowuje się na początku - przed pisaniem kodu, to chyba jest jasne, że nie wyrazić ich w postaci testów było by głupotą. No więc w ten sposób przykłady zachowań z BDD stykają się z testami akceptacyjnymi, prowadząc do A-TDD (Acceptance-Test Driven Development).

No, to chyba tyle. To teraz jak to się ma do Tumbler'a?
Jak już wiemy o co chodzi, to Tumbler po prostu realizuje tę ideę i trochę ją rozszerza (cóż - jestem przekonany, że Dan nie wymyślił tego po ubarwionej zielskiem wycieczce po Camden Town, tylko faktycznie miał to na myśli). Nie tylko pozwala on przekształcać pełnotekstowe przykłady/scenariusze (o składni +/- takiej jak powyższa) na testy JUnit'owe, ale generuje również raporty (aktualnie txt oraz html) z tego co przechodzi, co nie, a co jeszcze nie zostało zaimplementowane. To już dużo. Jednak główną myślą, która mi przyświecała przy tworzeniu tego narzędzia było, że większość programistów nie ma planu co ma zrealizować, tylko pisze co im się akurat wydaje w danym momencie ważne. Tak powstają nie tylko potwory i spółka, ale również po prostu niekompletne implementacje. A gdyby tak zastanowić się chwilę nad każdą funkcjonalnością, zapisać ją w formie przykładów i dopiero potem zrealizować? Dam głowę, że tak napisany kod nie powodowałby u autora myśli "gdybym tylko mógł napisać to jeszcze raz!" - bo raz piszemy to najpierw w głowie w przykładach, a potem przelewamy na papier -  tfu, klawiaturę - w dopracowanej formie.

PS. Tumbler z troszkę zmienionym API oraz nowymi funkcjonalnościami wyjdzie w ten weekend, więc kto żyw ściągać w poniedziałek rano i stosować! ;-)

Brak komentarzy:

Prześlij komentarz