Dlaczego dobre pytania są dziś największą przewagą programisty?
W świecie, w którym kod może powstać w kilka chwil, przewagą programisty staje się umiejętność rozpoznania właściwego problemu i zadania właściwego pytania.

Zostałem zaproszony na spotkanie biznesowe, a w sumie to nawet nie było wiadomo, jakie. Tytuł rozumiał chyba tylko organizator. Agenda była tak ogólna, że pasowałaby zarówno do projektowania systemu, jak i organizacji imprezy urodzinowej.
Na początku spotkania organizator zarysował kontekst w dwóch zdaniach i od razu przeszedł do rozwiązania. Naszym zadaniem było właściwie tylko odpowiedzieć na dwa pytania: czy rozwiązanie jest w porządku i kiedy możemy je dostarczyć.
Nikt nie lubi, jak się przychodzi do niego z rozwiązaniami. Więc naturalnie zaczęły padać niewygodne pytania. Także chciałem zrozumieć problem i dokładałem swoje pytania. O to, po co robimy tę zmianę, o założenia, o rozważane alternatywy. O to, co się stanie, jeśli nie zrobimy tego wcale. Zależało mi na tym by zrozumieć problem. Bo gdybym się na to zgodził, mój zespół musiałby porzucić akutalne projekty i zająć się tym tematem — a to by mocno podkopało nasze morale.
Po kilkunastu minutach okazało się, że nie jesteśmy jeszcze gotowi, aby podjąć decyzję o wdrożeniu zaproponowanego rozwiązania. Spotkanie, które miało zakończyć się zatwierdzeniem gotowego planu, skończyło się tymczasowym rozwiązaniem, bezpiecznym kosztowo. A my nie musieliśmy robić praktycznie nic.
Co to były za pytania?
Większość z tych pytań zaliczają się do grupy pytań krytycznych.
Mówiąc prostym językiem, jest to podejście podobne do detektywa, który specjalnymi pytaniami odkrywa luki w zeznaniach podejrzanego i rozwiązuje zagadkę.
Od czasów Sokratesa, który zaproponował pytania krytyczne, minęło 2424 lata. Zmieniło się prawie wszystko. Ale sama koncepcja jest jak najbardziej aktualna i po prostu genialna.
Weźmy na tapet losowy kod wygenerowany przez AI.
fun calculateDiscount(price: Double): Double {
return price * 0.8
}Przejdźmy po konkretnych grupach pytań, które zweryfikują ten kod. Nie jest to jedyny podział pytań krytycznych. To po prostu sześć grup, z których najczęściej korzystam.
1. Jakie są fakty!
Pytanie, co tu jest faktem! Pomocnicze pytanie — co widzę?
niezmienna price typu double jest mnożona przez 0.8
zwraca doubla
nazwa funkcji to „oblicz zniżkę”
funkcja nic nie loguje
nie ma warunków
Teraz możemy doprecyzowywać każdy z tych faktów — przeważnie będzie to pytanie „dlaczego” albo podobne. Szukamy podstaw, szukamy tzw. zasad pierwszych, głównych, niezmiennych.
Co to jest to 0.8? Dlaczego akurat 0.8? Może w przyszłości będzie 0.9?
Mnożenie — dlaczego akurat mnożenie? Dlaczego nie dzielenie albo odejmowanie?
Dlaczego double? Dlaczego taka precyzja? Dlaczego nie BigDecimal?
Już po pierwszych odpowiedziach znajdziemy potencjalne błędy i możliwości rozszerzeń, a to dopiero początek zabawy. Po ustaleniu faktów dyskusja na trudniejsze tematy trafia na właściwe tory, bo wszyscy zaczynają mówić o tym samym.
2. Weryfikacja założeń!
Co zakłada ten kod? Mając fakty, możemy teraz szukać założeń, które są niejawne. Dzięki temu można znaleźć błędy które wystąpią po uruchomieniu w realnym świecie np na produkcji. Zakładamy że:
price zawsze będzie uzupełniony?
to zawsze będzie naliczanie zniżek?
ktoś inny będzie logował, co tu się dzieje?
funkcja działa?
0.8 to stała?
będzie tylko mnożenie?
3. Perspektywa — jak ten fragment kodu widzą inni.
W tej sekcji próbujemy spojrzeć na problem z pozycji różnych osób, a nawet różnych systemów:
Jak ten kod widzi osoba, która będzie go utrzymywać za dwa lata?
Co na to księgowość, czy to są kwoty brutto czy netto?
Co na to audyt finansowy — czy wszystko audytujemy?
Kto ustawił tę stawkę 0.8? Ktoś to akceptował?
Co na to użytkownik — może chciałby zobaczyć, jak zostało to policzone?
4. Inwersja — odwrócenie — zepsujmy ten kod!
Odwracamy kota ogonem i konstruujemy pytania odwrotne. Zasymulujmy katastrofę.
Co musimy zrobić, aby ten kod się nie zepsuł?
Może przyjść kwota na minusie, null, max?
A co jak nie każdemu policzymy zniżkę?
Co, jak źle policzymy, będziemy o tym wiedzieć?
Może to nie my powinniśmy to liczyć, tylko inny moduł?
Propagator tego typu pytań Charlie Munger, mawiał, że zamiast być inteligentnym, po prostu lepiej nie być głupim. Chodzi tu o maksymalne uniknięcie błędów.
5. Szerszy kontekst i wpływ
Pytania uzupełniające perspektywę, zadane z innej strony które mogą
Jak to wpłynie na inne systemy, inne działy?
Jak będziemy liczyć za dużo zniżek, to może wpłynie to mocno na mniejszy przychód?
Może będziemy chcieli czasami wyłączyć te zniżki i powinna tam być ficzer flaga?
Kto o tym decyduje?
6. Prostota i zasadność: Co jak tego nie zrobimy?
Staramy się w tej sekcji obciąć wymagania do minimum — tak jak brzytwą obcinał Ockham niepotrzebne strony z książek (wtedy bezcenne), tak my pytamy, czy jest to ważne.
Może nie powinniśmy tego robić w ogóle?
Co się stanie, jak tego kodu nie wrzucimy na produkcję?
Jak inaczej wtedy zrobimy te zniżki?
Czasami najlepszym rozwiązaniem jest nie robić rozwiązania. Albo zrobić mniej. I skupić się na rzeczach istotnych.
Podsumowanie
Niesamowite, ile można mieć pytań do 3 linii kodu. Jak dużo fajnych pytań może się pojawić w trakcie rozmyślania za pomocą pytań krytycznych. Niektóre pytania się duplikują, ale lepiej jest zadać pytanie dwa razy niż go nie zadać i popełnić błąd.
