Friday, March 23, 2012

Craftsmanship nie dla wszystkich?

Big szacun dla tych, co wrzucają po 2 posty dziennie. Ja opierałem się wyrzutom sumienia aż do tej pory. Chyba właśnie regularność i rytm są tu kluczowymi rzeczami. Wiele razy przychodził mi pomysł na wpis, ale odkładałem na później. Pomysł tracił na wyrazistości, blakł, aż całkiem zupełnie znikał. No nic, pożyjemy zobaczymy.

Nawiedziło mnie następujące przemyślenie czy Craftsmanship jest dla wszystkich? Jeśli mówimy o ciągłym doskonaleniu warsztatu to jak najbardziej. Jako myśli filozoficzna i reguła życia zawodowego jest warta rzetelnego praktykowania. Zmieńmy jednak punkt widzenia i wejdźmy w buty szefa działu developmentu.

Ilu minimalnie czarodziei potrzebuję?

Umiejętności kosztują. W doświadczonego osobnika, który ma wysoko rozwinięte cechy pożądane u adepta Craftmanship
trzeba dużo zainwestować. Zupełnie naturalnie przychodzi do głowy pytanie, czy wszyscy programiści muszą być świetni.
Z całą odpowiedzialnością muszę powiedzieć, że nie. Tu niestety rządzi ekonomia. No i rozkłady statystyczne. Jeżeli na dwudziestu programistów przypada jeden czarodziej, który będzie strzegł ładu i składu w architekturze, to zespół spokojnie da sobie radę. Jeszcze raz bez ogródek: nie wszyscy programiści są tyle samo warci, nie we wszystkich warto w równym stopniu inwestować, można zadowolić się określoną liczbą ludzi przeciętnych albo nawet słabych i ile tylko będą potrafili napisać to, co im się każe. Jeśli w kilkusetosobowym dziale uda się zebrać powiedzmy 6-8 osobowy dream team, który wymyśli superrozwiązanie każdego problemu, to reszta tłumu może spokojnie robić swoje.

Jak uniezależnić się od kodera?

Kiedyś przy jakieś okazji powiedziałem "nie da się programisty zastąpić skończoną liczbą studentów; to tak jakby prezesa chcieć zastąpić skończoną liczba konsultantów". Trzeba uściślić tę opinię "nie każdego programistę można zastąpić skończoną ilością studentów". Tych pojedynczych najlepszych pewnie nie, ale znakomitą większość jak najbardziej. Potrzeba tylko, aby niezastąpieni tworzyli takie architektury, przygotowywali takie półprodukty, takie frameworki, w których nie trzeba za wiele myśleć, wystarczy kodować. W ten sposób można już traktować większość programistów jako wymienny zasób. Doprowadzenie do tej sytuacji to kwestia odpowiedniej strategii, czasu i pieniędzy.

Bezpańscy czeladnicy

Trzymajmy się dalej tej perspektywy. Za Craftmanship idzie zapomniany już niestety model Mistrz-Czeladnik. Uczeń szukał swojego mistrza, u boku którego praktykował. Myślę, że wielu programistów nie ma od kogo się uczyć. Albo nie spotykają na swojej drodze wystarczająco kompetentnych i cierpliwych mistrzów albo wtłoczeni w rolę wymiennego kodera, włóczą się od firmy do firmy. Tacy właśnie bezpańscy czeladnicy. Zdobędą trochę doświadczenia to tu to tam na własnych błędach, nie mając nikogo u boku kogo wskazał by im kierunki rozwoju i doradził.

No, na czarno dzisiaj trochę. Ale tak mnie dopadło:)

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.