01 listopada 2008

Refleksje po "Poznaj JUnit 4" z Internet MAKER 5/08

Kiedy przeglądałem półkę z czasopismami informatycznymi w kiosku na dworcu Warszawa Centralna (przed podróżą na NetBeans Day 2008 w Gdańsku) niewiele czasopism dotyczyło programowania w Javie - Software Developer's Journal (SDJ) oraz Internet MAKER. Paradoksalnie nie powinienem mieć żadnych trudności z wyborem i chciałbym móc napisać, że padło na SDJ, ale wybrałem (nie pierwszy już raz) Internet MAKERa 5/08 (wrzesień-październik). Jednym z artykułów, który przykuł moją uwagę był "Poznaj JUnit 4 - Wstęp do programowania sterowanego testami" autorstwa Tomasza Gębarowskiego. Zastanawiałem się cóż można napisać nowego o jednym z najbardziej rozpowszechnionym szkielecie aplikacyjny JUnit, czego jeszcze mógłbym nie wiedzieć. W zasadzie, z niewielką nadzieją na coś nowego, zabrałem się za lekturę i...nie żałuję. Chociażby samo poznanie adnotacji @Ignore oraz asercji assertThat (wspartej projektem Hamcrest) rekompensuje "dość obszerne wprowadzenie teoretyczne" (jak raczył zauważyć sam autor!). Poza tym, bardzo podobało mi się przedstawienie projektu JUnit po polsku bez korzystania z żargonu informatycznego (bo czyż Ci, którzy wiedzą jak posługiwać się żargonem informatycznym w stylu "framework" nie zakładają, że rozmówca w ogóle wie, czym jest framework?!). Wielokrotnie jestem pytany o wyjaśnienie działania technologii javowych i jeszcze nigdy nie spotkałem się z niezrozumieniem, kiedy zamiast framework używam szkielet aplikacyjny, czy ziarno zamiast bean. Jakkolwiek użycie "ziarno" zamiast "bean" wymaga porównywalnego nakładu pracy przy wyjaśnieniu, po co i dlaczego dany byt istnieje, to już w przypadku "szkielet aplikacyjny" (zamist "framework") można liczyć na pewne skojarzenia i intuicję rozmówcy. Właśnie dlatego uważam, że tłumaczenie technologii informatycznych korzystając z języka ojczystego adresata ostatecznie bardziej procentuje niż używanie zapożyczeń angielskich (licząc na ich znajomość u niego). Są takowe, których nie da się w prosty sposób zastąpić, jak "debugger", ale jak pokazuje przykład polskiego "logowanie" nawet one wciąż mogą prowadzić do nieporozumień. Jakich?! A proszę mi powiedzieć, o czym autor miał na myśli przy "logowaniu" - uwierzytelnianie (ang. log in/authenticate) czy zapis do dziennika zdarzeń (ang. log). A wracając do artykułu, to bardzo mile zaskoczył mnie język w jakim Tomasz wyjaśniał rolę JUnita w naszym warsztacie javowym. Pojawił się "szkielet aplikacyjny" i "programowanie sterowane testami", ale do czasu. Na 3. stronie artykułu pojawiły się wyjaśnienia w dedykowanych sekcjach (boksach?), gdzie zagościł "framework" i "plugin" przemieszany z "wtyczka", czy "kreator" zamiast "asystent" (czy "pomocnik"). Jakby pisała to już inna osoba (!)
Jako wadę artykułu możnaby nadmienić brak wyjaśnienia zalet programowania opartego o testy. Brak odpowiedzi, dlaczego warto zająć się nimi, przed faktycznym programowaniem samej aplikacji (już przy tym pytaniu widać, że rozróżniam testy od samej aplikacji, co nie twierdzę, że już samo w sobie jest niepoprawne). Mimo, że i testy, i sama aplikacja to wciąż programowanie, zdaje się, że przy tym pierwszym nie mamy tyle przyjemności. A ja pytam dlaczego? Zdaje się, że mimo, że podczas programowania myślimy o tym, co aplikacja ma robić, to po chwili i tak zaczynamy budować aplikację, jak nakazuje dany szkielet aplikacyjny i skupiamy się na niuansach niego samego, zamiast na czas realizować cele projektu (a nie swoje własne, jak poznanie nowego i w danej chwili popularnego szkieletu). Sądzę, że owe skupianie się na zawiłościach środowiska, które samemu sobie nałożyliśmy (również akceptacja zastałego środowiska rozważam w kategoriach świadomego własnego wyboru) przesłania nam faktyczny celu, jakim jest stworzenie działającej aplikacji w terminie. Jest to bodaj najczęstszy powód, dla kolejnego przesunięcia terminu oddania etapu projektu, bo poznanie danego szkieletu aplikacyjnego zabiera więcej czasu niż planowaliśmy (mimo wcześniejszych zapowiedzi, że jest tak prosty, jak tylko było to możliwe) lub posiada błąd, a niestety już nie mamy możliwości wycofać się z tej decyzji projektowej. Brzmi znajomo? Niejednokrotnie przyszło mi uczestniczyć w projekcie, w którym wybierałem co bardziej popularne rozwiązanie (szkielet aplikacyjny, serwer aplikacyjny, język programowania), zamiast sprawdzone czy właściwe. Consuetude altera natura est, co? Niejednokrotnie wybieram w projekcie rozwiązanie efektowniejsze, a nie efektywne. Drobna różnica w słowach, a jakie skutki w projekcie (!) Dlatego też, brakowało mi w artykule jakiegoś scenariusza, w którym byłaby próba przedstawienia wartości płynących z podejścia "najpierw testy" i w ten sposób upewnienie się, że bez względu na inne elementy wspomagające aplikację, np. interfejs użytkownika (aplikacja desktopowa vs webowa z ajaxem czy bez), jej podwaliny biznesowe (trzon aplikacji) ma gwarancję poprawności, tj. zgodności z założeniami. Kiedy mamy poprawnie skonstruowany trzon aplikacji możemy śmiało podejść do jej rozbudowywania i opakowania wymyślnym szkieletem aplikacyjnym, który *uprości* tworzenie wyrafinowanego rodzaju aplikacji. Podkreślam słowo uprości. Wiemy, co i jak mamy działające, ale efekt końcowy, który powali klienta na kolana warto już oprzeć o gotowe rozwiązanie, które spełnia rolę nakładki na już działające "bebechy". Właśnie owa gwarancja poprawności założeń daje nam pewność, że ostatecznie aplikacja w ogóle zaistnieje. Aby dojść do tego etapu, skorzystanie z JUnita (czy innego alternatywnego rozwiązania) wydaje się być kluczem do sukcesu. Skoncentrowanie się na pojedyńczych, wyizolowanych elementach naszej aplikacji sprawia, że "odpukujemy każdą z cegiełek i sprawdzamy, że żadna nie ma wady produkcyjnej". Samemu nie mam w zwyczaju rozrysowywać aplikacji w postaci diagramów UMLowych, na których widać byłoby, co w ogóle robimy, ale dostrzegam ich zaletę (chociażby dla nowoprzybyłych w projekcie). Z zastosowaniem JUnita jest podobnie. Widzimy ich zaletę, ale niewielu z nas (mnie włączając) ma wystarczające zacięcie, aby je wdrożyć. Dlaczego?! Czyżby moda na kolejny szkielet aplikacyjny sprawiała, że zapominamy o faktycznie wartościowej inżynierii programowania, gdzie posiadanie testów jednostkowych w projekcie, znajomość algorytmów ma znaczenie? Nie poświęcam wiele czasu na analizę algorytmów, nie tworzę wielu testów jednostkowych, nie stworzyłem żadnego szkieletu aplikacyjnego, ale mam nieodparte wrażenie, że dobry szkielet aplikacyjny nie obroni się bez testów jednostkowych, odpowiednich algorytmów i dokumentacji, np. w postaci diagramów UMLowych. Chciałbym móc spełnić choć jeden z tych postulatów. Poza kilkoma uwagami odnośnie zalecenia umieszczania testów jednostkowych w dedykowanym pakiecie test, który tym samym pozbawiłby nas możliwości testowania metod package protected, oraz kilku błędach w samej klasie testowej artykuł oceniam wysoko. Na zakończenie (chociaż wydaje się, że dopiero od tego momentu rozpoczyna się) artykułu pojawia się przedstawienie integracji JUnit w środowisku Eclipse IDE. Jakby uwypukleniem niesystematycznego użycia framework vs szkielet czy test-driven development vs programowanie sterowanym testami jest rozdział "Zakończenie". Autor nadmienił, że "tematyka (...) jest niezwykle szeroka i trudno jest przedstawić jej wszystkie założenia w jednym krótkim artykule". Oczekuję kolejnych.

p.s. W trakcie czytania nasunął mi się skrót odpowiadający programowaniu sterowanego testami, aby po prostu nazywać je "testosteronem" (TESTami STEROwaNe programowanie) ;-)

Nie cichną echa zeszłotygodniowej konferencji NetBeans Day 2008 w Poznaniu i Gdańsku. Na stronie głównej java.net Communities pojawiła się zajawka o wpisie na blogu Toniego - NetBeans DreamTeam visit to Poland on the java.net Communities tab + Polish JUGs helped organize these events. Najwyraźniej jest to pierwsza tak nagłośniona międzynarodowo, konferencja javowa w Polsce. Jam tam byłem, miodu i wina nie piłem, ale prezentacje odstawiłem ;-) Więcej w Wrażenia po NetBeans Day 2008 w Gdańsku. Gratulacje dla poznańskiego i gdańskiego JUGa!