Tuesday, November 29, 2011

Bounded Context

Jasne, że nie będę od teraz pisał o DDD, bo już inni o tym ciekawie piszą. Chciałbym się tylko trochę uzewnętrznić w temacie, który szczególnie mnie poruszył, gdyż rozwiązuje dość poważny problem z architekturą. Jeśli nie nie zetknąłeś się z filozofią (w moim rozumieniu to bardziej sposób myślenia niż toolbox; taka obiektowość podniesiona level wyżej - na poziom architektury) DDD to na wstępie proponuję:

O jakim problemie mowa?

Powiedzmy, że rozpoznajemy, co też dzieje się domenie sklepu internetowego (nie wiem dlaczego to sklep zazwyczaj przychodzi na myśl:)). Powiedzmy, że dzieje się jak poniżej:
Jest to jakaś interakcja pomiędzy obiektami w dziedzinie.

Gdy zaczynamy modelować, naturalnie pojawiają się klasy takie jak: Zamówienie, Koszyk, itd. Powstaje model złożony z powiedzmy 30-50 klas. Wszystko wygląda super świetnie, ale zbiegiem czasu coś zaczyna nie grać. Pojawiają się następujące symptomy:
  • W związku z kolejnymi wymaganiami, do obiektów dochodzi coraz więcej atrybutów i metod
  • Programista implementujący przypadek użycia związany ze złożeniem zamówienia z trudem odnajduje się w gąszczu atrybutów i metod dodanych przez kogoś, kto implementował realizację Zamówienia
  • Niektóre obiekty są używane w tak wielu miejscach systemu, że jakakolwiek w nich zmiana ma spore skutki w innych odległych miejscach
Co więcej: jeśli z wymagań wynika jakaś konkretna zmiana w jednym miejscu systemu, to obija się ona głośną czkawką w zupełnie innym właśnie z powodu "reużywania" obiektów modelu.

Niby wszystko zostało przygotowane zgodnie z regułami sztuki, ale jednak wszyscy czują, że coś śmierdzi...tylko nie wiadomo z jakiej przyczyny.

Powód jest taki, że ten sam obiekt modelu używany jest wielu różnych kontekstach. Zamówienie wynikające z interakcji użytkownika z Koszykiem jest nieco inną sprawą niż Zamówienie realizowane przez magazyn.

"Bounded context should have a name so that you can talk about them"

Rację mieli starzy Indianie, gdy twierdzili, że jeśli poznasz czyjeś imię, zyskujesz nad tym kimś władzę. Nie inaczej jest z bounded contexts. Jeśli nie zauważymy i nie nazwiemy kontekstów użycia modelu, to mogą nam zrobić krzywdę. Nienazwane lubią się mieszać i dokładać do obiektów modelu rożnego rodzaju dodatki właściwe dla swej specyfiki. W skutek czego powstaje model-potworek, który w założeniu miał być super, a w wykonaniu i tak jest kolejną wersją big ball of mud.

Jeden model w jednym kontekście

W związku z dokonanymi odkryciami warto zalecać:
  • Nazwij kontekst, w którym może być wykorzystywany model. Już sama próba nazwania sprawi, że kontekstów pojawi się kilka (o ile tam są).
  • Jeden model może być wykorzystywany tylko w jednym kontekście (bounded context). Zamówienie w kontekście Koszyka to nie dokładnie to samo, co zamówienie w kontekście Magazynu.
  • Odizoluj poszczególne konteksty i właściwe im modele od siebie

W powyższych zasadach można dopatrzyć się echa Single Resposibility Principle. Z odpowiedzialności modelu powinien wynikać jednoznaczny kontekst jego użycia. Tyle, że Bounded Context definiuje to wprost i wyraźnie, a z zasady odpowiedzialności trzeba sobie wywnioskować.

Jeżeli w konsekwencji mamy zdefiniowanych kilka zwartych modeli o jednoznacznie określonych kontekstach użycia, to musi istnieć coś, co będzie potrafiło skonwertować obiekty z jednego kontekstu w drugi (jeśli jest taka potrzeba). W DDD ta potrzeba jest zaspokajana poprzez zdefiniowanie Context map w postaci zestawu usług-translatorów (w apachowych commonsach nazywanych transformerami). Ich odpowiedzialność to właśnie konwersja.

Podsumowując zyski z wprowadzenia konceptu Bounded Context:
  • Redukcja echa w systemie - zmiana w modelu w jednym miejscu nie skutkuje oddźwiękiem w innym
  • Zmiany wynikające z biznesu mają na poziomie architektury ograniczony do kontekstu zasięg
  • Można lepiej zorganizować prace nad projektem (tutaj DDD proponuje kilka pomysłów w zależności od tego jakie relacje występują pomiędzy kontekstami).

Tuesday, November 22, 2011

Przeglądy kodu

Kilka słów o przeprowadzaniu code review. A zatem po co? Czy nie wystarczy podłączyć Sonara czy coś w tym stylu. Z pomocą przyszedł mi cytat zamieszczony na strone 33rd Degree Conference: A single conversation with a wise man is better than ten years of study. I właśnie dlatego warto przeprowadzać code review :) Prowadząc taką rozmowę z f2f robimy użytek efektu human infection, czyli przekazujemy sobie wiedzę i ideę w bardziej naturalny sposób niż na papierku, albo ciągiem bitów.

Informacje początkowe

Dalej streszczam mój sposób na przeprowadzanie przeglądu kodu, ale najpierw parę tematów wprowadzających.

Jak często przeprowadzać przeglądy?
Tu nic odkrywczego nie wymyślę, jeśli napiszę, że: raz na wydanie albo raz na iterację albo w regularnych odstępach czasu albo po zamknięciu zadania albo na żądanie :)

Kto przeprowadza przegląd?
Jestem fanem ról, a sceptykiem stanowisk więc sądzę, że przegląd powinien przeprowadzać lider. W żadnym razie lidero-kierownik mający pod sobą kilkanaście osób. Mówię o liderach np. konkretnych komponentów systemu, którzy przewodzą maksymalnie pięciu osobom. Jeśli brak takiego liderowato-centrycznego uporządkowania, to przegląd robią ludzie, którzy mają mandat od zespołu wskazujący, że "ten zna się na rzeczy". Rzecz jasna poszczególni programiści z biegiem czasu nabywają kompetencji do przeprowadzania przeglądów. Zespół żyje.

Jak szczegółowy ma być przegląd?
Ufam, że ludzie są mądrzy. Wystarczy pokazać im co i dlaczego robią źle, aby potem zgeneralizowali ideę i wprowadzali poprawki w reszcie kodu. Nie ma potrzeby pokazywania palcem absolutnie wszystkiego. Wiem, wiem pewnie, że są wyjątki. Ale co do zasady, wspomniane założenie ufności jest dość użyteczne.

Ile czasu zajmie przegląd?
Jeśli znasz i rozumiesz kod to w okolicach 30 min plus drugie tyle na rozmowę. Jeśli nie znasz kodu (bo na przykład analizujesz kod klienta) to już jest zupełnie inna bajka. Megaistotne jest zebranie informacji co z czym się je, żeby nie wydzwaniać do ludzi co parę minut. Sam późniejszy przegląd to 8h wzwyż.

Przegląd krok po kroku


1: Zdefiniuj w IDE tasktagi //SMELL i //REFACTOR
Będą potrzebne do oznaczania w kodzie różnych ciekawostek.

2: Ogranicz się do kodu: jednego user story | jednego zadania | jednej funkcjonalności
Generalnie mogę wpaść w cały moduł i nie wyjść z niego przez tydzień. Ale zgodnie z zasadą zaufania, chcemy wyłapać symptomatyczne niedociągnięcia delikwenta, a nie prześwietlić jego kod od A do Z. Który zatem kawałek kodu wybrać? Tu przyda się rozbudowany instynkt Dr Housa. Trzeba z premedytacją wybrać taki fragment kodu, który potencjalnie mógł programiście sprawić trudność. Przykład: ostatnim razem ustaliliście nad czym ma popracować, wiec teraz sprawdź podobne zadanie albo kątem ucha usłyszałeś jak rozmawia o jakimś trudnym zadaniu - sprawdź właśnie to. Jasne, że nie robimy tego z czystej złośliwości, lecz właśnie w tego typu zadaniach jest okazja, aby wyłapać największe niedociągnięcia i najszybciej skorygować styl pisania.

3: Wygeneruj diagram zależności między klasami/pakietami
Najczęściej korzystam z wbudowanych widoków Eclipse lub ficzerów ReSharpera, wspomagając się kartką. Teraz zaczynam zapoznawać się z CDA i jeszcze nie mam wniosków. Jeśli chodzi o C++ to Visual Assist X jest jakimś tam ułatwieniem. Ale konwencje utrzymywania projektów i plików w C++ są tak zróżnicowane, że niemal za każdym razem wymaga ode mnie kreatywnego podejścia. Zazwyczaj kończy się na Eclipse C/C++ oraz kartce i długopisie. (Nie, nie rysuję w tym przypadku diagramów w narzędziu UML, bo za długo to trwa; ewentualnie potem, gdy okazuje się na przykład, że dziesięciopoziomowa hierarchia dziedziczenia sprawia kłopoty, to coś tam przerysuję żeby efekciarsko wyglądało w raporcie).

4: Pobieżnie przyjrzyj się każdej klasie w wybranym fragmencie kodu
Przyglądamy się tu pod następującymi kątami:
  • ogólne wrażenie - elegancja kodu, czy woła o pomstę do nieba?
  • nazewnictwa - czy nazwa oddaje intencję?
  • wielkości klas i metod
  • Ilość współpracowników

5: Prześledź podstawową obsługę żądania
Chodzi o prześledzenie ścieżki od momentu, w którym ktoś zainicjował przetwarzanie

do chwili, gdy system odpowiedział na nie.

Oznacz //SMELL miejsca, w których kod wydaje Ci się niewłaściwy. Przez //REFACTOR oznacz miejsca, w których od razu wiesz, co należy zrefaktoryzować.

6: Przygotuj podsumowanie
Byle krótkie w punktach, które uwzględni relację kodu do: obowiązującego standardu kodowania, czystości kodu, przyjętych zasad architektury.

7: Przekaż informacje zwrotną
w rozmowie f2f oraz wskazuj kierunki poprawy, ewentualnie zaimprowizuj mikorszkolenie. Zanotuj sobie, aby zweryfikować, czy postanowienia z rozmowy zostały wdrożone. Jeśli ludzie będą zapominać, przeglądy nic nie wniosą i wszystkim odechce się w nie angażować.

Czy należy wnioskować, że nienawidzę narzędzi?

Absolutnie nie. Takie super gadżet jak Sonara przeanalizuje za Ciebie masę kodu i wskaże miejsca, w które warto zajrzeć osobiście. Jestem wielkim fantem użytecznych narzędzi z zastrzeżeniem, że nie wolno nam zafiksować, że narzędzia zrobią wszystko, a my będziemy mogli zwolnić się z myślenia.

Dodatkowo jestem entuzjastą minimalizowania ilości otwartych zadań (work in progress). Jeśli robię przegląd i używam fajnych okienek, wpisuję komentarze (które potem trzymane są w repo), to te komentarze tam sobie będą i będą, aż może ktoś się nimi zajmie, rośnie tendencja do odkładania. Jeśli teraz robię przegląd i mam kilka słów podsumowania na kartce, to będę dążył to tego, aby jak najszybciej złapać daną osobę, przekazać co mam do przekazania i niech ona to już zrobi. Problem zdiagnozowany, rozwiązany, można pisać dalej.

Thursday, November 10, 2011

Duch i litera


Trochę w nawiązaniu do posta W co gra się w projektach.

W okolicach wyborów słyszałem w radiu zażartą dyskusję nt. czy obecnemu rządowi wolno rządzić do końca roku czy nie. Premier się upierał, że chce spokojnie dokończyć prezydencję w UE i argumentował, że jest to zgodne z konstytucją, natomiast konstytucjonaliści ripostowali, że owszem jest to zgodne z konstytucją, lecz nie jest zgodne z jej duchem.

Otóż to, pomyślałem. Wdrażanie procedur/procesów/standardów w zespole kończy się niepowodzeniem, gdyż ludzie rozumieją ich literę, ale nie widzą ducha. Autorzy procedur mieli oczywiście bliski kontakt z duchem, a literę stworzyli po to, aby przekazać swoje odmienne stany świadomości. Ergo - przy okazji wdrażania czegokolwiek ludzie muszą nawiązać kontakt z duchem.

Zostawiwszy w spokoju spirytualistyczne metafory, trzeba wyraźnie powiedzieć, że ludzie muszą znać intencję wdrażania nowych standardów, czyli: po co to robimy, dlaczego to jest ważne, co z tego będziemy mieli. Dobrym pomysłem, w tym obszarze jest standaryzowanie tego co już działa. Jeśli w zespole samoczynnie wykształciła się jakaś praktyka, która przynosi dobre rezultaty, to wartą ją zinstytucjonalizować w postaci obowiązującego standardu - dwie pieczenie na jednym ogniu.