Suatu acara adalah pemberitahuan yang menggambarkan kejadian dari masa lalu baru-baru ini.
Implementasi tipikal dari sistem yang digerakkan oleh event menggunakan fungsi dispatcher dan fungsi handler (atau pelanggan ). Dispatcher menyediakan API untuk mengirim penangan ke acara (jQuery's bind
), dan metode untuk mempublikasikan acara kepada pelanggannya ( trigger
di jQuery). Saat Anda berbicara tentang acara IO atau UI, biasanya juga ada loop acara , yang mendeteksi acara baru seperti klik mouse dan meneruskannya ke operator. Di JS-land, dispatcher dan loop acara disediakan oleh browser.
Untuk kode yang berinteraksi langsung dengan pengguna - merespons penekanan tombol dan klik - pemrograman berdasarkan peristiwa (atau variasi daripadanya, seperti pemrograman reaktif fungsional ) hampir tidak dapat dihindari. Anda, sang programmer, tidak tahu kapan atau di mana pengguna akan mengklik, jadi tergantung pada kerangka kerja GUI atau browser untuk mendeteksi tindakan pengguna di loop acara dan memberi tahu kode Anda. Jenis infrastruktur ini juga digunakan dalam aplikasi jaringan (cf NodeJS).
Contoh Anda, di mana Anda meningkatkan suatu peristiwa dalam kode Anda daripada memanggil fungsi secara langsung memiliki beberapa tradeoff yang lebih menarik, yang akan saya bahas di bawah ini. Perbedaan utama adalah bahwa penerbit acara ( makeItSnow
) tidak menentukan penerima panggilan; yang terhubung di tempat lain (dalam panggilan ke bind
dalam contoh Anda). Ini disebut api-dan-lupakan : makeItSnow
mengumumkan kepada dunia bahwa salju turun, tetapi tidak peduli siapa yang mendengarkan, apa yang terjadi selanjutnya, atau ketika itu terjadi - ia hanya menyiarkan pesan dan membersihkan debu dari tangannya.
Jadi pendekatan event-driven decouples pengirim pesan dari penerima. Satu keuntungan yang bisa Anda dapatkan dari ini adalah bahwa suatu peristiwa tertentu mungkin memiliki banyak penangan. Anda dapat mengikat gritRoads
fungsi ke acara salju Anda tanpa mempengaruhi shovelSnow
penangan yang ada . Anda memiliki fleksibilitas dalam cara aplikasi Anda terhubung; untuk mematikan perilaku Anda hanya perlu menghapus bind
panggilan daripada pergi mencari kode untuk menemukan semua contoh perilaku.
Keuntungan lain dari pemrograman berbasis acara adalah memberi Anda tempat untuk menaruh keprihatinan yang saling terkait. Dispatcher peristiwa memainkan peran Mediator , dan beberapa perpustakaan (seperti Brighter ) menggunakan pipa sehingga Anda dapat dengan mudah memasang persyaratan umum seperti logging atau kualitas layanan.
Pengungkapan penuh: Brighter dikembangkan di Huddle, tempat saya bekerja.
Keuntungan ketiga dari memisahkan pengirim dari suatu peristiwa dari penerima adalah memberi Anda keleluasaan ketika Anda menangani acara tersebut. Anda dapat memproses setiap jenis acara dengan utasnya sendiri (jika pengirim acara Anda mendukungnya), atau Anda dapat menempatkan acara yang ditinggikan ke pialang pesan seperti RabbitMQ dan menanganinya dengan proses asinkron atau bahkan memprosesnya dalam semalam massal. Penerima acara dapat dalam proses yang terpisah atau pada mesin yang terpisah. Anda tidak perlu mengubah kode yang memunculkan acara untuk melakukan ini! Ini adalah Ide Besar di balik arsitektur "layanan mikro": layanan otonom berkomunikasi menggunakan acara, dengan pesan middleware sebagai tulang punggung aplikasi.
Untuk contoh yang agak berbeda dari gaya yang digerakkan oleh peristiwa, lihat desain yang digerakkan oleh domain, tempat acara domain digunakan untuk membantu memisahkan agregat. Misalnya, pertimbangkan toko online yang merekomendasikan produk berdasarkan riwayat pembelian Anda. A Customer
perlu memiliki riwayat pembelian yang diperbarui ketika a ShoppingCart
dibayar. The ShoppingCart
agregat mungkin memberitahu Customer
dengan mengangkat CheckoutCompleted
acara; itu Customer
akan diperbarui dalam transaksi terpisah dalam menanggapi acara tersebut.
Kelemahan utama dari model yang digerakkan oleh peristiwa ini adalah tipuan. Sekarang lebih sulit untuk menemukan kode yang menangani acara tersebut karena Anda tidak bisa menavigasi saja menggunakan IDE Anda; Anda harus mencari tahu di mana acara tersebut terikat dalam konfigurasi dan berharap bahwa Anda telah menemukan semua penangan. Masih ada banyak hal yang perlu diingat di suatu waktu. Konvensi gaya kode dapat membantu di sini (misalnya, meletakkan semua panggilan ke bind
dalam satu file). Demi kewarasan Anda, penting untuk hanya menggunakan satu pengirim acara dan menggunakannya secara konsisten.
Kerugian lain adalah sulit untuk memperbaiki acara. Jika Anda perlu mengubah format acara Anda juga harus mengubah semua penerima. Ini diperburuk ketika pelanggan suatu acara menggunakan mesin yang berbeda, karena sekarang Anda perlu menyinkronkan rilis perangkat lunak!
Dalam keadaan tertentu, kinerja dapat menjadi perhatian. Saat memproses pesan, operator harus:
- Cari penangan yang benar dalam beberapa struktur data.
- Buat saluran pemroses pesan untuk setiap penangan. Ini mungkin melibatkan banyak alokasi memori.
- Hubungi penangan secara dinamis (mungkin menggunakan refleksi jika bahasa membutuhkannya).
Ini tentu saja lebih lambat daripada pemanggilan fungsi biasa, yang hanya melibatkan mendorong bingkai baru pada stack. Namun, fleksibilitas yang diberikan arsitektur event-driven membuat Anda lebih mudah untuk mengisolasi dan mengoptimalkan kode lambat. Memiliki kemampuan untuk mengirimkan pekerjaan ke prosesor asinkron adalah kemenangan besar di sini, karena memungkinkan Anda untuk melayani permintaan segera sementara kerja keras ditangani di latar belakang. Bagaimanapun, jika Anda berinteraksi dengan DB atau menggambar hal-hal di layar maka biaya IO benar-benar akan membebani biaya pemrosesan pesan. Ini adalah kasus menghindari optimasi prematur.
Singkatnya, acara adalah cara yang bagus untuk membangun perangkat lunak yang digabungkan secara longgar, tetapi bukan tanpa biaya. Ini akan menjadi kesalahan, misalnya, untuk mengganti setiap panggilan fungsi dalam aplikasi Anda dengan suatu peristiwa. Gunakan acara untuk membuat divisi arsitektur yang bermakna.
$(document).bind('snow', shovelShow)
. Tidak perlu membungkusnya dalam fungsi anonim.