Tiba-tiba Vibe Coding
Thu. Jan 29th, 2026 11:43 PM8 mins read
Tiba-tiba Vibe Coding
Source: Ideogram - Vibe Code

Sejak beberapa bulan terakhir di tempat kerja gw udah pake AI buat development👨‍💻. Untuk saat ini gw pakai Claude Code dari Anthropic yang dibayarin kantor sebagai AI utama. Untuk beberapa case gw pakai Junie dari Jetbrains karena udah terintegrasi langsung dengan IntelliJ. Gw tiap bulan dapat credit gratis sebesar 3 credits pakai Junie karena IntelliJ gw udah Ultimate. Masalahnya, Junie makan banyak memory dibanding Claude Code, ga cocok buat laptop kentang punya kantor gw💻. Claude Code juga bisa terintegrasi dengan IntelliJ via plugin MCP Server dari Jetbrains, tapi masih terbatas integrasinya. Untuk brainstorm, selain pakai Junie dan Claude Code gw masih pakai ChatGpt, Gemini, dan DeepSeek juga buat minta second opinion.

Sebenarnya gw ga vibe code amat sih, kan menurut para ahli vibe code itu bermodalkan prompt doang tanpa perlu ngoding. Sedangkan gw masih perlu intervensi dan belum percaya 100% setiap code yang ditulis oleh AI. Kadang solusi yang ditawarkan AI itu sotoy, sering berasumsi seenak jidat, bahkan over-engineering🙄. Untuk flow yang cukup kompleks tetap perlu intervensi sih menurut gw, jangan dipercayakan begitu aja. Terlihat dari beberapa postingan influencer vibe coder di sosial media yang kualitas keamanannya sering vulnerable dan banyak bugs😱. Gw sendiri pun pernah mengalaminya.

When AI Breaks Logic

Sekitar bulan Oktober lalu gw develop tools untuk convert foto ke Webp agar foto produk yang di-upload lebih mini ukurannya sehingga lebih hemat storage. Code yg di-generate pakai Claude (dibaca Klad) kurang lebih begini:

Copy
private byte[] writeImage(BufferedImage image, ImageType imageType, ImageWriter writer) throws IOException{
	try(ByteArrayOutputStream baos = new ByteArrayOutputStream()){
		try(ImageOutputStream ios = ImageIO.createImageOutputStream(baos)){
			if(ios == null){
				throw new ImageProcessingException("Unable to create ImageOutputStream. No suitable writer found.");
			}
			writer.setOutput(ios);
			ImageWriteParam writeParam = writer.getDefaultWriteParam();
			if(imageType.getCompressionType() != null && writeParam.canWriteCompressed()){
				writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
				writeParam.setCompressionType(imageType.getCompressionType());
				writeParam.setCompressionQuality(imageType.getQuality());
			}
			if(imageType.isProgressive() && writeParam.canWriteProgressive()){
				writeParam.setProgressiveMode(ImageWriteParam.MODE_DEFAULT);
			}
			writer.write(null, new IIOImage(image, null, null), writeParam);
		}
		return baos.toByteArray();
	}
}

Ga lupa juga gw minta dia bikinin unit testnya. Semuanya berjalan normal seperti yang diinginkan. Unit testnya juga berhasil aman✅. Tapi code yang dihasilkan di atas kurang clean karena ada 2 try bercabang di method yang sama dan ga Single Responsibility. Gw perintahkan lagi Claude untuk refactor code tersebut biar lebih clean, hasilnya begini:

Copy
private byte[] writeImage(BufferedImage image, ImageType imageType, ImageWriter writer) throws IOException{
	try(ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ImageOutputStream ios = ImageIO.createImageOutputStream(baos)){
		if(ios == null){
			throw new ImageProcessingException("Unable to create ImageOutputStream. No suitable writer found.");
		}
		writer.setOutput(ios);
		ImageWriteParam writeParam = writer.getDefaultWriteParam();
		if(imageType.getCompressionType() != null && writeParam.canWriteCompressed()){
			writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
			writeParam.setCompressionType(imageType.getCompressionType());
			writeParam.setCompressionQuality(imageType.getQuality());
		}
		if(imageType.isProgressive() && writeParam.canWriteProgressive()){
			writeParam.setProgressiveMode(ImageWriteParam.MODE_DEFAULT);
		}
		writer.write(null, new IIOImage(image, null, null), writeParam);
		return baos.toByteArray();
	}
}

Sekilas itu tampak baik-baik saja. Berhubung udah malam, gw pun save kerjaan dan matiin laptop🛌. Keesokan harinya, gw cek lagi ternyata unit testnya failed. Gw coba debug, ternyata returnnya byte array kosong😨. Gw perintahkan lagi Claude untuk benerin kesalahannya semalam. Dia malah ngide over-engineering yang gw sendiri pun bingung ngapain dia bikin code yang makin kompleks kayak gini. Gw ga ingat dia bikin code apa karena gw ga sempat save dan commit juga perubahannya. Dengan code yang begitu kompleks dan ngalor ngidul pun errornya tetap sama, masih return array kosong🤦. Claude aja sampai bingung dan ga merasa melakukan kesalahan. Trus gw balikin lagi perubahannya untuk gw pelajari lebih lanjut. Gw juga saat itu ga ngerti apa yang bikin returnnya jadi array kosong karena ga terlalu memperhatikan perubahannya semalam😕.

Akhirnya gw nyari second opinion ke ChatGpt dan Junie, kebetulan saat itu credit Junie gratisan gw masih ada dikit. Di situlah gw paham kesalahannya. Keduanya ngejelasin bahwa ImageOutputStream harus di-flush dulu sebelum di-return agar gambarnya di-load ke byte array. Sebenarnya, dengan menggunakan try-with-resources di atas, ImageOutputStream udah auto-close dan saat method close() dipanggil oleh JVM dia akan eksekusi method flush() juga. Masalahnya, karena deklarasi ImageOutputStream dan return baos.toByteArray() dieksekusi di dalam scope try-with-resources yang sama, artinya method close() dan flush() dari ImageOutputStream akan dieksekusi setelah return baos.toByteArray(). Ini yang bikin return array kosong🫣. Setelah itu gw refactor sendiri code di atas jadi seperti berikut:

Copy
private byte[] writeImage(BufferedImage image, ImageType imageType, ImageWriter writer) throws IOException{
	try(ByteArrayOutputStream baos = new ByteArrayOutputStream()){
		writeOutputStream(image, imageType, writer, baos);
		return baos.toByteArray();
	}
}

private static void writeOutputStream(BufferedImage image, ImageType imageType, ImageWriter writer, ByteArrayOutputStream baos) throws IOException{
	try(ImageOutputStream ios = ImageIO.createImageOutputStream(baos)){
		if(ios == null){
			throw new ImageProcessingException("Unable to create ImageOutputStream. No suitable writer found.");
		}
		writer.setOutput(ios);
		ImageWriteParam writeParam = writer.getDefaultWriteParam();
		if(imageType.getCompressionType() != null && writeParam.canWriteCompressed()){
			writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
			writeParam.setCompressionType(imageType.getCompressionType());
			writeParam.setCompressionQuality(imageType.getQuality());
		}
		if(imageType.isProgressive() && writeParam.canWriteProgressive()){
			writeParam.setProgressiveMode(ImageWriteParam.MODE_DEFAULT);
		}
		writer.write(null, new IIOImage(image, null, null), writeParam);
	}
}

Kedua try tersebut memang harus dipisah dengan dua method yang berbeda biar Single Responsibility. Di sini setelah writeOutputStream() dieksekusi dia akan auto-close dan auto-flush ImageOutputStream terlebih dahulu karena punya scope try-with-resources sendiri. Barulah setelah itu method writeImage() return byte arrays yang benar. Ini yang bikin gw masih skeptis sama code bikinan AI🙄.

The Hallucinated Library

Masih di task terkait, gw kembali mengalami ke-sotoy-an AI. Kali ini bukan Claude Code doang, tapi juga ChatGpt. Waktu itu gw baca-baca ada format Avif yang lebih bagus lagi kompresannya dibanding Webp. Gw berniat mengeksplorasi format ini. Kali ini gw minta ChatGpt buat generate code trus gw paste ke project. ChatGpt nambahin module Avif dari TwelveMonkeys untuk dipasang ke pom.xml:

Copy
<dependency>
	<groupId>com.twelvemonkeys.imageio</groupId>
	<artifactId>imageio-avif</artifactId>
	<version>3.10.1</version>
</dependency>

Pas gw build module ternyata error, module itu ga ada di maven repository. Gw cek sendiri ke github TwelveMonkeys dan ternyata emang ga ada module imageio-avif di list supported format mereka. ChatGpt sekarang yang ngide😠. Saat itu Junie gw udah kehabisan credits, jadi gw ga nanya dia. Gw balik lagi ke Claude Code buat bikin hal yang sama. Claude Code mengonfirmasi bahwa TwelveMonkeys emang ga support format Avif, tapi malah ngasih library lain yang juga ga ada di maven repository😮‍💨. Setelah gw ngegas balik pada keduanya, barulah mereka mengakui untuk saat ini di Java emang belum ada library yang 100% compatible dan production-ready untuk handle format Avif. Gw coba googling sendiri ternyata emang ga ada dan harus install library native dulu di server untuk menggunakannya.

Confidently Incorrect Answers

Selain Vibe Coding, gw juga pakai AI sebagai asisten buat minta saran. Gw pernah develop aplikasi kompleks terkait Travelling Salesman Problem. Intinya, aplikasi itu untuk mencari rute terbaik yang harus dilewati driver untuk menjemput barang dari depot kendaraan menuju beberapa gudang, hingga mengantarkannya ke berbagai alamat tujuan. Gw pakai library Jsprit dan diproses lewat AWS Lambda untuk generate rute on-demand. Masalahnya, client minta banyak custom algoritma yang ga ada di fitur library tersebut, jadinya banyak custom manual yang gw lakukan😭. Di sini gw juga beberapa kali minta saran ke AI. Misalnya saat client minta custom waktu istirahat pengantaran, karena biasanya pengantaran barangnya dari luar kota dan perlu waktu lebih sehari sehingga waktu istirahat driver bisa beberapa kali. Masalahnya, dari fitur library itu sendiri ga ada opsi multiple break. Gw nanya ke ChatGpt dan dia malah pede banget bilang bisa, lalu memberikan gw code ngasal yang bahkan ga ada di library😡. Gw juga minta saran buat improve waktu generation rutenya karena client dalam sekali generate bisa menginput ratusan pengiriman sehingga agak lama generate rutenya. Dia malah bikin parameter-parameter yang waktu gw cek ke dokumentasi library dan baca-baca sendiri internal source code library tersebut ga ada parameter-parameter itu. Diboongin gw😮‍💨.

Gw juga pernah nanya tentang tipe data Numeric/Decimal di PostgreSql ke Gemini. Dia bilang PostgreSql menyimpan trailing zero dan padding seperti MySql. Padahal di website dokumentasinya gw cek PostgreSql ga menyimpan itu. Setelah gw counter baru dia koreksi pernyataannya. Ada aja alasannya buat ngeles. Hal-hal kayak gini yang bikin gw ga gampang percaya sama setiap solusi yang diberikan. Kadang saat brainstorm gw kesal juga berdebat sama mereka kalau ngasih informasi ngawur😠.

Where AI Truly Shines

Secara overall AI emang sangat membantu sih untuk beberapa kasus. Gw pernah fixing bugs race condition di class legacy yang cukup banyak, sekitar 60an files. Ada beberapa code yang jarang dipakai dalam bentuk Singleton, tapi terdapat mutable property di dalamnya🤦. Kalau itu gw ketik manual mungkin bisa seharian. Dengan Claude Code gw tinggal gambarkan aja pola permasalahannya gimana dan suruh dia buat fixing. Kurang lebih 5 menit langsung fixed😎. Ada juga bugs di code legacy yang jumlah line code mencapai ribuan di mana kalau ada input String di dalam file CSV berisi double-quote bisa bikin error. Daripada gw capek-capek ngecekin baris per baris di mana letak salahnya, tinggal suruh Claude Code buat nyari tau permasalahannya dan suruh fixing sendiri. Gw bagian review aja sambil makan mie😋.

Buat refactoring ini berguna banget. Yang paling menyeramkan saat refactoring adalah code yang kita refactor nyenggol ke use case lain. Dengan AI kita bisa meminimalisir itu. Dia bisa tau apa aja yang bakal nyenggol dan meminimialisirnya. Kita ga perlu analisa manual impact dari refactoring itu. Beberapa hari lalu gw dapat task buat handle performance issue karena N+1. Gw tinggal suruh AI buat refactor tanpa perlu mengotori tangan gw buat ngoding😎.

Mau bikin fitur baru pun sekarang gampang, tinggal jelasin apa aja yang mau gw bikin trus suruh dia liat referensi dari use case lain sebagai pedoman arsitekturnya. Jadi dia generate code tetap sesuai struktur code yang diadopsi, bukan generate seenaknya aja. Ga lupa juga gw minta dia generate unit tests dan suruh cover tiap edge cases. Untuk bikin unit tests ini juga sangat terbantu sih👍. Kita bisa minta AI buat generate edge cases yang mungkin ga kepikiran sebelum develop.

AI as a Brainstorming Partner

Ga hanya buat ngetik code, AI juga sangat membantu buat brainstorming. Salah satu platform integrasi aplikasi kantor menaikkan level security API mereka. Saat integrasi gw dapat error code 1010 dari Cloudflare mereka. Pas dikonfirmasi ternyata mereka juga ga paham impact dari menaikkan level security itu dan bingung juga solusinya. Error tersebut hanya terjadi saat integrasi via aplikasi, sedangkan kalau lewat curl aman. Gw tanya ke Claude Code, di situ dijelasin lengkap penyebabnya bahwa error code itu artinya request diblok sama Cloudflare karena dianggap bot dan harus kirim User-Agent di bagian header saat ngirim request dari aplikasi. Sedangkan kalau hit lewat curl di command line, itu udah otomatis ditambahin User-Agent oleh curl tanpa perlu kita tulis manual. Solusi ditemukan dalam waktu singkat beserta detail penyebabnya😁. Kalau dulu mungkin harus browsing google dan nyari-nyari di stackoverflow dulu yang bisa makan waktu lama.

Verdict

Untuk hal-hal tertentu gw akui jadi lebih produktif berkat AI🫰. Tapi tetap sih, untuk final product harus gw review lagi sebelum commit buat mastiin apa yang dia tulis benar. Sedangkan untuk hal-hal yang agak kompleks menurut gw memang masih butuh coding manual. Kalau dibiarin AI nulis code kompleks sendiri yang ada malah kebanyakan ngide mereka kayak di beberapa kasus yang gw alami. Menurut gw Vibe Code saat ini cocoknya untuk algoritma yang ga terlalu kompleks, aplikasi MVP, handle boilerplate & repeatable code, menganalisa code, refactoring, hingga bikin unit tests. Sedangkan untuk hal-hal kompleks menurut gw tetap perlu coding manual, tapi tetap minta petuah dari AI sebagai asisten untuk brainstorm dan gunakan beberapa AI lain sebagai second opinion. Dulu tiap ada masalah kita sering berjam-jam googling dan nyari-nyari di stackoverflow, sekarang tinggal ngetik prompt langsung ketemu penyebab dan solusinya😎.

© 2026 · Ferry Suhandri