← Semua tulisan

7 menit baca

AI Menulis Kode Lebih Cepat, tetapi Developer Tetap Harus Memahami Apa yang Dikirim ke Production

AI dapat mempercepat penulisan kode, tetapi developer tetap perlu memeriksa, menguji, dan memahami perubahan sebelum kode masuk production.

  • AI
  • Code Review
  • Engineering

Prompt-nya singkat: “buat endpoint untuk membuat pesanan, lengkap dengan validasi.” Beberapa detik kemudian muncul kode yang bentuknya masuk akal — ada route, ada pemanggilan model, ada try/catch. Kalau dijalankan di mesin lokal dengan data contoh, responsnya 201 Created. Kode itu bahkan lolos formatter dan linter.

Pertanyaan yang belum terjawab: apakah endpoint itu memvalidasi input dengan benar, memeriksa hak akses, menangani kegagalan di tengah jalan, dan mengikuti cara proyek ini biasanya menulis kode? Linter tidak menjawab itu. Yang bisa menjawab hanya orang yang memahami kebutuhannya.

Bagian tersulit dari pekerjaan ini bukan menulis kode lebih cepat. Bagian tersulit adalah memastikan kode yang ditulis — oleh siapa pun, termasuk AI — benar-benar layak berjalan di production.

Yang sebenarnya dipercepat AI

AI coding assistant memampatkan jarak antara niat dan teks. Anda punya gambaran kasar, lalu dalam hitungan detik ada sesuatu yang bisa dibaca, dikritik, dan diubah. Itu manfaat nyata, terutama untuk pekerjaan yang tidak menuntut keputusan desain baru.

Beberapa hal yang memang lebih cepat dikerjakan dengan bantuan AI:

  • Membuat kerangka: route, handler kosong, DTO, konfigurasi, dan file-file yang strukturnya sudah jelas.
  • Menulis kode repetitif yang polanya sudah ada di proyek, misalnya endpoint CRUD kesekian.
  • Menyusun draft unit test untuk fungsi yang sudah ada, yang kemudian Anda tinjau dan lengkapi.
  • Menjelaskan kode lama: “fungsi ini sebenarnya melakukan apa, dan siapa yang memanggilnya?”
  • Menerjemahkan pesan error atau stack trace menjadi dugaan penyebab.
  • Refactor kecil dengan cakupan yang jelas, seperti memecah satu fungsi panjang.

Yang tidak ikut memendek adalah sisa rantainya: memahami kebutuhan, menentukan aturan bisnis, memeriksa asumsi, menguji perilaku, meninjau dampak, dan mempertanggungjawabkan hasilnya. Menulis kode hanya satu langkah dari rantai itu. Kalau satu langkah menjadi sangat cepat sementara langkah lain tetap, keseluruhan proses tidak serta-merta menjadi lebih cepat — yang berubah hanya di mana waktu dihabiskan.

Contoh: endpoint pesanan

Anggap proyek ini punya tabel users, products, dan orders. Endpoint yang diminta adalah POST /api/orders. Proyek sudah punya layer service, sudah punya helper validasi, dan sudah punya konvensi format error.

Berikut ilustrasi kode yang kira-kira dihasilkan dari prompt tadi. Ini contoh untuk dibaca, bukan kode produksi:

// Ilustrasi. Bukan kode yang siap dipakai.
$router->post('/api/orders', function () {
    $body = json_decode(file_get_contents('php://input'), true);

    $order = Order::create([
        'user_id' => $body['user_id'],
        'product_id' => $body['product_id'],
        'quantity' => $body['quantity'],
        'note' => $body['note'] ?? null,
    ]);

    return json_encode(['id' => $order->id]);
});

Tidak ada yang salah secara sintaks. Masalahnya, kode ini lolos dari pertanyaan-pertanyaan yang justru menentukan apakah ia boleh masuk production.

Validasi input. Apakah quantity benar-benar bilangan bulat positif? Bagaimana kalau product_id tidak ada? Apakah note punya batas panjang? Apakah field asing ditolak atau diabaikan? Apakah permintaan yang sama yang terkirim dua kali (misalnya karena pengguna menekan tombol dua kali) akan membuat dua pesanan?

Otorisasi. user_id diambil dari body request. Artinya siapa pun yang punya token bisa membuat pesanan atas nama pengguna lain. Nilai itu seharusnya berasal dari sesi atau token yang sudah diverifikasi, bukan dari input yang bisa dikirim klien. Selain itu, apakah pengguna berhak membeli produk tersebut — misalnya produk khusus tenant, langganan, atau wilayah tertentu?

Keamanan. Pola Order::create($body) yang longgar bisa berubah menjadi mass assignment kalau kolom seperti status atau price ikut terkirim. Pesan error yang dikembalikan langsung ke klien juga berisiko membocorkan detail internal: nama tabel, potongan query, atau isi konfigurasi. Dan kalau nanti ada query yang dirakit dengan konkatenasi string, risiko injection kembali terbuka.

Logika bisnis. Apakah stok diperiksa? Harga diambil dari database atau dari body? Apakah ada jumlah minimum, batas per pengguna, atau aturan diskon yang harus diterapkan? Kondisi batas seperti ini jarang muncul di prompt, dan jarang juga muncul di kode yang dihasilkan.

Database. Membuat pesanan biasanya berarti menulis ke lebih dari satu tabel: orders, mungkin order_items, dan pengurangan stok. Semua itu perlu transaksi, agar kegagalan di langkah kedua tidak meninggalkan pesanan setengah jadi. Perlu juga dipastikan foreign key, tipe data, dan relasi sesuai skema yang benar-benar ada — bukan skema yang diasumsikan AI.

Penanganan error. Apakah respons untuk input tidak valid konsisten dengan endpoint lain? Apakah kegagalan database mengembalikan 500 dengan format yang sama, tanpa membocorkan detail? Apakah ada timeout ketika memanggil layanan pembayaran?

Kesesuaian proyek. Kode ini menulis logika langsung di handler, padahal proyek memakai service layer. Ia juga mengulang validasi manual, padahal sudah ada helper. Hal-hal seperti ini tidak membuat aplikasi crash, tetapi membuat basis kode makin sulit dirawat — dan justru inilah yang paling sering luput dari review cepat.

Setelah ditinjau, versi yang lebih masuk akal bukan sekadar “ditambal”, tetapi disesuaikan dengan pola proyek:

// Ilustrasi hasil review, tetap bukan kode siap pakai.
$router->post('/api/orders', function (Request $request, Response $response) {
    $user = $request->getAttribute('user'); // sudah diverifikasi middleware
    if ($user === null) {
        return $response->withStatus(401)->withJson(['error' => 'unauthenticated']);
    }

    $input = $request->getParsedBody();
    $errors = $this->validator->validate($input, [
        'product_id' => 'required|integer|exists:products,id',
        'quantity' => 'required|integer|min:1|max:100',
        'note' => 'max:500',
    ]);

    if ($errors) {
        return $response->withStatus(422)->withJson(['errors' => $errors]);
    }

    $order = $this->orders->place($user->id, $input); // transaksi + cek stok

    return $response->withStatus(201)->withJson(['id' => $order->id]);
});

Perhatikan bahwa perubahan terpentingnya bukan penambahan kode, melainkan pemindahan keputusan ke tempat yang benar: identitas dari middleware, validasi ke helper proyek, dan transaksi ke layer service.

Cara memeriksa hasil kode AI

Tidak ada urutan yang wajib, tetapi proses berikut berguna sebagai kerangka. Sesuaikan dengan risiko perubahan, bukan menjalankannya sebagai ritual.

  1. Baca diff-nya. Bukan hanya file yang berubah, tetapi juga file yang ikut tersentuh. AI kadang mengubah konfigurasi, menambah dependensi, atau menghapus kode yang tidak seharusnya.
  2. Cocokkan dengan kebutuhan. Buka kembali requirement atau tiket. Setiap perubahan harus bisa dijelaskan hubungannya dengan kebutuhan itu.
  3. Periksa validasi, otorisasi, penanganan error, dan kebocoran data. Ini area yang kesalahannya paling mahal dan paling jarang terlihat di pengujian bahagia.
  4. Jalankan alat yang sudah ada di proyek. Formatter, linter, pemeriksaan tipe, dan static analysis. Kalau alat ini menghasilkan error baru, jangan dimatikan — perbaiki kodenya.
  5. Tinjau test, lalu tambahkan kasus yang hilang. Test yang dihasilkan AI cenderung menguji jalur sukses. Kasus gagal, input kosong, nilai batas, dan duplikasi biasanya harus Anda tambahkan sendiri.
  6. Jalankan test dan baca hasilnya. Jangan mengandalkan kalimat “semua test lulus” dari ringkasan AI. Lihat outputnya, termasuk peringatan yang tidak menggagalkan build.
  7. Pikirkan dampak di luar kode. Perubahan skema, kontrak API, performa query, format log, dan kompatibilitas dengan klien lama.
  8. Review sebelum merge. Untuk perubahan berisiko tinggi — autentikasi, pembayaran, migrasi — minta reviewer kedua. AI tidak menghapus kebutuhan akan empat mata.

Workflow yang lebih aman

Alur yang saya anggap wajar untuk pekerjaan berbantuan AI tidak berbeda jauh dari alur biasa:

Kebutuhan jelas → AI membantu membuat perubahan → developer membaca diff → test dan pemeriksaan otomatis berjalan → review → merge → deploy dengan monitoring dan rencana rollback.

Yang membuat alur ini berhasil adalah konteks yang diberikan di awal. AI bekerja jauh lebih baik jika tahu struktur proyek, konvensi penamaan, layer yang tidak boleh ditembus, dependensi yang tidak boleh ditambah, dan kriteria penerimaan. Di banyak tool, konteks itu bisa diberikan lewat file instruksi proyek, tautan ke skema database, atau contoh endpoint yang sudah ada.

Dua hal yang tidak boleh dilakukan: menempelkan secrets (token, kredensial, connection string) dan data pribadi pengguna ke tool yang belum disetujui untuk menerimanya. Aturan ini sama dengan aturan yang berlaku ketika Anda memakai layanan pihak ketiga mana pun.

Cara paling sederhana untuk menjaga sikap yang benar: perlakukan output AI seperti pull request dari kontributor yang belum Anda kenal. Mungkin bagus, mungkin tepat, tetapi tetap harus dibaca, diuji, dan dipertanggungjawabkan sebelum masuk ke branch utama.

Kapan AI membantu, kapan perlu lebih hati-hati

Penggunaan yang relatif cocok:

  • Boilerplate dan kode repetitif dengan pola yang sudah mapan.
  • Draft unit test yang kemudian ditinjau dan dilengkapi.
  • Penjelasan kode lama dan penelusuran alur pemanggilan.
  • Refactor kecil dengan cakupan yang jelas dan mudah diverifikasi.
  • Dokumentasi yang disusun dari kode yang benar-benar ada, lalu diperiksa ulang terhadap perilaku sebenarnya.

Penggunaan yang menuntut pengawasan ketat:

  • Autentikasi dan otorisasi.
  • Pembayaran dan transaksi keuangan.
  • Perubahan skema database dan migrasi data.
  • Penanganan data pribadi dan kepatuhan terhadap aturan privasi.
  • Infrastruktur, permission, secrets, dan konfigurasi production.
  • Perubahan besar yang melintasi banyak modul atau layanan.

Perlu dicatat: tugas yang terlihat sederhana belum tentu aman. Menambahkan satu kolom ke tabel terlihat sepele sampai migrasinya mengunci tabel besar di jam sibuk.

Penutup

AI berguna justru karena ia menghasilkan sesuatu dengan cepat. Sesuatu itu menjadi bahan kerja: Anda bisa mengkritik, membandingkan, dan memperbaiki jauh lebih cepat daripada menulis dari nol. Tetapi kecepatan menghasilkan kode bukan ukuran keberhasilan. Ukuran yang sebenarnya adalah apakah perubahan memenuhi kebutuhan, bisa diuji, aman, dapat dipelihara, dan layak dipertanggungjawabkan oleh orang yang mengirimnya.

AI bisa membantu kita menulis kode lebih cepat. Memastikan kode itu layak dikirim ke production tetap pekerjaan engineering.


Catatan: artikel ini tidak memuat statistik atau hasil benchmark karena tidak ada pengukuran yang dilakukan untuk klaim semacam itu. Contoh kode di atas adalah ilustrasi, bukan potongan kode yang sudah dijalankan.

Bacaan lanjutan: OWASP Top Ten dan OWASP Application Security Verification Standard — rujukan umum untuk memeriksa validasi input, kontrol akses, dan penanganan error.