31 lip 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ę!

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ń.

21 lip 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.

Ewolucja Architektury - intro

JAVArsovia minęła (prawie 3 tyg temu...) więc zdecydowałem się zamieścić tu główne idee tematu który prezentowałem, czyli zagadnienie Ewoluującej Architektury, czy szerzej: architektury w zwinnych projektach. Część tych zagadnień bazuje na książce Dean'a Leffingwell'a Scaling Software Agility. Wszystkie zaś związane są z moim doświadczeniem i obserwacjami co do funkcjonowania działów architektury, developmentu i ich wzajemnych relacji.

Achitektura definiowana jest jako te elementy systemu, które powinny pozostać niezmienne. Te które decydują o kształcie i paramaterach niefunkcjonalnych systemu. Z tego względu chcemy zapewnić je jak najwcześniej. Architektura to zwykle również drogowskaz który mówi programistom tworzącym system jak rozwiązać krytyczne jego elementy. Z tego względu tworzona jest ona przez najbardziej doświadczone osoby, które już na początku potrafią przewidzieć okoliczności wykorzystania aplikacji, znają wymagania i mają niezbędne kompetencje techniczne by architekturę zdefiniować.
"Architektura" to termin, który wiele osób stara się zdefiniować, ale trudno wypracować jedną definicję. Są dwa wspólne elementy: pierwszym jest wysokopoziomowy podział systemu na części; drugi - decyzje, które ciężko zmienić.

Martin Fowler, PoEAA
W projektach programistycznych przywykliśmy jednak do tego, że projekty, których wymagania się nie zmieniają w czasie ich rozwoju prawie się nie zdarzają. Że znaczna część wymagań ujawnia się dopiero w czasie tworzenia systemu. Że systemy jednak czasem muszą ewoluować - obsługiwać większe obciążenie, pozwolić na integrację z jakimś systemem zewnętrznym, itp. itd. Stąd u podstaw zwinnych projektów leży:

Welcome changing requirements, even late in 
development. Agile processes harness change for 
the customer's competitive advantage.

The best architectures, requirements, and designs 
emerge from self-organizing teams.

Agile Manifesto, principles #2 & #11
Gdzie więc w zwinnych projektach miejsce na architekturę, na niezmienniki, na stanowisko architekta? Otóż staramy się stosować coś co nazywam ewoluującą architekturą. Jest to takie podejście do architektury, które zakłada, że nawet decyzje na najwyższym poziomie mogą się zmieniać. Np. że względem aplikacji w tej chwili monolitycznej mogą z czasem pojawić się wymagania modularności. Że aplikacja bazująca na współdzielonym stanie może z czasem wymagać modyfikacji na bezstanową. Zakładamy również, że część wymagań co do struktury aplikacji może ujawnić się dopiero na jakimś etapie jej rozwoju - np. nie mogły być przewidziane wcześniej, lub po prostu nie były wzięte pod uwagę (np. na jakimś etapie okazuje się, że aplikacja nie spełni zakładanych wymagań wydajnościowych ze względu na swoją architekturę).

Takie podejście do architektury zakłada, że podobnie jak inne elementy zwinnego projektu (kod, testy, dokumentacja), architektura rozwija się przez cały czas jego trwania - przez cały okres developmentu. Przecież na końcu architektura to nie to co było wstępnie pobożnie zakładane, ale struktura aplikacji - a więc kod. W najbliższych paru postach postaram się przedyskutować podstawowe elementy, które uważam za niezbędne do wprowadzenia i utrzymywania ewoluującej architektury (albo po prostu zwinnej architektury) i rolę architekta w zwinnych projektach.

Z perspektywy zmiany, rola architektury w zwinnym rozwoju oprogramowania staje się zupełnie jasna: dobra architektura jest responsywna i wspiera zwinność; kiepska będzie się opierać i ją ograniczać.

Kevlin Henney

3 lip 2009

Ewolucja Architektury

Zapraszam jutro na mój wykład o ewolucji architektury w zwinnych projektach na javarsovię. Ekipa konferencji nie zamieściła szczegółów które im przesłałem :) więc wrzucam tutaj:

Opis prelekcji:
Ewolucja Architektury
Architektura oprogramowania to ten jego składnik, co do którego
decyzje podejmowane są zwykle na samym początku projektu. Na czym
bardziej zaawansowanym etapie jest projekt, tym bardziej ryzykowne i
kosztowne są jej zmiany. Czasem jednak takie zmiany są niezbędne.
Czasem architektura ma oczywiste błędy. Czasem wymagania co do
funkcjonowania systemu zmieniają się do tego stopnia, że oryginalna
jego architektura nie może im sprostać. Paweł omówi sposoby radzenia
sobie w takich sytuacjach. Opisze jak kwestie ewolucji architektury
podejmowane są w projektach prowadzonych przy pomocy zwinnych
metodyk. Wskaże sposoby tworzenia aplikacji w taki sposób by jak
najmniej wiązać logikę aplikacji z jej architekturą, tak by umożliwić,
a czasem nawet promować jej ewolucję.

O mnie:
Paweł Lipiński jest programistą, architektem, trenerem zespołów. Przez
ostatnie parę lat pracował jako architekt aplikacji i systemowy,
głównie przy projektach klasy enterprise. Aktualnie pracuje w firmie
Pragmatists (będąc przy okazji jej właścicielem) zajmującej się
usługami dla zespołów programistycznych (coaching, szkolenie,
prowadzenie zespołów), pomocą zespołom i organizacjom w transformacji
na Scrum/XP, wyprowadzaniem projektów na prostą oraz tworzeniem
oprogramowania przy użyciu zwinnych metodyk. Posiada certyfikat
Certified Scrum Practitioner oraz niezliczone certyfikaty techniczne
związane z platformą Java/JEE.