Kapan proyek perlu menyederhanakan arsitektur atau ditutup? Jawaban singkatnya: ketika biaya mental dan operasional untuk mempertahankan sistem mulai lebih besar daripada nilai yang benar-benar bisa dikirim. Tanda-tandanya biasanya bukan satu bug besar, melainkan akumulasi kecil: release makin lambat, perubahan sederhana butuh menyentuh banyak lapisan, hanya satu atau dua orang yang paham sistem, dan tooling mulai lebih sering dilayani daripada membantu delivery.
Refleksi ini relevan untuk banyak proyek open source maupun internal product. Kisah penutupan Fornjot sering dijadikan pemicu berpikir bukan karena dramanya, tetapi karena ia menunjukkan pola yang umum dalam rekayasa software: ambisi arsitektur bisa tumbuh lebih cepat daripada kapasitas maintainer. Artikel ini membahas cara menilai apakah proyek sebaiknya mempertahankan arsitektur saat ini, menyederhanakannya, mengecilkan scope, atau menghentikannya secara sadar dan bertanggung jawab.
Mengapa proyek yang "bagus secara teknis" tetap bisa gagal dipertahankan
Banyak tim menganggap masalah utama proyek adalah kualitas implementasi. Padahal, cukup banyak proyek runtuh bukan karena kodenya buruk, melainkan karena biaya total pemeliharaan tidak lagi sebanding dengan manfaatnya.
Beberapa penyebab umum:
- Arsitektur terlalu ambisius untuk ukuran tim. Sistem modular, plugin-heavy, event-driven, atau highly extensible memang fleksibel, tetapi setiap titik ekstensi menambah kontrak yang harus dijaga.
- Tooling menumpuk. CI kompleks, generator kode, custom build pipeline, banyak environment, matrix testing, dan linting berlapis bisa memperlambat kontribusi.
- Bus factor rendah. Jika hanya satu maintainer memahami dependency graph, proses release, dan area kritis, proyek rapuh meskipun desainnya elegan.
- Scope produk kabur. Tim terus membangun fondasi untuk kemungkinan masa depan, sementara use case inti belum stabil atau belum tervalidasi.
- Biaya perubahan terlalu tinggi. Fitur kecil memerlukan update di banyak package, adapter, interface, migration, dan dokumentasi lintas modul.
Masalah-masalah ini sering tidak terlihat dari luar. Repository tampak rapi, test suite hijau, dan struktur paket terpisah dengan baik. Namun dari dalam, setiap perubahan bisa terasa seperti menggerakkan banyak roda sekaligus.
Empat opsi keputusan: pertahankan, sederhanakan, perkecil scope, atau tutup
Keputusan terbaik jarang hanya dua pilihan. Daripada berpikir "lanjut atau berhenti", lebih berguna memakai empat mode keputusan berikut.
1. Pertahankan arsitektur saat ini
Pilih ini jika arsitektur yang ada memang mendukung kebutuhan nyata dan tim masih mampu mengoperasikannya.
Cocok jika:
- Banyak modul benar-benar dipakai dan punya batas tanggung jawab yang jelas.
- Onboarding kontributor baru masih masuk akal.
- Release cadence stabil.
- Insiden operasional rendah dan debugging tidak terlalu mahal.
- Tim punya kapasitas untuk menjaga kontrak antar komponen.
2. Sederhanakan arsitektur
Ini pilihan paling sering masuk akal untuk tim kecil. Tujuannya bukan "mengurangi kualitas", tetapi mengurangi permukaan kompleksitas.
Contoh penyederhanaan:
- Menggabungkan package internal yang selalu berubah bersama.
- Menghapus abstraction layer yang hanya punya satu implementasi.
- Mengurangi plugin point yang tidak pernah dipakai pihak ketiga.
- Mengganti orkestrasi async kompleks dengan alur sinkron yang lebih mudah dilacak, jika skala masih memungkinkan.
- Menyatukan pipeline build/test yang terpecah tanpa manfaat kuat.
3. Perkecil scope produk
Kadang masalah utama bukan bentuk arsitekturnya, melainkan target produknya terlalu luas. Dalam kasus ini, yang dikurangi adalah area masalah, bukan sekadar lapisan teknis.
Contoh:
- Mendukung satu platform dulu, bukan tiga platform sekaligus.
- Menetapkan satu workflow inti sebagai fokus, bukan banyak mode penggunaan.
- Menghapus fitur eksperimen yang mahal dirawat tetapi sedikit dipakai.
- Menyatakan beberapa integrasi sebagai di luar scope resmi.
4. Tutup proyek
Menutup proyek bukan selalu kegagalan. Kadang itu keputusan engineering yang paling jujur jika:
- Nilai pengguna tidak sebanding dengan beban maintainability.
- Tidak ada kapasitas maintainer yang realistis dalam jangka menengah.
- Arsitektur tidak bisa disederhanakan tanpa menghapus alasan utama proyek itu ada.
- Proyek terus menyedot energi dari prioritas lain yang lebih bernilai.
Keputusan menghentikan proyek sering lebih sehat daripada mempertahankan ilusi keberlanjutan. Proyek yang tampak hidup tetapi tidak benar-benar bisa dipelihara akan membebani pengguna, kontributor, dan maintainer.
Framework keputusan praktis untuk tim engineering
Berikut kerangka evaluasi yang bisa dipakai pada proyek internal maupun open source. Fokusnya adalah membandingkan nilai yang dikirim dengan kompleksitas yang harus ditanggung.
Langkah 1: Petakan nilai inti proyek
Tuliskan dengan spesifik:
- Masalah utama apa yang diselesaikan proyek?
- Siapa pengguna aktifnya?
- Fitur atau komponen mana yang benar-benar membuat proyek ini bernilai?
- Bagian mana yang hanya "mungkin berguna nanti"?
Jika tim sulit menjawab nilai inti tanpa jargon arsitektur, itu sinyal bahwa proyek mungkin terlalu berfokus pada mekanisme internal.
Langkah 2: Hitung biaya kompleksitas, bukan hanya biaya infrastruktur
Banyak tim hanya menghitung biaya server, storage, atau CI minutes. Padahal biaya terbesar sering ada di sisi manusia:
- Waktu memahami struktur kode.
- Waktu review perubahan kecil.
- Waktu sinkronisasi lintas modul.
- Waktu debugging dependency dan integrasi.
- Energi maintainer untuk menjawab issue, menjaga kompatibilitas, dan merawat tooling.
Pertanyaan pentingnya bukan "apakah ini arsitektur yang bagus?" tetapi "apakah tim kita mampu membayar biaya perubahannya secara terus-menerus?"
Langkah 3: Ukur rasio perubahan terhadap gesekan
Ambil 5-10 perubahan terakhir, lalu audit:
- Berapa file atau package yang disentuh per perubahan?
- Apakah perubahan kecil sering memerlukan refactor kontrak publik?
- Berapa lama dari coding sampai merge atau release?
- Apakah kegagalan sering muncul di integration boundary?
Jika fitur sederhana selalu menyentuh banyak lapisan, arsitektur kemungkinan tidak proporsional terhadap kebutuhan saat ini.
Langkah 4: Evaluasi bus factor dan kapasitas maintainer
Tim kecil harus jujur soal kapasitas. Arsitektur modular yang indah di atas kertas bisa menjadi liabilitas jika hanya satu orang memahami bagaimana modul saling berinteraksi.
Tanyakan:
- Jika maintainer utama cuti sebulan, siapa yang bisa release?
- Siapa yang paham proses build, dependency graph, dan area performa sensitif?
- Apakah dokumentasi cukup untuk contributor baru memperbaiki bug non-trivial?
Jika jawaban mayoritas adalah satu nama yang sama, proyek berada di zona rawan.
Langkah 5: Putuskan berdasarkan tindakan yang bisa dieksekusi
Hasil evaluasi harus berujung pada keputusan operasional yang jelas, misalnya:
- Pertahankan: tidak ada perubahan struktur besar, fokus delivery.
- Sederhanakan: gabungkan modul A/B/C dalam satu codebase, hapus extension point X, kurangi matrix CI.
- Perkecil scope: hentikan dukungan fitur Y dan targetkan hanya use case Z.
- Tutup: freeze repo, dokumentasikan status, arsipkan roadmap, dan beri migrasi alternatif bila memungkinkan.
Sinyal peringatan bahwa arsitektur mulai terlalu mahal
1. Tooling lebih sering dibahas daripada fitur inti
Jika diskusi engineering didominasi oleh build orchestration, workspace layout, code generation, compatibility layer, atau plugin contract, sementara use case pengguna jarang bergerak, ada kemungkinan kompleksitas internal mengambil alih fokus.
2. Modularitas tidak menghasilkan independensi nyata
Secara teori, modul terpisah memudahkan evolusi. Dalam praktik, banyak proyek memiliki modul yang selalu berubah bersama. Jika package A, B, dan C hampir selalu dirilis bersamaan, pemisahan itu mungkin hanya memindahkan kompleksitas, bukan menguranginya.
3. Satu fitur kecil memerlukan banyak koordinasi
Misalnya, menambah satu field baru ke alur bisnis memerlukan perubahan pada domain model, event schema, adapter, API, UI state, test snapshot, migration, dan dokumentasi plugin. Itu tidak selalu salah, tetapi bila terlalu sering terjadi untuk perubahan kecil, struktur sistem mungkin terlalu berlapis.
4. Onboarding lambat meskipun dokumentasi ada
Dokumentasi yang baik tidak selalu cukup jika model mental sistem terlalu rumit. Bila engineer baru tetap butuh waktu lama untuk melakukan perubahan aman, penyebabnya sering ada pada desain interaksi antar bagian.
5. Maintainer lelah mengelola kompatibilitas
Semakin banyak public interface, plugin API, format data, atau internal contract yang dianggap stabil, semakin berat beban backward compatibility. Ini sering tidak terasa di awal, tetapi menjadi mahal seiring waktu.
6. Scope berkembang lebih cepat daripada validasi penggunaan
Fitur dan extension point bertambah untuk kemungkinan masa depan, bukan untuk kebutuhan yang sudah terbukti. Ini pola umum over-engineering: fondasi makin megah, tetapi jalan utama belum banyak dilewati.
Tabel trade-off: monolit vs modular/plugin-heavy
Tidak ada pendekatan yang selalu benar. Yang penting adalah kecocokannya terhadap ukuran tim, stabilitas domain, dan kebutuhan ekstensi.
| Aspek | Monolit Sederhana | Modular/Plugin-Heavy |
|---|---|---|
| Kecepatan awal delivery | Tinggi, karena alur perubahan langsung | Lebih lambat, karena perlu kontrak dan boundary |
| Kemudahan refactor lintas komponen | Biasanya lebih mudah jika tim kecil | Bisa sulit jika kompatibilitas antar modul harus dijaga |
| Ekstensi pihak ketiga | Terbatas | Lebih baik jika plugin API stabil dan benar-benar dipakai |
| Beban tooling | Relatif rendah | Sering lebih tinggi: build, versioning, compatibility testing |
| Bus factor | Bisa lebih aman bila struktur mudah dipahami | Sering lebih berisiko jika hanya sedikit orang paham boundary |
| Isolasi tanggung jawab | Bisa kabur jika disiplin lemah | Lebih jelas secara desain, tetapi lebih mahal dijaga |
| Skala organisasi | Cocok untuk tim kecil hingga menengah | Lebih cocok jika ada banyak kontributor atau kebutuhan ekstensi nyata |
| Biaya perubahan kecil | Sering lebih rendah | Sering lebih tinggi karena banyak titik integrasi |
| Risiko over-engineering | Ada, tetapi lebih terlihat | Tinggi jika extensibility dibangun terlalu dini |
Kapan memilih monolit sederhana? Saat domain belum stabil, tim kecil, dan prioritas utama adalah belajar cepat serta mengirim fitur inti.
Kapan modular/plugin-heavy masuk akal? Saat ada kebutuhan ekstensi yang nyata, boundary domain relatif matang, dan kapasitas maintainer cukup untuk menjaga kontrak antar komponen dalam jangka panjang.
Checklist audit maintainability untuk tim kecil
Gunakan checklist ini setiap kuartal atau sebelum memulai refactor besar.
A. Struktur kode dan boundary
- Apakah setiap modul punya alasan eksistensi yang jelas, bukan sekadar "biar rapi"?
- Apakah modul-modul tertentu hampir selalu berubah bersama?
- Apakah ada abstraction layer yang hanya memiliki satu implementasi tanpa kebutuhan substitusi nyata?
- Apakah dependency direction konsisten dan mudah dijelaskan?
- Apakah fitur inti bisa dipahami tanpa membaca seluruh codebase?
B. Delivery dan perubahan
- Apakah bug fix kecil bisa dirilis tanpa koordinasi besar?
- Apakah pipeline build/test cukup cepat untuk loop feedback yang sehat?
- Apakah engineer tahu area mana yang harus disentuh untuk perubahan umum?
- Apakah review sering tertahan karena struktur terlalu kompleks?
- Apakah perubahan lintas modul benar-benar sering dibutuhkan?
C. Tooling dan operasi
- Apakah ada tool internal yang hanya dipahami satu orang?
- Apakah CI punya job yang mahal tetapi jarang memberi sinyal berguna?
- Apakah proses release terdokumentasi dan bisa dijalankan orang lain?
- Apakah local setup untuk contributor baru masuk akal?
- Apakah observability cukup untuk tracing kegagalan tanpa ritual manual yang rumit?
D. Tim dan keberlanjutan
- Siapa yang bisa mengambil alih jika maintainer utama tidak tersedia?
- Apakah dokumentasi arsitektur menjelaskan keputusan, bukan hanya struktur folder?
- Apakah ada area kritis tanpa owner cadangan?
- Apakah jumlah issue, PR, dan permintaan pengguna sesuai kapasitas tim?
- Apakah roadmap masih realistis terhadap energi maintainer?
E. Produk dan scope
- Apakah fitur yang paling mahal dirawat juga yang paling bernilai bagi pengguna?
- Apakah ada mode penggunaan resmi yang sebenarnya hampir tidak dipakai?
- Apakah proyek masih menyelesaikan masalah inti dengan baik?
- Apakah scope bertambah karena kebutuhan nyata atau karena dorongan teknis internal?
Jika banyak jawaban negatif terkumpul pada area yang sama, itu petunjuk prioritas tindakan. Jangan jadikan audit ini sekadar dokumen; ia harus menghasilkan daftar penyederhanaan yang konkret.
Contoh keputusan arsitektur yang bisa disederhanakan
Terkadang tim tahu ada masalah, tetapi bingung mulai dari mana. Berikut beberapa intervensi yang biasanya memberi dampak besar.
Gabungkan modul yang selalu berubah bersama
Jika beberapa package internal punya release cycle yang sama dan jarang digunakan terpisah, gabungkan dulu. Ini mengurangi versioning overhead, compatibility friction, dan koordinasi review.
Turunkan level genericity
Hapus interface atau adapter yang dibuat untuk kemungkinan masa depan tetapi tidak dipakai. Generic design bernilai jika ada variasi nyata. Kalau belum ada, abstraksi itu hanya menambah jarak antara masalah dan solusi.
Batasi extension point
Plugin architecture masuk akal jika ada plugin author atau kebutuhan customization yang konsisten. Jika tidak, lebih aman membuat API internal yang boleh berubah, lalu menstabilkannya nanti ketika pola penggunaan sudah jelas.
Sederhanakan pipeline engineering
Kurangi matrix testing yang tidak kritis, satukan script build, hilangkan langkah manual yang bisa didokumentasikan ulang, dan prioritaskan feedback cepat pada jalur perubahan umum.
Bekukan fitur eksperimental
Daripada merawat banyak cabang arah produk, pilih satu jalur utama. Fitur eksperimental boleh tetap ada, tetapi secara eksplisit dinyatakan tidak stabil atau di luar dukungan utama.
Contoh format audit keputusan dalam repository
Agar evaluasi tidak berhenti di diskusi, simpan keputusan dalam dokumen sederhana yang bisa direview tim.
Keputusan: Sederhanakan arsitektur dalam 2 iterasi berikutnya
Masalah utama:
- Perubahan kecil sering menyentuh 4-6 modul
- Hanya 1 maintainer paham proses release penuh
- Pipeline CI lambat dan sering gagal di integration boundary
Nilai yang harus dipertahankan:
- Workflow inti pengguna
- API publik yang aktif dipakai
- Kualitas test pada domain inti
Yang akan disederhanakan:
- Gabungkan package internal A, B, C
- Hapus plugin hook yang belum pernah dipakai
- Kurangi target platform dari 3 menjadi 1 target resmi
- Ringkas pipeline CI menjadi jalur cepat + jalur lengkap terjadwal
Risiko:
- Refactor awal memperlambat delivery 1-2 iterasi
- Beberapa integrasi non-inti tidak lagi didukung
Kriteria berhasil:
- Bug fix umum cukup menyentuh 1-2 area kode
- Release dapat dilakukan oleh lebih dari 1 engineer
- Waktu review dan integrasi menurun secara nyata
Format seperti ini membantu tim membedakan antara niat dan komitmen operasional.
Kapan proyek sebaiknya ditutup, bukan diperbaiki lagi
Ada kondisi ketika refactor tambahan justru memperpanjang biaya tanpa mengubah kenyataan dasar.
Pertimbangkan penutupan jika:
- Tidak ada maintainer berkelanjutan. Bukan sekadar sibuk minggu ini, tetapi memang tidak ada kapasitas realistis ke depan.
- Use case inti tidak tervalidasi. Setelah cukup waktu, proyek belum menemukan pengguna atau kebutuhan yang stabil.
- Arsitektur inti dan tujuan produk bertabrakan. Untuk membuat proyek berkelanjutan, Anda harus menghapus karakter utama yang menjadi alasan proyek itu dibuat.
- Biaya emosional maintainer terlalu tinggi. Burnout adalah biaya engineering yang nyata.
- Alternatif lain sudah lebih layak. Kadang ekosistem sudah punya solusi lebih sehat untuk pengguna.
Jika memilih menutup, lakukan dengan disiplin:
- Jelaskan status proyek secara terbuka.
- Dokumentasikan alasan teknis dan operasionalnya.
- Tandai area yang masih berguna untuk dipelajari atau diambil ulang.
- Jika memungkinkan, arahkan pengguna ke alternatif atau strategi migrasi.
- Arsipkan roadmap yang tidak lagi aktif agar ekspektasi jelas.
Penutupan yang jujur jauh lebih bermanfaat daripada membiarkan proyek tampak aktif tetapi tidak benar-benar aman digunakan atau dikontribusikan.
Kesalahan umum saat mengevaluasi proyek
- Menganggap kompleksitas selalu tanda kematangan. Kompleksitas bisa jadi hanya utang koordinasi yang belum terasa penuh.
- Menilai arsitektur dari diagram, bukan dari biaya perubahan. Diagram bisa bersih, tetapi workflow engineering tetap menyakitkan.
- Mengabaikan kapasitas maintainer. Desain yang cocok untuk organisasi besar belum tentu cocok untuk satu atau dua orang.
- Mempertahankan semua compatibility point. Tidak semua kontrak layak dijaga selamanya.
- Menunda keputusan karena sunk cost. Banyak investasi masa lalu tidak otomatis membenarkan biaya masa depan.
Penutup
Kapan proyek perlu menyederhanakan arsitektur atau ditutup pada akhirnya adalah pertanyaan tentang keberlanjutan engineering, bukan gengsi teknis. Arsitektur yang baik bukan yang paling modular, paling abstrak, atau paling extensible, melainkan yang memungkinkan tim mengirim nilai dengan beban yang masih mampu mereka tanggung.
Jika tim kecil mulai tertahan oleh tooling, boundary, kompatibilitas, dan bus factor, langkah paling dewasa sering bukan menambah lapisan baru, tetapi mengurangi permukaan masalah. Sederhanakan ketika struktur sudah terlalu mahal, perkecil scope ketika target terlalu luas, dan tutup proyek ketika keberlanjutan sudah tidak realistis. Keputusan yang jujur biasanya lebih murah daripada mempertahankan kompleksitas yang tidak lagi membayar dirinya sendiri.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!