08-03-2010

Konferencje

To kolejny małotechniczny wpis, ale może być dla kogoś ważny. W najbliższym czasie będzie w Polsce przynajmniej parę ciekawych wydarzeń agile'owych, więc chciałem je tu wylistować.

Najbliżej jest Zimowy AgileTuning bo już 20 marca. Nie byłem na poprzednim (i żałuję) - tym razem nie odpuszczę :-) Spotkań zwinnego światka jest w Polsce mało, więc trzeba delektować się tym co jest. Z resztą program przekonuje, że warto się wybrać.

Następnie są spotkania z Mary Poppendieck (kiedyś sprawdzałem co oznacza po niemiecku 'poppen' i odwróciłem oczy; a ten dieck do tego to już w ogóle...) - jedno we Wrocławiu (23 marca) a następne w Krakowie (24 marca).  Ciekawe czy się będą od siebie czymś różnić...

Później (8-9 kwietnia) jest AgileCE. Do tego zachęcam szczególnie - nie tylko będzie masa zagranicznych prelegentów,  ale również trochę naszych. Ja opowiem coś o naszych doświadczeniach bycia nearshore'owym zespołem naszego klienta.

No a potem (19-21 kwietnia) jest nasze szkolenie TDD, do zgłaszania się na które serdecznie zachęcam. Kwestie ceny i miejsca są aktualnie ustalane, do końca tygodnia powinny być już ogłoszone.

Etykiety:

14-10-2009

Przedwczesna optymizacja

Przeglądając stronę wikipedii dotyczącą eXtreme Programming znalazłem wśród praktyk programistycznych następujące zalecenie: 'leave optimization till last'. No i faktycznie zdaje się, że jest to dość uznana zasada. Przywołuje na myśl znane zdanie Donalda Knutha
Premature optimization is the root of all evil.
Z drugiej strony zwinne metodyki zalecają utrzymywanie projektu przez cały czas jego rozwoju w stanie gotowości do wdrożenia. Scrum nazywa to potentially shippable product - na koniec każdej iteracji przygotowujemy więc wszystko co niezbędne, żeby produkt tej iteracji można było wdrożyć (nie dlatego, żeby to faktycznie co iterację robić, tylko dlatego, by utrzymywać taką możliwość i dać klientowi prawo do decyzji co do tego kiedy chce aplikację wdrożyć, zaprezentować użytkownikom itp. Poza tym robiąc to jesteśmy pewni, że projekt jest cały czas zintegrowany, i że nasz system CI i proces tworzenia oprogramowania są dobre. No i jeszcze kwestia morale zespołu, gdy wie, że projekt jest non-stop w stanie jakościowo gotowym na produkcję).

Wracając do zostawiania optymizacji na koniec, zupełnie nie zgadzam się z tym. To klasyczny przypadek zostawiania gdzieś praktyk fazowych (waterfall'owych). Jak można nazwać aplikację potencjalnie gotową do wdrożenia, jeśli nie jest wystarczająca wydajnościowo?
Tak więc optymizujmy kod w czasie jego rozwijania. Może nawet warto dodać do Definition of Done zadań zespołu warunek akceptowalności pod względem wydajnościowym.

Oczywiście we wszystkim należy zachować umiar. Ważne jest, by wydajność była akceptowalna / zadowalająca. To może oczywiście oznaczać bardzo rygorystyczne warunki np. dla systemów RT. Szczegółowy fine-tuning wydajności jakichś elementów aplikacji można jednak faktycznie zostawić na później. To znaczy jak się już okaże, że faktycznie jest problem wydajnościowy i będzie wiadomo dokładnie gdzie. Oczywiście nie sądzę, żeby było dobrym pomysłem czekanie aż okaże się to w środowisku produkcyjnym - dla aplikacji dla których wysoka wydajność jest ważna można ją kontrolować stale w czasie rozwoju aplikacji w przeznaczonym do tego środowisku CI z automatycznymi testami wydajnościowymi. Natomiast powinniśmy dbać o nieograniczanie (głównie architektonicznie) naszych możliwości optymizacji.

Z resztą powyższy cytat z Knuth'a nie jest kompletny (a większość programistów zna tylko ten jego fragment). Kompletny brzmi tak:
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

Etykiety: , ,

21-09-2009

Agileee retrospective

This post is in english, since the conference was mainly in english (and maybe some agileeestas would like to read it.)

So, the conference was simply great. Maybe not perfect, but great.
I even had a little influence on its shape by having a talk there (the slides are here...)

So let me summarise it:

WHAT WAS GOOD:
  • venue
  • lunch
  • keynotes (Jutta Eckstein with her 'distributed agile' talk - have heard her already twice with a similar subject before, but there's always something new; David Hussman with a really touching closing talk underlining how important it is to follow what you believe in)
  • many talks
  • speaker's night out (and I thought that Poles drink a lot...)
  • lots of nice, clever and experienced people
  • ratio: cost / value 


WHAT COULD BE BETTER:
  • coffee and water not always available 
  • some talks really for agile-beginners (maybe there should be some 'experience level' mark by each talk, so that you go to the level you're at)
  • stage in Russian (I mean I could be better and speak Russian, there must have been a lot of valueable stuff, otherwise unavailable for a non-ex-soviet-country guy)


PLANS TO HAVE A BETTER AGILEEE IN FUTURE:
  • learn Russian
  • don't loose the conference schedule and read in advance where you plan to go to
  • meet even more people on corridors


So in total I'd say 8/10 (just to leave the organisers some place for kaizen...)
I really hope to be there next year, and wish it to you all!

Etykiety: , , ,

07-09-2009

Pierwszy release

Dziś w Pragmatists mieliśmy pierwsze wdrożenie pierwszego projektu. To taki miły moment, kiedy jest wreszcie chwila na zastanowienie się jak poszło. Na przemyślenie co można następnym razem lepiej. Jak nie popełniać pewnych błędów, jak pomagać klientom nie wpadać w pułapki.

Projekt był hybrydowy - z naszej strony staraliśmy się robić wszystko zwinnie - zaczęliśmy klasycznie od ustalenia z klientem o co mu chodzi, utworzyliśmy masę User Stories, zrobiliśmy estymacje, backlogi, pracowaliśmy w parach, TDD, itp. itd. Z drugiej strony nasz klient, choć z grubsza chętny do zwinnego podejścia, jednak z własną historią i przyzwyczajeniami (bardzo niezwinnymi). I do tego z projektem, który miał już wyznaczony termin wdrożenia, choć jeszcze nie wiadomo było dokładnie co ma być zrobione. I to jest pierwsza pułapka i chyba bardzo częsta. Terminy rzadko ustala zespół. To często element negocjacji, jakby niemerytoryczny - ustalany między managerami i salesami. W naszym przypadku nasz klient naprawdę nie wiedział czego chce ich klient (który jest użytkownikiem aplikacji) poza ogólnikami i własnymi domysłami (z resztą błędnymi, więc po pierwszych 2 miesiącach pracy zakomunikowano nam, że trzeba zacząć od nowa i zrobić coś zupełnie innego :)). Myśmy na to przystali (no cóż, nie zdobywa się klientów od stawiania im warunków...) i skutek był taki, że ostatnie 4 tygodnie były zmaganiem z czasem, wymaganiami (prośba o ostatnią zmianę w aplikacji pojawiła się wczoraj, w niedzielę, o 22:30...) i stresem własnym i klienta.
To podstawowa różnica między projektem zwinnym a klasycznym - w zwinnym termin jest funkcją zakresu wymagań i prędkości zespołu. Dlatego staramy się dostarczać aplikacje przyrostowo, wtedy terminy przestają być kluczowe, bo klient zaczyna dostawać aplikację wcześniej i ma realny wpływ na jej zawartość, a więc również na termin kiedy zacznie ją wykorzystywać. A więc:
Action Point 1: zachęcić klienta do spróbowania teraz (po tych średnio miłych doświadczeniach ostatniego miesiąca) "naszego" sposobu - nie tylko pokazywać, ale dostarczać kolejne wersje aplikacji na produkcję co 2 tygodnie. Dzięki temu nie będzie gorączki przedwdrożeniowej, ale stały jasny dla wszystkich proces regularnego dostarczania już-nie-tylko-potentially shippable product'u (mamy zadbane środowisko CI, więc jakby się uprzeć, to z technicznego punktu widzenia moglibyśmy dostarczać nawet codziennie).
Kolejne doświadczenie to komunikacja. Tutaj mamy wciąż dużo do poprawy. To, że nie mamy bezpośredniego kontaktu z użytkownikiem wpływa na naszą niepewność co do tego, czego on może tak naprawdę potrzebować. Jak chciałby pracować z aplikacją. Np. dwa tygodnie przed wdrożeniem dowiedzieliśmy się, że użytkownik lubi na raz pracować z excel'ami o setkach wierszy, bo wtedy "wszystko widzi" - a nasz a'la-excel'owy mechanizm wspiera raczej nie więcej niż 50 wierszy.
Nasz klient jest 1300km od nas i sprawność komunikacji jest kluczowa. Maile nie zawsze starczają a cotygodniowe spotkania iteration review/planning nie dają nam odpowiedzi na kluczowe pytania: czy aplikacja się podoba, czy są zadowoleni (z aplikacji, postępu,itp.)
Action Point 2: Bardziej cisnąć o informacje w czasie planowania - w czasie trwania iteracji MUSIMY wiedzieć dokładnie co mamy robić i czemu to ma służyć.
Zespół = Ludzie + Interakcje. Widzę to codziennie. Są dni, kiedy widać jak na dłoni, że pracując razem stanowimy dużo więcej niż gdyby każdy pracował oddzielnie. Wpadamy na lepsze pomysły (bo dużo dyskutujemy, a więc projektujemy), tworzymy lepszy kod (bo wiele osób go czyta i pisze, a więc musi być zrozumiały), nakręcamy się do pracy (bo to nie tylko nasz chleb, ale głównie nasza pasja), zachęcamy się do nauki i ciągłego ulepszania samych siebie ("kuuuurde, chłopaki, ale książkę znalazłem...", "ej, Kamil, jest tam coś ciekawego w tym artykule?", "Paweł, w mordę, nie pisz takiego szitu, przecież to można ładniej zrobić!") Są dni, kiedy wychodząc z pracy dobrze rozumiem dlaczego moje dzieci płaczą, że nie chcą jeszcze wracać gdy ich odbieram z przedszkola.
Action Point 3: jeszcze więcej pracy w parach, jeszcze więcej dyskusji przy tablicy, jeszcze więcej chłonięcia wiedzy od siebie i wspólnego tworzenia nowej.
Testy, testy i jeszcze raz testy (automatyczne). To jedyny sposób robienia oprogramowania wysokiej jakości. To jedyny sposób żeby być pewnym, że możesz dostarczyć aplikację KIEDY TYLKO KLIENT ZECHCE. To jedyny sposób na uniknięcie długich niezrozumiałych metod i niejasnych rozwiązań. To jedyny sposób na weryfikowanie poprawności twoich pomysłów gdy aplikacja już się rozrosła (inaczej marnujesz długie godziny na klikanie i debugowanie). To w końcu jedyny sposób by móc sobie powiedzieć: zrobiłem (done) i jestem tego pewien. A to jedno z milszych uczuć jakie mamy w naszej pracy. Nie wierzę, że może twierdzić inaczej ktoś kto choć raz brał udział w tak rozwijanym projekcie (jest to zdecydowanie najwyższej jakości projekt w jakim brałem udział w życiu, a mam za sobą ponad 10 lat pracy w developmencie i pewnie ponad 20 projektów różnego rozmiaru za sobą).
Testy dają nam poczucie pewności a naszemu klientowi możliwość prawie dowolnego kształtowania i modyfikowania wymagań - a to przekłada się w prostej linii na jego przewagę nad konkurencją.
Action Point 4: weryfikacja (ciągła) pokrycia funkcjonalności testami (nie pokrycia linii kodu, ale pokrycia funkcjonalności) i dorabianie ich tam, gdzie ich brakuje.

Action Point 5: definiowanie zakresu iteracji za pomocą testów akceptacyjnych (A-TDD) - to dotyczy zarówno kwestii elastyczności wymagań, jakości produktu, jak i (a może przede wszystkim) komunikacji z klientem.
To tak z grubsza większość moich przemyśleń co do tego projektu. Widziałem w tym czasie zaangażowanie, kreatywność i pasję. Obserwowałem (a trochę może też wpływałem na) tworzenie się z grupy ludzi zespołu. Rodzenia się odpowiedzialności i poczucia wspólnego celu. Wiele jeszcze oczywiście przed nami. Ale przecież to zaledwie początek.

Etykiety: , ,

31-07-2009

Self Organizing Teams

W świecie agile'owym promuje się samoorganizację zespołów. Gdy zespół sam potrafi prowadzić swoją pracę, gdy bierze odpowiedzialność za swoje zobowiązania, ma wszelkie uprawnienia by je realizować i to robi można go nazwać samoorganizującym się. Takie zespoły działają dużo efektywniej niż prowadzone klasycznie metodą poleceń i kontroli ich wykonania. Po pierwsze bardziej im się chce, bo czują się odpowiedzialni za swoją pracę. Po drugie mają większą satysfakcję, ponieważ mają dużo większą wolność. Po trzecie nie czują się traktowani jak dzieci (na temat związku idei agile'owych z wychowaniem dzieci też mam swoją teorię, ale nie o tym ten post :-))

Od samego początku firmy Pragmatists chciałem stworzyć takie środowisko, w którym branie odpowiedzialności, zaangażowanie i samoorganizacja będą czymś normalnym. Środowisko, w którym o wszystkim decyduje zespół mając na względzie dobro swoje (wzajemnie poszczególnych osób w zespole), firmy i klientów. Gdzie zespół uzgadnia swój sposób pracy, co może zrobić i na kiedy, gdzie stoją biurka i jaką chcą pić kawę. Ale również chciałem by było miejsce na zrozumienie i szacunek dla potrzeb innych, dla decyzji klientów, dla możliwości firmy.

I to się udalo - mimo projektu w toku (a jego pierwszej fazy to właściwie pod koniec) wyjechałem na 3-tygodniowe wakacje zostawiając zespół na pastwę projektu i klienta :-). Przez ten czas funkcjonalności były dodawane wcale nie wolniej niż ze mną (niektórzy sądzą, że nawet szybciej...), odbywały się regularnie standupy i retrospekcje, zakupione zostały lepsze klawiatury i mleko do kawy, odbywał się ciągły kontakt z klientem i w końcu nawet potrzeba drobnej regulacji kontaktów z klientem z moim drobnym udziałem.
Był to w jakiejś mierze test realizacji moich oczekiwań (niniejszym patentuję termin Test-Driven Company Development). Teraz oczywiście pora na małą refaktoryzację, by jeszcze poprawić już dobrze działający mechanizm :)

Mój Drogi Zespole, bardzo Wam dziękuję!

Etykiety: ,

EA - KISS

Keep It Simple, Stupid! mówi starobrytyjskie porzekadło. Jak jest ono prawdziwe wie każdy, kto choć raz przedzierał się przez gąszcz klas, chaszcze metod i bagna logiki przesadnie zaprojektowanych aplikacji. Chęć przewidzenia przyszłych wymagań pcha nas często w pułapkę używania skomplikowanych konstrukcji tam gdzie dużo prostsze były by wystarczające. A skomplikowane struktury, gdy kod nie komunikuje jasno ich celu, rozwijają się szybko w totalnie niezrozumiałe monstra. Wystarczy dorzucić do nich jednego if-a tu, i jeszcze dwa tam, i początkowo śliczna implementacja wzorca przeradza się we włoskie danie z sosem bolognese.
W zwinnych projektach staramy się bronić przed takimi sytuacjami przez ciągłe projektowanie i refaktoryzację aplikacji (TDD). Praca w parach pozwala nam na ciągłe weryfikowanie wprowadzanego kodu niejako z zewnątrz - przez kolegę, który być może trzeźwiejszym okiem oceni nasze zapędy.
Ale to techniki które można stosować na poziomie kodu. A co z architekturą? Przecież cała idea definiowania architektury to przewidywanie przyszłości. Przecież to właśnie dzięki dobrym wstępnym decyzjom aplikację będzie można np. prawie liniowo skalować, czy umożliwić jej łatwą integrację z korporacyjnym ESB.

Żeby nie wpaść w pułapki podjęcia błędnych decyzji, lub roztrząsania zupełnie nieistotnych kwestii posługujemy się terminem last responsible moment. Jest to ten moment przed którym podjęcie decyzji może być przedwczesne (niewystarczające/niepełne informacje mogą spowodować podjęcie błędnej decyzji), a po którym jej niepodjęcie może powodować jakieś straty (np. zbyt wczesne podjęcie decyzji o wyborze Oracla a nie MySQL może narazić nas na ogromne koszty, zbyt późne podjęcie decyzji może oznaczać konieczność przepisania fragmentów aplikacji). Staramy się więc powstrzymywać od podejmowania decyzji w kwestiach które nas aktualnie nie dotyczą, ale bardzo pilnie obserwować i dyskutować te które mają wpływ na naszą aktualną pracę.

Aby móc pracować w taki sposób utrzymujemy naszą architekturę maksymalnie prostą, ale zawsze w takim stanie, by umożliwić jej modyfikację. Bo gdy założymy, że architektura ewoluuje wraz z rozwojem systemu, możemy też założyć, że ma ona wspierać wyłącznie te własności które są niezbędne TERAZ i których wymagalności jesteśmy absolutnie pewni (YAGNI). Z resztą czym prostsza architektura tym łatwiej ją komunikować w ramach zespołu i tym łatwiej zapanować nad nią zespołowi. A czym większy zespół tym bardziej jest to prawdziwe.

Podobnie jak w przypadku projektowania na niższym poziomie, staramy się cały czas patrzeć kiedy prostota techniczna rozwiązanie zaczyna przeszkadzać w utrzymaniu prostoty wyrazu. Taką sytuację można zwykle poznać po liczbie bezpośrednich zależności - jeśli jest ich za dużo, prostota techniczna naszego rozwiązania przestaje być wartością - trzeba więc poszukać rozwiązania bogatszego technicznie i poprawiającego komunikatywność, zrozumiałość naszego pomysłu. Powinniśmy cały czas utrzymywać balans między prostotą techniczną i prostotą wyrazu.

Dbamy więc symetrię, modularność (high cohesion, low coupling), rozdzielenie warstw, oddzielenie dziedziny od elementów infrastrukturalnych, uniezależnienie od zewnętrznych bibliotek / frameworków, itp. Jeśli pomyślimy o tych cechach w kontekście prostoty, to to jest to, co one faktycznie promują. Kod podzielony na małe moduliki jest prostszy od monolitycznej masy. Każdy z modułów z dobrze wydzieloną pojedynczą odpowiedzialnością jest prostszy niż masa if-ów i switch'y weryfikujących poszczególne przypadki.

Pilnowanie i dbanie o prostotę rozwiązań oraz zachowywanie zasady wysokiej wewnętrznej spójności i małego poziomu uzależnienia od zewnętrznych elementów (na każdym poziomie), ułatwia tworzenie zwinnych architektur pozwalających na reagowanie na zmiany wymagań.

Etykiety: , ,

21-07-2009

EA - zespół który koduje system musi go projektować

Poprzednim razem pisałem ogólnie o architekturze w projektach zwinnych. Generalna zasada jest taka, że nad architekturą staramy się zastanawiać nie (wyłącznie) na początku, ale w każdej iteracji. Ale żeby móc coś takiego osiągnąć zespół który koduje system musi go projektować. By decyzje architektoniczne były świadome a nie tylko pobożnymi życzeniami muszą być podejmowane na podstawie danych - faktów. A te ujawniają się w dużej mierze w czasie developmentu. Również informację o kosztach (w sensie czasowym) decyzji i zmian architektonicznych zna tylko zespół. Tak więc to zespół jest najbliżej wszystkich danych niezbędnych do podejmowania decyzji.

Podejmowanie decyzji architektonicznych przez zespół ma poza tym wpływ na jego zaangażowanie w projekt i wzmaga odpowiedzialność za projekt. Przekazywanie władzy "w dół" (team empowerment) to dobry sposób budowania zespołu. Kto nie chciałby pracować przy projekcie ze zmotywowanymi i zaangażowanymi współpracownikami? Jak poza tym pomagać mniej doświadczonym członkom zespołu zwiększać swoją wiedzę jak nie przez angażowanie ich w takie dyskusje?

Architektura projektu w przypadku większych rozwiązań czy firm o zdefiniowanej polityce w tym zakresie może wymagać uczestnictwa architekta. To on dba o zachowanie zgodności z polityką architektoniczną firmy, ale również może służyć zespołowi swoim doświadczeniem - ale do tego celu musi on być obecny w zespole przez cały czas developmentu. Czasem wymaga to zmiany funkcjonowania organizacji - gdy w firmie jest dział architektury, który zajmuje się tworzeniem dokumentacji architektonicznej przed rozpoczęciem developmentu, może być ciężko zaangażować architekta w działania zespołu - najpewniej ma on już kolejne systemy do projektowania.

Oczywiście w przypadku dużych projektów nie ma możliwości by cały zespół projektowy (np. parędziesiąt osób) podejmowało wszystkie decyzje. Wtedy możliwe są rozwiązania takie jak zespół architektoniczny złożony z programistów z poszczególnych podzespołów. Pozwala to na zachowanie spójnej architektury całego systemu przy zachowaniu decyzji co do jego kształtu na właściwym poziomie (dalej robią to programiści aktywnie zaangażowani w development). Rotowanie osób w tym zespole pomaga dodatkowo rozprzestrzeniać wiedzę o produkowanym systemie oraz zwiększać ogólną wiedzę i doświadczenie w zespole.

W niektórych projektach widziałem spotkania w rodzaju "architecture review" podczas których architekt który zaprojektował system siedział z zespołem i przeglądał system pod kątem realizacji jego założeń. Takie spotkania oczywiście zwiększają szansę na to, że system będzie zgodny z założoną architekturą, ale nie koniecznie wpływają na to, że będzie ona zgodna z wymaganiami co do systemu. Poza tym takie przeglądy są zwykle dość powierzchowne. To coś a'la code review - dobrze je robić jeśli się nie korzysta z programowania w parach i TDD. Jeśli jednak uda nam się wprowadzić te techniki, code review jest w większości przypadków zbędne. Co więcej przeglądy architektury (podobnie jak przeglądy kodu) mają formę hierarchiczną: o to architekt sprawdza czy programistyczna masa nie zniszczyła jego dzieła - architektury (no, może trochę przerysowałem...) Praca architektów w zespole ręka w rękę z mniej doświadczonymi programistami dużo lepiej wpływa na pozyskiwanie wiedzy tych drugich i całościową pracę zespołu umożliwiając dużo efektywniejszą jego pracę.
Ciągłe dbanie o utrzymywanie, weryfikowanie i modyfikowanie architektury umożliwia jej lepszą jakość i odpowiedniość wymaganiom, do tego zmiejszając szanse na to, że będzie niezbędna jej gruntowna (kosztowna) zmiana.

Etykiety: , ,