Pelajari cara menjaga kode yang dihasilkan tetap terpelihara dengan aturan arsitektur membosankan: batas folder jelas, penamaan konsisten, dan default sederhana yang mengurangi pekerjaan ulang.

Kode yang dihasilkan mengubah pekerjaan sehari-hari. Anda tidak hanya membangun fitur, Anda membimbing sistem yang bisa membuat banyak file dengan cepat. Kecepatannya nyata, tetapi ketidakkonsistenan kecil cepat sekali berkembang.
Keluaran yang dihasilkan sering tampak baik jika dilihat sendiri. Biayanya muncul pada perubahan kedua dan ketiga: Anda tidak tahu di mana sebuah bagian seharusnya berada, Anda memperbaiki perilaku yang sama di dua tempat, atau Anda menghindari menyentuh file karena tidak tahu apa efeknya ke tempat lain.
Struktur yang “cerdas” menjadi mahal karena sulit diprediksi. Pola kustom, magic tersembunyi, dan abstraksi berat masuk akal di hari pertama. Di minggu keenam, perubahan berikutnya melambat karena Anda harus mempelajari lagi trik itu sebelum bisa memperbaruinya dengan aman. Dengan generasi berbantuan AI, kepintaran itu juga bisa membingungkan generasi berikutnya dan menyebabkan logika terduplikasi atau lapisan baru menumpuk di atasnya.
Arsitektur membosankan adalah kebalikan: batas yang jelas, nama yang jelas, dan default yang mudah dimengerti. Bukan soal sempurna. Ini soal memilih tata letak yang bisa dipahami rekan tim yang lelah (atau Anda di masa depan) dalam 30 detik.
Tujuan sederhana: buat perubahan berikutnya mudah, bukan mengesankan. Itu biasanya berarti satu tempat jelas untuk tiap jenis kode (UI, API, data, utilitas bersama), nama yang dapat diprediksi sesuai fungsi file, dan sedikit “magic” seperti auto-wiring, global tersembunyi, atau metaprogramming.
Contoh: jika Anda minta Koder.ai menambahkan “team invites”, Anda ingin UI berada di area UI, tambahkan satu route API di area API, dan simpan data invite di lapisan data, tanpa menciptakan folder atau pola baru hanya untuk fitur itu. Konsistensi membosankan itulah yang membuat edit di masa depan tetap murah.
Kode yang dihasilkan jadi mahal ketika memberi banyak cara untuk melakukan hal yang sama. Aturan arsitektur membosankan sederhana: buat perubahan berikutnya dapat diprediksi, bahkan jika build pertama terasa kurang cerdas.
Anda harus bisa menjawab hal ini dengan cepat:
Pilih satu struktur yang sederhana dan patuhi di mana-mana. Ketika sebuah tool (atau rekan) menyarankan pola keren, jawaban default adalah “tidak” kecuali itu benar-benar menghilangkan masalah.
Default praktis yang tahan lama:
Bayangkan pengembang baru membuka repo Anda dan perlu menambahkan tombol “Cancel subscription”. Mereka tidak harus mempelajari arsitektur kustom dulu. Mereka harus menemukan area fitur yang jelas, komponen UI yang jelas, satu lokasi klien API, dan satu jalur akses data.
Aturan ini bekerja sangat baik dengan alat vibe-coding seperti Koder.ai: Anda bisa menghasilkan cepat, tapi tetap membimbing keluaran ke batas-batas membosankan yang sama tiap kali.
Kode yang dihasilkan cenderung tumbuh cepat. Cara paling aman untuk menjaga keterpeliharaan adalah peta folder membosankan di mana siapa pun bisa menebak di mana perubahan harus ditempatkan.
Tata letak top-level kecil yang cocok untuk banyak web app:
app/ layar, routing, dan state level-pagecomponents/ potongan UI yang dapat digunakan ulangfeatures/ satu folder per fitur (billing, projects, settings)api/ kode klien API dan helper requestserver/ handler backend, service, dan aturan bisnisIni membuat batas jelas: UI berada di app/ dan components/, panggilan API di api/, dan logika backend di server/.
Akses data juga harus membosankan. Simpan query SQL dan kode repository dekat dengan backend, jangan tersebar di file UI. Dalam setup Go + PostgreSQL sederhana, aturan yang baik adalah: HTTP handler memanggil service, service memanggil repository, repository berbicara ke database.
Tipe bersama dan utilitas pantas punya rumah jelas, tapi jaga ukurannya kecil. Taruh tipe lintas-cutting di types/ (DTO, enum, interface bersama) dan helper kecil di utils/ (format tanggal, validator sederhana). Jika utils/ mulai terasa seperti aplikasi kedua, kemungkinan besar kodenya seharusnya berada di folder fitur.
Perlakukan folder hasil generasi sebagai sesuatu yang bisa diganti.
generated/ (atau gen/) dan hindari mengeditnya langsung.features/ atau server/ agar regenerasi tidak menimpanya.Contoh: jika Koder.ai menghasilkan klien API, simpan di generated/api/, lalu buat wrapper tipis di api/ untuk menambahkan retry, logging, atau pesan error yang lebih jelas tanpa menyentuh file yang dihasilkan.
Kode yang dihasilkan mudah dibuat dan mudah menumpuk. Penamaan yang menjaga keterbacaan sebulan kemudian.
Pilih satu gaya penamaan dan jangan dicampur:
kebab-case (user-profile-card.tsx, billing-settings)PascalCase (UserProfileCard)camelCase (getUserProfile)SCREAMING_SNAKE_CASE (MAX_RETRY_COUNT)Namai berdasarkan peran, bukan bagaimana ia bekerja hari ini. user-repository.ts adalah peran. postgres-user-repository.ts adalah detail implementasi yang mungkin berubah. Gunakan sufiks implementasi hanya ketika benar-benar punya banyak implementasi.
Hindari laci sampah seperti misc, helpers, atau utils raksasa. Jika fungsi hanya dipakai oleh satu fitur, simpan dekat fitur itu. Jika dibagi, biarkan nama menjelaskan kapabilitas (date-format.ts, money-format.ts, id-generator.ts) dan pertahankan modul kecil.
Saat route, handler, dan komponen mengikuti pola, Anda bisa menemukan sesuatu tanpa searching:
routes/users.ts dengan path seperti /users/:userIdhandlers/users.get.ts, handlers/users.update.tsservices/user-profile-service.tsrepositories/user-repository.tscomponents/user/UserProfileCard.tsxJika Anda memakai Koder.ai (atau generator apa pun), masukkan aturan ini ke prompt dan pertahankan konsistensi saat mengedit. Intinya adalah prediktabilitas: jika Anda bisa menebak nama file, perubahan di masa depan tetap murah.
Kode yang dihasilkan bisa terlihat mengesankan di hari pertama dan menyakitkan di hari ketiga puluh. Pilih default yang membuat kode jelas, meskipun agak repetitif.
Mulailah dengan mengurangi magic. Lewati dynamic loading, trik gaya reflection, dan auto-wiring kecuali ada kebutuhan terukur. Fitur ini menyembunyikan asal sesuatu, yang memperlambat debugging dan refaktor.
Pilih import eksplisit dan dependensi yang jelas. Jika sebuah file butuh sesuatu, import langsung. Jika modul butuh wiring, lakukan di satu tempat yang terlihat (misalnya file komposisi tunggal). Pembaca tidak harus menebak apa yang berjalan duluan.
Jaga konfigurasi tetap membosankan dan terpusat. Taruh environment variable, feature flag, dan pengaturan aplikasi di satu modul dengan satu skema penamaan. Jangan sebarkan config di file acak karena terasa praktis.
Aturan praktis yang menjaga konsistensi tim:
Penanganan error adalah tempat kecerdikan paling merugikan. Pilih satu pola dan gunakan di mana-mana: kembalikan error terstruktur dari lapisan data, peta ke response HTTP di satu tempat, dan terjemahkan menjadi pesan pengguna di boundary UI. Jangan lempar tiga tipe error berbeda tergantung file.
Jika Anda menghasilkan aplikasi dengan Koder.ai, minta default ini sejak awal: wiring modul eksplisit, konfigurasi terpusat, dan satu pola error.
Garis yang jelas antara UI, API, dan data menjaga perubahan tetap terkandung. Sebagian besar bug misterius terjadi ketika satu lapisan mulai melakukan pekerjaan lapisan lain.
Anggap UI (sering React) sebagai tempat merender layar dan mengelola state yang hanya untuk UI: tab mana yang terbuka, error form, loading spinner, dan penanganan input dasar.
Jaga state server terpisah: daftar yang di-fetch, profil cache, dan apa pun yang harus cocok dengan backend. Saat komponen UI mulai menghitung total, memvalidasi aturan kompleks, atau memutuskan izin, logika menyebar ke layar dan menjadi mahal untuk diubah.
Jaga lapisan API dapat diprediksi. Ini harus menerjemahkan request HTTP menjadi panggilan ke kode bisnis, lalu menerjemahkan hasil kembali ke bentuk request/response yang stabil. Hindari mengirim model database langsung ke client. Response stabil memungkinkan Anda merombak bagian dalam tanpa merusak UI.
Jalur sederhana yang bekerja baik:
Taruh SQL (atau logika ORM) di balik batas repository sehingga sisa aplikasi tidak “tau” bagaimana data disimpan. Di Go + PostgreSQL, itu biasanya berarti repository seperti UserRepo atau InvoiceRepo dengan metode kecil dan jelas (GetByID, ListByAccount, Save).
Contoh konkret: menambahkan kode diskon. UI menampilkan field dan menunjukkan harga yang diperbarui. API menerima code dan mengembalikan {total, discount}. Service memutuskan apakah kode valid dan bagaimana diskon menumpuk. Repository mengambil dan menyimpan baris yang diperlukan.
Aplikasi yang dihasilkan bisa terlihat “selesai” dengan cepat, tapi strukturlah yang menjaga perubahan tetap murah nanti. Putuskan aturan membosankan dulu, lalu hasilkan hanya cukup kode untuk membuktikannya.
Mulai dengan sesi perencanaan singkat. Jika Anda menggunakan Koder.ai, Planning Mode adalah tempat yang baik untuk menulis peta folder dan beberapa aturan penamaan sebelum menghasilkan apa pun.
Lalu ikuti urutan ini:
ui/, api/, data/, features/) dan beberapa aturan penamaan.CONVENTIONS.md singkat dan perlakukan sebagai kontrak. Setelah codebase tumbuh, mengganti nama dan pola folder menjadi mahal.Realita: jika orang baru tidak bisa menebak di mana menaruh “edit contact” tanpa bertanya, arsitekturnya belum cukup membosankan.
Bayangkan CRM sederhana: halaman daftar kontak dan form edit kontak. Anda membangun versi pertama cepat, lalu seminggu kemudian perlu menambahkan “tags” ke kontak.
Perlakukan aplikasi sebagai tiga kotak membosankan: UI, API, dan data. Setiap kotak mendapat batas jelas dan nama literal sehingga perubahan “tags” tetap kecil.
Tata letak bersih bisa seperti ini:
web/src/pages/ContactsPage.tsx dan web/src/components/ContactForm.tsxserver/internal/http/contacts_handlers.goserver/internal/service/contacts_service.goserver/internal/repo/contacts_repo.goserver/migrations/Sekarang “tags” jadi dapat diprediksi. Perbarui skema (tabel contact_tags baru atau kolom tags), lalu sentuh satu lapis pada satu waktu: repo membaca/menulis tags, service memvalidasi, handler mengekspos field, UI merender dan mengeditnya. Jangan selundupkan SQL ke handler atau aturan bisnis ke komponen React.
Jika produk nanti meminta “filter by tag,” Anda sebagian besar akan bekerja di ContactsPage.tsx (state UI dan query params) dan handler HTTP (parsing request), sementara repo menangani query.
Untuk test dan fixture, jaga kecil dan dekat dengan kodenya:
server/internal/service/contacts_service_test.go untuk aturan seperti “nama tag harus unik per kontak”server/internal/repo/testdata/ untuk fixture minimalweb/src/components/__tests__/ContactForm.test.tsx untuk perilaku formJika Anda menghasilkan ini dengan Koder.ai, aturan yang sama berlaku setelah ekspor: jaga folder membosankan, jaga nama literal, dan edit berhenti terasa seperti arkeologi.
Kode yang dihasilkan bisa tampak bersih di hari pertama dan tetap mahal nanti. Penyebab umum bukanlah “kode buruk,” melainkan inkonsistensi.
Kebiasaan mahal adalah membiarkan generator menciptakan struktur sendiri setiap kali. Sebuah fitur datang dengan folder, gaya penamaan, dan helper sendiri, lalu Anda punya tiga cara melakukan hal yang sama. Pilih satu pola, tulis, dan anggap pola baru sebagai perubahan sadar, bukan default.
Perangkap lain adalah mencampur lapisan. Ketika komponen UI berbicara ke database, atau handler API membangun SQL, perubahan kecil berubah menjadi edit berisiko di seluruh aplikasi. Jaga batas: UI memanggil API, API memanggil service, service memanggil akses data.
Terlalu cepat menggunakan abstraksi generik juga menambah biaya. "BaseService" atau framework Repository universal terasa rapi, tapi abstraksi awal adalah tebakan. Saat realita berubah, Anda melawan framework Anda sendiri alih-alih mengirimkan fitur.
Penggantian nama dan reorganisasi yang konstan adalah bentuk hutang yang lebih halus. Jika file berpindah setiap minggu, orang berhenti mempercayai tata letak dan perbaikan cepat berakhir di tempat acak. Stabilkan peta folder dulu, lalu refaktor dalam chunk yang direncanakan.
Terakhir, hati-hati dengan "platform code" yang tidak punya pengguna nyata. Library bersama dan tooling buatan sendiri hanya terbayar ketika Anda punya kebutuhan berulang. Sampai saat itu, pilih default yang langsung.
Jika seseorang baru membuka repo, mereka harus bisa menjawab satu pertanyaan cepat: “Di mana saya menambahkan ini?”
Serahkan proyek ke rekan (atau Anda di masa depan) dan minta mereka menambahkan fitur kecil, seperti “tambah field ke form signup.” Jika mereka tidak menemukan tempat yang tepat dengan cepat, struktur belum menjalankan tugasnya.
Periksa tiga rumah yang jelas:
Jika platform Anda mendukung, sediakan jalur rollback. Snapshot dan rollback sangat berguna saat Anda bereksperimen dengan struktur dan butuh cara aman kembali.
Keterpeliharaan meningkat paling cepat ketika Anda berhenti berdebat soal gaya dan mulai membuat beberapa keputusan yang konsisten.
Tuliskan beberapa konvensi singkat yang menghilangkan keraguan harian: di mana file pergi, bagaimana dinamai, dan bagaimana error serta config ditangani. Buat singkat agar bisa dibaca dalam satu menit.
Lalu lakukan satu pembersihan untuk menyamakan kode dengan aturan itu dan hentikan penggeseran mingguan. Pengorganisasian ulang yang sering membuat perubahan berikutnya lebih lambat, meskipun kodenya terlihat lebih rapi.
Jika Anda membangun dengan Koder.ai (koder.ai), ada baiknya menyimpan konvensi ini sebagai prompt awal agar setiap generasi baru mendarat dalam struktur yang sama. Tool bisa bergerak cepat, tapi batas membosankan itulah yang menjaga kode mudah diubah.