19 stycznia 2009

Relacja z rozdziału 3. "More Advanced Groovy" z "Beginning Groovy and Grails"

Jedni na nartach spędzają urlop z rodziną, a ja wciąż przy lekturze Beginning Groovy and Grails: From Novice to Professional. W międzyczasie pojawiają się komentarze innych zainteresowanych własnym rozwojem w tematyce Groovy, co cieszy, bo będzie z kim obgadać temat, czy to podczas 4 Developers 2009, GeeCON 2009 (na której zagości współtwórca Grails - Guillaume Laforge), czy Javarsovia 2009 (auć, ta strona jeszcze w rozsypce!). Tak czy owak, skoro Groovy to Java z pewnymi atrakcjami, to możnaby pokusić się o rozpoznanie możliwości uruchamiania Groovy ze Spring Framework (to już wiem, że jest możliwe, ale nie próbowałem), albo nawet pisząc pakunki OSGi, potencjalnie ze wsparciem Spring-DM. Możnaby również spróbować zbadać wartość płynącą z wdrożenia ziaren EJB 3.1 pisanych w Groovy (groz(n)iej brzmi?* - ciekawostki z tym stwierdzeniem szukaj na samym końcu). Możnaby jeszcze kilka innych tematów zahaczyć, ale czy warto? Właśnie to mnie wciąż nurtuje - skoro programowanie w Groovy daje tyle uproszczeń, to co stoi na przeszkodzie do jego powszechnego użycia? Wyłącznie nieznajomość? Nie, to da się załatwić w kilka dni (czy tygodni) a zysk może być niewspółmierny do kosztów wdrożenia zespołu do nowego języka, który nie różni się wiele od Javy. A może niechęć do nauki nowego?! Eee, to byłoby zbyt straszne, aby było powszechne w javowych zespołach projektowych - wręcz nieprawdopodobne. Na razie dumanie zostawiam na boku i wracam do relacji z lektury książki o Groovy & Grails.

Muszę coś wymyśleć, aby relacje z lektury były bardziej skumulowane, bo czytam znacznie szybciej niż relacjonuję i pojawił się niewielki "backlog". Najlepiej odstawiłbym relacjonowanie i zabrałbym się za coś bardziej praktycznego, ale myślę sobie, że powolne dawkowanie czegoś nowego niejednego z pewnością uzależni i tym samym będzie więcej zainteresowanych rozpoznawaniem tematu. A o to chodzi! Więcej głów w dyskusji, to więcej za i przeciw stosowaniu go. Gdybym tak wszystko wyłożył przy pierwszym razie pewnie niejednego już bym stracił, a tak...może niekoniecznie. Z drugiej strony, chciałoby się przeczytać książkę i zabrać za projekty, ale wtedy rozbieżność między mną a czytelnikami mogłaby być zbyt wielka i też kilku stracę. Jeśli nie pojawią się propozycje, pozostaję przy w miarę codziennym relacjonowaniu kolejnych rozdziałów książki. A może ktoś pokusiłby się na jej przetłumaczenie na polski? To byłoby jeszcze jedno ułatwienie w promowaniu Groovy & Grails.

Kolejny rozdział 3. "More Advanced Groovy" to przegląd cech języka Groovy, które sprawiają, że codzienne bolączki programisty stają się mniej bolące (jeśli w ogóle można rozważać je w kategorii bólu). Rozpoczyna się od prezentacji zalet wykorzystania Groovy do testów jednostkowych. Skoro istnieje opór do wprowadzenia Groovy jako obowiązującego języka w projekcie, to może wykorzystać go do odświeżonego tworzenia testów? Pisanie testów jednostkowych nigdy nie było zbyt popularne, więc wprowadzenie Groovy mogłoby wprowadzić pewną świeżość, a tym samym zwiększyć zainteresowanie ich pisaniem. Groovy zawiera w sobie JUnit i udostępnia klasę groovy.util.GroovyTestCase, która dziedziczy z junit.framework.TestCase i dodaje własne metody assert - assertArrayEquals, assertContains, assertEquals, assertInspect, assertLength, assertScript oraz assertToString. W zasadzie, poza assertInspect oraz assertScript, można domyśleć się, do czego one służą, zgodnie z nazwą. Metoda assertInspect to sprawdzenie wyniku metody inspect() (nic mi to jednak jeszcze nie mówi), a assertScript weryfikuje bezwyjątkowe wykonanie skryptu. Pamiętamy, że groovy.util jest automatycznie importowane w skryptach Groovy, więc pozostaje jedynie rozszerzyć GroovyTestCase i pisać testy. Testy są bezparametrowymi metodami o nazwie test<DalszaNazwaMetodyTestującej> zwracającymi void. Dodatkowe uproszczenie, to brak konieczności deklarowania wyjątków w sygnaturze metody, gdyż Groovy automatycznie zamienia wszystkie wyjątki na niesprawdzane (ang. unchecked exceptions). Autorzy proponują pisanie testów jednostkowych jako sposób na dalsze rozpoznawanie języka Groovy. Uruchomienie testów to po prostu uruchomienie klasy/skryptu, która je zawiera za pomocą interpretera groovy. Na zakończenie sekcji o testach jednostkowych, autorzy zauważają, że skoro testy w Groovy to tak na prawdę testy junitowe, można je włączyć do wykonania w aktualnym zestawie testów projektowych uruchamianych przy pomocy Apache Ant czy Apache Maven.

Zadanie: Rozpoznać uruchomienie testów jednostkowych w Groovy z użyciem Apache Maven.

Kolejnym tematem rozdziału 3. jest obsługa plików XML. Groovy udostępnia klasy do tworzenia plików XML w różnej postaci, np. DOMBuilder, MarkupBuilder, NodeBuilder, ale w tej rodzinie można znaleźć również AntBuilder do budowania i wykonywania skryptów antowych oraz SwingBuilder do tworzenia UI (a może IU - interfejs użytkownika?). Istnieje również klasa XmlSlurper, której działaniem jest GPathResult, który wraz z konstrukcjami ala XPath pozwala na dostęp do różnych obszarów pliku XML (w książce można znaleźć przykłady, które ilustrują temat, więc zainteresowanych zapraszam do samodzielnej lektury). Groovy dostarcza klas do tworzenia szablonów - SimpleTemplateEngine (najczęściej stosowany), GStringTemplateEngine oraz XmlTemplateEngine. Wraz z innymi konstrukcjami w Groovy tworzenie systemów opartych o szablony może być znacznie odchudzone, w porównaniu z ich odpowiednikami w "czystej" Javie.

Następny temat to expandos, czyli klasa groovy.util.Expando, która może być dynamicznie rozbudowywana o nowe atrybuty czy domknięcia w trakcie działania. Jeśli dodamy do tego, "Groovy duck typing", czyli automatyczne rozpoznawanie przez Groovy typu obiektu na podstawie jego własności (atrybutów i metod) możemy sobie wyobrazić, jak łatwo jest dynamicznie zmienić obiekt jednego typu na inny. Wystarczy więc stworzyć egzemplarz Expando z new Expando i po prostu przypisywać wartości polom, jakby były one dostępne oraz definiować metody w postaci domknięć w podobny sposób, aby z niczego zrobić coś. I wszystko dynamicznie! Jeśli dodam, że tworzenie Expando możliwe jest z konstruktorami ze zdefiniowanymi atrybutami i ich wartościami, to robi się niezwykle ciekawie, np.
 def jacek = new Expando([ imie: 'Jacek', nazwisko: 'Laskowski' ])
Na zakończenie rozdziału przedstawione są Meta Object Protocol (MOP) oraz Domain-Specific Languages (DSL). DSL jest sposobem na wprowadzenie języka dziedzinowego, łatwiejszego do czytania przez osoby nieprogramujące, a mogące dostarczyć dużo więcej informacji o oprogramowywanym świecie niż sam programista. Zauważono, że jeśli programy czyta się częściej niż je tworzy, to DSL może znacząco podnieść jego czytelność korzystając z konstrukcji używanych w danej dziedzinie niż języku programowania (niech sobie nie myślą jednak studenci studiów informatycznych, że ominie ich "niezwykle interesujący" egzamin z Semantyki Języków Programowania ;-)). Prostota tworzenia DSLi w Groovy wynika z mechanizmu MOP, który pozwala na zmianę zachowania dowolnych klas (nawet finalnych!). Brrr, powiało grozą - najpierw .@ jako sposób na ominięcie metody odczytu, teraz MOP - zaczynam martwić się o swoje nawyki obiektowe. Działanie MOP opiera się na właściwości metaClass typu groovy.lang.MetaClass, która jest dostępna w każdej klasie, włączając w to klasy javowe (podobnie jak właściwość class we wszystkich klasach javowych). Podczas obsługi komunikatu do obiektu (brzmi jak na zajęciach ze Smalltalka), tj. dostępem do pola, atrybutu, czy metody, Groovy odpytuje MetaClass o dalsze kroki. Wystarczy więc dodać atrybut bądź metodę do metaClass (podobnie jak to miało miejsce przy Expando) i voila - możemy korzystać z nowej funkcjonalności, jak gdyby była ona dostępna od pierwszych dni tej klasy. Niezwykle użyteczna i jednocześnie groźna broń w rękach niewprawionego programisty Groovy. Można wprowadzić niezłe zamieszanie bawiąc się metaClass. Na zakończenie wspomina się jeszcze o pewnym obiekcie delegate, który jest referencją do obiektu, na którym wykonano daną metodę/domknięcie, np.
 String.metaClass.wyslijSmsaNaBlogRoku2008 = {
// tutaj delegate to egzemplarz typu String o wartości "jacek"
}

"jacek".wyslijSmsaNaBlogRoku2008()
I to by było na tyle z relacji lektury rozdziału 3. "More Advanced Groovy". Jak niejednokrotnie wspomniano w książce, więcej informacji można znaleźć na stronach dokumentacji projektu Groovy, bądź też zakupić książkę Koenig et al "Groovy in Action". Żądni wrażeń mają możliwość przestudiowania kodu źródłowego GroovyBlogs.org.

p.s. Zgłosiłem blog do konkursu Blog Roku 2008. Obecnie znajduje się na 36. miejscu i pnie się stopniowo w górę. Dziękuję za wysłane SMSy! Zainteresowani wyrażeniem swojej (dez)aprobaty postępującym schyłkiem tematyki bloga na języki dynamiczne reprezentowanymi przez tak (nie)lubianego Groovy są proszeni o natychmiastowe wysłanie SMSa o treści B00204 (czytaj: be-zero-zero-dwa-zero-cztery) pod numer 7144 za 1,22PLN brutto. Wdzięczność autora gwarantowana!

[*] groz(n)iej brzmi - GROovy + Z(n)Iarna EJB + rzmi - tak mi jakoś przyszło do głowy ;-)