Dlaczego AI nie napisze za Ciebie idealnego kodu?

Dlaczego AI nie napisze za Ciebie idealnego kodu?
Współczesna inżynieria oprogramowania zachłysnęła się możliwościami generatywnej sztucznej inteligencji. Obietnica automatycznego tworzenia systemów na podstawie prostych poleceń jest kosząca, ale kryje w sobie fundamentalne zagrożenie.

Inspiracją do tych rozważań stało się wystąpienie Gilesa Chamberlina na konferencji NDC TechTown 2025. W swoim wykładzie pod prowokacyjnym tytułem „Eliminating bugs: testing is not enough”, rzucił on wyzwanie tradycyjnemu podejściu do kontrola jakości. Jego teza jest prosta, ale wywraca stolik mówiąc, że samo testowanie to za mało, jeśli fundamenty, na których budujemy kod, są zbyt miękkie. 

Iluzja poprawności i słabość słów

Głównym problemem w relacji człowiek-maszyna jest fakt, że język naturalny jest z definicji płynny i kontekstowy. Kiedy prosimy AI o funkcję obsługującą porty sieciowe, system operuje na statystycznym prawdopodobieństwie wystąpienia słów, a nie na zrozumieniu fizycznych ograniczeń protokołu. 

Nawet najbardziej sformalizowane dokumenty techniczne bywają nieszczelne, gdy zostaną spisane w formie opisowej. Chamberlin przytoczył historię z życia swojej firmy, w której system konferencyjny crashował, bo technik wpisał w pole portu TCP… numer telefonu. Kod przyjął to bez mrugnięcia okiem, bo technicznie był to po prostu ciąg cyfr. 

*Warto wiedzieć czym jest port TCP. Wyobraź sobie IP jako adres biurowca. Porty to numery konkretnych okienek w tym budynku (np. jedno dla stron WWW, inne dla poczty). Standard przewiduje tylko 65 535 takich okienek. Numer telefonu jest po prostu za długi. To tak, jakbyś chciał wysłać list do mieszkania numer 9 000 000 w bloku, który ma tylko 100 mieszkań.

Jeśli profesjonalna specyfikacja potrafi zawieść człowieka, to sztuczna inteligencja, pozbawiona inżynierskiego instynktu, tym bardziej wygeneruje kod, który wygląda na doskonały, ale merytorycznie jest dziurawy jak sito. 

Lepiej, żeby system „wybuchł” wcześniej

Jednym z najważniejszych punktów prelekcji Chamberlina był postulat: „Wcześniejsza eksplozja (awaria) jest lepsza”. W informatyce nie ma nic gorszego niż błąd/defekt, który nie przerywa pracy programu, lecz po cichu niszczy dane. 

Sztuczna inteligencja ma tendencję do generowania rozwiązań „uprzejmych” i bezpiecznych wizerunkowo. Modele językowe często piszą kod, który za wszelką cenę unika nagłego przerwania pracy – stosują ogólne bloki przechwytywania wyjątków lub zwracają wartości domyślne tam, gdzie system powinien natychmiast zgłosić błąd krytyczny. 

To „wyciszanie” błędów to najgorsza możliwa praktyka. Sprawia, że błąd powstały głęboko w logice ujawnia się dopiero w interfejsie użytkownika, w formie trudnej do zdiagnozowania awarii. 

*Zasada fail-fast to filozofia projektowa „psuj się szybko”. Lepiej, żeby system wyłączył się natychmiast po wykryciu błędu (jak kontrolka braku oleju), niż żeby działał niepoprawnie przez kolejne godziny, korumpując bazę danych. 

Tester jako strażnik granic systemu

W dobie automatyzacji pisania kodu rola testera ewoluuje. Nie jesteśmy już tylko od wykonywania testów, ale od audytowania szczelności architektury informacji. Aby nie dać się złapać w pułapkę nieprecyzyjnych poleceń dla AI, musimy stosować mechanizmy, które nie zostawiają miejsca na domysły.

Jednym z nich jest porzucenie obsesji prostoty. Poleganie na zwykłych liczbach czy tekstach (np. int dla portu) to zaproszenie do katastrofy. Powinniśmy wymuszać stosowanie typów silnych, które same w sobie są walidacją (np. typ akceptujący tylko zakres 1-65535). Przykład: zamiast używać zwykłej liczby dla wieku, tworzymy typ Wiek. To inteligentne pudełko, które przyjmuje tylko wartości od 0 do 120. Jeśli użytkownik spróbuje tam wpisać -5 lub 2000, system natychmiast odrzuci taką prośbę. 

Kolejny dotyczy tego, że stany niemożliwe nie mogą istnieć. Dobry system to taki, w którym nie da się zaszyć defektu. Jeśli funkcja matematyczna wymaga liczb dodatnich, system typów powinien odrzucić ujemną wartość już na etapie kompilacji, zanim kod w ogóle trafi do wykonania. 

Ostatni z kolei zakłada jawność zamiast domysłów. Zamiast pustych wartości (null), które prowadzą do nieoczekiwanych crashy, należy stosować typy opcjonalne. Jest to zabezpieczenie, które zmusza programistę (lub AI) do sprawdzenia, czy dane na pewno dotarły, zanim spróbuje ich użyć. 

AI to tylko generator hipotez

Sztuczna inteligencja nie zastąpi rzetelności. Jest jedynie maszyną do zgadywania, jak może wyglądać rozwiązanie. Krytyczne podejście testera musi polegać na kwestionowaniu każdej linii wygenerowanej przez algorytmy.

Prawdziwa jakość nie bierze się ze sprawdzania, czy „wszystko działa”. Bierze się z takiego projektowania ograniczeń (często nazywanego Design by Contract – czyli traktowania kodu jak twardej umowy), by defekty nie miały przestrzeni do powstawania. W świecie zdominowanym przez modele językowe, to właśnie twarda, matematyczna struktura kodu staje się ostatnią barierą chroniącą nas przed chaosem wynikającym z niejasności ludzkiej mowy. 

Chcesz zgłębić temat? To tylko wycinek dość ciekawej argumentacji Gilesa Chamberlina. Jeśli chcesz dowiedzieć się więcej o tym, dlaczego testowanie to za mało i jak „oszukać” przeznaczenie w kodzie, koniecznie obejrzyj całe wystąpienie z konferencji NDC TechTown 2025. To godzina solidnej, inżynierskiej wiedzy podanej z brytyjskim humorem. 
 

To powinno Cię zainteresować