Stronnice Chlebika – Newbie Java Blog

czerwiec 8, 2009

HowToJava, ostateczny szlif

Zaszufladkowany do: Grails, Groovy, HowToJava — chlebik @ 10:58 pm

Po dłuższym okresie walki z językiem Groovy i Grailsami uznałem, że przyszedł czas by zakończyć prace nad aplikacją HowToJava. Ostateczny kształt nie poraża może możliwościami, ale podczas prac dowiedziałem się tylu nowych rzeczy, że to co powstało w pełni mi wystarcza (pewnie nie raz sypnie wyjątkiem na serwerze :).

Rzecz głównie w zupełnie odmiennej filozofii pracy z kodem (w odróżnieniu choby od używanego na co dzień PHP). Domyślam się, że to sprawka samego języka, ale też i frameworka, który upraszcza wszystko niemożebnie, co momentami jednakże prowadzi do wkurzających wręcz sytuacji, z którymi musiałem sobie poradzić. Z perspektywy czasu nie uważam poznania tej dziedziny programowania w Javie za stracony! Jak radził na początku Jacek Laskowski poznanie Grailsów daje możliwość zapoznania się z świetnie działającym konglomeratem kilkunastu uznanych powszechnie technologii/frameworków/abstrakcji, a ostatecznie przy bliższym poznaniu składowych – docenienie Grailsów w pełni.

Zakładam, że jednakże minie jeszcze trochę czasu, zanim będę mógł kompetentnie się w tej dziedzinie wypowiadać. Na razie kontynuuję przygotowania do certyfikacji SCJP. W końcu czerwca udaję się na tygodniowy urlop, zakładam zatem, że do tego czasu z całą pewnością do egzaminu nie będę podchodził. Ale lipiec to jak najbardziej realny termin. Z braku wykształcenia kierunkowego muszę nadrabiać zdawaniem certyfikatów, cóż począć :)

Zastanawiam się także nad rozpoczęciem prac nad nowym projektem (no bo ile można katować czystą Javę :) – teraz tylko pytanie o technologię. Czy wyjść z poziomu niewiele niższego niż Grails? Może zatem czysty Hibernate i Spring? A może trochę nowoczesności – GWT lub Seam (ten ostatni ma fajną dokumentację)? Ciągną też rozwiązania niskopoziomiowe – JSP, JSF, Struts. Każdy wybór ma swoje wady i zalety. Powiedzmy sobie szczerze – nikt raczej nie zatrudnia młodzika na juniora by od razu po przyjściu kodował olbrzymie systemy w Springu. Zaś do konserwacji przedpotopowego kodu pisanego w JSP już jak najbardziej tak. Ankieta u Jacka również jest ciekawa i daje wiele do myślenia. No nic, dam sobie kilka dni do przemyśleń.

PS. HowToJava można też obejrzeć pod łatwiejszym adresem http://chlebik.pl

kwiecień 28, 2009

TDD na przykładzie Grails – klasy domenowe i kontrolery

Zaszufladkowany do: Grails, Groovy, HowToJava — Tagi:, , , , — chlebik @ 3:57 pm

Zaczynam się sypać. Poważnie. Znów mnie coś w kręgosłupie strzyka, nic fajnego, siedzenie jeszcze jakoś mi wychodzi, ale chodzenie to już o wiele gorzej. Choć jedyna rzecz pozytywna z tego wynika – porządki na dysku i kolejny wpis na blogu.

W poprzednim wpisie przedstawiłem specyfikę TDD na przykładzie ograniczeń dla klas domenowych. Przed rozpoczęciem dalszej zabawy przytoczę dodatkowe asercje, które oferuje nam klasa GroovyTestCase, która jest używana zarówno do testów jednostkowych jak i integracyjnych w Grails (oczywiście skopiowane z dokumentacji).

  • assertArrayEquals(Object[] expected, Object[] value)
  • assertLength(int length, char[] array)
  • assertLength(int length, int[] array)
  • assertLength(int length, Object[] array)
  • assertContains(char expected, char[] array)
  • assertContains(int expected, int[] array)
  • assertToString(Object value, String expected)
  • assertInspect(Object value, String expected)
  • assertScript(final String script) // assert that a script runs without exceptions
  • shouldFail(Closure code) // assert that an exception was thrown in that closure
  • shouldFail(Class clazz, Closure code) // the same but for a class

Trochę ułatwiają życie, bez konieczności pisania własnych asercji na szybko. Przetestowaliśmy już ograniczenia dla kasy domenowej, teraz zajmijmy się jej metodami. Założenie, że wypadałoby testować takie metody jak save() czy metody wyszukujące jest trochę kontrowersyjne. Z jednej strony dobrze byłoby testować także i je, ale z drugiej strony to tak, jakbyśmy wątpili w umiejętności programistyczne twórców frameworka. Dlatego też nie jest to zalecana praktyka. Skupimy się zatem na przetestowaniu dopisanej przez programistę metody – a najprostszą metodą tego typu będzie oczywiście toString().

Nasz HtjTopic będzie oczywiście służył do ładnego wylistowania jego zawartości na stronie w formie tabeli, czy ładnej listy, ale zaprezentowana metoda toString() ma tylko charakter podglądowy (dodałem własności pominięte w poprzednim wpisie).

String toString() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd")
"${question} zadane: " + formatter.format(adddate) + " przez ${author.nick}"
}

Test napisany dla tej metody wygląda tak:

void testToString() {
DateFormat df = DateFormat.getDateInstance()
String adddateString = "2009-04-28"
Date adddate = df.parse(adddateString)
def topic = new HtjTopic( question: "Czy potrzebuję komputera?", author: new Htj_Users( nick: "Chlebik" ), adddate: adddate )
assertEquals "Czy potrzebuję komputera? zadane: 2009-04-28 przez Chlebik", topic.toString()
}

I tyle. Zasadniczo wywołanie metod napisanych przez nas samych w klasie domenowej jest podręcznikowym wręcz przykładem testu jednostkowego. Nie trzeba nawet odwoływać się do innych metod, dziedziczenia, etc. Sprawa jest zatem dość prosta i nie trzeba więcej komentarza.

Zajmijmy się teraz kontrolerami. Tutaj sprawa jest o wiele trudniejsza, gdyż kontroler (no chyba, że służy tylko jako ‘zaplecze’ dla wyświetlenia widoku) może zwracać często różne wyniki w zależności od przekazanych parametrów, rodzaju odebranego żądania i tak dalej. To kontrolery z definicji są najbardziej pokomplikowanymi elementami aplikacji zgodnej z wzorcem MVC. Mimo to da się je oczywiście testować, co zresztą zaraz zrobimy.

Testowanie kontrolerów to już nie są testy jednostkowe, choć typologia w tej dziedzinie jest momentami kulawa. Grailsy domyślnie przy tworzeniu klas domenowych tworzą klasę w katalogu z testami jednostkowymi, zaś przy tworzeniu kontrolerów odpowiedni test zostaje stworzony w ktalogu z tzw. testami integracyjnymi. Jak można się domyślić, testy integracyjne służą przetestowaniu relacji i przepływu w danym artefakcie (tutaj akurat kontrolerze). Nie odchodząc za bardzo znów do tworzenia kodu do testów, spróbujmy odnieść się do kodu klasy UsersController, który powstał przy okazji pisania kodu autoryzującego.

Grailsy (jak podaje dokumentacja) domyślnie wrappują tego typu testy (integracyjne) w obiekty Spring Mock Library, co pozwala na odwoływanie się do fałszywych obiektów żądania czy odpowiedzi (sesji też). Dzięki temu możemy stworzyć dla każdego testu warunki identyczne z tymi, w których najczęściej dana akcja będzie pracowała (i z tymi skrajnymi też, testowanie warunków brzegowych to istotna część procesu testowania). By nie przedłużać i komplikować napiszemy szybki test dla akcji login. Sprawdza ona czy użytkownik jest zalogowany, jeśli nie jest to wyświetla formularz, albo dobiera się do tablicy POST. Jednakże kiedy użytkownik nie jest zalogowany (session.user jest puste), wówczas redirectuje na stronę główną oraz wyświetla komunikat o tym, iż użytkownik jest już zalogowany. Oto jak wygląda test:

void testLogin() {
def c = new UsersController()
c.session.user = "jakisobiekt"
c.login()
assertEquals "/", c.response.redirectedUrl
}

I oczywiście test przechodzi nasz kod poprawnie. Należy zwrócić uwagę na ciekawą metodę redirectedUrl, która umozliwia zbadanie docelowego adresu, pod który zostanie skierowane nasze żądanie. Więcej tego typu metod można znaleźć w dokumentacji Spring Mock.

Oczywiście takie same założenia co do testowania odnoszą się do usług, czy command objectów. Testować można również własne znaczniki GSP. Zasadniczo testować można wszystko do czego zresztą gorąco zachęcam.

TDD na przykładzie Grails – klasy domenowe i ich reguły

Zaszufladkowany do: Grails, Groovy, HowToJava — Tagi:, , , — chlebik @ 12:22 am

Nie tak dawno temu zawędrowałem na spotkanie WJUGa, na którym poruszono temat DDD (Domain Driven Development). Okazało się, że Grailsy są pięknym przykładem tego podejścia w praktyce. Jednakże na razie skupimy się na tym, co do tej pory omijałem w moich postach dotyczących frameworka – testach. Pisałem o nich wcześniej w kontekście JUnit, teraz zobaczmy jak zostało to zrobione w Grails.

Framework rozróżnia dwa typy testów – testy jednostkowe oraz testy integracyjne. Póki co zajmiemy się tymi pierwszymi. Zacznijmy od klas domenowych, gdyż to na ich przykładzie najlepiej pokazać jak powinien przebiegać proces budowania aplikacji w oparciu o testy. Jako podstawa posłuży nam kolejna funkcjonalność w aplikacji HowToJava – zadawanie pytań. Stworzymy zatem dwie klasy dziedzinowe – jedna będzie reprezentowała założony temat (wątek pytania, tak samo działający jak post na forum), a także konkretny wpis w ramach tego pytania/tematu.

Tworzymy zatem klasę dziedzinową HtjTopic. Wykonanie polecenia:

grails create domain-class

Powoduje utworzenie nie tylko klasy domenowej, ale także stosownych dla niej testów. Utworzona klasa testowa wygląda tak:

import grails.test.*

class HtjTopicTests extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
}

protected void tearDown() {
super.tearDown()
}

void testSomething() {

}
}

Mamy jak widać metodę wykonywaną na rozpoczęciu testu, a także jedną wywoływaną na koniec. Oczywiście w środku mamy też metodę będącą sednem testu. Przed jego wykonaniem zastanówmy się jednakże czego potrzebujemy w naszej klasie domenowej. Z całą pewnością takie pytanie zadane w serwisie musi mieć autora, tytuł z całą pewnością również by się przydał, data dodania myślę też by się przydała. Ostatecznie po szybkim procesie myślowym powstała taka oto lista:

  • tytuł będący łańcuchem o określonej długości
  • data utworzenia wpisu
  • autor (będzie to zalogowany użytkownik)

Dodamy też później kategorię, do której przynależy nasze pytanie, jednakże by nie komplikować kodu póki co, pozostaniemy przy naszej wersji. Generalna zasada TDD głosi, aby nie pisać nowego kodu, jeżeli testy nie kończą się sukcesem. Na razie nie mamy ani testów, ani kodu, zatem problem jest czysto akademicki. Zasadniczo jedyną rzeczą, którą można przetestować w wyraźny sposób póki co są ograniczenia i to, czy nasza klasa ich przestrzega. Stworzymy sobie obiekt imitujący zachowanie prawdziwego obiektu (tzw. mock) i na nim będziemy testować. Można by zastanowić się po co testować ograniczenia wpisywane do klasy, które mają na celu właśnie kontrolę i testowanie, czy poprawne wartości zostały wpisane? Autorzy frameworka odpowiadają na to pytanie prosto – bo tak :), ale też by uniknąć literówek, które (rzekomo) są plagą w tym przypadku. Grailsy z definicji ułatwiają życie i w związku z czym oferują gotowy szkielet do testowania. Nasza metoda testująca powinna wyglądać na razie tak:

void testConstraints() {
def existingTopic = new HtjTopic()
mockForConstraintsTests(HtjTopic, [ existingTopic ])

// Testujemy constraint notNull
def topic = new HtjTopic()
assertFalse topic.validate()
assertEquals "nullable", topic.errors["question"]

// Testujemy constraint blank
topic = new HtjTopic( question: "" )
assertFalse topic.validate()
assertEquals "blank", topic.errors["question"]

// Testujemy constraint minSize
topic = new HtjTopic( question: "test")
assertFalse topic.validate()
assertEquals "size", topic.errors["question"]

// Testujemy constraint maxSize
topic = new HtjTopic( question: "test test test")
assertFalse topic.validate()
assertEquals "size", topic.errors["question"]

// Na koniec dla pewnosci, ze poprawne dane powoduja przejscie testow
topic = new HtjTopic( question: "Jak pisać" )
assertTrue topic.validate()
}

Jej zrozumienie nie powinno nastręczać problemów. Dziwić mogą tylko dwie pierwsze linijki. Wywołanie metody mockForConstraintsTests w takim kształcie ‘uzbraja’ egzemplarze klasy domenowej w metodę validate(), co pozwala na sprawdzenie poprawności constraints (Uwaga: skróciłem długość tematu by ładniej to wyglądało w kodzie na blogu. Normalnie oczywiście powinien być dłuższy). Testy (uruchamiane w NetBeans kombinacją klawiszy Alt-F6) pokażą po pierwszym wywołaniu błędy bo i pewnie nie ma jeszcze klasy, której to obiekty chcemy utworzyć. Oto kod klasy HtjTopic:

class HtjTopic {

String question

static constraints = {
question( blank: false, size: 5..10, nullable: false )
}
}

To oczywiście na razie tyle, aby łatwiej było pokazać ideę testów. Wyniki testów możemy ładnie sobie obejrzeć w przeglądarce (katalog /tests w folderze projektu) – każdy błąd lub niepowodzenie testu zostanie odnotowane. Filozofia pisania testów jest taka, aby nie napychać jednej metody chamską wręcz ilością linii kodu. Należy to rozbić, np. ograniczając metody do konkretych pól, albo też do walidacji metodami poszczególnych ograniczneń (np. tylko wartości NULL).

Dodam jeszcze tylko, że testowanie odbywa się w spejcalnym środowisku testowym, które posiada oddzielny wpis konfiguracyjny w pliku DataSource.groovy. Oto jak powinna wyglądać konfiguracja, aby opierała się na HSQLu.

test {
dataSource {
pooled = true
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
dbCreate = "create-drop"
url = "jdbc:hsqldb:mem:testDb"
}
}

To tyle na dziś. W następnym wpisie zajmiemy się dodatkowymi metodami klas dziedzinowych oraz zerkniemy na inne artefakty, które można podpiąć pod testy.

marzec 22, 2009

Koniec z linkami, czyli kontroler i widok pod kontrolą

Zaszufladkowany do: Grails, Groovy, HowToJava — chlebik @ 11:45 pm

Dziś ostateczne podsumowanie prac nad linkami w “How to Java”. Rzecz malutka, prosta, ale dająca dość obszerny obraz możliwości Grailsów. Na zakończenie szybki rzut oka na kontroler i troszeczkę większy na widok z użyciem GSP.

Jak pisałem w pierwszych postach o “How to Java” – statyczną zawartość umieszczę w jednym kontrolerze – StaticController, dodając ładne mapowanie adresów. Przyszedł czas by spełnić te obietnice. Oto kod kontrolera:


class StaticController {def defaultAction = 'linki'def linki = {[ linki: Htj_Links.list( sort: 'category') ]

}

def strona = { }

}

Jak widać definiujemy dwie akcje – strona oraz linki. Ta druga akcja będzie typowo statyczna – po prostu zostanie zaserwowany statyczny plik GSP. Sama definicja nie jest w tym przypadku konieczna – do tego jednakże wątku powrócę za chwilkę. Zastanowić się wypada co się stanie, kiedy w aplikacji odwołamy się do samego kontrolera, bez podania akcji. Standardowe mapowanie adresów w Grailsach nie wymaga podania akcji, konwencja przejmie tutaj sterowanie:

  • jeżeli w kontrolerze znajduje się tylko jedna akcja, wówczas domyślnie staje się ona podstawową akcją wywoływaną przy podaniu tylko nazwy kontrolera.
  • jeśli z kolei w kontrolerze mamy kilka akcji, domyślnie podstawową staje się ta o nazwie index
  • ostatecznie można tę akcję określić jawnie poprzez taki oto kod:
    def defaultAction = 'nazwaAkcji'

Zatem w kontrolerze dopisałem pro forma taką linijkę, choć docelowo kontroler Static nie będzie widoczny w aplikacji – jego użycie zostanie zakryte przez mapowanie. Teraz może kilka słów o akcji strona. Ma ona służyć wyświetleniu statycznego dokumentu HTML, w którym napisane byłoby kilka słów o stronce “How to Java”. Tak jak napisałem – jeżeli chodzi o wyrenderowanie widoku, bez konieczności jakichkolwiek działań w kontrolerze można ten przypadek obsłużyć inaczej. Należy dobrać się do pliku UrlMappings.groovy i dopisać tam następującą regułę:

"/strona" (view: "strona", controller: "static" )

I od dzisiaj przy wpisaniu po adresie: “/strona” nasze żądanie po prostu wyrenderuje wskazany widok, bez konieczności deklarowania akcji w kontrolerze. Możemy zatem na spokojnie usunąć linijkę z kontrolera.

Na sam koniec zostawiłem linki, gdyż tutaj sprawa jest poważniejsza. O przygodach z klasami domenowymi, które służą do obsługi tychże linków pisałem w poprzednich postach. Teraz zaś weźmiemy się za temat na poważnie:

[ linki: Htj_Links.list( sort: 'category') ]

Linijka ta robi tak wiele. Innymi słowy – wywołuje statycznie metodę list, która listuje wszystkie rekordy z tabeli. Do tego dorzucamy sortowanie po kategorii, a następnie to wszystko jest pakowane do widoku ( nawiasy kwadratowe na końcu akcji to po prostu zbiór zmiennych, które są przypisywane do widoku). Całkiem nieźle jak na krótką linijkę kodu.

Z kolei widok to w połowie otoczka związana z renderowaniem layoutu, zaś nas interesuje samo sedno:


<body><g:if test="${linki.size() > 0}" >
<ul>
<g:each in="${linki}" var="link"><g:if test="${link.category.category_name != poprzedniaKategoria}">
</ul>
<h2>${link.category.category_name}</h2>
<ul>
</g:if><li><a href="${link.address}">${link.title}</a> - ${link.description}</li>
<g:set scope="page" var="poprzedniaKategoria" value="${link.category.category_name}" />
</g:each>
</ul>
</g:if>

</body>

Po kolei. Na samym początku wykorzystujemy znacznik instrukcji warunkowej <g:if>, który sprawdza rozmiar przekazanego zbioru danych. Zasadniczo czynię to tylko po to, aby w razie pojawienia się pustego zbioru nie został wyrenderowany znacznik UL, który nie może być pusty jeśli chcemy pozostać w zgodzie z walidatorami HTML. Tworzymy listę, po czym przechodzimy po przekazanym nam zbiorze danych. I tutaj mała kwestia – kolejna instukcja IF. Rzecz w tym, iż w linkach są kategorie, głupotą zatem byłoby wrzucać wszystkie linki bez składu i rozkładu. Stąd instrukcja warunkowa, która sprawdza, czy poprzednia kategoria linku (zapisywana za pomocą znacznika <g:set>) była inna od obecnej. Jeśli była inna, wówczas zamykamy sobie listę, wyświetlamy nagłówek i tworzymy nową listę. Może i rozwiązanie to nie poraża geniuszem, ale swoją funkcję pełni wyśmienicie. W rezultacie po wprowadzeniu tego kodu (do bazy dodałem trochę danych przez PMA) u mnie przeglądarka wyświetliła coś takiego:

listalinkow

Piękne prawda? I to wszystko osiągnąłem dzięki relatywnie bardzo małej ilości kodu. Jedyne co może denerwować to brak porządku w nazwach linków w konkretnej kategorii – segregowanie językowe powinno na górę wypchnąć linki do Grailsów, zaś do mojego bloga na końcu. Dodamy zatem jeszcze jeden warunek do kontrolera:

[ linki: Htj_Links.list( [sort: 'category', sort: 'title' ]) ]

i możemy cieszyć się z ładniutkiej listy linków. Czysto, schludnie i bezpiecznie. Na dziś to tyle – w następnych wpisach zajmiemy się czymś bardziej dynamicznym – rejestracją użytkowników oraz ich autoryzacją.

marzec 19, 2009

Groovy in action, czyli to co tygrysy lubią najbardziej

Zaszufladkowany do: Groovy, Java — Tagi:, , , — chlebik @ 12:54 am

Zdałem sobie sprawę, iż powoli w swoich postach wychodzę poza klasy dziedzinowe/domenowe i z pola związanego z GORM wypada przejść do bardziej ‘programistycznych’ rzeczy, czyli do kontrolerów i widoków. I co z tego?

Ano to z tego, iż w tych elementach MVC przyda się kilka słów wyjaśnienia dotyczących języka Groovy. Prostota Grailsów umożliwia rozpoczęcie z nimi pracy bez lepszej znajomości języka Groovy. Jednakże jest to taka sama sytuacja jak w przypadku RoRa – pewnym momencie nieznajomość języka bazowego doprowadza do zatrzymania w rozwoju, ba, wręcz konieczności cofnięcia się w nauce. Dlatego też uprzedzając ten stan rzeczy dziś artykuł dotyczący kilku charakterystycznych dla Groovy’ego konstrukcji i rozwiązań.

Na pierwszy ogień idąc domknięcia (ang. closures). Jak piszą w mądrych książkach – “Domknięcia nie są trudne, są inne.” Myślę, że jest to najlepszy możliwy ich opis. Mówiąc zaś w skrócie – domknięcia są to obiekty, które zachowują się jak metody. Mogą przyjmować parametry, mogą zwracać wartość. Takie pomieszanie z poplątaniem, ale dzięki temu jest to konstrukcja kosmicznie wręcz skalowalna i efektowna (o efektywności pewnie kiedyś napiszę). Drugą definicją może być proste stwierdzenie, iż domknięcie to zwykły obiekt, który jest związany z pewnym fragmentem kodu. Jest to może mniej inticyjne, ale mam nadzieję, że przykłady pokażą o co chodzi.

Domknięcia można tworzyć tak:
- “w przelocie”
suma = 0
(1..10).each{ cyferka -> suma += cyferka }

- “z przypisaniem do zmiennej” (do tej pory używane przeze mnie w przykładach)
suma = 0
def domkniecie = { cyferka -> suma += cyferka }

Rozebrać należy ten temat na czyniki pierwsze. Otóż naturalnym odruchem dla programisty Groovy’ego powinno być myślenie – “nawiasy klamrowe, o, domknięcie”!!! Niezależnie od użytej formy ich tworzenia, zawsze jest to domknięcie. Konstrukcja ze strzałką przypomina PHP, ale jej znaczenie i istota jest daleka od odwoływania się do obiektu w PHP. Pewnie zresztą już jest jasne o co chodzi – wszystko, co jest po lewej stronie strzałki to parametry, które są przekazywane do domknięcia (jako parametry metody). To zaś, co znajduje się po prawej stronie strzałki to najzwyklejsze ciało metody. W przypadku domknięć do których przekazujemy tylko jeden parametr, nie wymaga on deklaracji, zaś w kodzie można odwoływać się do niego za pomocą domyślnej zmiennej it, np:

def domkniecie = { println it }
domkniecie("Tutaj chlebik");

Istnieje też trzecia możliwość stworzenia domknięcia. Wystarczy, że dysponujemy metodą w klasie, np:

class Rysowanko {

public void narysujCos( String tekst ) {
System.out.println( tekst );

}
}

To by potraktować tę metodę jako domknięcie wystarczy taka konstrukcja:

Rysowanko egzemplarzDoRysowania = new Rysowanko();
def rysujaceDomkniecie = egzemplarzDoRysowania.&narysujCos;
rysujaceDomkniecie( "Tutaj chlebik po raz drugi!" );

Czyli tworzymy domknięcie w formie pewnego typu wskaźnika do metody. Do czego to się może przydać? Ano na przykład mamy klasę taką jak powyższa, w której znajduje się kilka przeciążonych metod ( parametry to string, jakieś numerki, może jeszcze inne obiekty z własnymi metodami toString). Deklarujemy domknięcie dla tej przeciążonej metody i… i w zależności od przekazanych do domknięcia parametrów wywołuje ono konkretną metodę. Miłe, fajne i przyjemne. Zainteresowanych tematem odsyłam do dokumentacji Groovy, gdzie można sobie na ten temat poczytać więcej.

Innym dość ciekawym elementem języka są operatory specjalne. Znacząco potrafią ułatwić życie programiście, zwłaszcza w kontekście kontrolerów i widoków. Oto one:

  • spread operator ( *. ) – oznacza w skróconym zapisie, iż należy daną metodę/domknięcie wykonać na wszystkich elementach zbioru na rzecz którego została ona wywołana. Ufff, zamotałem. Oto kod:
    def lista = ["Chlebik ", "to ", "kiepski ", "programista."]
    print( lista*.toString() )

    Wyświetli on zgodnie z oczekiwaniami wszystkie elementy listy w formie ciągu wyrazów oddzielonych spacjami
  • Elvis operator ( ?: ) – bardzo przyjemna rzecz, która pozwala nadać zmiennej domyślną wartość na wypadek, gdyby przez przypadek z przypisania wyszły nici (zwrócona wartość to null lub jest po prostu pusta). Kod:
    tekst = jestemObiektem.wyciagnijMojaNazwe()?:"nie wiadomo"
  • Null-safe deference ( ?. ) – pamiętacie te wszytkie konstrukcje IF NOT NULL (lub coś w tym guście)? W Groovy istnieje operator, który wyręcza nas w tej brzydkiej czynności. Oto kod:
    println( zmiennaMogacaBycNullem?.jakiesJejPoleLubMetoda )"
    Jeżeli potencjalny obiekt, którego metodę chcielibyśmy wywołać okaże się być NULL to po prostu nic nie nastąpi. Tyle.

Na sam koniec zostawiłem tzw. Expando. Kolejna rzecz z ‘dynamicznej’ części Groovy, która jednakże może budzić pewne obawy. Zwrócił na to uwagę Jacek Laskowski w swojej prezentacji na WJUGu. Ale do rzeczy. Expando to po prostu obiekt, który zachowuje się w sposób, który określamy ‘na bieżąco’, bez konieczności tworzenia oddzielnej klasy lub pliku. Wkleję może przykład z książki:

def user = new Expando()

user.firstName = 'Christopher'
user.lastName = 'Judd'

user.greeting = { greeting ->
"${greeting} ${firstName} ${lastName}"
}

assert user.greeting("Hello") == 'Hello Christopher Judd'

Jak widać do takiego Expando możemy przypisać pewne wartości, zaś zachowanie (metody) deklarujemy poprzez domknięcia. Świetna sprawa, zwłaszcza by nie zaśmiecać kodu klasami wewnętrznymi.

To tyle jeśli chodzi o ten ciekawy język. Oczywiście rzecz jasna poruszyłem raptem trzy zagadnienia, jednakże uczyniłem tak tylko z powodu wyjaśnienia kilku rzeczy, które na 100% pojawią się w kolejnych wpisach, a wiedza o nich jest konieczna. Zainteresowanych poznaniem Groovy od podszewki zapraszam na oficjalne strony projektu. Można też zaopatrzyć się w literaturę poświęconą zagadnieniu, albo też skorzystać z masy linków, które prowadzą do miejsc związanych z Groovy.

Blog na WordPress.com.