środa, 4 kwietnia 2012

33 degree 2012 dzień 3


Dzień 1
Dzień 2
Warsztat z Wujkiem Bobem

Na początku 3ciego dnia konferencji miałem wielki dylemat na co pójść. Stwierdziłem, że z kolejnej prezentacji Venkat’a dużo nie wyniosę, a Jacka Laskowskiego pewnie jeszcze uda mi się zobaczyć w tym roku podczas innej konferencji. Ostatecznie poszedłem więc na prezentację Andreas'a Krogh'a pod tytułem: Lift from a JEE perspective. O tym framework’u słyszałem wiele dobrego (jest odporny na większość popularnych ataków) i spodziewałem się usłyszeć jak to widzi ktoś, kto go używał a siedział wcześniej w JEE (po prostu tytuł na to wskazywał).

Niestety była to moja najbardziej stracona godzina podczas całej konferencji. Prezentacja była kiepsko przygotowana (dużo tekstu, slajdy które były pomijane, XML’e z konkretną konfiguracją większości bibliotek użytych w projekcie prezentera), ale jeszcze gorzej było z samym prowadzącym, który mówił cicho monotonnie i chciało się tylko spać.

Co do treści prezentacji, to prelegent wymieniał początkowo co mu się w Javie nie podobało. Było o problemach w refaktoryzają (nie pamiętam w którym miejscu), z niedziałającymi testami GUI (przy zmianach w GUI wszystko im się sypało), z internacjonalizacją (m.in. chciano mieć w rzucanych wyjątkach komunikaty w języku natywnym prelegenta). Andreas narzekał, że nie ma w JPA standardu obsługi dla Lazy associations i że trzeba dużo kodu wygenerować na potrzeby DAO. Ponadto JSF jest pewnym standardem, ale mało kto go do końca rozumie, a alternatywne rozwiązania też mają sporo wad.

Później były przedstawiane już wcześniej wspomniane konfiguracje XMLowe i masa dziwnych rozwiązań (np. klasa JpaTextField która z JPA nie miała nic wspólnego). Generalnie prelegent brał udział w projekcie gdzie było jedno wielkie wymieszanie Javy i Scali z dodatkiem dziwnych pomysłów. Na koniec było krótkie demo i można było jedyne tam zobaczyć działanie push’a / pull'a oferowanego przez Comet. Dziękujemy temu panu, więcej nie zamierzam iść na jego prezentację.

Następnie byłem na wystapieniu Ken'a Sipe'a o MongoDB, czyli na temat bazy dokumentowej. Baza ta zawiera, dokładniej rzecz ujmując, kolekcje, które zawierają dokumenty. Prelegent pokazywał tworzenie nowej bazy i póki coś w niej nie wyląduje, to nie jest ona zapisywana na dysku.

Z MongoDB mamy możliwość zobaczenia planu wykonania zapytania. Możemy zakładać indeksy na właściwościach rozróżniających typy składowanych dokumentów i przez to poprawić wydajność. Ogółem chcąc coś wydajnie przechowywać w tej bazie, należy najpierw zrobić denormalizację.

Baza ta nie ma transakcji, przez co można bardzo łatwo ją skalować na wiele maszyn. Czyli zgodnie z CAP Theorem, tracimy na jednym, za zyskujemy na innym miejscu.

Następnie było wystąpienie Roberta C. Martina znanego bardziej jako Wujek Bob. Prezentacja była na temat 3 praw TDD. Początkowo wykład zaczął się od omówienia zasady działania lasera. Później było już powtórzenie tego co wujek pisze w swoich książkach. Było o zielonej opasce - symbolu, którego nie może zdjąć gdyż ma obsesję na temat testów i uważa siebie za profesjonalistę. Profesjonalista to ktoś taki, kto bierze na siebie odpowiedzialność za wykonywaną pracę, a managerowie potrzebują profesjonalistów w swoich zespołach.

Później było o krzywej Produktywności vs. Czas, o bagnie (w kodzie) i historia o redesign’ie systemu, czyli rozpoczęciu projektu od nowa, aby uzyskać lepszy design. Jednak zazwyczaj w takim przypadku stary zespól dalej rozwija poprzedni projekt, a ten nowy nigdy nie może dogonić starego. Sytuacja taka może trwać nawet 10 lat. Rozwiązaniem na to jest zasada skałtów, czyli poprzez niewielkie zmiany w kodzie, możemy pozbyć się tego całego bagna.

Dalej było o tym, że TDD zmusza nas do decoupling'u. Powinniśmy ufać swoim testom, analogicznie jak przy skokach spadochronowych, gdzie samemu musimy sobie odpowiednio spakować spadochron. TDD to gra z samym sobą – piszemy niedziałający test, który po chwili działa – i tak w kółko.

Co do tytułowych 3 praw TDD to nie było to: Red, Green, Refactor, a cos takiego:
  • Write no production code unless you have a failing unit test.
  • Do not write more of a unit test than is sufficient to fail. (And not compiling is failing.)
  • Do not write more production code than is sufficient to pass.

Później było trochę pytań od publiczności, m.in. jak wprowadzać zmiany w projekcie. Bob mówił, aby zacząć od siebie i wtedy inni zobaczą, że jest to fajne i również będą tak postępować. A jak nie to iść za radą Martina Fowlera: "Change your organization or change your organization".

Co do testów akceptacyjnych to należy zrobić wszystko, aby były one szybkie. Przede wszystkim jak jeden test sprawdza logowanie, a drugi składanie zamówienia, to ten drugi powinien się obejść bez logowania. Oznacza to, że trzeba czasem podmienić pewne zachowanie system i przez to testy powinny śmigać szybciej.

Następnie była prezentacja Code Craft prowadzona w przedziwnym stylu. Mianowicie Nathaniel Schutta miał 267 slajdów na godzinne wystąpienie, co daje ponad 4 slajdy na minutę. Fakt faktem, na slajdach były pojedyncze hasła, ale były one bardzo zgrane z prelegentem.

Prelegent wymienił kilka ciekawych narzędzi, których nie znałem, jak crap4jCrucible (do robienia review kodu), Clover (do prezentowania statystyk buildów – wykresów, pokrycia, można dużo konfigurować), Jester (do testów mutacyjnych, ciekawe jak on ma się do PIT’a) i Simian (detektor kodu pisanego metodą Copiego-Pastea).

Co do prowadzania zmian w projekcie (np. wprowadzenie FindBug’a), to prelegent przedstawił ciekawe podejście jak to robić. Nie można włączyć od razu wszystkich możliwych dobrych reguł jakie są, bo to spowoduje wyświetlanie brzydkich wykresów jakości kodu i nikt z tym nic nie będzie robił, a kod będzie dalej gnił. Trzeba na początek włączyć tylko kilka reguł, poprawić kod i sukcesywnie dołączać dalsze reguły.

Inną ciekawą rzeczą jest aktualizowane przez świeżaków Developrs handbooks, czyli dokumentów tłumaczących jak skonfigurować środowisko, jakie są standardy w projekcie itd.

Kolejnym ciekawym pomysłem, jest nagrywanie filmików, ze spotkań na których są podejmowane ważne decyzje projektowe. Jak się po jakimś czasie okazuje, że została podjęta jakaś zła decyzja w projekcie, to można zawsze wrócić do nagrania i przypomnieć sobie dlaczego tak to się stało a nie inaczej.

Następnie był wykład Jurgen Appelo pt. How to Change the World. Prelegent jest autorem książki Management 3.0 i podczas prezentacji opowiadał, jak można przekonywać innych ludzi do czegoś. Bazował na kilku książkach m.in. Influencer, Leading Changes, Fearless Change. Jedna z ciekawych metod wpływania na innych współpracowników, jest przedstawianie nowych pomyslów, podczas wspólnego jedzenia. Pewnie to wynika z tego, że rozmówca może na wtedy poświęcić więcej uwagi, niż gdy siedzi przy biurku i właśnie go wyrwaliśmy z flow.

Był jeszcze przedstawiony wykres innowacyjności, The Feedback Door (czyli karteczki przylepiane na drzwiach, aby dawać feedback) i jeszcze parę abstrakcyjnych przykładów, jak wprowadzać zmiany. Generalnie książkę autora można ściągnąć z ze strony management30.com.

Na koniec 3ciego dnia został wykład Wujka Boba. Standardowo na początku było trochę o fizyce/biologii, że ludzie mają 3 receptory koloru, a składowe RGB również są trzy.

Tym razem wykład był prowadzony kompletnie bez użycia rzutnika (kto by się tego spodziewał w tych czasach). Jedynie prelegent miał małe karteczki z notatkami do pomocy (których i tak prawie nie używał).

Bob tłumaczył nam, jak pracują obecni inżynierowie. Owocem ich pracy jest zazwyczaj jakiś dokument, który później się przekazuje dalej i ktoś go realizuje. Przykładowo architekci tworzą plan budynku, wraz z tym jak ma być urządzone wnętrze. Przekazują dokument ekipie budowlanej i ta już działa. Elektronicy przykładowo projektują płytkę / układ scalony, przekazują do fabryki i ta wytwarza gotowy produkt.

A jak to jest w naszej profesji? Co jest tym dokumentem, który generujemy i który dajemy fabryce do realizacji produktu? Okazuje się, że jedynym słusznym dokumentem wytwarzanym przez inżynierów oprogramowania jest kod źródłowy. Nie stosy dokumentacji fachowej, technicznej, analitycznej i jeszcze nie wiadomo jakiej, a kod. Kod jest zawsze aktualny i prawdziwy. Kod prawdę Ci powie. Fabryką w tym przypadku jest kompilator, który generuje zbiór bitów, czyli działającą aplikację.

Zasadniczą różnicą, pomiędzy naszą a innymi działkami szeroko pojętej inżynierii, jest to, że w naszym przypadku koszt przekazania kodu kompilatorowi, czyli wygenerowania gotowego produktu, jest zerowy. Tak więc wprowadzanie zmian jest tańsze niż w innych dziedzinach inżynierii. Przykladowo, gdyby koszt powiększenia kuchni w wybudowanym już domu (ale nie kosztem innych pomieszczeń) wynosiłby 1000 dolarów, to nikt by jakoś szczególnie nie projektował domów, a jedynie iteracyjnie je rozbudowywał.

Było jeszcze o kryzysie oprogramowania w 1968 i o dokumencie opisującym czym jest model kaskadowy. Podobno jest on na tyle fascynujący, ze każdy powinien go przeczytać.

Dalej była już znana opowiastka, że nasze obecne komputery (jeśli liczyć razem prędkość procesorów, dysków, pamięci i ich ilości) są ileś tam (10^26 jak dobrze pamiętam) razy szybsze od tych z lat 60tych. A dalej programiści piszą te same instrukcje if, for, while...

Pod koniec wykładu był jeszcze czas na pytania. Co do testowania bazy danych, to Wujek Bob ma ciekawe podejście. On generalnie uważa, że nie powinno się jej testować, albo testować w niewielkim stopniu. Generalnie na bazę danych powinno się patrzyć jak na pewną abstrakcję, gdzie są zachowywane dane. Nie powinno nas interesować jak są one składowane, a jedynie powinniśmy, na potrzeby testów, podmieniać klasy dające nam dostęp do tych danych. I tak dla przykładu: w FitNesse, który jest pisany prze Wujka Boba, bazą danych jest płaski plik.

Analogicznie powinniśmy postępować z testowaniem timeout’ów. Jest to też pewne „wejście” do systemu i powinniśmy podmienić je tak, aby testy szybciej chodziły.

I to by było na tyle jeśli chodzi o konferencję. Na koniec były podziękowania od Grześka Dudy i dla Grześka Dudy - organizatora. Ja również dziękuję, bo konferencja była super zorganizowana. Było ponad 630 uczestników, a jakiś wpadek (którym mógłby zapobiec organizator) nie było. Tablica, na której można było przyklejać karteczki, co idzie dobrze a co źle, bardzo mi się spodobała. No i fajnie były przerwy dobrane, tzn. czasem krótkie (aby zmienić tylko sale), a czasem dłuższe (aby pogadać na korytarzu).

Zostało mi jeszcze do opisania, jak wyglądał warsztat z Wujkiem Bobem w którym brałem udział. Ale to w kolejnym wpie.

Na stronie konferencji znajdziecie jeszcze relacje innych osób z 33 Degree 2012.

33 degree 2012 dzień 2

Dzień 1
Dzień 3
Warsztat z Wujkiem Bobem

Pierwszą prezentacją drugiego dnia 33 degree 2012 na którą się wybrałem, było wystąpienie Joonas'a Lehtinen'a na temat Vaadin’a. Jest to framework do tworzenia Interfejsu użytkownika dla „bogatych” aplikacji. Rozpowszechniany jest on na zasadach Apache License. Vaadin bazuje na GWT, jednak nie ma w nim RPC, serwisów dla UI, a kod renderowania widoku znajduje się po stronie serwera. Po stronie serwera przechowywany jest również stan interfejsu użytkownika, co powoduje brak trybu offline.

Po krótkim wprowadzeniu teoretycznym przyszedł czas na kodowanie na żywo. Do stworzenia projektu wymagany jest jedynie web.xml i jeden JAR. Prelegent pokazywał jak stworzyć prostą przeglądarkę / edytor stron HTML. Podobało mi się rozwiązanie Lazy Loadingu, np. gdy w rozwijanej liście, przewijając suwakiem w dół, ściągały się na życzenie potrzebne elementy. Na pewno generuje to sporo requestów do serwera, ale funkcjonalność ta mi się spodobała.

Kolejna rzecz która mi przypadła do gustu to spor ilość kontrolek, które mogą być od razu powiązane z różnymi źródłami danych. Gdy modyfikujemy jednocześnie te same źródła danych w jednym komponencie, to zmiany te są od razu widoczne w innych / różnych komponentach, które mają podpięte to samo źródło zasilania danych.

Co do dalszych zalet Vaadina, to jest fajny edytor Drag&Drop do Eclipsa / IDEI. Framework działa również na urządzeniach mobilnych i mamy od razu zdefiniowane kilka tematów kolorystycznych do wszystkich komponentów. Można pisać własne nowe komponenty (trzeba trochę grzebać w GWT) i mamy stronę skupiająca te komponenty. Można je ściągać i bezproblemowo integrować z edytorem.

Aplikacje Vaadinowe można podobno pisać w dowolnym języku działającym na JVM. Wspiera on IE6, nie trzeba instalować żadnych dodatków do przeglądarki, a samą aplikację można umieścić na dowolnym serwerze wspierającym Servlety. Na stronie framework’a jest dostępna darmowa książka do nauki, jak i tabela porównująca konkurencyjne rozwiązania. Prowadzący polecał przy okazji REFcardz DZone do nauki nowych technologii.

Co do prezentacji to była ona bardzo fajnie prowadzona, były przykłady, kodowanie, animacje pomiędzy slajdami, ale nie za dużo – dobrane z odpowiednim wyczuciem. Po prostu dobrze przygotowana prezentacja.

Następnie poszedłem na wykład Vogel’a na temat nowych funkcjonalności w Androidzie 4.0. Słychać było mocno niemiecki akcent prelegenta. Na prezentacji było trochę przykładów i kodu. Ogółem dobra prezentacja.

W nowym Androidzie dodano m.in. nową kompozycję kolorów, GridLayout, możliwość zmieniani rozmiarów widget’ów, obsługę Drag&Drop. Doszło jeszcze TextureView, Calendar API, ViewPager (do przesuwania (slidowania) ekranów), Fragments (dzięki czemu ułożenie telefonu zmienia layout) i Properties for Animation API. Jeszcze by się trochę poznajdywało, więcej na prezentacji Vogel'a.

Ciekawym rozwiązaniem jest biblioteka napisana na starsze wersje Androida, emulująca nowe gadżety. Ciekawie jak z jej używaniem.

Następnie wybrałem się ponownie na wykład Venkat’a. Tłumy szalały, miejsca pod ścianami i w drzwiach były obsadzone. Ty razem najlepszy prelegent konferencji opowiadał o programowaniu wielowątkowym. Było sporo kodowania na żywo i w dodatku jemu to wychodziło! Świadczy to o wysokim profesjonalizmie Venkat’a.

Zapamiętałem bardzo fajny trik, który może oszczędzić nam na prezentacji ewentualnych wpadek podczas kodowania na żywo. Mianowicie można tuż przez prezentacją naklepać dokładnie to do czego mamy dojść, a następnie stopniowo usuwać napisane linijki w odwrotnej kolejności, w jakiej chcemy je przedstawić. A na samej prezentacji wystarczy już wciskać kombinację Ctrl + Z i kod będzie się przyrostowo pojawiał przed oczami.

Prezentację zaczęliśmy od standardowego książkowego przykładu z klasą Account, na której można wykonać operacje deposit() i withdraw(), czyli przelać kasę z jednego konta [bankowego] na drugie. Czyli mamy prostą logikę: jeżeli na koncie jest wystarczająco kasy, to ją pobieramy i deponujemy kwotę na innym koncie. Wiadomo nikt nie chce aby znikły mu pieniądze z konta, więc trzeba dobrze to oprogramować. No i zaczęło się.

Prelegent implementował na żywo sugestie proponowane przez publiczność. Jak po chwili dotarliśmy do synchronizacji dwóch obiektów, to się okazywało, że przez to może powstać dead lock. Później rozwiązanie zaczęło ewoluować do monitora, aby ostatecznie prelegent ujawnił preferowane eleganckie rozwiązanie. Mianowicie można dodać do naszego projektu bibliotekę z Clojure’a i już możemy się cieszyć ładnymi transakcjami. Jeśli będziemy chcieli wykonać jakąś „wrażliwą” operację poza transakcją, to biblioteka rzuci nam odpowiednim wyjątkiem i trzeba będzie poprawić kod.

Rozwiązanie bardzo eleganckie i trzeba koniecznie przyjrzeć mu się z bliska. Prelegent twierdził jeszcze, że Clojure jest jedynym bezpiecznym językiem programowania dla JVM’a. Mi ta prezentacja uświadomiła, że obecnie w czasach serwerów aplikacyjnych i super framework’ów mało kiedy piszemy coś na wątkach. A wiedza ucieka. Ja z tego powodu zajrzałem do książki Core Java 2 Techniki zaawansowane (Rozdział Wielowątkowość -> Synchronizacja), aby przypomnieć sobie jak to się powinno robić w czystej Javie.

Następnie, po przerwie obiadowej udałem się na prezentację Sławomira Sobótki na temat technik w inżynierii oprogramowania. Początkowo zaczęło się od charakterystycznych terminów, które można poczytać na blogu prelegenta: 8tysiecznik, osobliwość, boska klasa, ofiary muszą być. Ale na szczęście nie było o tym :)

Sławek przedstawił kilka technik, których stosowanie ma sens w większych projektach. Część z nich w jakiś tam sposób łączy się z DDD (o którym Sławek prowadził później warsztaty), ale można je również stosować po za światem DDD. I tak baza danych nie jest modelem. Model to coś co można pokazać (np. model samochodu, domu), a nie właściwości zapisywane na temat danego modelu. Baza danych może być jedynie strukturą danych, która służy do modelowania.

Kolejną pomocną techniką, o której często zapominamy, to zastosowanie Value Object’ów. Czyli tworzymy sobie abstrakcję, przykładowo klasę Money, aby nie przekazywać wszędzie double (wiadomo dlaczego, było to na 3ch prelekcjach wałkowane). Value Object pełni w tym momencie rolę Adaptera pomiędzy typem technicznym, a domenowym.

Kolejną techniką jest stosowanie Agregatów, aby opakowywać anemiczne encje. Można dodatkowo tworzyć transformacje tego samego obiektu domenowego, zależnie w jakim kontekście jest on używany. Przykładowo pracownik magazynu i pani księgowa inaczej patrzą na ten sam byt, jakim jest faktura. Interesują ich inne dane z tej faktury, jak i mogą wykonywać odmienne operacje na niej.

Następnie było o zasadzie OCP w praktyce. Czyli powinniśmy tworzyć polityki w odpowiednich miejscach, w których mogą później przyjść zmiany. Dzięki temu nasz kod będzie łatwiej rozszerzalny, jak kiedyś przyjdzie konieczność innego sposobu wyliczania podatku, rabatu, czy wypłaty. Dobry kod powinien dać nam w tedy możliwość napisania nowej klasy, implementującej zdefiniowany interfejs, w celu spełnienia wymagania. Zyskujemy również dzięki temu na testowaniu i czytelności kodu (zamiast dopisywać kolejne if’y).

Było jeszcze m.in. zalecenie, aby umieszczać cały zły coupling w fabrykach – smutnych miejscach systemu, czyli w „czarnych dziurach”. Było jeszcze o zastosowaniu wzorców Wizytator i Kompozyt.

Podsumowując wystąpienie Sławka, stosując się do zaproponowanych prze niego technik można uzyskać logikę aplikacji z dużą liczbą zależności, ale za to z prostymi metodami. Więcej można poczytać na blogu Sławka.

Następnie chciałem iść na prezentację Jarosława Pałki, aby posłuchać o architekturze. Niestety wykład został odwołany a w jego miejsce wskoczyło cos innego. Ciężko również było się dostać inne wykłady (z powodu tłoku), więc sobie zrobiłem przerwę.

Następnie znów poszedłem na prezentację Venkat’a, tym razem na temat Scali. Prelegent pokazywał jak w Scali łatwiejsze jest używanie XML’a (nie trzeba jak w Javie całości zamykać cudzysłowami). Język ten jest zorientowany na używanie finalnych obiektów. Można kodować w stylu imperatywnym jak i funkcjonalnym. Można bez przeszkód mieszać te style.

Dalej było o różnicach pomiędzy var a val i że jest to lepsze niż final w Javie. Również nie trzeba na każdym miejscu pisać co jakim typem jest, jedynie tam gdzie jest to niezbędne. Słowo return jest opcjonalne, podobnie jak i średnik. Scala daje nam za darmo konstruktor gettery i settery. Mnie ucieszył fakt, ze nie ma metod statycznych (na pewno poprawia to testowalność kodu). Mamy za to coś takiego jak  wbudowany wzorzec Singeleton w język (object). Również w Scali mamy strategię (za pomocą słwa kluczowego trait).

Na koniec dnia poszedłem jeszcze na sesję BoF m.in. Jakuba Nabrdalika na temat porażek. Cieszę się, że prelegenci nie bali się mówić o swoich niepowodzeniach. Przykładowo u nich w projekcie okazało się, że samoorganizujące się teamy nie działały najlepiej. Potrzebna była osoba decyzyjna, bo demokracja nie zawsze jest najlepsza. Było jeszcze trochę o innych porażkach. Dobrze czasem posłuchać, że nie tylko nam się coś nie udaje.

33 degree 2012 dzień 1

Dzień 2
Dzień 3
Warsztat z Wujkiem Bobem

Konferencja 33 Degree 2012 zaczęła się od szybkiego 10minutowego przywitania o godzinie 9:10 przez organizatora Grześka Dudę. Potem było chwilę o platynowym sponsorze Luxoftcie i o 9:25 zaczęła się pierwsza prezentacja Raffi’ego Krikorian’a z Twittera. Opowiadał on o powodach migracji z Ruby on Rails do JVM’a.

Twitter posiada 100 Milionów użytkowników, którzy tworzą 250 Milionów twittów na dzień, co daje prawie 3000 tweetów na sekundę. Serwis ten cechuje ogromna liczba równoległych połączeń, wiele operacji I/O i nie wielka liczba obiektów trwałych. Twitter potrzebował więc wydajnego języka, do obsługi takiego obciążenia.

Początkowo serwis ten był pisany w Rubym. Sam język nie jest zły, pisze się w nim przyjemnie, szybko, jest bardzo ekspresywny. Słabym punktem są w nim garbage collector i wielowątkowość. Nie wiem jak działa zrównoleglanie w Ruby’im, ale według Raffiego nie dawało to rady, nawet na 60 rdzeniach.

Postanowiono wiec zmigrować kluczowe części systemu na wirtualna maszynę Javy. Początkowo wybór padł na Scalę. Jest ona funkcyjna, ekspresyjna, elastyczna, statycznie typowana i z dobrą współbieżnością. No i do tego jest piękna. Po za Scalą Twitter jeszcze używa Clojure’a. Było jeszcze coś wspomniane o bibliotece Finagle powstałej w Twitterze, ale nie pamiętam w jakim kontekście.

Ogółem prelegent fajnie gadał, chwilowo mikrofon nie dawał rady. Mi trochę brakowało więcej konkretów, jakie rozwiązania zostały zastosowane i co się gdzie sprawdziło. Z chęcią również bym zobaczył model bazodanowy. Było jedynie wspomniane, że dzieli się on na 4 części (Timeline storage, twitts, social graph i user storage).

Następny był wykład Ken’a Sipe pod tytułem Complexity of Complexity. Zdania na temat tego wykładu są podzielone, jednym się podobał, ale mi nie do końca. Generalnie głównym przesłaniem wykładu było to, że nie ma jednego rozwiązania dobrego do wszystkiego i należy poszukiwać najlepszej drogi.

Jak dla mnie to Ken za bardzo skakał po różnych tematach. Było o modelu dreyfus’a, CAP Theorem i jeszcze paru sprawach. Prelegent wspominał, że SOAP nie zawsze jest dobrym rozwiązaniem, gdy w danej infrastrukturze występują spore zależności pomiędzy komunikującymi się systemami. SOAP ładnie to na schemacie przedstawia, ludziom biznesu się to podoba, ale de facto te zależności dalej pozostają.

Był przykład z liczeniem: 2.0 – 1.1 (o tym więcej za chwilę), o adnotacji @Immutable z Groovi’ego i książce: Hackers & Painters. Oraz że eBay nie stosuje rozproszonych transakcji.

Podsumowując, to najważniejszy jest dobry zespół, język (z odpowiednim poziomem abstrakcji) i design aplikacji. Co do stosowanych języków, to powinny one być wygodne, łatwe, znane i proste do nauczenia przez świeże osoby w projekcie.

Następne było wystąpienie Venkat’a Subramaniam’a. Już jakiś czas temu byłem nakręcony na jego wystąpienia, gdyż były mocno wychwalane przez innych polskich blogerów (niestety nie pamiętam gdzie to czytałem). I rzeczywiście sposób prowadzenia prezentacji jest pierwszorzędny, istny majstersztyk. Prelegent zaprosił jedną osobę na scenę i czasem prowadził z nią dialog. Pytał, jak się czuje jako programista, czy odczuwa przyjemność z tego co robi.

Venkat mówił o „Pointy haired bosses” i pragmatycznych programistach. Czyli o zderzeniu dwóch światów: bezmyślnych szefów i programistów. Zastanawiałem się o co chodzi z tym pierwszym terminem, ale wystarczy spojrzeć na pewną postać z komiksów Dilberta: Pointy-haired Boss i już jest wszystko jasne.

Venkat opowiadał dalej o pewnych uniwersalnych prawdach. Porównywał managerów, do rekinów, z którymi musimy walczyć (niczym Janek Lisewski ostatnimi czasy). Ponadto najważniejsi w projekcie są... ludzie. Nie metodyki, technologie, a ludzie. Projekt nie wygrywa ze względu na proces a na ludzi. Aby wygrać ludzie muszą mieć pasję, kompetencję i odpowiedzialność.

Dwoma słowami jakich nienawidzi Venkat to „Best Practice”, jeżeli są one wypowiadane bez kontekstu. Jeśli jest inaczej to trzeba uciekać.

Następnie prelegent prezentował zabawne filmiki, o tym jak ludzie mogą wpływać na innych. Tłumaczył wpływ praktyk (przykład z szerokością silników rakietowych) i że zawsze powinniśmy pytać dlaczego. A do szefa to zamiast mówić, że „mamy problem”, to należy mówić, że „mamy wyzwanie”.

Venkat odwoływał się również do książek: Dreaming in Code i do The Paradox of Choice: Why More Is Less.

Prelegent mówił również, że standaryzacja rozwiązań przed innowacją, to zła droga. Najpierw należy coś wynaleźć, znaleźć kilka następnych, możliwych, ponownych zastosowań, dopiero ustandaryzować i na koniec sprzedawać. Niestety sporo rzeczy w świecie Javy nie idzie tym torem, gdyż często do danej specyfikacji (która powstawała latami), dopiero jest dopisywana implementacja. Jako przykład framework’ów, które szły tą lepszą ścieżką Venkant podał Rails’y i Spring’a.

Następnie zostały wytłumaczone różnice w językach programowania na podstawie wykresu podobnego jak poniżej.



Następnie było trochę praktyki, czyli ponownie lekcja liczenia. Proponuję każdemu odpalić i sprawdzić co się stanie (jeśli jeszcze ktoś nie wie).
System.out.println(2.0 - 1.1);
System.out.println(new BigDecimal(2.0).subtract(new BigDecimal(1.1)));
System.out.println(new BigDecimal("2.0").subtract(new BigDecimal("1.1")));
Przykładowo w Groovy’m mamy to za darmo.

W kolejnym przykładzie Venkant przedstawił bardziej interesujący kod:
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.remove(0);
System.out.println(numbers.size());
Podczas prezentacji dałem się nabrać i dziwiłem się z wyświetlanego wyniku. Dopiero pisząc tego posta zrozumiałem co się dzieje.

To  że Java jako język jest silnie typowany i ze statyczną kontrolą typów sprawia, że musimy się dostosowywać do kompilatora, np. poprzez deklarowanie w sygnaturze metody Checked Exceptions. Podsumowaniem całego wykładu była sentencja: „A Professional who doesn't learn to fail, fails to learn”. Let’s be a champions.

Po wykładzie był obiad, bardzo smaczny. Nieporównywalny z innymi konferencjami w których brałem udział.

Następna prezentacja na którą się udałem była o Dart’cie a przedstawiał ją pracownik Google’a, a dokładniej z Chrome’a: Mike West. Dart to nowopowstający opensource’owy język do budowania web aplikacji, kompilowany do JavaScript’u. Jest to dopiero technology preview, więc nie ma jeszcze nawet wersji alfa tego wynalazku.

Najciekawszy jest sposób powstawania języka. Mianowicie tęgie głowy wymyślają, co by tutaj dodać do języka, a społeczność dyskutuje na grupie o danej funkcjonalności i od tego zależy, czy pojawi się w języku czy nie.

Przeznaczeniem języka mają być małe i średnie aplikacje, niezależne od platformy, szeroko dystrybuowane i bez instalacji. Dart bazuje na HTML’u 5 i modelu DOM, ma być wsparcie dla testów jednostkowych. Przy języku pracuje sporo ludzi od GWT i język ma być bardziej popularny od CoffeeScript’a.

Na prezentacji było trochę kodu, ale ja osobiście jakoś się nie przekonałem i coś nie czuję aby to wypaliło. Jednakże model powstawania języka jest bardzo ciekawy. Co do samej prezentacji, to troszkę dziwna akustyka była w sali a i prelegent jakoś mało ciekawie przedstawiał temat.

Następna prezentacja była bardzo ciekawa. Andrey Breslav pracownik JetBrains’a przedstawił język Kotlin  (nazwa dokładnie taka jak polskie miasto i firma produkująca keczup). Prelegent obecnie pracuje przy tym wynalazku. Jakiś czas temu widziałem informacje o tym języku, ale się nie przyglądałem bliżej.

Język jest statycznie typowany, ogólnego przeznaczenia, open source’owy i do zastosowań przemysłowych. Kompilowany jest on do bytekodu JVM’a lub do JavaScriptu, tyle że wówczas nie można używać wszystkich bibliotek.

Ciekawa jest motywacja firmy do tworzenia kolejnego języka. JetBrains tworzy aktualnie środowiska programistyczne (IDE) dla 7 języków. Wiodącym jest to dla Javy, ale Java rozwija się bardzo powoli w stosunku do IDEI. Jako że inne języki wspierają produkty tej firmy, to postanowiono wesprzeć samego siebie. I tak oto powstaje język eliminujący niedoskonałości Javy, mający od razu wsparcie IDE do tworzenia kodu. Ponadto można bezproblemowo mieszać kod Kotlina i Javy w projekcie i nawet debugować w jednym IDE. To sprawia, że integracja i ewentualna migracja może być bezbolesna. I jest również dostępne wsparcie dla podpowiadania składni, refaktoringu itd.

Kotlin nie jest research’owym projektem, ani nie jest pod specyficzną domenę, czy może raczej pod specyficzne zastosowanie. Zanim kolejna wersja języka wyjdzie, to jest ona używana na produkcji w JetBrains. Są już nawet jakieś zewnętrzne firmy, które wykorzystują ten język.

Co do samego języka: Nie ma słowa kluczowego new, argumenty przekazywane do konstruktora są od razu zapisywane jako pola klasy, są extension functions, przeciążanie operatorów matematycznych i nie tylko, wyjątki tylko unchecked, operacje bezpieczne na występowanie null’a, inne rzutowanie pozwalające pozbyć się javowego rzutowania i switch’a, Trait’y czyli interfejsy z domyślną implementacją, a adnotacjom można nadać coś jakby alias i później używać w kodzie, co eliminuje znak ‘@’. Mają być również zaimplementowane Run-time generics.

Z ciekawostek, to kod jest kompilowany do modułów, a nie do pojedynczych plików jak w Javie, przez co można lepszą optymalizację kodu wykonać. Kto chce to może się dołączyć do Community i trochę porozwijać język.

Prezentacja była bardzo ciekawie prowadzona. Były filmiki pokazujące jak kodować (opatrzone w razie potrzeby odpowiednim komentarzem prowadzącego). I jak całość działa. Był po raz drugi przykład a odejmowaniem (2.0 – 1.1) z którym Kotlin radzi sobie podobnie jak Groovy (czyli lepiej niż Java). Prezentacja bardzo mi się podobała i uważam, że język może być ciekawą alternatywą w niedalekiej przyszłości dla Javy. Nie wiem dokładniej jak się to ma do innych obecnie coraz popularniejszych języków jak Scala, Groovy, Ruby, ale przyjrzę się jemu bliżej niedługo. Na stronie JetBrains’a można sobie przeczytać porównanie do Javy lub Scali. Widać, że język sporo czerpie inspiracji ze Scali i Grooviego. Można się jeszcze „na żywo” pobawić językiem nie instalując żadnych aplikacji wchodząc na stronę kotlin-demo.

Następnie wybrałem się na prezentację o testach którą prowadził Wojciech Seliga. Opowiadał on o swoich 10 latach testowania przy tworzeniu oprogramowania JIRA. W początkowej części prezentacji było sporo danych statystycznych, wykresów itp. I tak projekt ma: około 500 zależności, 1.5 miliona LOC, 13 tysięcy testów jednostkowych, 1000 testów z Selenium, 4000 funkcjonalnych i integracyjnych, pokrycie kodu testami na poziomie 60-80% do ~92% dla krytycznych funkcjonalności…

Wszystko to jest kompilowane i odpalane na ponad 70 maszynach w chmurze Amazona. Jednak i tak trwa to bardzo długo, a poprawa testów jeszcze dłużej, przez co zaczął się pojawiać u nich w projekcie syndrom wybitego okna. Po pewnym czasie, aby developerom wróciło zaufanie do testów, zaczęto komentować (a z czasem usuwać gdy nie szło naprawić) te testy, które za długo były czerwone – ale nie profesjonalne zachowanie.

Co do ciekawych praktyk, to dowiedziałem się o Page Object Pattern co mocno ułatwia testowanie i jest niezależne od zmian w GUI. A jeżeli już chcemy testować po GUI, to lepiej skorzystać z JQuery Selectors niż z XPatch i/lub używać ID’ków zamiast CSS’a. Dobre jest również podzielenie kodu testowego na moduły, które znajdują się w miarę blisko kodu źródłowego. Pozwala to developerom odpalać testy dotyczące danego modułu, zamiast testów dla całego systemu. Przydatne również może być mockowanie zewnętrznych systemów.

I to by było tyle jeśli chodzi o tą prezentację. Ja spodziewałem się dowiedzieć czegoś więcej, tzn. oczekiwałem przykładów, dobrych rozwiązań, stosowanych wzorców, technik, ciekawych wniosków. Jak na kogoś kto ma dziesięcioletni kontakt z testami, to wypadło bardzo słabo.

Po wykładzie chciałem iść jeszcze na sesję BOF, ale skończyło się na tym, że zacząłem rozmawiać z ludźmi na korytarzu i dołączyłem do imprezy piwnej sponsorowanej przez ZeroTurnaround wydawcę JRebel’a Bardzo mi się spodobała taka forma integracji i możliwości nawiązania kontaktów.

Podsumowanie kolejnych dni w kolejnych wpisach.

piątek, 30 marca 2012

Nowa ksiazka o testowaniu jednostkowym


Dnia 28 marca 2012 pojawiła sie oficjalnie książka: Practical Unit Testing with TestNG and Mockito napisana przez Tomka Kaczanowskiego. Wspominałem w jednym z poprzednich wpisów (na temat testowania wyjatków), że ta książka nadchodzi. Już oficjalnie jest dostępna do kupienia na practicalunittesting.com do czego zachecam.

Dlaczego o tym pisze?

Powodów jest kilka.

Po pierwsze jest to książka polskiego autora (co prawda po angielsku, ale spolszczenie jest w przygotowaniu), a tych należy wspierać. Łatwiej (podobno) jest napisać książkę techniczną po angielsku i później ją przetłumaczyć na nasze, niż pisać po polsku i później się męczyć.

Po drugie jest to kompletny, uporządkowany i aktualny zbiór technik z przykładami, jak pisać dobre testy. Książka wyjaśnia wszelkie wątpliwości związane z nazewnictwem, konwencjami i dobrymi praktykami, jak i daje wiele cennych wskazówek.

Dla kogo jest ta książka?

Książka jest bardzo dobra dla osób, które chcą właśnie zacząć pisać testy jednostkowe do swojego kodu i nie wiedzą jak wystartować. Książka wprowadza krok po korku do lepszego świata kodu pokrytego testami. Również dla startych wyjadaczy znajdzie się sporo cennych informacji. Dalsze rozdziały książki omawiają zaawansowane zagadnienia ze świata testowania. Tomek wskazuje również dobre praktyki jak pisać testy, a także prezentuje narzędzia powiązane z nimi(jak catch-exception czy testy mutacyjne).

Dlaczego więc się wypowiadam o tej książce, skoro dopiero co się ukazała?

Dobra, dość tej krypto reklamy, czas na konkrety ;)

Powodem dla którego piszę na blogu o tej książce, jest fakt, że brałem udział w jej powstawaniu. Mianowicie robiłem korektę (review) książki, za co dostałem podziękowania uwiecznione na jednej ze stron w książce:
In various different ways a number of people have helped me with writing this book – some by giving feedback, others by comforting me in times of doubt.
Marcin Stachniuk was the first person to offer to review the book in the early stages of its being written, and at the same time the most persistent of my reviewers. He read every part of the book and gallantly overcame the obstacles I frequently put in his way: frequent releases, constant juggling of the contents, minor piecemeal adjustments, etc.
Nadszedł teraz czas podzielenia się moimi wrażeniami ze wspólnej pracy z autorem.

Wszystko zaczęło się na konferencji GeeCON 2011 w Krakowie, Podczas (za)ostatniego dnia konferencji (tzw. Community Day) Tomek miał swoją prezentację pt.: Who watches the watchmen? - on quality of tests. Na prezentacji trochę się wynudziłem, gdyż otarłem się już o większość omawianych tam zagadnień. Pod koniec jednak prelegent pochwalił się, że właśnie pisze książkę o testach. Wówczas jeden z uczestników (nazwisko do wiadomości redakcji) zaproponował, że chętnie by zrobił review jego książki. Bardzo zaciekawiła mnie ta inicjatywa, i mimo iż wszyscy już wychodzili z sali, zostałem chwilę dłużej, aby przysłuchać się rozmowie na temat recenzowania książki.

Tomek zaproponował aby chętni się do niego zgłosili mail’owo, aby ustalić szczegóły współpracy.  I tak to się zaczęło. Stwierdziliśmy, że najlepszą formą wymiany informacji będzie założona na Google prywatna grupa dyskusyjna, poprzez którą Tomek będzie podsyłać nowe wersje książki. Tym kanałem można również podyskutować i wyjaśnić ewentualne kwestie sporne. Rozwiązanie to sprawdziło się.

Preferowanym sposobem zgłaszania uwag, było odsyłanie aktualnego pdf’a ze wstawionymi komentarzami w teksie, w formie żółtych karteczek. Funkcjonalność taką daje nam Foxit Reader. Dzięki temu Tomek widział dokładnie, którego miejsca dotyczy uwaga. Było to również wygodne dla mnie, gdyż fragmenty czytałem na ekranie komputera. Niektórzy zgłaszali swoje uwagi w postaci wiadomości na grupie, ale dla mnie żółte karteczki i tak były lepsze, gdyż dokładniej wskazywały miejsce, gdzie jest coś nie tak.

Na podstawie e-maili naliczyłem jakieś 20 „release’ów” książki, tzn. fragmentów, które Tomek podsyłał do korekty. Początkowo przychodziły pojedyncze rozdziały do czytania, ale lepszym wyjściem, jak się później okazało, było podsyłanie całości. Dzięki temu nie było rozdziałów wyrwanych z kontekstu i było widać ogólnego zarys całości książki, w którą stronę ona dąży.

Koleje wersje pojawiały się z różną częstotliwością. Czasem było kilka w tygodniu, a czasem była cisza przez dłuższy czas. Ale to już była kwestia Tomka jak sobie organizuje pracę nad książką. Ze swojej strony mogę powiedzieć, że często nowe wersje się pojawiały, jak akurat mocno byłem zajęty innymi sprawami i niemiałem możliwości aby usiąść od razu do lektury. Kilka razy dogoniła mnie kolejna wersja i wtedy już trzeba było się zmobilizować i przeczytać to co tam Tomek naskrobał :)

Co do zgłaszanych uwag, to Tomek zazwyczaj je akceptował. Jak nie widziałem poprawy w następnej wersji, to początkowo się czepiałem, że moje sugestie są nieuwzględniane, ale w późniejszym czasie doszedłem do wniosku, że nie powinienem się tym przejmować. W końcu to książka Tomka i Jego koncepcja, a nie moja. Jedynie sprawy edytorsko/estetyczne (zła czcionka, rozjeżdżające się tabelki) były dla mnie bardzo irytujące, ale to chyba przez spędzenie dawniej sporej ilości czasu z LaTeX’em. Tomek postanowił zostawić to sobie na sam koniec, przez co ciągle widziałem te niedoskonałości. To była chyba jedyna pierdółka, która mi troszkę przeszkadzała w naszej współpracy.

Moje zaangażowanie zostało wynagrodzone cytowanymi wyżej podziękowaniami w książce (Dzięki Tomek!). Właściwie to nie nawet nie ustaliliśmy szczegółów współpracy, tzn. co ewentualnie będę z tego miał. Do samego końca nie wiedziałem nawet, czy pojawią się te podziękowania w książce (po cichu na nie liczyłem). W końcu w jednej z ostatnich wersji książki zobaczyłem, że są :) Świadczy to o tym, że moje zaangażowanie było kompletnie non-profit.

Podsumowując współpracę cieszę się, że wziąłem udział w tym przedsięwzięciu. Było to bardzo ciekawe doświadczenie i mogłem przez to poznać proces powstawania książki. Robienie review sprawia wielka frajdę, czego zwieńczeniem jest oczywiście ukazanie się książki „na produkcji”. Szczerze polecam każdemu zaangażowanie się w tego typu akcję.


Btw. Co do relacji z 33 degree (kilka osób już o nią pytało), to musi ona jeszcze poczekać kilka dni, z powodu natłoku innych zajęć (w tym korekty ostatecznej wersji książki Tomka), jak i obecnych sporych zmian życiowych.

sobota, 4 lutego 2012

Testowanie wyjątków

Testowanie wyjątków w testach jednostkowych od zawsze trochę mnie irytowało. Niby sprawa banalna, ale jak do tego dołączymy słynny szablon // given // when // then to nie bardzo wiadomo gdzie powinniśmy umieścić słówko // then, aby test był dalej przejrzysty.

Problem nie jest nowy. Zastanawiano się nad dobrym rozwiązaniem już podczas prezentacji Bartosza Bańkowskiego i Szczepana Fabera pt. Pokochaj swoje testy [czas - 18.04] na Wroc JUG, albo pewnie jeszcze wcześniej. Idąc za radą lepszych, zawsze korzystałem z try / catch’a, aby wiedzieć gdzie dokładnie spodziewam się wyjątku.

@Test
public void shouldThrowSomeException() throws Exception {
    // given
    SomeClass someClass = new SomeClass();

    try {
        // when
        someClass.doSomething();
        fail("This method should throw SomeException");
    } catch(SomeException e) {
        // then
        assertThat(e.getMessage()).isEqualTo("Some message");
    }

}


Blok instrukcji try / catch wymusza na nas pewien sposób formatowania kodu i przez to nie do końca widać gdzie jest // when i // then. Można oczywiście próbować umieszczać je w trochę innym miejscu, np. // when przed try, a // then przed fail().

@Test
public void shouldThrowSomeException() throws Exception {
    // given
    SomeClass someClass = new SomeClass();

    // when
    try {
        someClass.doSomething();
        // then
        fail("This method should throw SomeException");
    } catch(SomeException e) {
        assertThat(e.getMessage()).isEqualTo("Some message");
    }

}

Jednak rozwiązanie dalej jest nie do końca czytelne. Gdyby jeszcze nic nie umieszczać w bloku catch, to już w ogóle, trzeba się chwilę zastanowić, co my tu tak na prawdę chcemy przetestować. Całe szczęście narzędzia do statycznej analizy kodu dbają o to, aby nie zostawiać pustych bloków catch.

Alternatywnym rozwiązaniem dla testowania rzucanych wyjątków, jest stosowanie andotacji @Test z parametrem expected w JUnit’cie  :

@Test(expected = SomeException.class)
public void shouldThrowSomeException() throws Exception {
    // given
    SomeClass someClass = new SomeClass();

    // when
    someClass.doSomething();

    // then
    fail("This method should throw SomeException");
}

Test wygląda już lepiej, ale ma swoje wady. Jak mi jakiś test nie przechodzi, to pierwsze co robię, to czytam sekcję // then testu. W tym przypadku widzę wywołanie fail() co sugeruje mi, że test zawsze powinien nie przechodzić. Dopiero po chwili zauważam, że test został zadeklarowany jako @Test(expected = SomeException.class), czyli spodziewam się wyjątku typu SomeException. Jest tutaj jednak pewne niebezpieczeństwo. Jeżeli faza // given testu, czyli przygotowania środowiska testowego, będzie trochę dłuższa, to może się zdarzyć, że tam gdzieś poleci wyjątek. Test będzie dalej przechodził, a tak naprawdę nie będzie testowane to co chcieliśmy. Wspominał o tym już Szczepan Faber w cytowanym fragmencie video. Dodatkowo nie można, jeśli byśmy chcieli sprawdzić np. treść komunikatu wyjątku. Z tych względów nie stosowałem tej konstrukcji.

Sprawa wygląda trochę  lepiej w przypadku TestNG. Tutaj mamy analogiczna adnotację, mianowicie zamiast expected używamy expectedExceptions.

@Test(expectedExceptions = SomeException.class,
        expectedExceptionsMessageRegExp = "Some Message.*")
public void shouldThrowSomeException() throws Exception {
    // given
    SomeClass someClass = new SomeClass();

    // when
    someClass.doSomething();

    // then
    fail("This method should throw SomeException");
}

Tu jeszcze dochodzi fajna zabawka w postaci expectedExceptionsMessageRegExp, czyli możemy za pomocą wyrażeń regularnych sprawdzić, czy wyjątek posiada spodziewaną wiadomość. Dalej jednak istnieje ryzyko wyrzucenia tego wyjątku w sekcji // given.

Podobną zabawkę daje nam JUnit, ale w trochę innym wydaniu. Mianowicie od wersji 4.7 można zastosować ExpectedException:

public class SomeClassTest {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void shouldThrowSomeException() throws Exception {
        // given
        thrown.expect(SomeException.class);
        thrown.expectMessage("Some Message");
        SomeClass someClass = new SomeClass();

        // when
        someClass.doSomething();

        // then
        fail("This method should throw SomeException");
    }
}

Tutaj w klasie testowej musimy zdefiniować regułę (linie 3 i 4), która początkowo mówi, że nie spodziewamy się wyjątków. Natomiast już w naszych metodach testowych, redefiniujemy to zachowanie i mówimy, czego się spodziewamy w danym teście (linie 9 i 10). Możemy dzięki temu sprawdzić komunikat rzucanego wyjątku. Tutaj jednak podajemy fragment wiadomości, którą ma zawierać nasz wyjątek. Istnieje również przeciążona wersja tej metody, która jako argument przyjmuje Matcher’a Hamcrest’owego.

Do niedawna były to jedyne rozwiązania, jakie były dostępne w temacie testowania wyjątku. Jakiś czas temu jednak pojawiła się ciekawa biblioteka: catch-exception. Kod napisany za jej pomocą może wyglądać tak:

@Test
public void shouldThrowSomeException() throws Exception {
    // given
    SomeClass someClass = new SomeClass();

    // when
    caughtException(someClass).doSomething();

    // then
    assertThat(caughtException())
            .isInstanceOf(SomeException.class)
            .as("Some Message");

}


Czyli mamy metodę CatchException.catchException(), gdzie jako argument przekazujemy obiekt naszej klasy. Następnie wywołujemy metodę, którą chcemy przetestować. Na koniec w sekcji // then sprawdzamy czy otrzymaliśmy wyjątek, którego się spodziewaliśmy. Bezargumentowa wersja caughtException() zwraca wyjątek rzucony przez ostatnią klasę, którą przekazaliśmy do metody caughtException(). W naszym wypadku jest to ostatni wyjątek wygenerowany przez someClass.

I to rozwiązanie mi się podoba. W sekcji // when informuję, że będę łapał wyjątki, a w sekcji // then sprawdzam czy poleciał ten wyjątek, którego oczekiwałem. I do tego nie bruździ to przy formatowaniu kodu i użyciu // given // when // then. I mamy czytelny kod :)

Zafascynowany tą biblioteką postanowiłem zajrzeć do środka (kod jest dostępny na googlecode.com), aby zobaczyć jak zbudowano takie rozwiązanie.

public class CatchException {

    public static <T> T catchException(T obj) {
        return processException(obj, Exception.class, false);
    }

}

Czyli mamy delegację pracy do metody processException(), która zwraca obiekt tego samego typu, jaki został przekazany w argumencie. Dzięki temu możemy używać biblioteki w sposób jaki pokazałem powyżej. Zobaczmy co kryje się za tą metodą:

private static <T, E extends Exception> T processException(T obj,
        Class<E> exceptionClazz, boolean assertException) {

    if (obj == null) {
        throw new IllegalArgumentException("obj must not be null");
    }

    return new SubclassProxyFactory().<T> createProxy(obj.getClass(),
            new ExceptionProcessingInterceptor<E>(obj, exceptionClazz,
                    assertException));

}

Po upewnieniu się, że argument nie jest null’em tworzymy (jak można się domyśleć po nazwach) proxy dla naszej klasy. Brnąc dalej w las, jeżeli klasa nie jest ani prymitywem, ani finalna, to proxy tworzone jest  w ten sposób:

proxy = (T) ClassImposterizer.INSTANCE.imposterise(
        interceptor, targetClass);

czyli wykorzystywany jest ExceptionProcessingInterceptor z poprzedniegu listingu, wewnątrz którego znajduje się następująca metoda, gdzie już widać całą magię:

public Object intercept(Object obj, Method method, Object[] args,
        MethodProxy proxy) throws Throwable {

    beforeInvocation();

    try {
        Object retval = proxy.invoke(target, args);
        return afterInvocation(retval);
    } catch (Exception e) {
        return afterInvocationThrowsException(e, method);
    }

}

Metoda beforeInvocation() czyści ostatnio złapany wyjątek, np. z wywołania poprzedniej metody. Następnie w bloku try wywoływana jest nasza rzeczywista metoda (linia 5), a następie zwracana jest (w naszym sposobie wykorzystania biblioteki) wartość wygenerowana przez oryginalną metodę. Jak coś pójdzie nie tak, to w bloku catch jest zapamiętywany rzucony wyjątek (zajmuje się tym metoda afterInvocationThrowsException()). Bardzo sprytny sposób na łapanie wyjątków, a jaki banalny zarazem.

Z ciekawostek jeszcze, to biblioteka korzysta z Mockito, a dokładniej cglib. Nie działa ona z klasami finalnymi (gdyż dla nich nie można teoretycznie tworzyć proxy), no chyba że skorzystamy w PowerMock’a i odpowiednich adnotacji w deklaracji klasy testowej:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ SomeClass.class })
public class SomeClassFinalPowerTest {
    // ...
}


Wtedy zadziała :)



Na koniec wpisu, jeszcze informacja skąd się dowiedziałem o tej bibliotece. Mianowicie powstaje teraz ciekawa książka o testach: Practical Unit Testing with TestNG and Mockito. Pisana jest ona przez Tomka Kaczanowskiego i już niedługo ujrzy światło dzienne. Książka poszła już do recenzji do Szczepana Fabra, więc lipy nie będzie. Będzie można się z niej dowiedzieć m.in. o catch-exception, jak i o testach mutacyjnych, o których pisałem ostatnio. Na razie wyjdzie wersja angielska, ale będzie też robione tłumaczenie na nasz ojczysty język. Zachęcam więc do śledzenia informacji o książce jak i do jej zakupu.

Więcej informacji o tym jak powstawała książka w kolejnych wpisach.

niedziela, 8 stycznia 2012

Testowanie mutacyjne z PIT Mutation Testing

Przeglądając dzisiaj (a właściwie to wczoraj) blogosferę natrafiłem na ciekawy post Tomka Kaczanowskiego First Glance At PIT Mutation Testing Tool na temat testowania mutacyjnego, za pomocą nowej biblioteki PIT Mutation Testing. Co to jest testowanie mutacyjne to można poczytać na Wikipedii: Testowanie mutacyjne (co ciekawe w tej chwili dostępny jest tylko artykuł w wersji angielskiej i polskiej).

PIT modyfikuje w locie nasz kod produkcyjny, puszcza testy i sprawdza, czy mutacje kodu są wykrywane przez nasze testy. Sprawdzamy dzięki temu jakość naszego kodu testowego, a dokładniej to, jak ściśle zdefiniowaliśmy zachowanie naszego kodu produkcyjnego za pomocą testów. Jest to trochę więcej niż pokrycie kodu testami wyrażone w procentach, gdyż raport ten podpowiada nam co jeszcze należało by przetestować.

Tomek stworzył przykładowy projekt i umieścił na github’ie. Ściągnąłem go, odpaliłem i przeglądnąłem raporty wygenerowane przez PIT’a. Jako że jest to prosty projekt na potrzeby testu tej biblioteki, postanowiłem zastosować go do swojego projektu MFCCChart. Co prawda nowej funkcjonalności do tego projektu już nie dodaję, ale się nim zabawiam testując jakieś ciekawe rozwiązania.

Patrząc na to co może PIT na stronie Mutation testing systems for Java compared w końcowej sekcji: Summary Of Mutation Testing Systems, to narzędzie to nie ma bezpośrednio wsparcia dla Ant’a, ale mamy interfejs linii komend. Przygotowałem więc komendę, dostosowaną do moich potrzeb:

java -cp out\test\MFCCChart;out\production\MFCCChart;testlib\junit-4.8.jar;testlib\mockito-all-1.8.5.jar;testlib\pitest-0.24.jar;lib\forms_rt.jar;lib\jcommon-1.0.16.jar;lib\jfreechart-1.0.13.jar org.pitest.mutationtest.MutationCoverageReport --outputFormats XML,HTML --reportDir reportspitests --targetClasses org.bitbucket.mstachniuk.mfccchart.* --targetTests org.bitbucket.mstachniuk.mfccchart.* --sourceDirs src --verbose --excludedMethods hasCode,equals --excludedClasses org.bitbucket.mstachniuk.mfccchart.view.*,org.bitbucket.mstachniuk.mfccchart.presenter.*

Najpierw mamy definicję naszego classpath’a. W katalogu out\test\MFCCChart mój ant’owy skrypt budujący wrzuca skompilowane testowe klasy, a do: out\production\MFCCChart klasy produkcyjne aplikacji. Następnie dołączyłem wszystkie wymagane do uruchomienia aplikacji jak i testów biblioteki. Klasa org.pitest.mutationtest.MutationCoverageReport jest klasą startową projektu PIT, a dalej mamy już argumenty dla tejże aplikacji. Ja zapragnąłem raportu w dwóch formatach (XML i HTML) w katalogu reportspitests. Następnie zapodałem klasy, które mają być mutowane, testowe klasy, kody źródłowe (aby można było zobaczyć gdzie wprowadzano mutacje). Jako że jest to biblioteka, której jeszcze nie znam to warto spojrzeć na szczegóły działania (opcja --verbose)  i wyłączyłem z testowania metody hasCode() i equals(), a także klasy z pakietów, które są odpowiedzialne za GUI i spinanie całości (do kupy).

Początkowo miałem problem z opcjami --outputFormats i --excludedClasses, gdyż nie chciały mi działać. Zgłosiłem nawet błąd na stronie projektu: Issue 23, ale szybko się okazało, że podczas kopiowania flag ze strony z Command Line Quick Start Notepad++ zamias zwykłego myślnika wstawił znak wyglądający niemal tak samo, ale o innym kodzie (najprawdopodobniej z po za zestawu ASCII).

Jak już się przekonałem, że generacja raportów działa, postanowiłem dorzucić tą analizę do skryptu budującego aplikację. Początkowo próbowałem to wykonać za pomocą taska exec ale nie chciało hulać. Po za tym task ten jest zależny od systemu operacyjnego i zarzuciłem go na rzecz taska java. I teraz poszło lepiej:

<target name="pitests">
    <java jvmargs="-Xmx600m" fork="true"
            classpath="${mfccchart.testoutput.dir};${mfccchart.output.dir};${basedir}/lib/jcommon-1.0.16.jar;${basedir}/lib/jfreechart-1.0.13.jar;${basedir}/lib/forms_rt.jar;${basedir}/testlib/junit-4.8.jar;${basedir}/testlib/mockito-all-1.8.5.jar;${basedir}/testlib/pitest-0.24.jar"
            classname="org.pitest.mutationtest.MutationCoverageReport"
            args="--reportDir reportspitests --targetClasses org.bitbucket.mstachniuk.mfccchart.* --targetTests org.bitbucket.mstachniuk.mfccchart.* --sourceDirs src --verbose --excludedMethods hasCode,equals --excludedClasses org.bitbucket.mstachniuk.mfccchart.view.*,org.bitbucket.mstachniuk.mfccchart.presenter.* --outputFormats XML,HTML">
    </java>
</target>


Bez fork'a nie chciało mi działać (zresztą pewnie jak większość tego typu rozszerzeń wywoływanych z Ant'a) Co mogłem to pozamieniałem na ścieżki zdefiniowane w pozostałej części skryptu. Jeszcze podaję sporą ilość ścieżek do konkretnych bibliotek co mi się nie podoba. Podejrzewam, że jest lepszy sposób na to ale mistrzem Ant’a nie jestem. Jak by ktoś wiedział, to proszę o komentarz.

Teraz czas na analizę raportu: „Detected 84 of 93 mutations”. Czyli na 9 różnych mutacji podatny jest mój kod. Patrząc na pokrycie klasowy, to chyba bardzo dobrze to wypadło:

Mutated classesLine coverageMutation coverage
OneMfccFileStatistic100%85%
MfccFileReader 100%97%
FrameInformation 100% 100% 
ChartSettings 100% 100% 
MfccFrame 100% 100% 
StatisticTableModel 100% 80% 

Ja jestem zadowolony z wyniku. Jak ktoś chce to niech sobie przejrzy mój przykładowy raport: MFCCChart_pit_reports_201201080158.zip

Teraz pozostaje tylko rozkminienie czego ode mnie chce ten raport (czyli co jeszcze mogę poprawić w swoich testach), jak i przyjrzenie się konkurencyjnym rozwiązaniom, których zestawienie można obejrzeć na wspominanej już stronie: Mutation testing systems for Java compared.

poniedziałek, 12 grudnia 2011

Agile Development Day

W sobotę 10 grudnia odbył się w Warszawie Agile Development Day. Była to impreza zorganizowana przez firmy Sages i Pragmatis. Event polegał na wspólnym tworzeniu aplikacji, ćwiczeniu TDD, programowania w parach i innych zwinnych praktykach. Był do tego Continous Integration (build był uruchamiany co git push) i Continous Delivery (deployment co udany build).

Aby dostać się na warsztaty trzeba było się wcześniej zapisać. Z ponad 60 osób chętnych, wybrano 22 w tym mnie :) Została przygotowana startowa baza kodu i udostępniona na github’ie. Trzeba było więc wcześniej ściągnąć kod i przygotować środowisko. Technologicznie był Spring Core, Spring MVC, JSP, Casandra, Maven. Jako że nie miałem wcześniej możliwości korzystać ze Spring’a w warunkach bojowych (po za jakimiś szkoleniami / prezentacjami), to miałem z czym się bawić. Zaprzyjaźniłem się więc z książkami na ten temat i archetypami kodu, aby porozkminiać te technologie i aby było na czym bazować.

Event zaczął się o 8 rano w Millennium Plaza. Najpierw było przywitanie i omówienie zasad, co będziemy robić w ciągu dnia. Następnie było o aplikacji jaką mamy stworzyć. Mianowicie za pomocą pisanego serwisu internetowego można się chwalić czego się nauczyliśmy, ile czasu na to poświeciliśmy i ile punktów zebraliśmy. Taki jakby twitter, tyle że piszemy co poznaliśmy, jaki był stopień trudności, system nalicza jakieś tam punkty i chwalimy się tym przed znajomymi. Plus jeszcze jakieś pierdoły do tego.

Po omówieniu wymagań aplikacji było wprowadzenie do Casandry, gdyż była to najbardziej „dziwna” i nieznana technologia z używanego technology stack. Później było szybciutko o Spring MVC i zaczęło się. Uczestnicy mieli wybrać sobie couch’a i osobę do pary (najlepiej aby ktoś znał Springa MVC). Jako że znałem Piotra (jednego z prowadzących) to się z nim dogadałem i wraz z Marcinem usiedliśmy do pierwszego user story.

Wybraliśmy sobie na tapetę formatowanie czasu, ile zajęła nam nauka danej technologii. Napisaliśmy kilka testów i zaczęła się zabawa. Postanowiliśmy dodać do projektu bibliotekę JUnitParams do pisania sparametryzowanych testów w JUnit’cie. Swoją drogą jest to biblioteka napisana przez Pawła Lipińskiego, który organizował, prowadził i kodował na warsztatach. Pomogło nam to pisać ładniejsze, parametryzowane testy w JUnicie, podczas pierwszej iteracji.

Wcześniej ustalono, że iteracje będą trwały po półtorej godziny i pomiędzy nimi będą zmiany par, a co kilka iteracji będzie retrospekcja. Czyli jakby jeden dzień ze sprintu został skompresowany do 1,5h a cały Sprint do 5ciu dni (czyli pięciu iteracji). Taka organizacja pracy bardzo motywowała do jak najszybszego kończenia zadań. Nie inaczej było w naszej parze, gdyż chcieliśmy jak najszybciej zobaczyć choćby częściowy efekt naszej pracy na „live”, mimo że nie wszystkie przypadki mieliśmy obsłużone. No i tu zaczęła się prawdziwa walka z technologiami.

Gdy jeszcze wczoraj Piotrek w projekcie dodał Tiles’y zaczęła się cała aplikacja wysypywać. Doszedł on do wniosku, że Casandra z Tiles’ami nie funkcjonuje ;) i wycofał zmiany. W naszej historyjce chcieliśmy (wręcz musieliśmy) skorzystać z JSTL’owego Taga c:forEach, ale też nie chciało działać. Był ten sam błąd co w przypadku Tiles’ów. Nasza koncepcja zamknięcia wyświetlania czasu we własny Tag JSTL’owy również nie zadziałała i trzeba było to jakoś inaczej obmyślić. To wszystko pewnie przez Casandrę ;)

Akurat nadszedł koniec pierwszej iteracji i nastąpiła rotacja par. Jako, ze pracowaliśmy na moim laptopie, to Marcin odszedł, a dołączył się Michał. Porozmawialiśmy chwilę, co zrobić z naszym problemem niemożliwości użycia JSTL’a i zaproponowałem, aby stworzyć Data Transfer Object (DTO) i za jego pomocą wyświetlać już odpowiednio sformatowany tekst. Coś tam niby się udało, ale potem było trochę walki z merge’owaniem zmian. Niestety szybko się okazało, że user story bardzo nachodzą na siebie, wręcz się powtarzają. Powodowało to masę konfliktów i trudności z push’owaniem zmian, gdyż po pull’u, odpaleniu testów, i przy próbie ponownego push’a okazywało się, że ktoś w między czasie zdążył wypushować swoje zmiany i proces trzeba było powtarzać ponownie.

Po drugiej iteracji postanowiono zrobić retrospekcję. Mieliśmy na małych, przylepnych karteczkach wypisać, co nam się podobało, a co nie i przykleić to na ścianę. Później trzeba było w ciszy to pogrupować (silent sorting) i ponazywać grupy. Po „uroczystym” przeczytaniu tego co jest fajne i niefajne, każda para wraz ze swoim mentorem miała się zastanowić, co zrobić, aby było lepiej. Super pomysłem było wprowadzenie stand-up meeting’ów - w trakcie trwania iteracji - [chyba] co 20 minut, aby poprawić komunikację w zespole i wiedzieć, kto co robi i na kiedy będzie. Innym ciekawym pomysłem było wpisywanie podczas commit'a / push’a jako autor numer implementowanego user story i nazwiska autorów. I rzeczywiście, początkowo brakło konwencji wypychania zmian do repozytorium, aby były one jednolite i czytelne.

Następnie był obiad i kolejna iteracja. Tym razem osoby, które przez dwie iteracje robiły jedną opowieść, miały się przesiąść. Może to trochę nieoptymalne posunięcie z punktu widzenia ukończenia zadania, ale podczas eventu chodziło o wspólną naukę. Trafiłem więc do zadania wyświetlania podpowiedzi. Mianowicie gdy wpisujemy technologię, której się właśnie nauczyliśmy, ma nam podpowiadać czy było to łatwe, średnie czy trudne. Wiązało się to z koniecznością napisania kawałka JavaScript’a, ale na szczęście to akurat poszło gładko. Problemem się jednak okazało, gdy coś co było zależne od naszego zadania (mianowicie dodawanie nowych umiejętności) czy jest już skończone i czy dane lądują tam, skąd je odczytujemy. Niestety ciężko w Casandrze cokolwiek podejrzeć, co wylądowało w bazie danych, gdyż zapisują się tam dane binarne. Nad tym zadaniem pracowałem przez dwie iteracje i później na ostatnią iterację, znów trzeba było się przesiąść.

Dosiadłem się więc do Bartka i tam nawet początkowo było fajnie (nie znaczy to wcale, że wcześniej było źle). Dostałem szybkie wprowadzenie co robimy, że właśnie jest test z nową funkcjonalnością i mam ją zaimplementować. Chwila ogarniania / czytania kodu i z pomocą Bartka udało się. Problem niemożliwości skorzystania z JSTL’a rozwiązano użyciem Skryptletów. Coś tam nawet się udało wyświetlić, ale nie można było wypchać zmian, gdyż najpierw trzeba było powalczyć  z kwestią, co wyświetlać, jak ktoś jest niezalogowany. Inny zespół pisał back-end do tej funkcjonalności i niestety czas warsztatów nie pozwolił już na połączenie naszych zmian.

Po piątej iteracji przejrzeliśmy backlog zapisywany na tinypm.com. Okazało się, że niewiele funkcjonalności udało się w pełni zaimplementować. Paweł pokazał jednak na żywym środowisku, że coś tam działa. Patrząc na statystyki na Jenkinsie, było widać, że w ciągu zmian udało się wypchnąć do repozytorium kod 54 razy z czego tylko 9 się wywaliło. Uważam to za niezły wynik, biorąc pod uwagę to, że dla uczestników był to świeży projekt, bez wypracowanych konwencji i nie każdy musiał znać wszystkie wykorzystywane technologie. Poniżej przedstawiam trend tesów.


Podczas warsztatów budowały się build’y od 88 do 142. Wcześniejsze build’y pochodziły z przygotowań do warsztatów. Widać wyraźnie że od 95 build’a liczba testów zaczęła znacząco rosnąć, z każdą nową zmianą.

Na koniec nadszedł czas na podsumowanie. Poprzestawialiśmy trochę stoły i ułożyliśmy krzesła w dwa kółka. W środku było 5 krzeseł, a  na zewnątrz reszta. Kto siedział w środku ten mógł mówić, pod warunkiem, że cztery wewnętrzne krzesła były zajęte. Jedno było wolne, aby kogoś mógł się dosiąść i oczywiście można było spokojnie opuścić wewnętrzny krąg. Osoby siedzące w środku mówiły o swoich odczuciach dotyczących warsztatów, co się nauczyły itd. Czyli taka runda feedback’owa dla innych uczestników i organizatorów.

Jako że ja nie miałem okazji zasiąść w środku, to swoją opinię wyrażę teraz. Ogółem event wyszedł bardzo fajnie. Organizacja w porządku: były kanapki rano, napoje i ciasteczka przez caly dzień, dobry obiad w trakcie (i nie była to pizza). Lokalizacja warsztatów bardzo dobra, mianowicie blisko centralnego – ważna kwestia dla osób przyjezdnych, a tych nie brakowało. Ja sam przyjechałem z Wrocławia, ale spotkałem również ludzi z Gdyni, Gdańska, Wrocławia, a nawet z Berlina. Organizacja pod względem technicznym również dobra – były dwa rzutniki, na jednym Jenkins, a na drugim live aplikacja. Bardzo dobrym pomysłem było przygotowanie zaczynu aplikacji i jej udostępnieniu w necie. Również Continous Integration i Delivery daje bardzo fajny efekt psychologiczny. Można było szybko zobaczyć swoje zmiany na Jenkinsie jak i na na środowisku „produkcyjnym”.

Niestety, jak to sami organizatorzy przyznali, rozpoczęcie przygotowywania tej aplikacji na tydzień przed warsztatami to było trochę za późno. Wynikały później z tego problemy z technologiami (niemożliwość użycia Tiles’ów i JSTL’a). Uważam również, że dobranie stosu technologicznego było nienajszczęśliwsze. Fajnie, że było cos egzotycznego (Casandra), ale mało kto wiedział, jak z tego odpowiednio korzystać. Do tego zastosowanie Springa MVC i JSP powodowało, że czasem trzeba było się męczyć z JavaScriptem (AJAX i jQuery). Te problemy technologiczne powodowały, ze ciężko było się skupić na czystym pisaniu kodu (nie wspominając już o TDD), a trzeba było się męczyć ze zgraniem technologii i merge’owaniem zmian.

Wcześniej wydawało mi się że w miarę ogarnąłem już Git’a, ale dopiero tutaj w warunkach bojowych zweryfikowałem swoje poglądy na ten temat. Problem scalania zmian występuje (pushowaliśmy do jednej gałęzi, aby Continous Server już dalej robił swoje), jak w każdym innym systemie kontroli wersji. Jakub Nabrdalik mówił, że jednym z możliwych sposobów jest zrobienie miecza z dwóch zwiniętych kartek papieru i ten kto aktualnie posiada miecz może push’ować. Jak ktoś innyc chce to robić, to musi uzyskać ten miecz. Wydaje mi się, że skorzystanie z Mercuriala mogło by trochę ułatwić sprawę z łączeniem zmian w kodzie, ale nie jestem ekspertem w tym temacie.

Innym poważnym minusem co do warsztatów, było przygotowanie user story’s. Bardzo często były one do siebie podobne, zachodziły na siebie i od siebie zależały. Jednak podczas wyboru user story nie posiadaliśmy tej wiedzy. Na przyszłość trzeba lepiej przygotować historyjki do zaimplementowania, wraz z grafem, co od czego zależy, co trzeba zrobić najpierw i z lepszym opisem. Większość opowiastek dotyczyła strony głównej, przez co wzajemnie sobie modyfikowaliśmy zawartość tych samych plików, co prowadziło do problematycznych konfliktów. Na przyszłość można kilka opowiastek udostępnić np. tydzień wcześniej, aby można było w domu coś na rozgrzewkę napisać. Zachęciło by to bardziej do zajrzenia w kod i do lepszego przygotowania do warsztatów. I najlepiej aby były one możliwie jak najbardziej rozłączne.

Również wybór Casandry na bazę danych nie było chyba najlepsze, gdyż z rozmów pomiędzy ludźmi słyszałem, że niektóre zespoły sporo się z nią męczyły. Fajnie poznać przy takiej okazji coś nowego, ale wybór chyba nie był najszęśliwszy. Jak bym proponował na następny raz jakąś bazę działającą w pamięci, inną NoSQL’ową (obiektową, key-value) lub jakąś lekką SQLową, którą wszyscy znają. Jako technologię widoku proponowałbym GWT (lub coś o podobnej koncepcji), gdyż tam nie trzeba się bawić z JavaScriptem, ani z JSP, a maksymalnie z niewielkimi kawałkami HTML’a.

Nie oznacza to, ze nic nie wyniosłem z warsztatów. Miałem w końcu motywację do lepszego poznania Springa, Git’a, JUnitParams… Zrozumiałem, że nie tylko testy jednostkowe są najważniejsze, ale obok nich musi się znajdować kilka integracyjnych i akceptacyjnych (już w początkowym stadium projektu). Przykładowo prosty test end-to-end uruchamiający przeglądarkę na stronie głównej i sprawdzający czy jakiś tam przycisk istnieje, pozwolił nam szybko wykryć, że Tagi w JSP nie chcą działać. Inna sprawa ze testy nie były podzielone na jednostokowe i inne (trwające dłużej), przez co ich uruchamianie było trochę przydługie.

Dowiedziałem się też o fajnej technice, podkreślającej współwłasność kod. Mianowicie po za wywaleniem z szablonów plików / klas i metod informacji o autorze, można dać wszystkim pracownikom z danego projektu, jedno konto i hasło do repozytorium. Dopiero wtedy powstaje wspólny kod i nikt się nie boi modyfikować nieswoich części. Poznałem również trochę bardziej w praktyce procesy zachodzące w procesie Agile'owym, jak i mogłem się dowiedzieć jak wygląda IT w innych miastach.

Zawsze z takich wydarzeń można wynieść ciekawe skróty klawiaturowe. I tak dla IDEI: Crtl + Shift + Enter - Statement Comlete, czyli dodanie średnika na końcu linii. Z analogicznych skrotów korzystałem w NetBeans’ie, ale tam to było to Ctrl + ; i Ctrl + Shift + ;. Innymi interesującymi skrótami w Idei są: Ctrl + Shift + T czyli przejście do klasy, która testuję aktualną klasę, w której jesteśmy i Ctrl + Shift + N (odpowiednik Eclipsowego Ctrl + Shift + R), czyli wyszukiwanie po nazwie pliku z projektu.

Ciekawe, nowopoznane skróty dla Eclipse’a to Ctrl + Shift + M - zaimportowanie statyczne danej metody na której znajduje się aktualnie focus. Przydatne zwłaszcza jak mockujemy z Mockito i chcemy samo when() zamiast Mockito.when(). Ponadto Ctrl + Shift + O czyli organizacja importów (w Idei można zrobić, aby automatycznie narzędzie przed commitem zmian, odpowiednio organizowało importy). I na koniec syso + Ctrl + Spacja, czyli skrót od System.out.println();. W Idei jest to sout + Tab co jest według mojego gustu fajniejsze.

Dobra to chyba tyle z podsumowania wydarzenia. W tym roku już się żadna konferencja / warsztaty nie szykują, więc trzeba będzie z tym poczekać do przyszłego roku. Mam nadzieję na kolejną edycję Agile Development Day lub podobny tego typu event.