Section ini telah menempuh perjalanan panjang: prinsip SOLID, separation of concerns, layered hingga hexagonal architecture, DDD, dan belasan design pattern. Seluruh bekal tersebut kini menghadapi pertanyaan yang tidak punya jawaban tunggal: untuk aplikasi yang sedang Anda bangun, arsitektur mana yang paling tepat? Jawabannya bergantung pada hal yang sering bukan teknis — ukuran tim, kerumitan domain, dan kendala operasional. Chapter penutup ini merangkum perjalanan section menjadi kerangka keputusan, dengan kesimpulan yang tegas: kesederhanaan adalah fitur, bukan kekurangan.
Pertanyaan Penentu #
Empat pertanyaan berikut menyaring keputusan arsitektur lebih baik daripada daftar tren teknologi:
- Berapa ukuran tim? Arsitektur rumit untuk tim kecil adalah beban: satu orang tidak sanggup merawat enam layanan sekaligus. Hukum Conway mengingatkan bahwa arsitektur cenderung meniru struktur komunikasi tim.
- Berapa kompleksitas domain? Domain dengan banyak bounded context yang berbeda aturannya (katalog, gudang, ekspedisi) menuntut pemisahan model lebih daripada domain tunggal. Dua-tiga konteks jarang memerlukan pemecahan proses.
- Kendala SLA apa yang berlaku? Fungsi dengan janji waktu respons ketat bisa jadi perlu dijalankan terpisah agar bebannya tidak saling menumpuk — tetapi sering cukup diselesaikan dengan cache di dalam monolit.
- Adakah bagian yang butuh skala mandiri? Pemecahan layanan paling masuk akal ketika satu bagian butuh ribuan instance sementara bagian lain cukup dua — pola beban timpang dan terukur.
Mulai dari Monolit Modular #
Jawaban bawaan untuk mayoritas proyek baru adalah monolit modular: satu aplikasi yang di-deploy sebagai satu kesatuan, dengan batas modul yang tegas di dalam — package terpisah, API publik yang sempit, port-adapter ala hexagonal pada titik integrasi. Bentuk ini memberi kecepatan awal (satu build, satu deploy, satu tempat membaca alur), debugging yang mudah (satu stack trace, tanpa pelacakan lintas proses), dan tetap menyimpan pintu keluar: batas modul yang disiplin adalah tempat sambungan yang bisa diekstrak menjadi layanan terpisah saat bukti kebutuhan muncul.
Martin Fowler menyebut pendekatan ini monolith first: mulai monolit, ukur dulu, ekstrak kemudian. Kebalikannya — langsung memecah ke puluhan layanan sejak hari pertama — sering berujung pada distributed monolith: banyak layanan yang tetap di-deploy serentak dan saling menunggu sinkron, menyeret kerumitan terdistribusi tanpa satu pun manfaat kemandirian.
| Profil proyek | Rekomendasi |
|---|---|
| Tim kecil, domain sederhana | Monolit modular; batasi modul lewat package |
| Tim sedang, beberapa konteks | Monolit modular + hexagonal; port siap diekstrak |
| Tim besar tanpa kebutuhan ekstraksi | Monolit dengan observability kuat; tunda pemecahan |
| Tim besar, konteks banyak, skala timpang terukur | Layanan per bounded context, ekstraksi bertahap |
Kerangka Keputusan dalam Kode #
Aturan keputusan yang tertulis di tabel bisa pula diuji — dan menjadikannya kode memaksa kita menuliskan urutan serta syaratnya secara eksplisit. Program berikut mengambil empat profil proyek dan mengembalikan rekomendasinya:
import java.util.List;
public class SaranArsitektur {
public static void main(String[] args) {
// Empat profil proyek dengan kendala yang berbeda
List<Proyek> daftarProyek = List.of(
new Proyek("Aplikasi Kasir", 3, 2, false, false),
new Proyek("Modul Penjualan", 12, 4, false, true),
new Proyek("Portal Berita", 20, 3, false, false),
new Proyek("Platform Olahraga", 40, 9, true, true));
for (Proyek proyek : daftarProyek) {
System.out.println(proyek.nama() + " -> " + rekomendasi(proyek));
}
}
// Tabel keputusan dalam bentuk kode: aturan eksplisit dan dapat diuji
static String rekomendasi(Proyek proyek) {
if (proyek.tim() <= 8 && proyek.konteks() <= 3) {
return "monolit modular: satu deployable, batasi modul lewat package";
}
if (proyek.tim() <= 15 && proyek.konteks() <= 5 && !proyek.slaKetat()) {
return "monolit modular + hexagonal: port-adapter siap diekstrak";
}
if (proyek.ekstraksi() && proyek.konteks() > 5) {
return "layanan per bounded context, ekstraksi satu per satu";
}
return "monolit dengan observability; tunda pemecahan sampai bukti muncul";
}
}
record Proyek(String nama, int tim, int konteks, boolean slaKetat, boolean ekstraksi) {
}Output yang Dihasilkan:
Aplikasi Kasir -> monolit modular: satu deployable, batasi modul lewat package
Modul Penjualan -> monolit modular + hexagonal: port-adapter siap diekstrak
Portal Berita -> monolit dengan observability; tunda pemecahan sampai bukti muncul
Platform Olahraga -> layanan per bounded context, ekstraksi satu per satuBedah singkat program di atas:
- Baris 32-34 (
record Proyek): profil proyek menjadi data — tim, jumlah konteks domain, SLA ketat, dan kebutuhan ekstraksi. Profil sebagai data berarti aturan keputusan bisa diuji dengan seluruh variasi masukan tanpa membangun aplikasi sungguhan. - Baris 18-29 (
rekomendasi): aturan tersusun dari yang paling spesifik ke yang paling umum; syarat pertama yang terpenuhi menang. Setiap cabang terbaca sebagai kalimat keputusan, dan urutan cabang adalah keputusan desain yang bisa dikritik secara terbuka. - Baris 7-10 (empat profil uji): masing-masing profil sengaja jatuh ke cabang yang berbeda — bukti bahwa keempat aturan memang tersentuh.
Platform Olahragamemenuhi syarat ekstraksi dan konteks banyak, sehingga satu-satunya yang direkomendasikan menjadi layanan terpisah.
Kesederhanaan adalah Fitur #
Setiap komponen yang bisa di-deploy terpisah membawa ongkos tetap: kontrak API yang harus dijaga, penanganan kegagalan jaringan, penelusuran lintas proses, pipeline rilis sendiri, dan klarifikasi kepemilikan data. Ongkos tersebut adil hanya bila dibayar oleh manfaat yang sepadan. Karena itu arsitektur terbaik bukan yang paling canggih, melainkan yang paling sederhana namun masih memenuhi SLA dan domain — dan tetap menyediakan jalan keluar ketika asumsi meleset.
Penutup Section #
Kita menutup section ini dengan tiga benang merah. Pertama, kualitas desain berangkat dari aturan kecil yang dijaga konsisten: fungsi melakukan satu hal, dependensi mengalir ke arah abstraksi, invarian dijaga aggregate. Kedua, pola — SOLID, GoF, hingga repository dan unit kerja — adalah kosakata untuk masalah berulang; kosakata itu menjadi kebiasaan baik justru ketika kita tahu kapan tidak memakainya. Ketiga, arsitektur adalah keputusan yang dapat dibalik dengan biaya, bukan status kebanggaan; ukur dulu, ekstrak kemudian.
Kerangka berpikir ini akan menemani kita ke section berikutnya, tempat fondasi struktural program diuji dari sisi lain: Algorithms dan Data Structures, bagaimana memilih struktur data dan algoritma yang tepat agar desain yang bersih juga berjalan efisien.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
SaranArsitektur.java
Unduh berkasimport java.util.List;
public class SaranArsitektur {
public static void main(String[] args) {
// Empat profil proyek dengan kendala yang berbeda
List<Proyek> daftarProyek = List.of(
new Proyek("Aplikasi Kasir", 3, 2, false, false),
new Proyek("Modul Penjualan", 12, 4, false, true),
new Proyek("Portal Berita", 20, 3, false, false),
new Proyek("Platform Olahraga", 40, 9, true, true));
for (Proyek proyek : daftarProyek) {
System.out.println(proyek.nama() + " -> " + rekomendasi(proyek));
}
}
// Tabel keputusan dalam bentuk kode: aturan eksplisit dan dapat diuji
static String rekomendasi(Proyek proyek) {
if (proyek.tim() <= 8 && proyek.konteks() <= 3) {
return "monolit modular: satu deployable, batasi modul lewat package";
}
if (proyek.tim() <= 15 && proyek.konteks() <= 5 && !proyek.slaKetat()) {
return "monolit modular + hexagonal: port-adapter siap diekstrak";
}
if (proyek.ekstraksi() && proyek.konteks() > 5) {
return "layanan per bounded context, ekstraksi satu per satu";
}
return "monolit dengan observability; tunda pemecahan sampai bukti muncul";
}
}
record Proyek(String nama, int tim, int konteks, boolean slaKetat, boolean ekstraksi) {
}