LLM, code review i aktualizacja wiedzy
Za kilka dni pojawi się nowa wersja Javy. Opatrzona numerkiem 21 i literkami LTS, jak Lej Te Setkie. Można świętować. Z tej okazji przypomniał mi się pewien ciekawy problem z jakim miałem do czynienia pewien czas temu. Uważam, że LLM nie odbiorą nam pracy. Wręcz tej pracy będzie więcej. Modele takie jak GPT3-4 potrafią robić za żółtą kaczuszkę. To ważna umiejętność. W dodatku robią to za darmo (no karmimy je kodem, ale to inna sprawa), więc jest taniej niż junior z aktywnym efektem D-K. Do brzegu jednak.
Kod, który napisałem
Był ok.
Listing 1. Proste przepisywanie strumieni
tuple->{
int readLen;
byte[] readBuffer = new byte[4096];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
while ((readLen = tuple._1().read(readBuffer)) != -1) {
outputStream.write(readBuffer, 0, readLen);
}
String content = outputStream.toString();
outputStream.close();
fileContentMap.put(tuple._2().getFileName().replace("dist/", ""), content);
return tuple._2().getFileName();
}
Mamy jakąś krotkę, w której siedzi sobie (Zip)InputStream
i String
. Chcemy ten plik wrzucić do mapy, w taki sposób, że nazwa pliku jest kluczem, a
treść pliku jako String
to wartość. Wrzuciłem powyższy kawałeczek kodu do ChatGPT i poprosiłem o optymalizację.
Listing 2. Wersja od ChatGPT z babolem
tuple->{
try (InputStream inputStream = tuple._1();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
String content = new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
fileContentMap.put(tuple._2().getFileName().replace("dist/", ""), content);
return tuple._2().getFileName();
} catch (IOException e) {
// Handle the exception if needed
e.printStackTrace();
return null;
}
}
IMO, nie jest to idealne. Co prawda nie dałem mu szerszego kontekstu (zamykam to w vavrowski Try
), ale nawet po poprawkach (wywalenie catch
)
wyglądało to średnio w kierunku kiepsko. W dodatku Chat wprowadził dość wrednego buga, który nie jest widoczny na pierwszy rzut oka, ale po porównaniu
fragmentów kodu powinno być to jasne. Nie jest? Podpowiem, że w pierwszym przypadku nie zamykaliśmy IS, bo było to robiona później. Chat zamyka IS i
później to się sypie.
Ale tutaj coś mnie tknęło. Nie jest możliwe, żeby kopiowanie strumieni wymagało napisania aż takiej ilości kodu. Zacząłem grzebać w dokumentacji IS i nagle okazało się, że można napisać „jednolinijkowca”:
Listing 3. Jednolinijkowiec
tuple->{
try(ByteArrayOutputStream outputStream=new ByteArrayOutputStream()){
tuple._1().transferTo(outputStream);
String content=new String(outputStream.toByteArray(),StandardCharsets.UTF_8);
fileContentMap.put(tuple._2().getFileName().replace("dist/",""),content);
return tuple._2().getFileName();
}
}
InputStream
ma metodę transferTo
, która robi wszystko, co potrzeba. Dla spokoju ducha odpaliłem testy i było OK. Plik skopiowany, strumień
otwarty, zero potrzeb. Z ciekawości zapytałem Chat, czy potrafi zamienić pętle na stream API. Wynik był zaskakujący, bo zamiast mapowania i
filtrowania dostałem kod podobny do powyższego. Oczywiście z bugiem. Po zwróceniu uwagi, dostałem „poprawiony kod”… dalej z bugiem. Ale to dopiero
wstęp.
Aktualizacja wiedzy jest trudna
Pierwotny kod napisałem „z głowy”. Robiłem to kilka razy w życiu w różnych językach, ale mechanika była zawsze podobna. Wejście, tablica tymczasowa,
wyjście, powtarzać do osiągnięcia EOF. Tak nauczyli mnie w szkole , tak pisałem w FORTRANie, tak to się pisało dawno temu w C, tak pisało się w Javie.
Istnienie metody transferTo
kołatało się raczej na zasadzie „to musi być prostsze” niż pewności „jest coś takiego”. W dodatku metoda została dodana
już dawno temu. W Javie 9.
Wniosek 1
Ciężko jest aktualizować wiedzę na bieżąco. Ciężko też jest pamiętać o wszystkich zmianach, które zostały wdrożone po tym, jak zakończyłeś intensywną naukę. I nie jest to jakiś odkrywczy wniosek. Młodzi lekarze-radiolodzy lepiej rozpoznają zmiany na zdjęciach niż starsi koledzy. Po prostu są świeżo po praktykach i egzaminach, więc mają dużo większy „współczynnik przerobionego materiału”.
Wniosek 2
Używaj LLM do rozwoju swojego kodu. Każ mu robić code review, ale nie wierz ślepo w wyniki. Analizuj to co podpowie, bo może okazać się, że co prawda nie działa, ale zawiera wartościowe elementy.
Na koniec jeszcze jedno. Pamiętaj, że korporacje dostają sraczki, cholery, wścieklizny i pierdolca na raz, gdy chcesz użyć AI. Dlatego, zanim wrzucisz kod, to się zastanów. Bycie DOBRYM inżynierem jest cenniejsze niż użeranie się z jakimś idiotą, ale może być stresujące.