Manifest AI

Piszę ten wpis żebym mógł na niego wskazać mówiąc „A nie mówiłem?” ewentualnie żeby ludzie o przeciwnym zdaniu mogli zrobić to samo i wskazać, że to ja się myliłem.

LLMy to trochę inna wersja Googla, pod pewnymi względami lepsza pod innymi gorsza. Nie wydaje mi się, żeby to była „technologia przyszłości” podobnie jak nie uważam, że rozwijanie „kompetencji AI” to teraz podstawowa ścieżka rozwoju programisty. 

Uczenie maszynowe (ktoś używa jeszcze tego określenia?) ma swoje zastosowania, im węższe tym lepiej sobie radzi. A LLMom nieźle idzie sprawdzanie pisowni, poprawianie gramatyki,  tłumaczenie czy przeglądanie dużej ilości tekstu. Niektóre proste poprawki w kodzie robią całkiem nieźle, niektóre typy błędów przyzwoicie wyłapują – to coś przydatnego!

Żeby zrobić coś bardziej skomplikowanego ilość promptowania które muszę zrobić dorównuje napisaniu tego samemu. Ktoś może argumentować, że nie posiadam tajemnej umiejętności poprawnego promptowania. Pewnie tak. Ale dla mnie to umiejętność bardziej krucha niż znajomość losowego frameworka JS. 

Zastosowanie AI w programowaniu podsumowałbym jako „No nie jest idealnie ale jest prawie dobrze.. przeważnie… no generalnie musisz to sprawdzać”.  Opiera się na obietnicy, że lada moment, jeszcze miesiąc, maksymalnie rok rzeczywiście będzie produkowało coś porównywalnego z kodem kolegi z pracy.

Kilka miesięcy temu CTO firmy dla której pracuje (napewno korzystałeś\korzystałaś z jej usług), na moje pytanie czy jest jeszcze w organizacji miejsce dla ludzi którzy chcieliby rozwijać się tylko w tradycyjnym programowaniu zaprzeczył twierdząc że AI skills to przyszłość. Porównał też brak chęci rozwoju w tym kierunku do programowania w Cobolu.

Z mojej perspektywy CTO większości firm mają zbiorowe FOMO dt. tego że ich firma nie będzie wystarczająco dobra w AI i „zostanie w tyle”. Nikt nie licytuje  się już kto ma lepszy uptime, monitoring, bardziej bezobsługowy samoleczący system czy więcej kontrybucji do Open Source. Dopuszczam możliwość, że są wśród nich osoby o bardziej wyważonym podejściu do AI ale nie dają po sobie poznać przez presje akcjonariuszy. Czekam z niecierpliwością na pierwszego CTO który zmieni podejście do wpychania wszędzie LLMów, czekam też na tłumaczenia w stylu ”To wydawało się słuszne podejście, wszyscy tak robili”.

Nie zaprzeczam, że kiedyś może  powstać technologia AI która będzie robiła wszystko to co ja (także niezwiązane z programowaniem) dużo lepiej ode mnie. Ale to nie będzie papuga która zastanawia się nad każdym słowem osobno.  Znam koncepcje Chińskiego pokoju i nie uważam że żeby AI było porównywalne z ludzkimi umiejętnościami musi odzwierciedlać działanie mózgu ale nie wydaje mi się żeby było w stanie to osiągnąć aktualnym podejściem typu Mądry Hans

Gdyby jednak się okazało że bardzo się myliłem to wcale nie – ja tylko halucynowałem.

TDD Test Driven Development: By Example

TDD zaczyna od końca

Opis systemu zaczyna się od opisywania funkcji które oferuje.
Opis funkcji zaczyna się od opisania pożądanego stanu którym skutkuje wywołanie funkcji.
Implementacje zaczyna się od napisania testów które wykorzystują tą implementacje.
Testy zaczyna się od pisania asercji która weryfikuje czy test przeszedł.

Cykl TDD

  • napisanie testu który nie przechodzi
  • napisanie kodu który przechodzi test jak najprostszym sposobem
  • refactor

Test nie przechodzi

Pierwsza część cyklu sprawdza założenia (być może warunek będzie już spełniony np. przez wykorzystywaną bibliotekę).
Istotne jest żeby być jak najkrócej w „CZERWONYM” etapie. To sprawia że skomplikowany problem jest rozbijany na mniejsze fragmenty o których łatwiej myśleć.
Istotna jest umiejętność robienia zmian w wielu krokach by utrzymać powyższy cykl. Jeśli coś jest oczywiste można skumulować kilka zmian ale jeśli testy nie przechodzą należy wrócić do małych kroków.
Zmniejszanie „CZERWONEGO” etapu skutukuje szybszą informacją czy poprzednia decyzja (najlepiej jedna) była słuszna.

Banalna implementacja

Druga część cyklu sprawdza zasadność testu – wyklucza pisanie skomplikowanej implementacji czegoś niepotrzebnego/błędnego. Jest to realizowane przez:

  • napisanie kodu który hardcoduje pożądaną wartość (Fake)
  • zaimplmentowanie oczywistego rozwiązania (Obvious Implementation)

Refactor

Trzecia wprowadza porządek. Wraz z dopisywaniem testów implementacja staje się coraz bardziej ogólna.
Jeśli kod dalej jest tylko sumą różnych przypadków może pomóc triangulacja czyli napisanie testów dla różnych danych (nie koniecznie skrajnych). To może uwidocznić algorytm do zaimplementowania.

Zbyt silne powiązanie testów z implementacją jest złe. Musi być możliwość dopisywania kolejnych testów bez zmiany kodu źródłowego.

Kolejny cykl

Należy zajmować się tylko jednym zagadnieniem na raz a pozostałe spisywać. Ze spisanych najlepiej wybierać te które wydają się proste do zrobienia (ale nie koniecznie te najprostsze – te nic nie wniosą).
Jeśli już praca nad zagadnieniem jest przerwana czymś pobocznym nie należy przerywać przerwania.
TDD i YAGNI są bardzo blisko związane. Nie należy pisać czegoś do czego nie ma testów a nie należy pisać testów do czegoś co nie jest wymagane w tym momencie.
Nowe funkcje można dodawać tylko w „ZIELONYM” etapie (żeby pracować tylko nad jedną rzeczą na raz).

Ogólne

TDD sprawia, że architektura jest dopasowana do aktualnych, nie przyszłych, wymagań.
Wątpliwości trzeba wyrażać w formie testu.
Zaczynać pisanie testów od przypadku który nie wymaga żadnego działania (zdegenerowany przypadek) lub dla najprostszych wariantów.

Dobrze pisać testy służące do nauki zewnętrznej biblioteki. Jak za długo nie ma postępu to zacznij od nowa.
Dobrze zostawiać czerwony test na następny dzień – będzie wiadomo od czego zacząć.

Źródła:
„Test Driven Development: By Example” Wydanie I Kent Beck