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.

14 komentarzy:

  1. Dzieki za ciekawa relacje. Mozna sie z niej sporo ciekawych rzeczy dowiedziec. Bardzo podoba mi sie Twoja konstruktywna krytyka. Nie marudzisz tylko ale podajesz rowniez sposoby jak mozna cos zrobic inaczej. Najezdziles sie w tym roku troche, naogladales. Kiedy zorganizujesz cos we Wrocku?

    OdpowiedzUsuń
  2. No fakt najeździłem się trochę, ale też przegapiłem np. eventy na których Ty byłeś, mianowicie Code Retreat w Berlinie i Martina Fowlera też w Berlinie.
    Co do organizacji czegoś we Wrocku, to trochę nie czuję się na siłach, aby wziąć na swoje barki odpowiedzialność za całość. Mogę się skupić na jakiejś konkretnej części. No i do tego trzeba mieć ludzi w 100% zaufanych. Pożyjemy, zobaczymy.

    OdpowiedzUsuń
  3. Cześć Marcin,

    Relacja super! Bardzo miło się czytało i nawet nie zaglądałem, kiedy koniec. Po prostu pochłonęło mnie bez reszty.

    Co do "W Idei jest to sout + Tab co jest według mojego gustu fajniejsze.", sprawdź "sout+tab" w Eclipse. Powinno Cię mile zaskoczyć!

    Czy mógłbyś napisać wpis o użyciu Gita? Jak Ty go używałeś, jak rozwiązywaliście problemy, itp. Wpisy mogłyby być przyczynkiem do całej serii, w której przedstawiłbyś gita krok po kroku z przykładowym repo, w którym rozwijasz jakąś tam aplikację. Nie muszą to być długie wpisy, ale widać, że Twoje wpisy wspaniale się czyta. Potrzebuję więcej, więcej, więcej...

    OdpowiedzUsuń
  4. Cześć Jacku,

    Motywujący komentarz :) Co do sout+tab w Eclipse to sprawdziłem dzisiaj na 3ch wersjach (Galileo, Helios, Indygo) i nic mnie nie zaskoczyło :P Może sam sobie zdefiniowałeś taki szablon? Albo Ci się pomyliło z NetBeans'em, bo tam też to działa?

    Co do serii wpisów o Gitcie to się zastanowię. Gdybym go używał na codzień w warunkach bojowych, to bym pewnie coś już napisał.

    OdpowiedzUsuń
  5. Zamiast sout+TAB, miało być sysout i Ctrl+spacja. Za dużo tych IDE i jedynie człowiek się rozdrabnia, zamiast zabrać się za jedno, a porządnie. Jak jakiś człowiek renesansu :)

    A odnośnie gita - czy nie jest tak, że gdybyś używał w warunkach bojowych, to może i nie zauważyłbyś tych wszystkich niuansów jego stosowania. Mogłyby zatrzeć się granice tego, co łatwe, a tego, co ważne. Uważam, że jesteś w tym momencie swojej kariery z gitem, że to właśnie teraz powinieneś o nim pisać. Namawiam, bo służy to moim prywatnym celom edukacyjnym :)

    OdpowiedzUsuń
  6. Świetna relacja!
    A propos "Ponadto Ctrl + Shift + O czyli organizacja importów (w Idei można zrobić, aby automatycznie narzędzie przed commitem zmian, odpowiednio organizowało importy)" - w Eclipsie mozna dac: Window->Preferences->java->editor->save actions i mam organize import (i np. auto formatowanie). BTW polecam tez java->editor->content assist->favorites new type i np. junit.framework.Assert. Potem w klasie z testami wpisz samo "assert" i ctrl+spacja... :)

    OdpowiedzUsuń
  7. @Jacek
    Jak zrealizuję tematy, które mam jeszcze do zakończenia, to postaram się coś o GITcie napisać.

    @rafalmag
    Z auto formatowaniem trzeba uważać! Jeżeli masz dobry, zgrany Team, gdzie każdy przestrzega formatowania (każdy ma ten sam formatter i jego wywołanie na save action) to jest dobrze i kłopotu nie ma. W momencie jednak gdy pracujesz ze starym kodem, gdzie formatter nie był wprowadzony od początku, to możesz mieć problemy, gdy formatter przeorze cały plik, a ktoś później będzie musiał zmergeować swoje zmiany.

    Co do "content assist" to dzięki za przypomnienie. Kiedyś, gdzieś widziałem taką możliwość, ale uleciało mi z głowy, a samemu nie mogłem tego odnaleźć. Rozwiązałem to tak, że do szablonu metody testowej dodałem sobie statyczny import junit.framework.Assert

    OdpowiedzUsuń
  8. @Marcin
    W takich przypadkach Eclipse daje opcje "format edited lines" zamiast "format all lines".
    BTW: Gdzies czytalem o zasadzie, by komitowac(svn)/pushowac(git) zmiany zwiazane z formatowaniem oddzielnie do "faktycznych" zmian. Wtedy gdy ktos bedzie miec konflikt, moze czasem cofnac zmiane polegajaca na "przeformatowaniu". U mnie w teamie mamy wspolny formater, gdy dostalismy "legacy code" to wrzucilismy go w SVN w 3 etapach:
    1. na zywca - calosc - jak byl
    2. przeformatowanie calosci (ktos recznie przeklikal 100 klas...)
    3. inne zmiany ()

    OdpowiedzUsuń
  9. @Rafal
    Bardzo dobrze zrobiliście :)

    OdpowiedzUsuń
  10. @Rafał
    W kroku 2 można (przynajmniej w Eclipse) kliknąć prawym myszki na dowolny fragment drzewa plików/pakietów - i wybrać Source -> Format. Sam przejedzie po wszystkich klasach.

    OdpowiedzUsuń
  11. @Marcin: Dzięki za szczegółową relację. Kilka uwag ode mnie.
    Jsp -> w pełni zgoda, juck. Co do GWT, to czytając komentarze użytkowników, to mam wrażenie, że nie zdążylibyście zrobić pierwszej kompilacji, a event by się skończył ;)

    JUnitParams? Nie zrozumiem dlaczego ludzie tak uparcie olewają TestNg. Po tym jak JUnit zaczął stosować adnotację to działają i wyglądają niemal identycznie. A w ng z bomby jest znakomita obsługa data providerów + kilka innych fajnych bajerów.
    Uparciuchy z was wszystkich

    Co do IDE to wolę Intellij, choć lata pracy z Eclipsem odcisnęły swoje piętno.
    ctrl+1 jest wygodniejsze od alt+enter a ctrl+space do wszystkich jest dużo bardziej intuicyjny niż cltr+space/+tab/+space+shift/+space+alt/+cokolwiek.
    Mimo iż z Intellij za chwilę drugi rok mi stuknie, to i tak dalej nie rozróżniam tych skrótów :P

    A co do wymagań, to trudno jest zorganizować coś takiego o czym pisałeś. No i mieliście namiastkę prawdziwego projektu dzięki temu.

    Trochę mi napisanie tej odpowiedzi zabrało, ale miałem jeno TODO, że mam Ci odpisać i tak jakoś to postponowałem ;)

    OdpowiedzUsuń
  12. @Michał
    No niestety tylko bardzo niewielki procent historyjek udało się w pełni zaimplementować :/ Przy GWT również by było ryzyko zaimplementowania niewielu historyjek, ale gdyby szkielet początkowy był porządnie przygotowany, to wg. mnie lepiej by się udało.

    Co do JUnit'a to wydaje mi się, że to kwestia przyzwyczajenia. Ten kto choć raz się spotkał w projekcie z TestNG pewnie nie będzie chciał wracać do JUnita, albo przynajmniej będzie mu brakowało kilku rzeczy. Ponadto wydaje mi się (tzn. nie mam 100% pewności), że jakieś tam testy (integracyjne czy też akceptacyjne) wykorzystywane w aplikacji, rozszerzały szkielet JUnit'owy i z tąd wynikło jego zastosowanie.

    Ja akurat nie lubię ctrl + 1 i eclipse'owych "fochów". Wole IntelliJ'a. Kwestia gustu. Na pewno przyzwyczajenia są złe i trzeba z nimi walczyć.

    OdpowiedzUsuń
  13. Po 2 latach z Intellij tez go wole nad Eclipsa:P

    Ot brak mi kilku prostych rzeczy z Eclipsa (np wspomniane przez kogos favorites), niemniej juz nie wroce do starego IDE, chyba ze z obowiazku i pod przymusem.

    OdpowiedzUsuń
  14. @Michał
    Favorites są w IDEI :) Alt+Shift+F dodajesz aktualny plik do ulubionych i potem możesz je podejrzeć w oknie Procjet -> View as: Favourites.

    W nowej IDEI (11) będzie to jeszcze prostrze, bo podepną to okienko pod Alt+2. Sprawdź: Favorites tool-window in IntelliJ IDEA 11

    Szkoda tylko, że nie mam darmowego update'a do nowej wersji :/

    OdpowiedzUsuń