bookmark_borderRozkład oprogramowania

Od lat zajmuje mnie rozkład. Jędrne, gładkie ciała obumierają w zmarszczone, poplamione truchła. Imperia pełne chwały i potęgi rozpadają się na symetryczne zgliszcza gruzu, obmywane deszczem i spiekane słońcem. Lśniące atomowym blaskiem gwiazdy zapadają się w parujące oddechem wymarłych światów czarne dziury. Nic nie jest wolne od rozkładu, bo panta rhei kai ouden menei. Również to, co spod naszych palców wyrasta – oprogramowanie.

Kod oczywiście jest doskonały, cyfrowy, nie poddaje się entropii. Tak samo jak nie poddaje się jej choćby Odyseja Homera. Tyle, że stworzony dawno temu program, jak i wieki temu spisana Odyseja nie żyją w próżni. Powstały dla odbiorców. I tak jak dziś inni są Europejczycy od Greków sprzed tysiącleci, tak samo ewoluuje ekosystem, w którym przychodzi egzystować oprogramowaniu.

Choć jest właściwie jeszcze gorzej. Programy bowiem powstają latami. Rozwijane są nowe funkcjonalności, aktualizowana jest ich integracja ze światem zewnętrznym, czasami wręcz zmianie ulegają technologie, z jakich aplikacje się składają.

I tu pojawia się rozkład. I błędne koło.

Na początku program tworzy się szybko. Stąd pewnie zachwyt wielu początkujących programistów (oraz gorycz doświadczonych). Im więcej kodu, tym więcej zmartwień, jak i w przysłowiowym lesie więcej drzew im głębiej. Zaś im więcej ludzi w projekcie tym już piekło jest wybrukowane…

Pierwsi programiści w projekcie często są bardzo doceniani. Siadają, piszą, działa. Można wdrażać na produkcję albo pokazać klientom lub przełożonym. Sukces. Za ten sukces zwykle są nagradzani. Awansują albo są kierowani do kolejnych nowych projektów. Ci mniej lubiani trafiają zaś do projektów już istniejących. Im niżej w hierarchii dziobania tym do starszych i bardziej zapleśniałych.

Sęk w tym, że bodźce kształtujące zachowanie są zwykle rozłożone niekorzystnie. Tworzy to koszmarne zjawiska i prowadzi do wspomnianego błędnego koła. Błędnego koła tworzenia, próchnienia i burzenia.

Programiści tworzący projekty greenfield (nowe, od zera) nie zmagają się z konsekwencjami swoich czynów. Mogą pisać co chcą, jak chcą, byle wytrwać z rok, czy dwa, do odkorkowania szampana i wdrożenia projektu. Mogą eksperymentować, ale też nagradzani będą ci, którzy jak najszybciej i jak najtaniej zaimplementują zestaw podstawowych funkcjonalności. Bodźce więc są proste – pisz szybko, byle jak (choć nie za bardzo), używaj nowych technologii, które ładnie wyglądają w CV, a jak napiszesz to oczekuj, że trafisz do nowego projektu albo poszukaj go na rynku pracy. Co dalej z kodem? Pal licho, nie twój interes.

Programiści utaplani w błocie legacy z kolei mają małe albo wręcz żadne – w zależności od stopnia rozkładu – szanse na poprawienie sytuacji. Jeśli projekt jest jeszcze względnie nowy, mogą próbować coś ratować, ale nie mogą uciekać od tworzenia nowych funkcjonalności. W każdym wypadku wypadną gorzej od pierwotnych twórców – będą zawsze pisać wolniej. Dlatego, że twórcy narobili bałaganu, w którym teraz trzeba się odnaleźć albo dlatego, że kodu jest więcej i jest trudniej nawet jak jest schludnie albo też jest średnio i trzeba posprzątać, więc również robi się to wolniej, niż na początku. Bodźce są takie, że najlepiej nic nie sprzątać i nie usprawniać, bo za to chwały nie będzie. Więc zwykle się nie sprząta. Tym bardziej, że biznes również tym sprzątaniem nie jest zainteresowany – kosztuje to, skutki bałaganu nadejdą za rok, dwa, pięć, gdy już ich nie będzie, a poza tym trzeba klepać nowe ficzery, bo to przynosi zysk.

Finalna faza rozkładu oprogramowania to legacy dojrzałe. Taka gorgonzola cremoso. Już nie tylko pleśń zielonymi żyłkami przecina nam kod jak w Matriksie, ale też sama struktura jest miękka i z lekka galaretowata. Poprawić nic się nie da, jak nie da się skleić szklanki. Można ją tylko – cytując klasyka – pogryźć i połknąć. I to też robią całymi dniami deweloperzy skazani na opiekę paliatywną nad projektami u progu śmierci. Bug za bugiem, debug za debugiem, w beznadziei dnia codziennego. Nikt nie porywa się tam na zmiany. Zmienić można co najwyżej pracę, ale i o to trudno, bo pracuje się przecież w starych technologiach, a i zapomniało się już nawet jak pisać przyzwoicie, patrząc przez dłuższy czas na starcze wynaturzenia – zrakowiałe struktury danych, zdegenerowane algorytmu i ułomne, antyczne narzędzia o finezji cepa bojowego, ewentualnie wekiery…

Programowanie w ostatniej fazie czeka na decyzję. Na decyzję o przepisaniu go od nowa. I tak zamyka się błędne koło – projekt dostają programiści z ładnym CV, którzy zawsze robią greenfieldy, potem ci mniej bohaterscy, którzy utrzymują systemy wieku średniego, aż w końcu trafia on znów do pielęgniarzy i pielęgniarek, którzy ostatnim ticketem zamkną mu oczy i wyślą na wieczny odpoczynek do krainy wiecznych pętli.

Tyle, jeśli chodzi o diagnozę. Pytanie – co z receptą? Nie umiem sobie do tej pory na nie odpowiedzieć. Wydaje się, że większość systemów informatycznych kończy właśnie w taki sposób i jest to jakimś naturalnym biegiem w cyklu życia oprogramowania. A wy, znacie jakieś alternatywy?

bookmark_borderParada atrakcji

Programowanie to przygoda. Naprawdę. Siadając do komputera i chcąc coś zaprogramować igracie z losem. Jesteście jak bohater antycznej tragedii, który jakby się nie szarpał, jak nie manewrował i tak przeżyje przygody jakich się nie spodziewał. Może nawet polegnie.

Dziś poległem ja.

Nie jest to nic nowego. Dzień jak co dzień w życiu programisty. Pomyślałem jednak, że warto to zanotować nie dla koderów, ale dla – tak zwanego – biznesu, dla osób bez koderskiej praktyki, które dziwią się, że programiści nie lubią wyceniać zadań, że spóźniają się z wykonaniem projektów i że wykonanie prostej czynności zajmuje im kilka dni. Muszą się lenić ci arystokraci IT najpewniej! Czyżby?

Historia zaczyna się niewinnie: chcę wizualnie odświeżyć bloga. Nie lubię jednak – jak większość frontendowców – PHP, więc nikły jest mój entuzjazm w kwestii tworzenia nowego szablonu WordPress. Niewielki research i szybko pojawił się w główce głupi pomysł. Zrobię w Gatsby. Nowy, seksowny framework, oparty na React, musi być przyjemnie i ciekawie!

Zaczynam więc. Szybka instalacja, nieco dokumentacji i jedziemy z dewelopmentem. Już na wstępie nadzieja, że będzie łatwo pada ofiarą rzeczywistości. Gatsby niby to ma coś wygenerować z endpointa GraphQLowego, ale w gruncie rzeczy nie generuje nic. Trudno, napiszę „z palca”.

Do WordPressa dodaję pluginy WP GraphQL i WP Gatsby, jak kontrybutor w dokumentacji przykazał. I nawet udaje się coś pobrać. Tyle, że jakby nie wszystko. GraphQL zwraca jedynie posty po angielsku. No tak – bloga prowadzę w dwóch językach. Trzeba więc wymyślić, jak pobrać te drugie. Łatwo to jednak tylko brzmi. Okazuje się bowiem, że plugin Polylang do obsługi wielu języków rozkłada na łopatki plugin WP Gatsby. Trzeba użyć innego – WP GraphQL Polylang, który jednak odbiera nam możliwość korzystania z wbudowanego w Gatsby klienta GraphQL.

Zainstalowałem zatem klilenta Apollo. Wydawał się działać. Ucieszony napisałem prosty komponent wyświetlający listę postów. Nagłówki, pięknie, wyświetlały się. Tyle, że już nie treść. Treść przychodziła z backendu pusta. Co ciekawe plugin to samo zapytanie inaczej rozwiązywał po stronie klienta i w oknie pluginu WordPress. Ciekawy przypadek. Ciekawy…

Tak był ciekawy, że godzinę co najmniej spędziłem na analizowaniu różnic, nie dopatrzywszy się żadnych istotnych. Kolejne pół godziny zaś na przeszukiwaniu Google w próbie rozwiązania tej zagadki. Tak jednak niestety się okazało, że jest to dość świeża sprawa i w zasadzie nikt o tym nie pisze. Wreszcie znalazłem kanał Slack pluginu i udało mi się w jego historii odnaleźć wzmiankę o autentykacji. Potencjalnie więc brak treści postów wynika z braku uwierzytelnienia. No to już pewnie jesteśmy w domu…

Niefortunnie droga do tego domu okazuje się prosta jak u Barei. Żeby dokonać autentykacji należy zainstalować – i to ręcznie, ściągając samemu z repozytorium Githuba – plugin WPGraphQL JWT Authentication, a następnie wygenerować gdzieś sekret, wkleic go do pliku konfiguracyjnego wp-config, a także upewnić się, że serwer wspiera nagłówek HTTP_AUTHORIZATION. A żeby wspierał trzeba w apache skonfigurować .htaccess i…

I zrobiła się pierwsza w nocy.

Nad tak banalnym zadaniem jak wyświetlenie listy postów pobranych z backendu oraz jego konfiguracja spędziłem dobre 8 godzin i udało mi się jedynie wyświetlić ich nagłówki. To, co miało być najprostsze (konfiguracja backendu) okazało się piramidalnie trudne, a tego, nad czym planowałem spędzić większość pracy (layout frontu, routing, struktura stron) nie udało mi się nawet zacząć.

Owszem – są to w większości technologie mi nieznane, ani z Gatsbym, ani z pluginem  WPGraphQL wcześniej nie pracowałem – ale jednak nie są to tak zupełnie obce mi kwestie. Mimo wszystko kompletnie ugrzęzłem w bagnie ustawień, nieprzewidzianych zależności, specjalnych przypadków i niedoróbek opensource’owym oprogramowaniu.

I tak się proszę państwa uprawia tę deweloperską rolę, co łamie pług i plecy łamie.

bookmark_borderCzytanie kodu

Jako programiści robimy przede wszystkim dwie rzeczy: piszemy nowy kod i czytamy kod stary. Jest to rzecz tak oczywista, że nikt się nad tym nie zastanawia. Mnie samemu wydawało się to banałem. Oczywiście prawie zawsze, żeby napisać jakiś nowy kod trzeba przeczytać istniejący. Często nie trzeba nawet zbyt wiele dodawać, wystarczy zmiana kilku linijek, by wykonać zadanie.

I tak w gruncie rzeczy więcej tego kodu czytamy niż piszemy. Tymczasem od studiów i kursów, przez konferencje, aż po szkolenia – wszystko kręci się wokół pisania. Czysty kod, nowe języki, nowe frameworki. Na rekrutacjach proszą nas o napisanie jakiejś funkcji, na meetupach pokazują jak ładnie i sprawnie pisać przy użyciu nowych narzędzi. I nikt – ale to naprawdę nikt! – nie skupia się na tym, na czym spędzamy większość czasu w pracy: na czytaniu kodu.

Ile znacie narzędzi pomagających w pisaniu? Formatery, lintery, wtyczki do refaktoryzacji, test runnery, podkreślanie błędów, podpowiadanie nazw metod – cuda wianki. A ile znacie narzędzi pomagających w czytaniu? Kolorowanie składni i debugger? Coś jeszcze?

Powiem więcej. Wymienicie choćby trzy książki, które dotyczą czytania kodu?

Ja znam tylko jedną – Praca z zastanym kodem. Najlepsze techniki, Michaela Feathersa. Co więcej jest to książka raczej mało popularna, choć ceniona i polecana…

Oczywiście niełatwe jest stworzenie takich narzędzi. Czytanie kodu to tak naprawdę nauka, to próba zrozumienia pewnego modelu rzeczywistości, który stworzył inny programista. To żmudny proces poznawania struktur danych i algorytmów. Lecz mimo wszystko jest to esencja zawodu programisty. I prawie nikt się nad tą kwestią nie pochyla.

Nienawidzimy brzydkiego kodu, uciekamy z pracy przed spaghetti, przed legacy, a jednocześnie w każdym projekcie spotykam się z debugowaniem przez console.log / printf / WriteLine i brakiem albo co najmniej niedoborem testów jednostkowych. Jest to chyba nasz wspólny grzeszek, że tak mało serca wkładamy w czytanie kodu…

bookmark_borderProgramista. Przewodnik po zawodzie

Właśnie ukazała się w druku moja pierwsza książka – „Programista. Przewodnik po zawodzie”. Napisałem ją dla osób zainteresowanych programowaniem, które szukają odpowiedzi na pytanie – jak to jest być programistą? Skierowana jest do nastolatków zapatrzonych w kod źródłowy, do studentów informatyki oraz do dojrzałych ludzi myślących o przebranżowieniu. Nie jest to kurs programowania – tych jest już wystarczająco wiele. To opowieść o zawodzie.

Z książki tej dowiecie się na czym polega praca w charakterze programisty. Poznacie specjalizacje, wady i zalety zawodu, ścieżki awansu i kariery, zarobki. Przeczytacie w niej o podstawach teoretycznych: systemie binarnym, działaniu procesora, językach programowania, bazach danych i narzędziach, jakich używają w pracy programiści. Dowiecie się, czy programista musi znać matematykę oraz jakie predyspozycje pomogą wam w byciu koderem. Poznacie też kilka słów z programistycznego slangu. Mówiąc krótko – przeczytacie o wszystkim, co was spotka, jeśli wybierzecie zawód programisty.

Jeśli zastanawiacie się, czy programowanie jest dla was, jeśli lubicie je, ale nie wiecie, jaką karierę wybrać, jeśli zastanawiacie się, czy warto się przebranżowić – zachęcam do lektury. Książka jest dość krótka, ale odpowiada na większość pytań.

Mam nadzieję, że „Programista. Przewodnik po zawodzie” wzbudzi entuzjazm wśród tych z was, którzy programowanie lubią i się w nim odnajdują. Wierzę, że przygotuje was do pracy lepiej niż studia albo kurs – bo tam nauczycie się tylko podstaw teoretycznych. Zwykle jednak nikt wam nie powie na czym tak naprawdę ta praca polega. A nie polega tylko na pisaniu programów…

Zachęcam do lektury i powodzenia w kodzeniu 🙂

bookmark_borderSzach-mat w 2.27 KB

Programiści to bystrzy ludzie. Niektórzy z nich to jednak naprawdę piekielnie inteligentne bestie. Nic nie dowodzi tego lepiej niż perwersyjne zabawy z kodem…

Konkursów na dziwny kod jest sporo, wiele też jest konkurencji. Jedną z nich jest quine. Zabawa polega tu na stworzeniu aplikacji, która wypisze własny kod źródłowy. Problem zrozumiały, ale daleki od prostoty. W przypadku JavaScriptu przykładowy quine wygląda tak:

(function $(){console.log('('+$+')()');})()

Idea tworzenia quine’ów ma zresztą dość ciekawe początki. Nazwa pochodzi od nazwiska amerykańskiego filozofa Willarda Van Orman’a Quine’a, który zajmował się m.in. teorią poznania, empiryzmem i logiką. Szczególnie ważnym tematem zajmującym Quine’a w kontekście programowania była pośrednia auto-referencja. Ciekawą rzeczą jest też Paradoks Quine’a. Przyjrzyjmy się poniższemu zdaniu:

„zwraca fałsz, gdy poprzedza je cytat” zwraca fałsz, gdy poprzedza je cytat.

Zdanie to sugeruje, że jest fałszywe, co jest paradoksalne – ponieważ jeśli jest fałszywe, to, co stwierdza, jest prawdą…

Poza konkursami istnieją też szalone idee. Na przykład języki ezoteryczne – skomplikowane, złożone, nieczytelne i z pozoru bezsensowne języki programowania, które jednakże działają. Tak wygląda kod źródłowy programu wypisującego „Hello world” w jednym z nich, Brainfuck’u:

++++++++++[>+++++++>++++++++++>+++<<<-]>++.>+.+++++++
 ..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.

Na koniec zaś tytułowe szachy. Niejeden programista ma tendencję do uwielbiania programów krótkich, zwięzłych i konkurowania z innymi w skracaniu. „Usunął połowę i robi to samo” – brzmi dla wielu jak komplement. Konkursy na skracanie kodu idą tu o kilka kroków dalej. Jednym z barwnych przykładów są szachy Oscara Toledo napisane w JavaScript.

Program zajmuje 2.27 KB i… generuje szachownicę, figury, umozliwia nam grę i w dodatku gra z nami. Kod wygląda tak:

<script>//(c)2010 Oscar Toledo G.
var B,i,y,u,b,I=[],G=120,x=10,z=15,M=1e4,l=[5,3,4,6,2,4,3,5,1,1,1,1,1,1,1,1,9,9
,9,9,9,9,9,9,13,11,12,14,10,12,11,13,0,99,0,306,297,495,846,-1,0,1,2,2,1,0,-1,-
1,1,-10,10,-11,-9,9,11,10,20,-9,-11,-10,-20,-21,-19,-12,-8,8,12,19,21];function
X(w,c,h,e,S,s){var t,o,L,E,d,O=e,N=-M*M,K=78-h<<x,p,g,n,m,A,q,r,C,J,a=y?-x:x;
y^=8;G++;d=w||s&&s>=h&&X(0,0,0,21,0,0)>M;do{if(o=I[p=O]){q=o&z^y;if(q<7){A=q--&
2?8:4;C=o-9&z?[53,47,61,51,47,47][q]:57;do{r=I[p+=l[C]];if(!w|p==w){g=q|p+a-S?0
:S;if(!r&(!!q|A<3||!!g)||(r+1&z^y)>9&&q|A>2){if(m=!(r-2&7))return y^=8,I[G--]=
O,K;J=n=o&z;E=I[p-a]&z;t=q|E-7?n:(n+=2,6^y);while(n<=t){L=r?l[r&7|32]-h-q:0;if(
s)L+=(1-q?l[(p-p%x)/x+37]-l[(O-O%x)/x+37]+l[p%x+38]*(q?1:2)-l[O%x+38]+(o&16)/2:
!!m*9)+(!q?!(I[p-1]^n)+!(I[p+1]^n)+l[n&7|32]-99+!!g*99+(A<2):0)+!(E^y^9);if(s>h
||1<s&s==h&&L>z|d){I[p]=n,I[O]=m?(I[g]=I[m],I[m]=0):g?I[g]=0:0;L-=X(s>h|d?0:p,L
-N,h+1,I[G+1],J=q|A>1?0:p,s);if(!(h||s-1|B-O|i-n|p-b|L<-M))return W(),G--,u=J;
J=q-1|A<7||m||!s|d|r|o<z||X(0,0,0,21,0,0)>M;I[O]=o;I[p]=r;m?(I[m]=I[g],I[g]=0):
g?I[g]=9^y:0;}if(L>N||s>1&&L==N&&!h&&Math.random()<.5){I[G]=O;if(s>1){if(h&&c-L
<0)return y^=8,G--,L;if(!h)i=n,B=O,b=p;}N=L;}n+=J||(g=p,m=p<O?g-3:g+2,I[m]<z|I[
m+O-p]||I[p+=p-O])?1:0;}}}}while(!r&q>2||(p=O,q|A>2|o>z&!r&&++C*--A));}}}while(
++O>98?O=20:e-O);return y^=8,G--,N+M*M&&N>-K+1924|d?N:0;}B=i=y=u=0;while(B++<
120)I[B-1]=B%x?B/x%x<2|B%x<2?7:B/x&4?0:l[i++]|16:7;for(a=
"<table cellspacing=0 align=center>",i=18;i<100;a+=++i%10-9?
"<th width=60 height=60 onclick=Y("+i+") id=o"+i+
" style='line-height:50px;font-size:50px;border:2px solid #dde' bgcolor=#"+
(i*.9&1?"c0c":"f0f")+"0f0>":(i++,"<tr>"));
a+="<th colspan=8><select id=t style='font-size:20px'><option>♛<option>";
document.write(a+"♜<option>♝<option>♞</select></table>");
function W(){B=b;for(p=21;p<99;++p)if(q=document.getElementById("o"+p)){q.
innerHTML="\xa0\u265f\u265a\u265e\u265d\u265c\u265b  \u2659\u2654\u2658\u2657\u2656\u2655".charAt(I[p]&z);
q.style.borderColor=p==B?"red":"#dde";}}W();
function Y(s){i=(I[s]^y)&z;if(i>8){b=s;W();}else if(B&&i<9){b=s;i=I[B]&z;if((i&
7)==1&(b<29|b>90))i=14-document.getElementById("t").selectedIndex^y;X(0,0,0,21,
u,1);if(y)setTimeout("X(0,0,0,21,u,2/*ply*/),X(0,0,0,21,u,1)",250);}}
</script>

            Resultat zaś tak: