Protocol for Modularity in Swift
Kecelakaan kerja yang saya alami ini bukan rekayasa. Duar!! sesaat setelah kejadian itu warna merah ada dimana-mana. saya shock!. Mereka membanjiri xcode sebagai tanda error.
Begini kronologinya.
Tiket dan deadline itu datang silih berganti, tak kenal kompromi. Akhirnya demi kecepatan development, saya menggunakan SJProgressHUD untuk merender tampilan loading. Dengan membabibuta, SJProgressHUD dipasang di banyak ViewController. Prinsip pertama yang saya langgar : Don’t repeat your self!.
Project selesai. Selanjutnya tinggal maintenace saja. Pada awalnya project dikembangkan dengan Swift 2.0. Namun ada kondisi tertentu yang menyebabkan project ini harus di konversi ke Swift 3.0. Maka kami diinstruksikan untuk melakukan revolusi!.
Konversi besar-besaranpun kami lakukan dengan penuh kecemasan. Benar saja, apa yang saya khawatirkan selama ini terjadi juga. Error dimana-mana membanjiri workspace xcode. Sayapun tersadar, prinsip kedua yang saya langgar : Single Responsibility. Akibatnya terjadi ikatan yang sangat kuat antar bagian code. Mereka bilang fenomena ini disebut dengan tighly coupled.
Spaghetti code harus segera di Refactor!
Hikmah yang bisa saya pelajari dari kejadian ini sebaiknya arsitektur apps dibuat semodular mungkin. Ok, mari kita diskusikan solusinya.
Ada beberapa cara untuk memperbaiki spaghetti code diatas. Cara pertama, dengan menurunkan (inheritance) class UIViewController
melalui extension
. Didalam extension
ini kita bisa menambahkan fungsi-fungsi seperti showLoading
, showError
, showSucces
.
kemudian, keajaiban terjadi. Kita bisa memanggil fungsi showWaiting
diatas dari semua turunan class UIViewController
. Keren kan? Tapi, sayangnya ada kondisi diamana UIViewController
tidak perlu mengetahui fungsi ini. Misalnya class AboutVC
yang dibuat khusus untuk menampilkan infromasi tentang aplikasi kita. Class ini tidak perlu tahu bahwa dirinya dapat memanggil showWaiting
. Sehingga kalau saja cara ini dipaksakan, maka tidak beda dengan kasus pemerkosaan eh pemaksaan.
Oke, mungkin solusinya akan lebih bagus dengan cara kedua. Kita buat saja subclassing atau class turunan UIViewController yang khusus menampilkan render popup. Begini contohnya.
Hmmm… its look nice! Sehingga semua ViewController yang ingin merender popup loading, harus menurunkan dari class UILoadingViewController
. Sekarang begini masalahnya. Tiba-tiba ada seorang programmer baru saja bergabung. Dengan rasa ingin tahunya yang tinggi, dia coba meng- override
fungsi showWaiting
dan membuat implementasinya. Apa yang akan terjadi? Fungsi yang asli tidak akan pernah dipanggil! Kecuali kalau menambahkan super.showWaiting("blaballa")
didalam fungsi tersebut. Cukup berbahaya, menjebak dan fragile
kalau tidak hati-hati.
Keep your apps modular!
Nah ini dia cara ketiga yang saya tawarkan. Orang bilang bahwa inti dari Swift adalah abstraction dan simplicity. Saya buatkan sebuah adapter UILoadingView
yang sangat fleksibel, bisa ditaruh sesuai kebutuhan. Artinya apabila sebuah UIViewController
ingin mendapatkan fungsi showWaiting()
maka cukup mencolokkan adapter UILoadingView
. Begini implementasinya.
Mereka para ahli selalu berpesan, untuk melakukan protocol oriented programming, mulalilah dengan membuat protocol. Artinya kita mulai dengan sebuah abstraksi tanpa implementasi.
Berikutnya baru dibuat implementasi dari protocol UILoadingView
dengan cara meng- extension
.
Kalau dalam gambar, ini saya ilustrasikan dengan adapter. Satu hal yang perlu digarisbawahi, … where Self: UIViewController
artinya ekstensi yang dilakukan ini akan berjalan jika dan hanya jika dipasangkan dengan keluargaUIViewController
. Sehingga dengan kata lain, adapter ini hanya cocok dipasangkan dengan UIViewController
. Lain waktu dikemudian hari, apabila ada rencaa mengganti librari PKHUD dengan librari lain, saya cukup mer-refactor bagian ini saja. Bagus kan?! hehe.. Lalu bagaimana cara memasangkannya dengan UIViewController
? berikut caranya.
Kesimpulan.
Sebelum aplikasi kita kompleks, pikirkan betul-betul tentang modulariti!. Semoga tulisan ini bermanfaat.