Kodni AI yozdi. Javobgarlik baribir sizda.
Kod yozish arzonlashdi, uni tushunish esa yo'q. Endi eng tor joy — tekshiruv, va generatsiya qilingan kodni tekshirish hamkasbning kodini tekshirishdan qiyinroq.

Diff qirq qatordan iborat edi va to'g'ri ko'rinardi. Mijoz dashboardi uchun narx xulosasi: bandlarni olib kel, guruhla, o'rtachasini hisobla, formatlangan jamini qaytar. Toza nomlar, erta return'lar, kerakli joyda izoh. Ikki marta o'qidim, tasdiqladim va e'tiborimni ko'proq talab qiladigandek tuyulgan boshqa ishga o'tdim.
Payshanba kuni chiqdi. Juma kuni support ticket keldi: mijozning dashboardida son turishi kerak bo'lgan joyda NaN ko'rinyapti. Mijoz yangi edi. Uning hali birorta bandi yo'q edi. O'rtacha nolga teng uzunlikdagi massivga bo'lindi, NaN formatter orqali o'tib ketdi, formatter esa — u ham generatsiya qilingan, u ham ishonarli — hech qanday e'tirozsiz uni to'g'ridan-to'g'ri UI'ga uzatdi.
O'sha diffda hech narsa xato ko'rinmasdi. Meni qayta-qayta shu joy o'ylantiradi.
Arzon qism yanada arzonlashdi
Yurgan gap shu: AI dasturiy injiniringni avtomatlashtiryapti. Bu gap bir necha yil shu ishni qilgan har kim yolg'onligini biladigan asosga suyanadi — go'yo qimmat qism kod terish bo'lgan.
Hech qachon unday bo'lmagan. Qimmat qismi — nima qurishni hal qilish, tizimni boshqa uch narsani sindirmasdan o'zgartira oladigan darajada tushunish va qurgan narsang haqiqatan to'g'ri ekaniga ishonch hosil qilish edi. Terish esa shu jarayonning oxiridagi kichkina dumcha edi. Yaxshi kunimda men bir soat kod yozardim va qaysi bir soatlik kodni yozish kerakligini aniqlashga besh soat sarflardim.
Ya'ni aslida yuz bergan narsa o'sha gapdan torroq, lekin baribir ulkan: arzon qism deyarli bepul bo'ldi. Endi men deyarli har qanday narsaning birinchi qoralamasini soniyalarda olaman. Bu chinakam qadrli va men uni har kuni ishlataman — jonimga tekkan boilerplate uchun, hujjatini qirq daqiqa o'qishim kerak bo'lgan notanish API uchun, jumagacha kechiktirib yuradigan migratsiya skripti uchun. "Nima xohlashimni bilaman" bilan "ekranda kod turibdi" orasidagi ishqalanish asosan yo'qoldi.
Lekin bularning hech biri qimmat qismni arzonlashtirmadi. Qaror qabul qilish va tekshirish qanchaga tushgan bo'lsa, shunchaga tushyapti. Generatsiya ancha tezlashgani uchun endi quvurning tor joyi — tekshiruv. Hamma narsa uning ortida navbatda turadi.
Mashinani tekshirish odamni tekshirishga o'xshamaydi
Men ko'p odam kodini review qilganman va o'sha ko'nikma o'tib ketadi deb o'ylagandim. Kutganimdan kamroq o'tar ekan, sababini esa aniq aytish arziydi.
Hamkasb g'alati narsa yozganda, o'sha g'alatilik axborot tashiydi. Alahsiragandek retry loop, ortiqchaga o'xshagan null tekshiruv, teskari ko'ringan taqqoslash — bular odatda biror ma'no anglatadi. Balki u o'tgan chorakda o'sha kutubxonada bugga duch kelgandir. Balki o'sha endpoint chindan seshanba kunlari null qaytarardir. G'alatilik — sabab borligining signali, va so'raydigan odam bor. Mening eng yaxshi review savollarimning yarmi "bu nega bu yerda?" degan savolning u yoki bu ko'rinishi bo'lgan.
Generatsiya qilingan kodda bunday signal yo'q, chunki unda niyat yo'q. G'alati qator model minglab shunga o'xshash kod bazalaridan o'rgangan haqiqiy chekka holatni ifodalayotgan bo'lishi mumkin. Yoki shunchaki statistik jihatdan oldingi qatordan keyin kelgani uchun turgan bo'lishi mumkin. So'raydigan odam yo'q. Modeldan so'rasangiz, u ishonchli, ravon va butunlay keyin to'qilgan tushuntirish beradi — bu xotira emas, ratsionalizatsiya.
Ustki qatlam esa bir tekis. Junior injiner kodi junior yozganday ko'rinadi: nomlar chayqaladi, struktura cho'kadi va ko'zingiz kerakli joylarda sekinlashadi. Generatsiya qilingan kod esa hamma joyda uslub jihatdan a'lo. Nomlar izchil, dekompozitsiya mantiqli, izohlar joyida. Review sezgim mashq qilgan vizual belgilar — meni yaqinroq engashishga majburlaydiganlari — asosdagi to'g'rilikdan uzilib qolgan. Hamma narsa malakali odam yozganday o'qiladi, jumladan xato bo'lgan qismlar ham.
Ishonarlilik bilan to'g'rilik bir-biridan ajralib ketdi, mening sezgim esa ular birga yuradigan dunyoda kalibrlangan edi.
Nosozlikning shakli
Nosozliklarning o'ziga xos shakli bor. Ular deyarli hech qachon o'rtada xato bo'lmaydi. Happy path'da to'g'ri va chekkalarda jimgina xato.
// Generatsiya qilingan. Men o'ylagan har qanday kirish uchun to'g'ri.
function averageOrderValue(orders: Order[]): number {
const total = orders.reduce((sum, o) => sum + o.amount, 0);
return total / orders.length;
}Buyurtmalari bor mijoz uchun bu aynan to'g'ri. Yangi mijoz uchun esa NaN qaytaradi, NaN esa mumkin bo'lgan eng yomon nosozlik qiymati, chunki u exception tashlamaydi. U oqim bo'ylab pastga oqadi, satrga formatlanadi, hisobotga yoziladi va tug'ilgan joyidan uch tizim narida yuzaga chiqadi.
Bir marta ko'ra boshlasangiz, xuddi shu shakl hamma joyda uchraydi. Timezone:
// Generatsiya qilingan. UTC'da to'g'ri. Dunyoning yarmi uchun xato.
function isToday(date: Date): boolean {
return date.toISOString().slice(0, 10)
=== new Date().toISOString().slice(0, 10);
}Bu mutlaqo oqilona ko'rinadigan kod qatori, lekin u jimgina "bugunmi — UTC bo'yicha" degan ma'noni anglatadi. Toshkentdagi foydalanuvchi uchun u har kuni besh soat davomida xato ishlaydi va mashinasi UTC'da ishlaydigan odam yozgan har qanday testdan o'tib ketaveradi.
Parallellikda ham xuddi shu tabiat:
// Generatsiya qilingan. Bitta chaqiruvchi bilan to'g'ri. Ikkitasi bilan — race.
async function incrementUsage(userId: string) {
const row = await db.usage.find(userId);
await db.usage.update(userId, { count: row.count + 1 });
}O'qi-o'zgartir-yoz, tranzaksiyasiz, atomik increment'siz. Har qanday qo'lda testda ham, CI'da ham ishlaydi. Yuk ostida esa hisobni yo'qotadi — hech kim qayta hosil qila olmaydigan billing nomuvofiqligi ko'rinishida.
Bularning birortasi ahmoqona emas. Xavfli qiladigan narsa aynan shu. Har biri — malakali, biroz shoshayotgan injiner asosiy holat haqida o'ylab turib yozadigan kod. Bu esa modelning qilayotgan ishini adolatli tasvirlaydi. Modelning o'tmishida timezone'ni shaxsiy dushmanga aylantirgan production incident bo'lmagan.
Tekshiruv o'qishdan ishga tushirishga ko'chdi
Amaliy oqibat shuki, endi men ko'zimga kamroq, asboblarimga ko'proq ishonaman.
Ilgari o'qish yaxshi tekshiruv usuli edi. Kod odatlarini bilgan odamdan kelganda, uni o'qish menga ko'p narsa aytardi. Endi o'qish menga kod yaxshi tuzilganini aytadi — bu esa hech qachon savol bo'lmagan. Shuning uchun chindan bajariladigan narsalarning qiymati oshdi: yomon holatni ifodalab bo'lmaydigan qiladigan tiplar, kontraktni mixlab qo'yadigan testlar va g'alati kirish bilan haqiqatan ishga tushirib ko'rish degan mutlaqo jozibasiz amal.
Tiplar ilgarigidan ko'proq foyda beradi. function averageOrderValue(orders: Order[]): number son va'da qiladi, NaN yetkazadi. Agar imzo number | null bo'lganida yoki parametr bo'sh bo'lmagan massiv tipida bo'lganida, nosozlik support ticket emas, kompilyatsiya xatosi bo'lardi. Ilgari ortiqcha marosimdek tuyulgan cheklovlar endi o'zini oqlaydi, chunki ular review'ning kechqurun soat oltida charchamaydigan qismi.
Testlar ham ko'proq foyda beradi, lekin faqat ularning to'g'ri uchidan ushlab tursangiz. Modeldan test so'rasangiz, u o'tadigan testlar yozadi — ko'pincha bugni tug'dirgan o'sha taxminlarni qayta kodlab. U orders.length ni bo'luvchi qilib generatsiya qildi; endi u orders hech qachon bo'sh bo'lmaydigan test to'plamini generatsiya qiladi. Test va kod bir tomonga xato bo'ladi, bu esa testsizlikdan yomonroq, chunki endi sizda yashil belgi bor.
Shuning uchun men bitta chiziqni ushlab turaman: test kontraktni belgilaydigan bo'lsa, uni men yozaman. Hamma testni emas — testlarning ko'pi hajm, hajm esa modelning aynan kuchli tomoni. Lekin bu funksiya aslida nima va'da qilishini aytadigan sanoqli testlar — jumladan massiv bo'sh bo'lganda va soat Toshkentda bo'lganda nima va'da qilishini — bu spetsifikatsiya. Spetsifikatsiyani tekshirmoqchi bo'lgan narsangizga topshirish — aylanma mantiq.
Aniq spetsifikatsiya — qiymati oshayotgan ko'nikma
Foydali kod olish-olmasligimni eng ishonchli bashorat qiladigan narsa — qanchalik aniq so'raganim.
Noaniq prompt siz so'ramagan savolga ishonarli javob beradi. "Bu endpoint'ga caching qo'sh" degan so'rovga caching olasiz — o'ylab topilgan TTL, o'ylab topilgan kalit sxemasi va hech qanday invalidatsiyasiz, chunki bularning hech biri aytilmagan, demak hammasi taxmin qilingan. Kod yaxshi ko'rinadi. Taxminlar esa diffda ko'rinmaydi; ular oddiy qatorlar sifatida turadi.
"Buni foydalanuvchi kesimida 60 soniyaga cache qil, kalit userId plus tarif darajasi bo'lsin, obuna o'zgarganda invalidatsiya qil va xatolarni cache qilma" degan so'rov menga chindan baholay oladigan narsa beradi, chunki endi diff yo aytganimga mos keladi, yo kelmaydi. Review'ni umuman mumkin qiladigan narsa — spetsifikatsiya.
Bu junior injinerga vazifa topshirishni yaxshi eplaydigan odamdagi ko'nikmaning o'zi, faqat tezroq ishlaydi va qarshilik ko'rsatmaydi. "Qarshilik ko'rsatmaydi" degani — xavfli yarmi. Junior "shoshmang, buyurtmasi bo'lmasa nima bo'lishi kerak?" deb so'raydi. Bu savol — sovg'a; bu kod paydo bo'lishidan oldin sodir bo'ladigan review. Model so'ramaydi. U oqilona ko'rinadigan bir narsani tanlab, oldinga yuradi va siz hech qachon qabul qilmagan qaror endi kod bazangizda o'zingiz qabul qilgan qarorday bo'lib o'tiribdi.
Men qat'iy turmaydigan joy
Atrofiya dalilida ishonchim komil emas va bu noaniqlikni chiroyli qilib hal qilgandan ko'ra, ochiq aytmoqchiman.
Xavotir tushunarli: agar men o'sha loop'ni hech qachon yozmasam, loop'ning his-tuyg'usini yo'qotaman, generatsiya qilingan variant g'alizligini aytadigan narsa esa aynan o'sha his. Bunda jon bor. Bir yil davomida topshirib kelgan ishlarimda sekinlashganimni sezyapman.
Lekin qarshi dalil kuchli va uni qo'l siltab yuborib bo'lmaydi deb o'ylayman. Biz assembly yozishdan allaqachon voz kechganmiz. Ishlayotgan injinerlarning deyarli hech biri o'z dasturi aylanadigan mashina kodini qo'lda yoza olmaydi, sanoat esa qulab tushmadi; aksincha, qo'lda qurib bo'lmaydigan narsalarni qurdi. Biz qo'lda xotira boshqaruvidan, keyin qo'lda DOM manipulyatsiyasidan, keyin qo'lda server provisioning'dan voz kechdik. Bu o'tishlarning har birida kimdir hunar o'lyapti deb turib olgan. Har safar hunar bir pog'ona yuqoriga ko'chdi va yanada shijoatliroq bo'ldi. Bu qonuniyat shu qadar kuchliki, unga qarshi tikish qo'yish ahmoqona ko'rinadi.
Mana shu qonuniyatga sig'dira olmayotgan narsam. Oldingi har bir abstraksiya deterministik edi. Kompilyator bir xil kirish uchun bir xil natija beradi, xato qilsa ham qayta hosil qilinadigan tarzda xato qiladi, bug esa ochiladi, tuzatiladi va hamma uchun tuzatilgan qoladi. Men assembly o'qishni to'xtatdim, chunki kompilyatorga kategorik ishonardim — "odatda" emas, tizimning xossasi sifatida.
Bu abstraksiya unday emas. U ko'p hollarda to'g'ri, lekin bu kafolatlanmagan, qayta hosil qilinmaydigan va kirishlar fazosi bo'ylab bir tekis emas. Kompilyatorga ishonish — bir marta qabul qilinadigan qaror. Modelga ishonish — har bir diffda, doimo qabul qilinadigan qaror, va bu qarorni yaxshi qabul qilish uchun kerak bo'lgan ko'nikma — aynan abstraksiya yemirayotgan ko'nikma.
Bu qanday hal bo'lishini bilmayman. Balki tekshiruv asboblari shu darajaga yetadiki, kafolat boshqa joydan keladi — tip tizimi, isbot, chindan ishonsa bo'ladigan test generatori — va o'xshatish oxir-oqibat o'z kuchida qoladi. Balki yozish emas, review qilish bilan o'sgan bir avlod injinerlar menga bu yerdan tasavvur qilib bo'lmaydigan sezgilarni rivojlantirar. Ikkalasi ham mumkin ko'rinadi. Men ikkalasiga ham katta tikish qo'ymasdim va qo'yadigan odamga shubha bilan qarayman.
Commit'da sizning ismingiz turadi
Javob qanday bo'lishidan qat'i nazar, asboblar o'zgartirmaydigan bitta narsa bor.
"Buni AI yozgan" — postmortemda himoya emas. "Stack Overflow'dan ko'chirgandim" hech qachon himoya bo'lmagani sababdan himoya emas. Uni diffga qo'yishni siz tanladingiz, siz tasdiqladingiz va u sizning ismingiz ostida chiqdi. Belgilar qayerdan kelgani uchun hech kim sizni javobgar qilmagan.
Men ushlab turadigan qoida: qatorni tushuntira olmasam, u kirmaydi. "Ehtimol tushunib olardim" emas. Tushuntir — nima qiladi, nega shu yerda, kirish bo'sh bo'lganda nima bo'ladi. Tushuntira olmasam, ikkita variantim bor va odatda to'g'risi — o'chirish.
Buni ishlaydigan qiladigan odatlar jozibasiz:
Chatni emas, diffni review qil. Suhbat ishontiradi, diff esa haqiqat. Modelning tushuntirishini koddan oldin o'qish — bu unga qo'shilishga oldindan tayyorlanish. Avval kodni o'qing, sovuqqonlik bilan, begona odamdan kelgan diffni o'qigandek.
Iloji boricha kichik o'zgarish so'ra. 400 qatorlik diff durustroq review qilinmaydi. Na men tomonidan, na boshqa kim tomonidan, model esa bunday diffni mamnuniyat bilan yasab beradi. Uni siz so'ragan o'zgarish bilan cheklang, review qiling, keyin keyingisini so'rang.
Qabul qilishdan oldin nosozlik holatlarini tushuntirtir. "Bu massiv bo'sh bo'lsa, ikki so'rov bir vaqtda kelsa, foydalanuvchi boshqa timezone'da bo'lsa, bu chaqiruv yarim yo'lda timeout bo'lsa — nima sinadi?" Model ko'pincha buni yaxshi eplaydi — chindan yaxshi, kechqurun soat oltidagi charchagan ko'zlarimdan yaxshiroq. Faqat o'zi aytmaydi. Butun review — shu so'rashning o'zi.
Kontraktni belgilaydigan testlar odam qo'li bilan yozilsin. Qolgan hamma narsani generatsiya qilsa bo'ladi.
Bularning hech biri yangi injinerlik donoligi emas. Diqqat bilan review qil, kontraktlaringni belgila, koding nima qilishini bil. Yangi narsa shundaki, ilgari bu intizomni qisman ishqalanishning o'zi majburlab turardi — to'rt yuz qatorni qo'lda yozish o'sha to'rt yuz qator haqida o'ylagan bo'lishingni anglatardi. Bu majburlash yo'qoldi. Ishqalanish o'zi bajarayotganini bilmagan ishni bajarardi, endi esa siz qilmasangiz, uni hech kim qilmaydi.
Bu asboblar bilan yaxshi ishlayotgan injinerlar — eng tez teradiganlar emas. Ular nima xohlashini allaqachon aniq biladigan va yaxshi ko'ringan kodga allaqachon shubha bilan qaraydigan odamlar. Asboblar bu odatlarni yaratmadi. Ular shunchaki bu odatlar yo'qligi uchun haq ola boshladi.
Ruknlar


