04 marca 2010

"Nie ma geniuszu bez ziarna szaleństwa" - "wątpliwa" lektura o TDD z "Growing Object-Oriented Software, Guided by Tests"

Growing Object-Oriented Software, Guided by TestsO Test-Driven Development (TDD) każdy gdzieś tam słyszał i niejeden obiecywał wdrożenie jego zasad. Jednym się udaje (albo sądzą, że tak jest), a inni polegli i zarzucili temat. Smutna prawda, ale prawda. Pewnie w dużej mierze dlatego, że pomimo wiadomych zysków - przede wszystkim skoncentrowanie na celu, jakim jest stworzenie działającego oprogramowania, zamiast rozdmuchiwania modelu, później kontrolerów, później widoku i jeszcze tysiąca innych warstw, aby ostatecznie przekonać się, że połowy nie potrzebowano, albo że i tak nie wiadomo, po co i na co, a termin i klient dawno poszli w zapomnienie - wdrożenie takiego podejścia wymaga niezwykłego zdeterminowania zespołu do zrealizowania postawionego celu. Innymi słowy - rygoru i dyscypliny! A kto by tam lubił rygor i dyscyplinę?! Niewielu osobom kojarzy się to z czymś przyjemnym. Mi na pewno nie.

Po recenzji Tomka Kaczanowskiego "Growing Object-Oriented Software Guided by Tests - Book Review" i namowie Bartka "Koziołek" Kuczyńskiego (Fwd: A free copy of "Growing Object-Oriented Software, Guided by Tests" for review doable?), aby ją zamówić do Biblioteki Warszawskiego JUGa dotarła i do mnie. W zeszłym tygodniu rozpocząłem jej lekturę i...jestem pod ogromnym jej wrażeniem. Niesamowicie nabałaganiła w mojej głowie. Stąd to użycie słowa "watpliwa" w tytule wpisu, bo narodziło mi się wątpliwości cała masa (i oby nie zakończyło się psychiatrą :)).

Książkę "Growing Object-Oriented Software, Guided by Tests" panów Steve Freeman i Nat Pryce (Oct 12, 2009 by Addison-Wesley Professional) czyta się lekko i przyjemnie. Jestem przy rozdziale 11. "Passing the First Test" (z 27-miu i 2 dodatków), więc praktycznie (dosłownie i w przenośni) niewiele mogę o niej napisać, ale mimo jej początkowego namolnego przekonywania o wyższości TDD nad tradycyjnym podejściem do tworzenia oprogramowania (najpierw model, później interakcje w jego ramach z testami jednostkowymi w międzyczasie), widać jedną wyraźną różnicę w moim postrzeganiu TDD, a tym, co autorzy rozumieją pod tym akronimem.

Do tej pory sądziłem, że TDD to przede wszystkim testy, co jest do tego momentu prawdziwe. W moim jednak rozumowaniu były to przede wszystkim testy jednostkowe przy tworzeniu konkretnych klas (dowolnej warstwy). W tej książce dowiedziałem się prawdy i to nie takiej, jakiej oczekiwałem początkowo. Miałem świadomość różnic w moim postrzeganiu TDD a jego zasadami, głównie z braku praktycznego doświadczenia i niezbyt dalekoidącym zainteresowaniem tematyką, ale to, w jaki sposób TDD przedstawia ta książka przeszło moje najśmielsze oczekiwania. Sprawa rozbija się o te "nieszczęsne" testy. Książka podzielona jest na 5 części, z których pierwszą mam już za sobą Part I. "Introduction", w której dowiedziałem się o teorii TDD i testach...funkcjonalnych, ale nie takich, które weryfikują przydatność gotowego produktu przez klienta (prawdopodobnie wykonanych wspólnie z nim manualnie), ale takich, które zweryfikują automatycznie, że dana funkcjonalność jest gotowa do testowania końcowego z klientem (!) To było dla mnie zabójcze doświadczenie, kiedy dodać do tego, że owe testy tworzy się zanim cokolwiek w naszej aplikacji powstanie, nawet infrastruktura. Czyż to nie (sarkazm włączony) "odświeżające" podejście (sarkazm wyłączony)?!

Zatem, jeśliby potraktować podejście książkowe, to zaczynamy od przekrojowego testu wybranej, pierwszej, zwykle łatwej do osiągnięcia, funkcjonalności końcowej aplikacji. Nie piszę tutaj o testach klasy XYZ, czy testach użyteczności technologi ABC, ale o pokrojeniu całej ostatecznej aplikacji (znanej na bazie dotychczasowych wymagań klienta) na kawałki funkcjonalne - rozpoczynające się od interfejsu użytkownika, a kończące się na systemach wewnętrznych - i bez rozstawionej infrastruktury stworzenie dla wybranego kawałka testu. Z oczywistych względów nie będzie to działający test - nic nie mamy - ale właśnie o to chodzi. Tylko, który zespół to wytrzymuje?! Chyba tylko te najbardziej zdeterminowane, zdyscyplinowane i...tu należałoby dopisać inne zalety zespołów, o których istnieniu nie miałem pojęcia. Jeśli takie istnieją, koniecznie muszę się dowiedzieć o ich stanie duchowym, kiedy nic nie ma, a trzeba stworzyć dla tego czegoś nieistniejącego kod testujący, w którym czerwonego więcej niż czarnego (czerwone to podkreślenie błędu w IDE, a czarne to wpisane litery składające się na test). W/g mnie praca w takim zespole może być tylko przywilejem, a dostosowanie się do reguł TDD...szaleństwem. W tym ujęciu jednak "szaleństwo" jest dla mnie czymś niezwykłym i zagadkowym. "Choć to szaleństwo, jest w nim przecie metoda" powiedział William Shakespeare w Hamlecie, ale podobają mi się też takie powiedzenia (zaczerpnięte z Wikicytaty) - "Kto ukrywa własne szaleństwo, umiera niemy" czy "W szalonym świecie tylko szaleńcy są rozsądni" i "Nie ma geniuszu bez ziarna szaleństwa". Naczytanie się takich powiedzonek nie może pozostać obojętne na nasze postrzeganie świata i podobnie jest z tą książką.

Zgodnie z nią, pierwsza faza TDD to stworzenie testu przekrojowego zwana The Walking Skeleton. Ów "chodzący szkielet" to szkielet przyszłego rozwiązania funkcjonalnego. Jego zadaniem jest sprawdzenie naszej świadomości architektonicznej tworzonej aplikacji i zaproponowanie architektury docelowej. Najlepiej jest, aby test był niewielki, ale dotykał wszystkich warstw, począwszy od interfejsu końcowego użytkownika a skończywszy na systemach zewnętrznych. W książce tworzony jest system aukcyjny jako samodzielna aplikacja desktopowa w JFC/Swingu i komunikująca się przez XMPP (w tej roli Smack) z płatnym systemem aukcyjnym. Do testowania GUI w Swingu wykorzystuje się WindowLicker, o którym nigdy wcześniej nie słyszałem (co, choćby z tego tylko powodu, już stanowi wartość z czytania tej książki). Dopiero w rozdziale 11. "Passing the First Test" przekonam się, jak autorzy zestawiają całe środowisko, więc nie napiszę, co o takim podejściu myślę teraz, poza tym, że jestem równie zdruzgotany, jak niewiele wiedziałem o TDD, jak zaintrygowany nowatorskim podejściem do tworzenia oprogramowania. Oby mi się nie udzieliło, bo nieznającym tematu ciężko będzie zrozumieć...szaleńca :)

Na bazie doświadczeń z tej książki chciałbym zrealizować pewien swój pomysł na aplikację desktopową z GUI w JFC/Swingu. Jednym z problemów, z jakim się obecnie borykam, to wybór między Eclipse RCP a NetBeans RCP. O tych słyszałem, że warto je rozważyć, ale może są inne? Chciałbym, aby tworzenie GUI było równie proste, co ostatnio stworzona przeze mnie aplikacja w Objective-C/Cocoa w Xcode na bazie lektury Introduction to Cocoa Application Tutorial. To było tak niezwykle proste, że uwierzyłem w swoje ukryte pokłady wiary na powrót do C w wersji obiektowej i na MacOS :) Nie chciałym jednak wchodzić w ten temat, kiedy tworzę aplikację GUI przede wszystkim na MS Windows i Linuksa, a Mac OS przy okazji, więc pewnie wybór padnie na Eclipse RCP vs NetBeans RCP. Jako, że nie chciałbym wracać do silnie typizowanego programowania w Javie i Swingu, więc przyjdzie mi skorzystać z Griffon, który jest (jak rozumiem) połączeniem NetBeans RCP i Groovy. Jak się coś nawinie z Clojure może zrobię przeskok, ale na chwilę obecną tnę moje żądze do realizowalnego minimum.

A jak Wam idzie TDD z tworzeniem aplikacji desktopowych w JFC/Swing, NetBeans RCP czy Eclipse RCP? Co polecacie na warsztat? Gdyby jeszcze było na tyle lekkie, aby dało się to puścić przez Java Web Start byłoby cudnie (aczkolwiek jest to wymaganie niewielkiego znaczenia).