Komunikasi Orangtua-Anak di Elm: OutMsg vs Translator vs NoMap Patterns

Saat aplikasi Anda Elm mulai tumbuh, Anda harus memecahnya menjadi potongan-potongan kecil untuk dapat menskala. Saya membahas hal ini di blogpost lain: Contoh TodoMVC terstruktur dengan Elm.

Sebagian jika penskalaan ini pada akhirnya melibatkan kebutuhan mengirim pesan dari modul ke induknya, seperti ketika tombol navigasi pada tampilan tertentu perlu mengirim pesan ke Router tingkat atas.

Setelah beberapa waktu saya mulai memperhatikan 3 pola berbeda untuk penanganan ini, dan saya refactored Elm TodoMVC ke semua pendekatan yang berbeda dalam repositori ini sehingga Anda dapat membandingkannya berdampingan.

Pola OutMsg

Saya percaya Folkertdev adalah orang pertama yang saya lihat untuk menulis tentang komunikasi anak-orang tua di Elm, posting blognya menjelaskan pendekatan ini dengan cukup baik.

Tetapi, untuk meringkas, pada dasarnya Anda mengembalikan nilai ekstra dalam fungsi pembaruan Anda. Jadi alih-alih mengembalikan ini:

(Model, Cmd Msg)

Anda mengembalikan ini:

(Model, Cmd Msg, OutMsg)

Kemudian, fungsi pembaruan orang tua bertanggung jawab untuk menangani hal itu. Dengan cara ini anak tidak perlu tahu apa-apa tentang orang tuanya, tetapi orang tua perlu tahu tentang Keluaran anaknya.

Saya telah mengimplementasikan TodoMVC menggunakan pendekatan ini. Tetapi jika Anda ingin memeriksa skala dunia nyata ini, Richard Feldman menerapkan contoh-elm-spa dengan cara ini.

Contoh lain yang menggunakan pendekatan ini adalah elm-datepicker.

Pola Penerjemah

Pola Penerjemah sangat mirip dengan yang OutMsg, tetapi alih-alih orang tua mengetahui tentang jenis Msg anak, itu adalah orang tua yang melewati Msg mana yang akan dihasilkan, melalui penerjemah. Alex Lew menjelaskan pendekatannya jauh lebih baik di sini.

Pada dasarnya Anda memiliki penerjemah yang merupakan catatan seperti ini:

ketik alias Terjemahan TerjemahanTuliskan =
  {onInternalMessage: InternalMsg -> msg
  , onPlayerWin: Int -> msg
  , onPlayerLose: msg
  }

Saya juga menerapkan TodoMVC menggunakan pendekatan ini, dan saya percaya elm-autocomplete juga merupakan contoh yang baik.

Pembaruan elm-parent-child adalah perpustakaan yang membantu Anda dengan pembaruan child-parent yang tampaknya mengikuti pola ini.

Pola NoMap

Ini adalah sesuatu yang saya perhatikan sedang saya lakukan. Ide dasarnya adalah untuk menghindari melakukan Cmd.map dan Html.map, jadi alih-alih semua orang perlu berbicara bahasa yang sama, dengan kata lain, fungsi pembaruan dan tampilan Anda harus mengembalikan tipe Msg tingkat atas.

Dengan ini Anda mungkin akan memiliki Msg seperti MsgForLogin, MsgForRouter, dll, jadi dalam Tampilan Anda, Anda akan melakukan sesuatu seperti:

tombol [onClick (Pendaftaran MsgForLogin)] []

Inilah bagaimana saya pertama kali refactored TodoMVC, pada kenyataannya, pertama kali saya melihat OutMsg saya tidak mengerti alasannya, karena saya tidak memetakan Msgs saya.

Lihat aplikasi petir-bicara-untuk contoh yang lebih besar dengan pendekatan ini. Selain itu, aplikasi ini tampaknya mengikuti cara Kris Jenkins menyusun struktur aplikasi Elm, yang mendukung pendekatan ini saat ia memisahkan tipe Msgs dalam file Types.elm.

Perpustakaan elm-taco agak menggunakan campuran pola OutMsg dan NoMap dengan memiliki "taco" tingkat atas yang dapat Anda kirimi pesan.

Pengamatan dan Perbandingan

Saat meneliti dan refactoring untuk pola-pola itu, saya mencatat sesuatu, yang dapat menjadi keuntungan atau kerugian tergantung dari kebutuhan Anda:

  • Di NoMap, fungsi pembaruan orang tua hampir sama dengan aplikasi Anda tumbuh, sedangkan pada OutMsg dan Terjemahkan fungsi pembaruan orangtua mungkin menjadi sangat besar, karena Anda perlu menangani OutMsg setiap anak (contoh)
  • Pada OutMsg dan Translate, modul bersarang tidak perlu mengimpor apa pun dari orang tua yang lebih tinggi, membuatnya lebih dienkapsulasi, akan lebih mudah untuk mengekstrak dan menerbitkan beberapa sub-modul sebagai perpustakaan misalnya
  • Agar NoMap berfungsi, Msg Anda harus hidup dalam file terpisah dari Pembaruan, atau Anda akan memiliki loop ketergantungan. Ini adalah penyebab yang baik memaksa Anda untuk membagi hal-hal, tetapi buruk pada saat yang sama jika Anda ingin memiliki satu file untuk setiap modul (Home.elm, Login.elm, Router.elm)
  • Di NoMap, lebih mudah mengirim Msg ke tempat lain, tetapi mungkin lebih sulit untuk mengikuti semua perubahan kondisi yang disebabkannya.
  • Seperti yang diukur pada saat penulisan ini, untuk para refactor TodoMVC, pendekatan NoMap memiliki 546 LOC, OutMsg 561 dan Translator 612 jika ini penting bagi Anda
  • Pada NoMap Anda akhirnya perlu menggunakan case _ catch-all untuk mengabaikan Msgs dari tempat lain yang tidak ingin Anda tangani, jadi ada sedikit bantuan dari kompiler, ia tidak dapat memberi tahu apa yang Anda lewatkan (terima kasih atas @mordrax untuk menunjuknya bahwa pada elm slack)
  • Di OutMsg dan Penerjemah Anda bisa melihat jenis atau penerjemah untuk menemukan komunikasi anak-orang tua mana yang diperlukan, sehingga kompiler dapat memandu Anda menerapkannya, sedangkan di NoMap komunikasi ini lebih tersirat
  • Pendekatan penerjemah tampaknya merupakan ide bagus untuk memberikan pesan Anda sendiri ke komponen eksternal, seperti elm-autocomplete
  • Saya menemukan pola penerjemah sulit diikuti dengan lebih sulit untuk memahami pesan kesalahan dari kompiler Elm sambil membangunnya
  • Jika Anda tidak mengubah standar (Model, Cmd Msg) Anda dapat menggunakan pustaka elm-return halus
  • Beberapa orang menganggap tidak memiliki Html.map sebagai praktik yang baik untuk menghindari membuat "komponen"
  • Anda bisa mendapatkan banyak manfaat dari menggabungkan pendekatan-pendekatan itu, misalnya, Anda bisa saja menghindari Html.map untuk tampilan, sambil tetap menggunakan OutMsg untuk pembaruan, atau Anda bisa menggunakan NoMap hanya untuk Msg tingkat atas, dengan OutMsg di bawah, saat merender komponen Diterjemahkan eksternal

Sumber daya

Saya percaya Komunikasi Orangtua-Anak seringkali lebih penting ketika melakukan penskalaan dan melakukan SPA, itu sebabnya banyak hal yang saya temukan adalah membaca utas reddit ini tentang Scaling Elm Apps:

Tepuk tangan!