Hegel Driven Development

Ten tekst pojawił się oryginalnie w formie listu otwartego na LinkedIn, jako odpowiedź na artykuł mojego przyjaciela Krzysztofa Trojana, dostępny pod tym adresem.

Drogi Krzysztofie,

z wielkim zainteresowaniem przeczytałem Twój artykuł o zaniku zdolności syntezy przy budowie cyfrowych produktów i usług. Narzekasz w nim na upadek umiejętności uogólniania, budowania wzorów i reguł. Zwracasz uwagę, że w przeważającej większości przypadków oprogramowanie rozwija się w sposób przypadkowy: od-klienta-do-klienta, case-by-case a nie według zadanej, opartej o strategię trajektorii. Nie było tego w artykule, ale wciąż mam w pamięci jak kiedyś w pracy wspaniale skrytykowałeś pomysł na jakiś feature mówiąc: będziemy robić Ruchy Browna. Myślę, że tą myślą mógłbyś wyrazić sedno również i tego artykułu.

Na wstępnie zaznaczam, że mam podobny stosunek do rozwiązań tworzonych ad-hoc. Dlatego zgadzam się z istotą publikacji, choć sam ostrożny byłbym w formułowaniu wniosków o całych pokoleniach (po prostu za młody jestem, mi nie przystoi 😉 ). Niniejszy list otwarty nie ma zatem charakteru polemiki. Jest raczej próbą rozwinięcia pewnych myśli.

Atak, który przypuściłeś w artykule, jest zbyt mało precyzyjny i odbił się rykoszetem od dwóch praktyk, w obronie których chcę stanąć: rozwoju iteracyjnego (agile) oraz zasady YAGNI.

Ja jednak nie będę uciekał od filozofii (choć dla mnie to też pole minowe) – mam ten komfort, że nie piszę do szerokiego grona.

Ty mówisz Synteza – ja myślę: Hegel. I ta słynna dialektyczna triada: teza – antyteza – synteza, która wyznacza złożony z trzech faz, powtarzalny proces dochodzenia do prawdy. Najpierw teza: pierwsza myśl opisująca rzeczywistość. Potem pojawia się jej przeciwieństwo, przypadek który nie mieści się w tezie. Uogólnienie, które jest w stanie pogodzić tezę i antytezę, jest właśnie syntezą. Ta z kolei staje się kolejną tezą i tak w kółko.

Z łatwością da się to zaadaptować do naszej, programistycznej rzeczywistości. Pierwszy klient i jego proces – teza. Drugi klient, którego nie da się obsłużyć obecną aplikacją – antyteza. Nowa wersja systemu, która obsłuży obydwu – synteza.

Pisząc ten list natrafiłem na Wikipedii na obrazek, który przedstawia powyższy proces:

Źródło: wikipedia.org

Zaraz zaraz… Czy my już tego gdzieś nie widzieliśmy? Ależ tak: toż to standardowa wizualizacja różnicy między waterfallem a agile:

Źródło: pngkit.com

Możemy zatem znaleźć uzasadnienie dla przyrostowego, iteracyjnego rozwoju systemów w XIX wiecznej filozofii. Jest jednak różnica między heglowskim idealizmem a praktyczną realizacją agile’a. Z jednej strony jest elegancka i czysta synteza. Z drugiej: doklejanie kolejnych grudek błota i plątanina trytytek.

Tak: tutaj zgadzam się z Tobą w 100%, że zanika zdolność do przeprowadzenia zgrabnej i kunsztownej syntezy. Zamiast zadbanego modelu pojęciowego, poprawionych reguł i ulepszonych definicji dostajemy kolejnego IFa. Poniższy fragment, mimo że pozwala zamknąć sprint, nie jest syntezą, o którą chodziło Heglowi:

if (pierwszy klient) {
  TEZA;
} else {
  ANTYTEZA;
}

Ale jeśli Twoją intencją było wskazanie, że należy już na samym początku przeprowadzić pełną syntezę (tzn przejście z punktu A do B na wykresie logica classica) to tutaj się nie zgodzę. Owszem: zanim napiszemy pierwsze linijki kodu warto jest zrobić kilka okrążeń na heglowskiej spirali na sucho. Przewidzieć, przemyśleć, poprawić, znów się zastanowić. Ale trzeba uważać by się w tym wirze nie zamotać. Bo każda kolejna myślowa iteracja to są kolejne założenia o świecie, przyjmowane z dozą prawdopodobieństwa a błędy w jego ocenie się kumulują.

Oczywiście czym innym jest pisanie kodu, który można sto razy poprawić bez większego wpływu na działanie systemu, a czym innym projektowanie API. Ale to API i tak trzeba będzie poprawić. Bo każda przeprowadzona przez Ciebie synteza ostatecznie stanie się tezą do kolejnej iteracji. W tym sensie ważniejsze od dobrze przeprowadzonej syntezy będą dobre zasady wersjonowania API i dokumentacji, by umożliwić ich szybki rozwój.

Wspomniałem o założeniach, czyli o tym, że na etapie analizy wymyślamy różne przypadki (tezy i antytezy), które nasz system powinien obsłużyć (w ramach tworzonej syntezy). A raczej: które wydaje nam się, że ma obsługiwać. Racjonalnie jest zastąpić spekulacje danymi. A gdy ich nie ma to można zrobić badania i testy na prototypach co z kolei prowadzi nas do technik z rodziny Product Discovery. Im wcześniej zastąpimy wymyślanie odkrywaniem tym lepiej, dlatego kiedyś trzeba uciąć teoretyzowanie.

A skoro mowa o ucinaniu to na myśl przychodzi brzytwa. Oczywiście Brzytwa Ockhama. Utnijmy kolejne iteracje heglowskiego procesu jeśli nie są nam na pewno potrzebne. Bo za każdym razem gdy robimy syntezę to tworzymy nowe pojęcia a nie jest dobrze mnożyć byty ponad potrzebę.

Owszem, napisałeś zdanie: YAGNI ma swoje miejsce, to przejaw podejścia praktycznego, a także balansującego zwrot z planowania, ale to nie może być ślepe. Nie negujesz tej zasady. Ale nazwanie jej zinstytucjonalizowaną formą walki z podejściem syntetycznym jest przesadą. Możliwe, że była to tylko hiperbola by wyraźnie napiętnować przesadne jej stosowanie. Ale nie wylewajmy dziecka z kąpielą. Ja sam w obecnej firmie kilka razy dostałem po łapach za nie trzymanie się YAGNI i wyszło mi to na dobre.

Na koniec, w ramach dygresji, podzielę się pewnym spostrzeżeniem. W artykule stwierdzasz, że coś się zepsuło,w świecie, w szkole, w naszych głowach. Tutaj wchodzi aspekt kulturowy, o którym przeczytałem kiedyś w książce pt. The Culture Map: Breaking the Through the Invisible Boundaries of Global Business, autorstwa Erin Meyer. W rozdziale o różnicach w sposobach przekonywania autorka wskazuje, że są dwa sposoby rozumowania: Principles First oraz Applications First. W pierwszym wychodzimy od ogólnej zasady, reguły, wzoru i z niej potrafimy wyprowadzić konkretne przypadki. W drugim sposobie najpierw są konkretne zastosowania a reguła dopiero się z nich wyłania.

Na przykład możesz uczyć dzieci obliczania powierzchni prostokątów tłumacząc im najpierw wzór na pole a potem robiąc kilka zadań, które potwierdzą, że wzór działa. Albo możesz narysować kilka prostokątów, policzyć z dziećmi kwadraciki w środku, długość boków i zauważyć, że w każdym przypadku występuje między nimi zależność.

Erin Meyer wskazuje, że różni ludzie lubią jak się do nich mówi w różny sposób. Jedni wolą przez ogólną zasadę a inni przez konkretne zastosowania. Meyer udowadnia, że te różnice wynikają z różnic kulturowych i można zakładać że generalnie Niemcy będą woleli tak a Amerykanie inaczej (w książce prezentuje skalę dla różnych narodów).

Ja w pracy nie mam do czynienia z innymi kulturami ale widzę różnice w podejściach w podziale na role w firmie. Programiści zwykle są zwolennikami Principles First podczas gdy sprzedaż i Customer Support to głównie Applications First. Więc może, idąc za prawem Conway’a, problemy z syntezą w budowanym oprogramowaniu, wynikają bardziej z firmowych struktur niż z faktu, że przestali się rodzić ludzie zdolni do uogólnienia?

Bardzo dziękuję Ci Krzysztofie za Twój artykuł, którym sprowokowałeś mnie do napisania tego listu. Mam nadzieję, że Cię nie zanudziłem 🙂

ciekawy wpis? nie przegap kolejnych!

Wprowadź swój email a WordPress powiadomi Cię o nowych wpisach na blogu.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *