Dalam arsitektur yang digerakkan oleh peristiwa, setiap komponen hanya bertindak ketika suatu peristiwa dikirim melalui sistem.
Bayangkan sebuah mobil hipotetis dengan pedal rem dan lampu rem.
- Rem bergantian cahaya pada saat menerima brake_on acara, dan off ketika menerima brake_off acara.
- Pedal rem mengirimkan acara brake_on saat ditekan ke bawah, dan acara brake_off saat dilepaskan.
Ini semua baik dan bagus, sampai Anda memiliki situasi di mana mobil dihidupkan dengan pedal rem sudah ditekan . Karena lampu rem tidak pernah menerima acara rem_on , lampu rem akan tetap mati - jelas situasi yang tidak diinginkan. Menyalakan lampu rem secara default hanya membalikkan situasi.
Apa yang bisa dilakukan untuk menyelesaikan 'masalah keadaan awal' ini?
EDIT: Terima kasih atas semua tanggapan. Pertanyaan saya bukan tentang mobil yang sebenarnya. Di mobil mereka memecahkan masalah ini dengan terus mengirim negara - karena itu tidak ada masalah startup di domain itu. Dalam domain perangkat lunak saya, solusi itu akan menggunakan banyak siklus CPU yang tidak perlu.
EDIT 2: Selain jawaban @ gbjbaanb , saya akan mencari sistem di mana:
- pedal rem hipotetis, setelah inisialisasi, mengirimkan peristiwa dengan kondisinya, dan
- lampu rem hipotetis, setelah inisialisasi, mengirimkan peristiwa yang meminta keadaan peristiwa dari pedal rem.
Dengan solusi ini, tidak ada ketergantungan antara komponen, tidak ada kondisi balapan, tidak ada antrian pesan untuk basi, dan tidak ada komponen 'master'.
sumber
initialize
) yang berisi data sensor yang dibutuhkan.Jawaban:
Ada banyak cara untuk melakukan ini, tetapi saya lebih memilih untuk menjaga sistem berbasis pesan sedapat mungkin dipisahkan. Ini berarti bahwa keseluruhan sistem tidak dapat membaca status komponen apa pun, atau komponen apa pun membaca status komponen lainnya (karena dengan demikian terletak ikatan spaghetti dari ketergantungan).
Jadi, sementara sistem yang berjalan akan menjaga dirinya sendiri, kita perlu cara untuk memberitahu setiap komponen untuk memulai sendiri, dan kita sudah memiliki hal seperti itu dalam pendaftaran komponen, yaitu pada saat startup sistem inti harus menginformasikan setiap komponen bahwa itu adalah sekarang terdaftar (atau akan meminta setiap komponen untuk mengembalikan rinciannya sehingga dapat didaftarkan). Ini adalah tahap di mana komponen dapat melakukan tugas-tugas startupnya, dan dapat mengirim pesan seperti yang akan dilakukan dalam operasi normal.
Jadi pedal rem, ketika kunci kontak dimulai, akan menerima pesan registrasi / cek dari manajemen mobil dan itu akan mengembalikan tidak hanya pesan "Aku di sini dan bekerja", tetapi kemudian akan memeriksa keadaannya sendiri dan mengirim pesan untuk keadaan itu (mis. pesan yang ditekan pedal).
Masalahnya kemudian menjadi salah satu ketergantungan startup, karena jika lampu rem belum terdaftar maka tidak akan menerima pesan, tetapi ini mudah diselesaikan dengan mengantri semua pesan ini sampai sistem inti telah menyelesaikan startup, pendaftaran dan pemeriksaan rutinnya .
Manfaat terbesar adalah bahwa tidak ada kode khusus yang diperlukan untuk menangani inisialisasi kecuali bahwa Anda sudah harus menulis (ok, jika pengiriman pesan Anda untuk acara pedal rem ada dalam handler pedal rem, Anda harus memanggil itu dalam inisialisasi Anda juga , tapi itu biasanya bukan masalah kecuali Anda telah menulis kode yang sangat terkait dengan logika handler) dan tidak ada interaksi antara komponen kecuali yang sudah mereka kirim satu sama lain seperti biasa. Arsitektur message passing sangat baik karena ini!
sumber
Anda dapat memiliki acara inisialisasi yang menetapkan status secara tepat saat memuat / memulai. Ini dapat diinginkan untuk sistem atau program sederhana yang tidak termasuk beberapa bagian perangkat keras, namun untuk sistem yang lebih rumit dengan banyak komponen fisik saat Anda menjalankan risiko yang sama dengan tidak menginisialisasi sama sekali - jika acara "rem pada" dilewatkan atau hilang selama komunikasi Anda sistem (misalnya, sistem berbasis CAN) Anda mungkin secara tidak sengaja mengatur sistem Anda mundur seolah-olah Anda memulainya dengan rem ditekan. Semakin banyak pengendali yang mungkin Anda miliki, seperti dengan mobil, semakin tinggi kemungkinan ada sesuatu yang terlewatkan.
Untuk menjelaskan hal ini, Anda dapat meminta logika "rem pada" berulang kali mengirimkan "rem pada". Mungkin setiap 1/100 detik atau sesuatu. Kode Anda yang berisi otak dapat mendengarkan peristiwa-peristiwa ini dan memicu "rem on" ketika sedang menerima mereka. Setelah 1 / 10sec dari tidak menerima sinyal "rem pada" itu memicu acara "rem_off" internal.
Peristiwa yang berbeda akan memiliki persyaratan waktu yang sangat berbeda. Di mobil, lampu rem Anda harus jauh lebih cepat daripada lampu bahan bakar cek Anda (di mana penundaan multisecond mungkin diterima) atau sistem lain yang kurang penting.
Kompleksitas sistem fisik Anda akan menentukan pendekatan mana yang lebih tepat. Mengingat contoh Anda adalah kendaraan, Anda mungkin ingin sesuatu yang mirip dengan yang terakhir.
Either way, dengan sistem fisik, Anda TIDAK ingin bergantung pada satu peristiwa yang diterima / diproses dengan benar. Mikrokontroler yang terhubung pada sistem jaringan sering kali memiliki batas waktu "Saya hidup" karena alasan ini.
sumber
Dalam hal ini, saya tidak akan memodelkan rem sebagai on / off sederhana. Sebaliknya, saya akan mengirim acara "tekanan rem". Misalnya, tekanan 0 akan menunjukkan mati dan tekanan 100 akan sepenuhnya tertekan. Sistem (simpul) akan secara konstan mengirimkan peristiwa tekanan putus (pada interval tertentu) ke pengontrol sesuai kebutuhan.
Ketika sistem dimulai itu akan mulai menerima peristiwa tekanan sampai dimatikan.
sumber
Jika satu-satunya cara Anda menyampaikan informasi negara adalah melalui acara, maka Anda dalam masalah. Sebaliknya, Anda harus dapat keduanya:
Lampu rem dapat dilihat sebagai pengamat pedal rem. Dengan kata lain, pedal rem tidak tahu apa-apa tentang lampu rem, dan dapat beroperasi tanpanya. (Ini berarti bahwa setiap gagasan tentang pedal rem secara proaktif mengirimkan "kondisi awal" ke lampu rem tidak dipahami.)
Setelah instantiasi sistem, lampu rem mendaftar dengan pedal rem untuk menerima pemberitahuan pengereman, dan juga membaca keadaan pedal rem saat ini dan menyalakan atau mematikan dirinya sendiri.
Kemudian, notifikasi pengereman dapat diimplementasikan dalam satu dari tiga cara:
Saya lebih suka pendekatan pertama, yang berarti bahwa setelah menerima pemberitahuan, lampu rem hanya akan melakukan apa yang sudah diketahui caranya: membaca keadaan pedal rem saat ini dan menghidupkan atau mematikannya sendiri.
sumber
Dalam sistem yang digerakkan oleh peristiwa (yang saat ini saya gunakan dan cintai), saya merasa penting untuk menjaga hal-hal yang terpisah sebanyak mungkin. Jadi dengan gagasan itu dalam pikiran, mari kita selami.
Sangat penting untuk memiliki beberapa status default. Lampu rem Anda akan mengambil status default 'mati' dan pedal rem Anda akan mengambil status default 'naik'. Setiap perubahan setelah itu akan menjadi suatu peristiwa.
Sekarang untuk menjawab pertanyaan Anda. Bayangkan pedal rem Anda diinisialisasi dan ditekan, acara menyala, tetapi belum ada lampu rem untuk menerima acara. Saya merasa paling mudah untuk memisahkan penciptaan objek (di mana pendengar acara akan diinisialisasi) sebagai langkah terpisah sebelum menginisialisasi logika apa pun. Itu akan mencegah segala kondisi balapan seperti yang telah Anda jelaskan.
Saya juga merasa canggung menggunakan dua peristiwa berbeda untuk hal yang secara efektif sama .
brake_off
danbrake_on
bisa disederhanakan menjadie_brake
dengan parameterbool on
. Anda dapat menyederhanakan acara Anda dengan cara ini dengan menambahkan data pendukung.sumber
Yang Anda butuhkan adalah acara siaran dan kotak masuk pesan. Siaran adalah pesan yang dipublikasikan ke sejumlah pendengar yang tidak ditentukan. Komponen dapat berlangganan untuk acara siaran sehingga hanya menerima acara yang menarik. Ini memberikan decoupling, karena pengirim tidak perlu tahu siapa penerima. Tabel berlangganan perlu dikonfigurasikan secara statis selama instalasi komponen (alih-alih ketika diinisialisasi). Kotak masuk adalah bagian dari router pesan yang bertindak sebagai penyangga untuk menyimpan pesan ketika komponen tujuan sedang offline.
Menggunakan faktur membawa satu masalah, yaitu ukuran kotak masuk. Anda tidak ingin sistem harus mempertahankan semakin banyak pesan untuk komponen yang tidak akan pernah online lagi. Ini penting terutama dengan sistem tertanam dengan batasan memori yang ketat. Untuk mengatasi batas ukuran kotak masuk, semua pesan yang disiarkan perlu mengikuti beberapa aturan. Aturannya adalah:
Nama siaran harus dinyatakan selama waktu pemasangan komponen. Jika suatu komponen mengirimkan siaran kedua dengan nama yang sama sebelum penerima memproses yang sebelumnya, siaran yang baru menimpa yang sebelumnya. Sekarang Anda dapat memiliki batas ukuran kotak masuk statis, yang dapat dijamin tidak akan pernah melebihi ukuran tertentu dan dapat dihitung berdasarkan tabel langganan.
Akhirnya, Anda juga membutuhkan arsip siaran. Arsip siaran adalah tabel yang menampung acara terakhir dari setiap nama siaran. Komponen-komponen baru yang baru saja diinstal akan memiliki kotak masuknya yang diisi sebelumnya dengan pesan-pesan dari arsip siaran. Seperti kotak masuk pesan, arsip siaran juga dapat memiliki ukuran statis.
Selain itu, untuk menangani situasi di mana router pesan itu sendiri sedang offline, Anda juga perlu kotak keluar pesan. Kotak keluar pesan adalah bagian dari komponen yang menyimpan pesan keluar sementara.
sumber