Mengelola State Dengan Observer Pattern (Typescript)
Tujuan dari penulisan artikel ini adalah untuk mendemonstrasikan bahwa untuk me-manage state secara reaktif itu tidaklah sulit. Kita tak perlu harus selalu bergantung kepada third party library seperti Rxjs, Redux, Zustand, atau malah React. Saya percaya bahwa dengan memahami Observer Pattern saja sudah cukup untuk mengimplementasikan state yang reaktif.
Studi Kasus
Oke langsung masuk ke studi kasus: anggap saja kita sedang membuat aplikasi video player, dimana selain user bisa memainkan video, ia juga bisa mengganti tema player. Jadi state kita ada dua: isPlaying
, dan theme
.
Looks good. Dari sisi consumer pun cukup jelas.
Wow emejing. Tapi kemudian requirement berubah: tim UX memutuskan untuk mengubah behavior dimana ketika player sedang dijalankan (isPlaying == true
) elemen-elemen UI lain harus disembunyikan untuk memaksimalkan user experience.
Kalau dilihat baik-baik, fungsi onPlayback
kini mengatur semua side effect dari perubahan state isPlaying
. Bagaimana kalau kita ingin menjalankan side effect lain seperti
- Mengirimkan event analytics saat player di-play
- Menampilkan iklan saat player di-pause (eeww)
- Meredupkan halaman saat di-play
- … dan lain lain
Wah bakal terjadi banyak code coupling di dalam fungsi onPlayback
nantinya karena ia tau terlalu banyak behavior dari elemen-elemen lain.
Kalau situasinya seperti ini, mungkin akan lebih baik jika semua side effect ini yang justru bereaksi terhadap perubahan state isPlaying
. Jadi kita balik tanggungjawabnya. Kita ingin ada mekanisme dimana semua yang tertarik dengan nilai isPlaying
bisa meninggalkan “nomor” mereka dan nomor-nomor ini akan ditelepon ketika terjadi perubahan terhadap nilai isPlaying
.
Nomor-nomor ini berbentuk callback. Untuk menyembunyikan navbar saat player dimainkan, tinggal cantolin aja:
Atau misal, aplikasi utama kita ditulis menggunakan React dan halaman akan diredupkan saat video sedang diputar dan iklan akan ditampilkan saat di-pause:
Dan pada saat component unmount kita bisa unsubscribe agar bersih dari efek samping yang tak diinginkan.
Mekanisme subsciribe-unsubscribe inilah yang disebut Observer Pattern: playerUI
sebagai observee, dan callback-callback ini sebagai observer-nya. Dipikir-pikir cara kerja Observer Pattern ini mirip seperti addEventListener(event, callback)
dimana callback yang kita tinggalkan akan dijalankan saat suatu event terjadi.
Lalu bagaimana implementasinya?
Singkatnya, semua pihak yang tertarik dengan perubahan state harus menyediakan callback lewat fungsi subscribe
. Callback-callback ini lalu didaftarkan ke dalam variable listeners
. Dan ketika isPlaying
berubah semuanya akan dijalankan. Jika tak terarik lagi, mereka bisa menjalankan fungsi unsubscribe
.
Refactor
Jika kita perhatikan fungsi playerUI
, fungsi ini menjalankan 2 hal yang berbeda sekaligus: mengelola listeners untuk reaktifitas, dan menyediakan behavior-nya sendiri (togglePlay
dan toggleTheme
). Harus kita pisahkan biar comply sama Single Responsibility Principle.
Pertama, mari kita ekstrak kode pengelolaan state ke dalam fungsi sendiri, sebut saja observable
.
Kedua, kita gunakan observable
di dalam fungsi playerUI
yang kini hanya berfokus pada behavior player:
Saya lampirkan code di atas ke dalam link playground ini buat teman-teman yang mau ngulik lebih lanjut.
Kesimpulan
Observer Pattern memungkinkan kita untuk mendapat “notifikasi” update suatu value saat terjadi perubahan, macam push notification. Makanya Observer Pattern ini cocok untuk masalah yang sifatnya one-to-many tanpa harus khawatir dengan code coupling. Si listener-nya pun bisa sebanyak mungkin. Seperti push notification, kita bisa “ubah settingannya” untuk tidak menerima update-an lagi dengan memanggil fungsi unsubscribe
.
Sekian dulu, saya harap artikel ini bermanfaat. Cheers.