Jelajahi pandangan praktis Martin Fowler tentang arsitektur: pola, refaktorisasi, dan arsitektur evolusioner yang bertahan melampaui stack tren dan mengurangi risiko jangka panjang.

Framework baru, layanan cloud yang mengilap, atau “stack standar” di perusahaan populer bisa terasa seperti jalan pintas menuju kualitas. Namun pemikiran yang menempatkan stack di depan sering membingungkan alat dengan struktur. Anda bisa membangun sistem yang berantakan dan sulit diubah dengan teknologi paling modern—atau sistem yang bersih dan mudah beradaptasi dengan pilihan yang membosankan dan sudah dikenal.
Memilih stack terlebih dahulu mendorong tim ke keputusan yang terlihat mengesankan di slide tetapi tidak menjawab pertanyaan nyata:
Saat pilihan teknologi memimpin, arsitektur menjadi produk sampingan kebetulan—menghasilkan coupling yang ketat, logika duplikat, dan dependensi yang membuat perubahan sederhana jadi mahal.
Itu sebabnya “kami menggunakan microservices” (atau “kami sekarang serverless”) bukanlah arsitektur. Itu adalah arah deployment dan tooling. Arsitektur berbicara tentang bagaimana bagian-bagian sistem berkolaborasi, bagaimana keputusan membatasi pekerjaan di masa depan, dan seberapa mudah produk bisa berevolusi.
Satu implikasi praktis: alat bisa mempercepat delivery, tetapi mereka tidak menggantikan pemikiran arsitektural. Bahkan dengan pendekatan “vibe-coding” modern—di mana Anda menghasilkan dan iterasi cepat lewat chat—pertanyaan yang sama tetap berlaku. Platform seperti Koder.ai dapat mempercepat pembuatan aplikasi web, backend, dan mobile secara dramatis, tetapi tim yang mendapatkan hasil terbaik tetap memperlakukan batas-batas, kepemilikan, dan kemudahan perubahan sebagai perhatian utama (bukan sesuatu yang akan diselesaikan framework secara ajaib).
Tulisan Martin Fowler secara konsisten mengembalikan perhatian pada apa yang penting: desain yang jelas ketimbang komponen trendi, trade-off praktis ketimbang ideologi, dan kemampuan untuk mengembangkan sistem saat Anda belajar. Karyanya memandang arsitektur sebagai sesuatu yang terus-menerus Anda perbaiki—bukan tonggak "big design" satu kali.
Harapkan tiga tema berulang: menggunakan pola sebagai alat opsional (bukan aturan), refaktorisasi sebagai kebiasaan rutin, dan arsitektur evolusioner—membangun untuk perubahan, bukan kepastian.
Jika Anda pemimpin engineering, tech lead, atau tim produk yang mencoba mengirim lebih cepat tanpa kualitas runtuh, ini untuk Anda. Tujuannya bukan memilih stack "sempurna"—melainkan membuat keputusan yang menjaga perangkat lunak tetap mudah diubah ketika roadmap pasti bergeser.
Arsitektur perangkat lunak adalah kumpulan keputusan yang membentuk sistem dengan cara yang sulit (dan mahal) untuk diubah kemudian.
Definisi itu sengaja sederhana. Tidak memerlukan diagram khusus atau gelar "arsitek." Ini tentang pilihan yang menentukan bagaimana perangkat lunak bisa tumbuh, bagaimana tim bisa bekerja, dan berapa biayanya untuk mengoperasikan.
Framework, alat, dan gaya coding penting—tetapi sebagian besar dari mereka mudah diganti dibandingkan dengan keputusan arsitektural sejati.
Arsitektur lebih mendekati struktur dan batas: bagaimana bagian sistem berkomunikasi, di mana data tinggal, bagaimana kegagalan ditangani, dan perubahan mana yang membutuhkan koordinasi lintas tim.
Tidak ada arsitektur “terbaik” universal. Setiap keputusan besar mengoptimalkan beberapa tujuan dan membebani yang lain:
Arsitektur yang baik membuat trade-off ini eksplisit daripada kebetulan.
Keputusan arsitektur: “Kita akan memisahkan billing pelanggan menjadi service yang dapat dideploy sendiri dengan database sendiri, dan sisa sistem akan berintegrasi melalui event asinkron.”
Ini memengaruhi deployment, kepemilikan data, mode kegagalan, monitoring, dan koordinasi tim.
Pilihan pustaka: “Kita akan menggunakan Library X untuk menghasilkan PDF.”
Berguna, tetapi biasanya dapat diganti dengan blast radius terbatas.
Jika sebuah keputusan membutuhkan minggu kerja terkoordinasi untuk dibalik, kemungkinan itu adalah arsitektur.
Pola desain paling baik dipahami sebagai solusi yang dapat digunakan ulang untuk masalah berulang, bukan perintah. Sikap umum Fowler adalah pragmatis: pola berguna ketika mereka memperjelas desain, dan berbahaya ketika mereka menggantikan pemikiran.
Jika digunakan dengan baik, pola memberi tim kosakata bersama. Mengatakan “strategy” atau “repository” bisa meringkas penjelasan panjang menjadi satu istilah, membuat review lebih cepat dan mengurangi salah paham.
Pola juga membuat perilaku sistem lebih dapat diprediksi. Pola yang familiar menetapkan ekspektasi tentang di mana logika berada, bagaimana objek berkolaborasi, dan perubahan apa yang kemungkinan besar menimbulkan dampak. Prediktabilitas itu mengurangi kejutan di produksi dan momen “bagaimana ini bekerja?” bagi anggota tim baru.
Mode kegagalan adalah cargo-culting: menerapkan pola karena populer, karena ada di buku, atau karena “begitulah cara kita melakukan di sini.” Ini sering menyebabkan over-engineering—lapisan ekstra, indirection, dan abstraksi yang tidak memberi nilai sebanding.
Perangkap umum lain adalah “pola untuk segala hal.” Ketika setiap masalah kecil diberi solusi bernama, basis kode bisa berubah menjadi museum kecerdikan daripada alat untuk mengirim dan memelihara perangkat lunak.
Mulai dari masalah, bukan pola.
Tanyakan:
Kemudian pilih pola paling sederhana yang cocok dan menjaga opsi tetap terbuka. Jika desain membutuhkan struktur lebih nanti, perkenalkan secara bertahap—sering dipandu oleh rasa sakit nyata dan dikonfirmasi oleh refaktorisasi, bukan ditebak sebelumnya.
Refaktorisasi adalah praktik memperbaiki desain internal perangkat lunak tanpa mengubah apa yang dilakukannya. Pengguna tidak boleh melihat perbedaan setelah refaktor—kecuali perubahan itu membuat perubahan masa depan lebih mudah, aman, dan cepat.
Inti poin Martin Fowler bukanlah "menjaga kode tetap indah." Melainkan bahwa arsitektur bukan diagram satu kali yang Anda gambar di awal. Arsitektur adalah kumpulan keputusan yang menentukan seberapa mudah sistem bisa berubah. Refaktorisasi adalah cara Anda mencegah keputusan itu mengeras menjadi batasan.
Seiring waktu, bahkan sistem yang dirancang baik dapat menyimpang. Fitur baru ditambahkan dengan tekanan waktu, perbaikan cepat menjadi permanen, dan batas-batas menjadi kabur. Refaktorisasi adalah cara Anda mengembalikan pemisahan yang jelas dan mengurangi kompleksitas kebetulan, sehingga sistem tetap mudah diubah.
Arsitektur yang sehat adalah yang:
Refaktorisasi adalah pekerjaan sehari-hari yang mempertahankan kualitas-kualitas itu.
Anda biasanya tidak menjadwalkan refaktor karena pengingat kalender. Anda melakukannya karena kode mulai menolak:
Ketika itu muncul, arsitektur sudah terpengaruh—refaktorisasi adalah perbaikannya.
Refaktor yang aman bergantung pada beberapa kebiasaan:
Dengan cara ini, refaktorisasi menjadi pemeliharaan rutin—menjaga sistem siap untuk perubahan berikutnya daripada rapuh setelah perubahan terakhir.
Utang teknis adalah biaya masa depan yang tercipta oleh jalan pintas hari ini. Bukan "kode buruk" sebagai kegagalan moral; itu adalah trade-off yang Anda buat (kadang dengan penuh kesadaran) yang meningkatkan harga perubahan nanti. Pandangan Martin Fowler berguna di sini: utang hanya jadi masalah ketika Anda berhenti melacaknya dan mulai berpura-pura tidak ada.
Utang yang disengaja diambil dengan mata terbuka: “Kita kirim versi lebih sederhana sekarang, lalu perkuat sprint berikutnya.” Itu bisa rasional—jika Anda juga merencanakan pelunasannya.
Utang tak disengaja terjadi ketika tim tidak menyadari mereka meminjam: dependensi berantakan merayap, model domain tidak jelas menyebar, atau solusi cepat menjadi default. Utang tak disengaja sering lebih mahal karena tak seorang pun memilikinya.
Utang bertambah lewat tekanan normal:
Hasilnya dapat diprediksi: fitur melambat, bug meningkat, dan refaktorisasi terasa berisiko alih-alih rutin.
Anda tidak perlu program besar untuk mulai melunasi utang:
Jika Anda juga membuat keputusan terkait utang terlihat (lihat /blog/architecture-decision-records), Anda mengubah biaya tersembunyi menjadi pekerjaan yang dapat dikelola.
Arsitektur perangkat lunak bukan cetak biru yang Anda "benar" dalam sekali. Pandangan Fowler mendorong gagasan lebih praktis: anggaplah kebutuhan, trafik, tim, dan batasan akan bergeser—lalu desain supaya sistem bisa beradaptasi tanpa rewrite yang menyakitkan.
Arsitektur evolusioner adalah merancang untuk perubahan, bukan kesempurnaan. Alih-alih bertaruh pada prediksi jangka panjang ("kita akan butuh microservices", "kita akan scale 100x"), Anda membangun arsitektur yang bisa berevolusi dengan aman: batas yang jelas, test otomatis, dan praktik deployment yang memungkinkan penyesuaian sering dan berisiko rendah.
Rencana adalah tebakan; produksi adalah kenyataan. Merilis increment kecil membantu Anda belajar apa yang pengguna benar-benar lakukan, berapa biaya operasional sistem, dan di mana performa atau reliabilitas benar-benar penting.
Rilis kecil juga mengubah gaya pengambilan keputusan: Anda bisa mencoba perbaikan moderat (mis. memecah satu modul atau memperkenalkan versi API baru) dan mengukur apakah itu membantu—daripada berkomitmen pada migrasi besar.
Di sinilah alat iterasi cepat bisa membantu—asal Anda tetap menjaga pedoman arsitektural. Misalnya, jika Anda menggunakan platform seperti Koder.ai untuk menghasilkan dan iterasi fitur dengan cepat, memadukan kecepatan itu dengan batas modul yang stabil, test yang baik, dan deployment sering membantu Anda menghindari “mengirim dengan cepat ke pojok yang buntu.”
Ide evolusioner kunci adalah “fitness function”: pemeriksaan terukur yang melindungi tujuan arsitektural. Anggap itu sebagai pagar pengaman. Jika pagar pengaman otomatis dan berjalan terus-menerus, Anda bisa mengubah sistem dengan percaya diri karena pagar akan memperingatkan ketika Anda melenceng.
Fitness function tidak harus rumit. Mereka bisa metrik sederhana, tes, atau ambang yang mencerminkan apa yang Anda pedulikan.
Poinnya bukan mengukur semuanya. Pilih beberapa pemeriksaan yang mencerminkan janji arsitektural Anda—kecepatan perubahan, reliabilitas, keamanan, dan interoperabilitas—dan biarkan pemeriksaan itu mengarahkan keputusan sehari-hari.
Microservices bukanlah lencana kematangan engineering. Poin Fowler lebih sederhana: memecah sistem menjadi layanan adalah gerakan organisasi sebanyak aspek teknis. Jika tim Anda tidak bisa memiliki layanan secara end-to-end (build, deploy, operate, dan evolve), Anda akan mendapat kompleksitas tanpa manfaat.
Sebuah monolith adalah satu unit yang dapat dideploy. Itu bisa jadi kekuatan: lebih sedikit bagian yang bergerak, debugging lebih sederhana, dan konsistensi data langsung. Kekurangannya muncul ketika codebase menjadi kusut—perubahan kecil memerlukan koordinasi besar.
Modular monolith masih satu unit yang dapat dideploy, tetapi kode sengaja dipisah menjadi modul jelas dengan batas yang ditegakkan. Anda mempertahankan kesederhanaan operasional monolith sambil mengurangi coupling internal. Bagi banyak tim, ini adalah default terbaik.
Microservices memberi setiap layanan lifecycle dan deployment sendiri. Itu bisa membuka rilis independen yang lebih cepat dan kepemilikan yang lebih jelas—jika organisasi siap. Jika tidak, seringkali mengubah "satu masalah sulit" menjadi "sepuluh masalah sulit."
Microservices menambah overhead yang tidak terlihat di diagram arsitektur:
Mulai dengan modular monolith. Ukur tekanan nyata sebelum memecah: bottleneck rilis, kontensi tim di sekitar modul, hotspot scaling, atau kebutuhan isolasi reliabilitas. Ketika tekanan itu persisten dan terkuantifikasi, potong layanan dengan batas yang jelas, kepemilikan khusus, dan rencana operasi—bukan sekadar kode.
Arsitektur yang baik bukan soal berapa banyak layanan yang Anda punya; melainkan seberapa baik Anda bisa mengubah satu bagian tanpa tak sengaja merusak tiga bagian lain. Martin Fowler sering memandang ini sebagai mengelola coupling (seberapa terjerat bagian-bagian) dan cohesion (seberapa baik sebuah bagian “menyatu”).
Bayangkan dapur restoran. Stasiun yang kohesif (seperti "salad") punya segala yang dibutuhkan—bahan, alat, dan tanggung jawab yang jelas. Dapur yang sangat terikat adalah tempat membuat salad memaksa juru panggang berhenti, pastry chef menyetujui dressing, dan manajer membuka lemari es.
Perangkat lunak bekerja sama: modul yang kohesif memiliki tugas jelas; modul yang longgar berinteraksi lewat perjanjian sederhana dan stabil.
Coupling yang tidak sehat biasanya terlihat di jadwal sebelum terlihat di kode. Sinyal umum:
Jika proses delivery Anda rutin memerlukan koreografi kelompok, biaya dependensi sudah dibayar—hanya dalam bentuk rapat dan delay.
Mengurangi coupling tidak memerlukan rewrite. Langkah praktis meliputi:
Saat keputusan penting, tangkap dengan catatan ringan seperti /blog/architecture-decision-records supaya batas tetap disengaja.
Database bersama menciptakan coupling “rahasia”: tim mana pun bisa mengubah tabel dan tanpa sengaja memecahkan orang lain. DB bersama sering memaksa rilis terkoordinasi, meski layanan tampak independen.
Pendekatan yang lebih sehat adalah kepemilikan data: satu sistem memiliki dataset dan mengeksposnya lewat API atau event. Ini membuat dependensi terlihat—dan karenanya dapat dikelola.
Arsitektur perangkat lunak bukan hanya tentang kotak dan panah. Ini juga tentang orang: bagaimana kerja dibagi, bagaimana keputusan diambil, dan seberapa cepat tim bisa merespon ketika kenyataan tidak sesuai desain. Ini adalah arsitektur sosio-teknis—gagasan bahwa struktur sistem cenderung mencerminkan struktur tim Anda.
Mode kegagalan umum adalah merancang batas yang “bersih” di kertas sementara alur kerja sehari-hari melintas batas itu. Sistem mungkin teknisnya bisa dikompilasi dan dideploy, tetapi terasa mahal untuk diubah.
Tanda mismatch termasuk:
Mulai dengan kepemilikan, bukan kesempurnaan. Bidik batas yang sesuai dengan bagaimana tim Anda bisa beroperasi secara realistis.
Kadang Anda tidak bisa reorganisasi tim, memecah modul legacy, atau merekrut untuk mengatasi bottleneck. Dalam kasus itu, perlakukan arsitektur sebagai negosiasi: pilih batas yang mengurangi koordinasi paling mahal, investasikan di refaktor yang membuka otonomi, dan terima kompromi transisional sambil melunasi utang teknis dan organisasi.
Arsitektur perangkat lunak bukan hanya apa yang Anda bangun—itu juga keputusan yang Anda ambil di sepanjang jalan. Architecture Decision Records (ADRs) adalah catatan singkat yang menangkap keputusan tersebut sementara konteks masih segar.
ADRs adalah memo satu halaman yang menjawab: “Apa yang kita putuskan, dan mengapa?” Bukan dokumen desain panjang, dan bukan izin. Anggap itu memori tahan lama untuk tim.
Jaga struktur konsisten agar orang bisa cepat memindai. ADR ringan biasanya berisi:
ADRs mempercepat onboarding karena rekan baru bisa mengikuti alasan, bukan hanya hasil akhirnya. Mereka juga mencegah perdebatan berulang: ketika pertanyaan sama muncul lagi beberapa bulan kemudian, Anda bisa meninjau ADR dan memperbaruinya daripada berdebat dari awal. Yang paling penting, ADR membuat trade-off eksplisit—berguna saat realitas berubah dan Anda perlu merevisi rencana.
Gunakan template sederhana, simpan ADR di dekat kode (misalnya, di /docs/adr/), dan targetkan 10–20 menit untuk menulis satu.
# ADR 012: API versioning strategy
Date: 2025-12-26
Status: Accepted
Owners: Platform team
Context:
We need to evolve public APIs without breaking partners.
Decision:
Adopt URL-based versioning (/v1/, /v2/).
Alternatives:
- Header-based versioning
- No versioning; rely on backward compatibility
Consequences:
+ Clear routing and documentation
- More endpoints to support over time
Jika sebuah ADR terasa seperti administrasi berlebihan, singkatkan—jangan tinggalkan kebiasaan.
Arsitektur tidak “tetap baik” karena seseorang menggambar diagram yang rapi sekali. Arsitektur tetap baik ketika sistem bisa berubah dengan aman, dalam langkah kecil, di bawah tekanan dunia nyata. Itulah mengapa continuous delivery (CD) dan loop umpan balik cepat sangat penting: mereka mengubah evolusi dari peristiwa berisiko menjadi kebiasaan normal.
Refaktor paling mudah ketika perubahan kecil dan dapat dibalik. Pipeline CI/CD yang sehat mendukung itu dengan otomatis membangun, mengetes, dan memvalidasi setiap perubahan sebelum mencapai pengguna. Ketika pipeline dapat dipercaya, tim bisa memperbaiki desain terus-menerus alih-alih menunggu "rewrite besar" yang tidak pernah selesai.
Gerbang kualitas harus cepat, konsisten, dan terkait hasil yang Anda pedulikan. Gerbang umum termasuk:
Tujuannya bukan kesempurnaan; melainkan menaikkan biaya perubahan yang merusak sambil menurunkan biaya perbaikan aman.
Arsitektur yang baik sebagian tentang mengetahui apa yang sistem lakukan di produksi. Tanpa umpan balik, Anda mengoptimalkan berdasarkan tebakan.
Dengan sinyal-sinyal ini, Anda dapat memvalidasi keputusan arsitektural dengan bukti, bukan opini.
Evolusi memerlukan rilis sering, jadi Anda butuh jalan keluar. Feature flags memungkinkan memisahkan deploy dari release. Canary release membatasi blast radius dengan rollout ke sebagian kecil lebih dulu. Strategi rollback yang jelas (termasuk pertimbangan database) mengubah kegagalan menjadi peristiwa yang dapat dipulihkan.
Jika Anda menggunakan platform aplikasi yang mendukung snapshot dan rollback (misalnya, Koder.ai), Anda bisa memperkuat prinsip yang sama di lapisan pengiriman produk: bergerak cepat, tetapi jadikan reversibilitas dan keselamatan operasional sebagai default.
Bersama-sama, CI/CD plus umpan balik menciptakan sistem yang bisa berevolusi terus-menerus—tepat jenis arsitektur yang tahan terhadap tren.
Anda tidak perlu rewrite untuk mendapatkan arsitektur yang lebih baik. Anda butuh beberapa kebiasaan berulang yang membuat masalah desain terlihat, dapat dibalik, dan terus diperbaiki.
30 hari berikutnya: Pilih satu “hot spot” (churn tinggi, insiden sering). Tambah suite test karakterisasi, sederhanakan satu rantai dependensi, dan mulai menulis catatan keputusan ringan untuk perubahan baru.
60 hari: Refaktor satu seam bermasalah: ekstrak modul, definisikan interface, atau isolasi kekhawatiran infrastruktur (seperti persistence atau messaging) di balik batas. Kurangi “blast radius” perubahan.
90 hari: Perbaiki loop delivery Anda. Bidik PR lebih kecil, build lebih cepat, dan cadence rilis yang dapat diprediksi. Jika mempertimbangkan microservices, buktikan kebutuhan dengan menunjukkan bahwa sebuah batas tidak bisa dikelola di dalam codebase yang ada.
(Jika sebagian tujuan Anda sekadar mengirim lebih banyak produk dengan lebih sedikit handoff, pertimbangkan di mana otomatisasi bisa membantu. Untuk beberapa tim, menggunakan workflow build berbasis chat seperti Koder.ai—dengan mode planning, ekspor sumber, deployment/hosting, domain kustom, dan tier harga dari gratis sampai enterprise—dapat mengurangi overhead mekanis sementara Anda memfokuskan perhatian arsitektural pada batas, test, dan umpan balik operasional.)
Lacak beberapa sinyal tiap bulan:
Jika ini tidak membaik, sesuaikan rencana—arsitektur hanya "lebih baik" ketika membuat perubahan lebih aman dan lebih murah.
Stacks akan terus berubah. Fundamental—batas yang jelas, disiplin refaktorisasi, dan umpan balik cepat—bertahan lama.
Arsitektur adalah kumpulan keputusan yang mahal untuk dibalik nanti: batas-batas, kepemilikan data, gaya integrasi, dan cara menangani kegagalan.
Stack teknologi adalah alat yang Anda gunakan untuk menerapkan keputusan itu (framework, pustaka, produk cloud). Banyak alat bisa diganti dengan dampak terbatas, tetapi mengubah batas atau aliran data sering kali memerlukan minggu kerja terkoordinasi.
Uji pembalikan: jika membatalkan keputusan membutuhkan minggu dan melibatkan beberapa tim yang harus berkoordinasi, itu bersifat arsitektural.
Contoh:
Gunakan pola ketika mereka menyelesaikan masalah berulang tertentu, bukan untuk membuat desain terlihat "profesional".
Checklist singkat:
Jika Anda tidak bisa menjelaskan masalahnya dengan jelas, jangan tambahkan pola dulu.
Anggap refaktorisasi sebagai pemeliharaan rutin yang terkait gesekan nyata, bukan proyek "bersih-bersih" yang jarang.
Pemicu umum:
Amankan dengan test, langkah kecil, dan scope review kode yang ketat.
Lacak utang teknis seperti biaya, bukan rahasia memalukan.
Cara praktis:
Buat keputusan utang eksplisit (misalnya, dengan ADR ringan).
Artinya merancang supaya Anda bisa berubah arah dengan aman saat belajar, bukannya bertaruh pada prediksi jangka panjang.
Komponen khas:
Tujuannya adalah adaptabilitas, bukan cetak biru sempurna di awal.
Fitness function adalah pembatas otomatis yang melindungi tujuan arsitektural.
Contoh berguna:
Pilih beberapa yang mencerminkan janji Anda (kecepatan perubahan, keandalan, keamanan) dan jalankan terus-menerus.
Mulai dari modular monolith kecuali Anda punya tekanan terukur dan berulang yang membutuhkan deploy independen.
Mikroservis memberikan keuntungan jika Anda memiliki:
Jika Anda belum mampu menjalankan satu layanan dengan nyaman di produksi, memecah menjadi sepuluh biasanya memperbanyak masalah.
Mulai dengan membuat ketergantungan terlihat dan disengaja.
Langkah berdampak tinggi:
DB bersama menciptakan “secret coupling” yang memaksa rilis terkoordinasi meski sistem terlihat terpisah.
Gunakan ADR untuk menangkap apa yang Anda putuskan dan mengapa, sementara konteks masih segar.
ADRs ringan berisi:
Simpan dekat kode (misalnya, ) dan tautkan panduan terkait seperti .
/docs/adr/