Skala Bertambah, Batas Tercapai: Alasan Kuat Meninggalkan GetX
Holigo adalah aplikasi mobile multi-layanan yang menggabungkan banyak solusi transaksi dalam satu ekosistem: pembayaran tagihan, top-up digital, serta pemesanan tiket perjalanan mulai dari bus, kereta api, pesawat, hingga kapal laut.
Seiring bertambahnya variasi layanan dan volume transaksi, kami makin menyadari bahwa fondasi arsitektur aplikasi menentukan seberapa cepat dan aman tim bisa merilis fitur baru. Sebagai lead mobile developer di proyek ini, saya dihadapkan pada kenyataan bahwa arsitektur bawaan yang digunakan sebelumnya sudah mulai menunjukkan batas kemampuannya.
GetX memang terasa sangat praktis dan cepat di awal pengembangan. Namun untuk aplikasi skala besar dengan transaksi finansial aktif, kepraktisan itu harus dibayar mahal: reactivity otomatis GetX sering kali mem-bypass siklus hidup (lifecycle) standar Flutter, mutasi state sulit diprediksi, dan controller yang terikat erat ke UI membuat pengujian otomatis (unit & widget test) sangat sulit dieksekusi secara konsisten.
- 01State Implisit: Reactivity otomatis melewati lifecycle standar Flutter, mutasi state sulit ditelusuri.
- 02Sulit Ditest: Business logic dan controllers terikat erat ke UI, mocking dan isolasi unit test sangat rumit.
- 03Struktur Variatif: Tidak ada layer contract yang ketat; tiap fitur disusun dengan pola berbeda-beda.
- 04Tight Coupling: Perubahan kecil di satu modul rentan memicu side-effect pada transaksi layanan lain.
- 01Unidirectional Flow: Event → State yang eksplisit dan deterministik via BLoC stream yang mudah di-debug.
- 02100% Testable Domain: Layer Domain murni Dart tanpa dependensi UI maupun framework, menjamin uji logika aman.
- 03Pemisahan Lapisan Tegas: Presentation, Domain, dan Data terisolasi rapi melalui kontrak repository interface.
- 04Blueprint Tim Seragam: Onboarding cepat & refactoring aman karena struktur di setiap fitur seragam dan terdokumentasi.
Pelajaran Kunci: Untuk aplikasi transaksi bernilai finansial, kemampuan pengujian otomatis dan alur state yang terprediksi bukan pelengkap, melainkan kebutuhan mutlak.
Menghindari Jebakan Rewrite: Memilih Strategi Migrasi Bertahap per Fitur
Ketika sebuah basis kode mulai terasa kusut, godaan terbesar bagi seorang engineer adalah melakukan "Big Bang Rewrite" — membuang seluruh kode lama dan menulis ulang aplikasi secara total dari nol.
Namun, menulis ulang seluruh aplikasi sekaligus adalah jebakan klasik rekayasa perangkat lunak: tim akan terjebak dalam masa vakum rilis berbulan-bulan tanpa memberikan value nyata ke pengguna, sementara risiko integrasi menumpuk dan baru meledak serentak saat hari peluncuran. Kami tidak bisa membiarkan operasional bisnis dan pendapatan perusahaan terganggu.
Karena itu, kami memilih pola migrasi bertahap (Strangler Fig pattern): aplikasi live GetX tetap berjalan melayani pengguna setiap hari, sementara fitur-fitur baru dibangun di atas fondasi Clean Architecture dan digantikan satu per satu. Pendekatan ini memecah risiko besar menjadi pecahan-pecahan kecil yang terkontrol, sehingga setiap modul bisa diuji, diverifikasi, dan dirilis mandiri ke store dengan aman.
- ✕Radio Silence Berbulan-bulan: Tim bekerja dalam isolasi lama tanpa ada update atau value nyata yang bisa dirilis ke pengguna.
- ✕Risiko Menumpuk di Akhir: Semua bug integrasi dan edge case baru ketahuan serentak saat app diganti secara menyeluruh.
- ✕Menghambat Roadmap Bisnis: Menuntut feature freeze pada app lama, memperlambat respon terhadap kebutuhan pasar.
- ✓Continuous Delivery: Tiap modul fitur selesai langsung diuji menyeluruh dan dirilis ke store tanpa menunggu modul lain.
- ✓Blast Radius Terisolasi: Jika muncul kendala di live environment, masalahnya terisolasi spesifik hanya pada fitur bersangkutan.
- ✓Operasional Bisnis Normal: App lama tetap melayani transaksi setiap hari, meminimalkan risiko kerugian pendapatan.
Pelajaran Kunci: Migrasi arsitektur terbaik adalah migrasi yang tidak pernah menghentikan roda bisnis dan memecah risiko teknis menjadi pecahan terkecil.
Memilih Fitur Kapal (PELNI): Menjadikan Scope Terkecil Sebagai Blueprint
Pilihan fitur pertama memegang peranan krusial karena akan menentukan standar penulisan kode untuk seluruh fitur berikutnya. Dari berbagai layanan tiket yang tersedia di Holigo, kami secara sadar memilih tiket Kapal (PELNI) sebagai proyek percontohan (pilot project).
Kami memilih Kapal bukan karena fitur ini paling prestisius, melainkan karena cakupan fiturnya paling ringkas dan terisolasi dibanding pesawat atau kereta yang memiliki alur multi-passenger, bagasi, dan add-ons kompleks. Dengan scope yang terukur, tim bisa memusatkan seluruh energi untuk membentuk cetak biru (blueprint) arsitektur yang solid.
Di fitur Kapal inilah kami merumuskan standar pemisahan lapisan Presentation, Domain, dan Data, alur BLoC event-to-state yang deterministik, kontrak repository yang bersih, hingga standarisasi penanganan error jaringan. Ketika fitur pesawat dan kereta menyusul kemudian, polanya sudah teruji dan tim developer bisa langsung berfokus pada keunikan logika bisnis masing-masing fitur tanpa harus mendesain fondasi dari nol lagi.
Kapal (PELNI)
Pilot BlueprintScope paling ringkas. Menjadi tempat menyusun standar Presentation, Domain, Data, alur BLoC, dan error handling.
Kereta & Bus
Pattern ExpansionKompleksitas menengah (stasiun, rute transit & kursi). Mengadopsi blueprint dari Kapal tanpa membangun fondasi dari nol.
Pesawat
High ComplexityAlur multi-passenger, bagasi, add-ons, dan validasi dinamis dieksekusi di atas arsitektur yang sudah teruji stabil.
PPOB & Core
Final CutoverMigrasi pembayaran tagihan, top-up, auth, dan melepaskan seluruh controller GetX lama dari codebase secara penuh.
Pelajaran Kunci: Fitur pertama sebaiknya dipilih bukan karena paling penting atau kompleks, melainkan karena paling cocok dijadikan contoh cetak biru (blueprint) bagi fitur-fitur berikutnya.
Fondasi dan Trade-off: Menjaga Dua Sistem Hidup Berdampingan
Sebelum fitur pertama dipindahkan, bagian fondasi bersama di layer Core harus benar-benar matang terlebih dahulu. Kami menyiapkan router bridge untuk navigasi mulus lintas arsitektur, design system tokens, network client terpusat, dan dependency injection (DI) service locator yang kokoh.
Selama masa transisi, modul GetX lama dan modul Clean Architecture baru harus hidup berdampingan di satu aplikasi yang sama. Agar pengguna tidak merasakan kejanggalan visual maupun alur sesi, kami menyusun panduan migrasi yang ketat untuk state manajemen, standarisasi warna, font, padding, dan dialog konfirmasi di kedua belah pihak.
Tentu ada harga yang harus dibayar: Clean Architecture + BLoC menuntut lebih banyak file dan boilerplate untuk perubahan kecil dibanding kepraktisan GetX. Namun trade-off ini kami terima dengan senang hati, karena pemisahan tanggung jawab yang tegas antar lapisan serta tingginya kemampuan pengujian (testability) memberikan ketenangan pikiran dan kestabilan jangka panjang bagi tim.
Melayani fitur yang belum dimigrasi (Pesawat, Bus, PPOB) tanpa downtime.
Melayani fitur Kapal dengan alur Presentation → Domain → Data yang terisolasi.
Trade-off yang Diterima: Clean Architecture menuntut lebih banyak file dan boilerplate untuk perubahan kecil, namun memberikan kepastian pengujian, batas tanggung jawab yang tegas, dan kemudahan kolaborasi tim jangka panjang.
Apa yang Bisa Dibawa dari Cerita Ini
Jika diringkas, ada beberapa pelajaran penting yang bisa dipakai kalau kamu sedang menghadapi situasi migrasi serupa:
Pilih fitur pertama yang kecil tapi representatif: Fitur pertama berfungsi sebagai contoh cetak biru bagi fitur-fitur berikutnya, sehingga cakupan yang ringkas membantu standarisasi pola arsitektur terbentuk jauh lebih cepat.
Tetapkan pola sebelum menambah fitur kedua: Konsistensi tim jauh lebih mudah dijaga ketika struktur lapisan kode, alur BLoC, dan penanganan error sudah disepakati bersama sejak awal.
Rawat konsistensi visual lewat panduan migrasi: Selama dua arsitektur hidup berdampingan, panduan bersama untuk state, warna, font, dan ukuran menjaga pengalaman pengguna tetap seragam tanpa friksi.
Jangan menunggu semua fitur selesai untuk mulai merilis: Rilis bertahap membuat risiko terbagi ke dalam unit-unit kecil, masalah di production terdeteksi lebih cepat, dan roda bisnis aplikasi tetap berjalan normal.
Penutup
Migrasi arsitektur pada dasarnya bukan sekadar mengganti library atau state management, melainkan menata ulang cara tim membangun, menguji, dan merawat produk dalam jangka panjang. Di Part 2 nanti, kita akan masuk lebih dalam ke struktur teknis lapisan presentation, domain, dan data dengan fitur Kapal sebagai contoh implementasi konkretnya.
Terima kasih telah membaca cerita saya :)
P.S. Seri ini ditulis di level keputusan dan arsitektur, tanpa membuka kode atau data internal perusahaan. Kalau ada pertanyaan, tanggapan, atau pengalaman migrasi serupa di tim mobile-mu, mari berdiskusi!
