Kuidas ma kasutan AI-d töös, kus ma enam ise koodi ei kirjuta
Mul on Claude tokenid selleks nädalaks peaaegu otsas, reset tuleb kolmapäeva hommikul, seega pean vahepeal leidma muid tegevusi. Otsustasin seega kirja panna, kuidas ma AI-d enda töös kasutan.
Ja ma kasutan seda palju.
Ehitan ja müün tarkvara nimega EmailEngine, mille kliendid on eelkõige teised tarkvaraettevõtted. Praeguseks on maksvaid kliente üle 200, nii tuntud kui tundmatuid nimesid 38 erinevast riigist.
Ma ei hakanud koodi ajalugu üle kontrollima, aga julgen üsna kindlalt väita, et viimase aasta jooksul pole ma käsitsi kirjutanud mitte ühtegi koodirida. Kogu uus kood tuleb AI-lt.
Minu roll on muutunud pigem tootejuhiks, kes kirjeldab, mida on vaja teha, kontrollib tulemust ja otsustab, kas see lahendus on üldse mõistlik. Koodi ennast ma enam eriti ei kirjuta.
Et anda mingit mõõtkava, siis viimase 12 kuu müügitulu, ehk perioodil, mil kogu uus kood tuli AI-lt, on olnud veidi üle 200 000 euro. Ettevõttes on üks töötaja - mina. Seega päris mänguprojektiga enam tegemist ei ole.
Kolm subscriptionit
Mul on hetkel kolm erinevat AI subscriptionit, millest igaühel on üsna konkreetne roll.
- Claude Max 20x koodi kirjutamiseks, põhiliselt Opus 5
- ChatGPT tavaliseks AI chatiks ja Codex masintõlgete jaoks, seal kasutan GPT-6 Astra mudelit
- Kimi turvaauditite jaoks, mudeliks K3
Koodi kirjutamine
Koodi kirjutab täielikult Claude.
Enamiku ülesandeid teeb Opus 5, suuremate tööde jaoks kasutan Fable 5.1. Vahe nende vahel tuleb eriti hästi välja ülesannete puhul, kus ei ole vaja muuta ühte funktsiooni, vaid korraga suurt osa rakendusest.
Näiteks liigutasin hiljuti EmailEngine veebiliidese Bootstrap + SB Admin 2 pealt Tailwind + FlyonUI peale.
Olin seda tegelikult juba aastaid plaaninud, aga käsitsi tehes tundus ettevõtmine röögatult suur. Vana UI töötas, kliendid said hakkama ning minu aeg tundus mõistlikum kuhugi mujale panna. Klassikaline "teen kunagi ära" ülesanne, kus "kunagi" tavaliselt tähendab "mitte kunagi".
Opusega ei olnud nii suurt migratsiooni eriti mõtet teha. Ta suudab küll suure osa tööst ära teha, aga pärast jääb liiga palju väikeseid katkiseid asju püsti ning lõpuks tuleb hakata neid ükshaaval taga ajama.
Fable 5.1 tegi sisuliselt kogu migratsiooni paari tunniga ära. Järgmises EmailEngine release'is oligi uus frontend juba sees.
See ei tähenda muidugi, et annan prompti "tee uus UI" ja lähen ise lõunale. Suurem osa tööst on lihtsalt liikunud teisele tasandile.
Pean piisavalt täpselt kirjeldama, millist tulemust tahan, millised olemasolevad asjad peavad endiselt töötama, mida ei tohi muuta ja kuidas ma saan lõpuks kontrollida, et tulemus on õige. Kui kirjeldus on halb, tuleb enamasti ka tulemus halb. Ainult et nüüd ei pea ma halva idee realiseerimiseks enam ise mitu päeva koodi kirjutama.
Tavapärane ülesanne näeb välja umbes nii, et kirjeldan Claude'ile soovitud tulemust ning palun tal:
- teha vajalikud koodimuudatused
- lisada või muuta selle funktsionaalsusega seotud teste
- vajadusel uuendada npm mooduleid
- jooksutada "/simplify"
- jooksutada "/security-review"
- parandada kõik leitud probleemid
- lasta kood Prettieriga üle
- käivitada testid
Alles siis tuleb commit ja push.
Push triggerdab serveripoolse CI ning deploymenti testinstantsidesse, kus saan muudatust juba päris rakenduses katsetada.
Ehk AI kirjutab küll kogu koodi, aga päris niisama ma repository suunas muudatusi ei loobi.
Koodi ülevaatamine
Sellega on lihtne - ma enam ei tee seda.
Kui hakkasin paar aastat tagasi AI abil koodi kirjutama, lasin tal teha ainult väikeseid juppe ja lugesin pärast kõik käsitsi üle. Alguses tundus täiesti arusaamatu mõte panna productionisse koodi, mida ma ise rida-realt kontrollinud ei olnud.
Praeguseks on AI kirjutatud koodi maht kasvanud nii suureks, et mul pole selleks lihtsalt enam aega.
Selle asemel olen käsitsi code review asendanud AI code review ja automaattestidega.
Kui EmailEngine'il oli alguses umbes 100 integratsioonitesti, siis praegu on neid ligikaudu 8000. Ka testid kirjutab AI ning need tulevad koos muudatusega.
Põhimõte on üsna lihtne. Kui parandatakse bugi või lisatakse uus käitumine, peab AI võimalusel kõigepealt näitama, et uus test ilma parandatud koodita feiliks ning pärast muudatust töötab. See ei tõesta, et koodis pole ühtegi probleemi, aga vähemalt tõestab midagi.
Kas see püüab 100% vigadest kinni? Loomulikult mitte.
Aga ei püüdnud ka siis, kui kogu koodi kirjutasin ja kontrollisin ise.
Mul on mõned suuremad kliendid, kes üritavad EmailEngine'ist maksimumi välja pigistada ja satuvad seetõttu aeg-ajalt sellistesse kohtadesse, kuhu keegi varem sattunud pole. Sealt tuleb endiselt bugisid välja.
Varem olid need minu bugid. Nüüd on AI bugid.
Kliendi seisukohast pole sellel ilmselt erilist vahet.
TypeScript aitab AI-d rohkem kui mind
Uuema koodi olen järjest liigutanud TypeScripti peale.
Ise ma käsitsi TypeScripti kirjutada väga ei viitsi ning JavaScriptiga sain üle 20 aasta üsna hästi hakkama, aga AI puhul on TypeScript minu meelest selgelt parem variant.
Põhjus on lihtne - tüübikontroll annab veel ühe automaatse piiri, millest valesti kirjutatud kood peab läbi pääsema. Kui AI annab funktsioonile vale tüüpi väärtuse või muudab kusagil interface'i ära nii, et ülejäänud kood sellega enam kokku ei sobi, saab kompilaator vähemalt protestida.
AI jaoks pole ka erilist vahet, kas kirjutada JavaScripti või TypeScripti. Ta ei väsi tüüpe lisades ära.
Mina küll väsiks.
Tõlked
EmailEngine avalik osa on mitmekeelne.
Esimesed tõlked tulid kunagi päris inimestelt, aga praeguseks on kogu protsess masintõlke peal.
Kui Claude lisab uue funktsionaalsuse, teeb ta tavaliselt kohe ka esimese ringi tõlkeid. Need on kasutatavad, aga üsna keskpärased.
Kui funktsioon on valmis, lasen Codexil kõik uued ja muudetud tõlked GPT-6 Astra mudeliga üle käia.
Siin on Codexil üks päris suur eelis tavalise copy-paste tõlkimise ees - ta näeb kogu koodi ning saab vaadata otse koodist, kus konkreetset stringi kasutatakse. Kas see on nupu tekst, veateade, seadistuse kirjeldus või midagi muud. Claude saab teha sama ja teebki, aga kvaliteet on kuidagi konarlikum, eriti pikemate tekstide puhul.
Turvavigade otsimine
Turvavigade jaoks on mul kaks taset.
Esimene on Claude'i "/security-review", mida jooksutan iga suurema muudatuse juures. See vaatab eelkõige värskelt muudetud koodi ja leiab sealt tüüpilisemaid probleeme - näiteks XSS võimalusi, valesti tehtud input validationit, kahtlaseid permission check'e ja muud taolist.
Kõik, mida ta leiab, tuleb enne commiti ära lahendada.
Teine tase on Kimi K3, mida kasutan aeg-ajalt sügavamaks auditiks. Seal ei anna ma ette ainult viimaseid muudatus, vaid lasen tal vaadata suuremaid koodiosi ning proovida aktiivsemalt leida kohti, mida oleks võimalik kuritarvitada.
Claude'i ja Fable'iga on selliste auditite tegemine olnud keerulisem, sest mingist hetkest hakkavad nende turvapiirangud ette tulema - mudel ei tea, kas repository, mida ma palun rünnata, kuulub tegelikult mulle. Hiina mudelitel selliseid moraalseid dilemmasid vähemalt praegu eriti ei paista olevat.
Mida ma siis ise teen?
Ma ei kirjuta enam üldse koodi, aga tarkvara arendamisega tegelen vähemalt sama palju kui varem.
Ma loen klientide bugiraporteid, vaatan logisid, mõtlen läbi, mis tegelikult katki on, otsustan, kuidas mingi funktsioon peaks töötama, kirjeldan lahenduse AI-le, kontrollin testinstantsis tulemust ja vahel saadan agendi tagasi, sest lahendus tehniliselt töötab, aga on ikkagi vale.
Ehk pudelikael pole enam see, kui kiiresti ma suudan koodi klaviatuurilt sisse toksida. Pudelikael on see, kui hästi ma suudan aru saada, mida üldse teha tuleb.
See sobib mulle tegelikult päris hästi. Olen tarkvara kirjutanud piisavalt kaua, et järjekordse API endpointi või HTML vormi käsitsi valmis toksimine ei anna mulle enam mingit erilist elamust.
Probleemi välja mõtlemine on huvitavam.
Kas ma läheks tagasi käsitsi kodeerimise juurde?
Ma ei kujuta seda eriti ette.
Ma saan täiesti aru, miks inimestele käsitsi kodeerimine meeldib. Mulle meeldis ka ja teatud tüüpi probleemide puhul on see kindlasti endiselt parim viis töötada.
Aga enamiku rakendustarkvara puhul tundub see mulle praeguseks lihtsalt kohutavalt aeglane ja ebapraktiline.
Ilmselt ei kao käsitsi programmeerimine kunagi täielikult ära. Ka assemblerit kirjutatakse siiani, sest on olukordi, kus on vaja saavutada väga konkreetne tulemus ning iga detail loeb.
Lihtsalt enamik meist ei kirjuta veebirakendusi assembleris. Ma kahtlustan, et käsitsi koodi kirjutamisega läheb lõpuks sarnaselt.