Kami bertarung dengan Msg terlalu besar dalam aplikasi Elm

Menurut Elm Architecture, semua logika aplikasi terkonsentrasi di satu tempat. Ini adalah pendekatan yang cukup sederhana dan nyaman, tetapi dengan pertumbuhan aplikasi, Anda dapat melihat fungsi update dengan panjang 700 baris, Msg dengan seratus konstruktor dan Model , yang tidak sesuai di layar.


Kode semacam itu cukup sulit untuk dipelajari dan sering dipelihara. Saya ingin menunjukkan teknik yang sangat sederhana yang akan meningkatkan level abstraksi dalam aplikasi Anda.


Mari kita lihat contoh sederhana.


Pertama, buat aplikasi kecil dengan hanya satu bidang teks. Kode lengkap dapat ditemukan di sini .


 type alias Model = { name : String } view : Model -> Html Msg view model = div [] [ input [ placeholder "Name", value model.name, onInput ChangeName ] [] ] type Msg = ChangeName String update : Msg -> Model -> Model update msg model = case msg of ChangeName newName -> { model | name = newName } 

Aplikasi ini berkembang, kami menambahkan nama belakang, "tentang diri kita sendiri" dan tombol "Simpan". Berkomitmen di sini .


 type alias Model = { name : String , surname : String , bio : String } view : Model -> Html Msg view model = div [] [ input [ placeholder "Name", value model.name, onInput ChangeName ] [] , br [] [] , input [ placeholder "Surname", value model.surname, onInput ChangeSurname ] [] , br [] [] , textarea [ placeholder "Bio", onInput ChangeBio, value model.bio ] [] , br [] [] , button [ onClick Save ] [ text "Save" ] ] type Msg = ChangeName String | ChangeSurname String | ChangeBio String | Save update : Msg -> Model -> Model update msg model = case msg of ChangeName newName -> { model | name = newName } ChangeSurname newSurname -> { model | surname = newSurname } ChangeBio newBio -> { model | bio = newBio } Save -> ... 

Tidak ada yang luar biasa, semuanya baik-baik saja.


Tetapi kompleksitas meningkat secara dramatis ketika kami memutuskan untuk menambahkan komponen lain ke halaman kami yang sama sekali tidak terkait dengan yang ada - bentuk untuk anjing. Berkomitmen


 type Msg = ChangeName String | ChangeSurname String | ChangeBio String | Save | ChangeDogName String | ChangeBreed String | ChangeDogBio String | SaveDog update : Msg -> Model -> Model update msg model = case msg of ChangeName newName -> { model | name = newName } ChangeSurname newSurname -> { model | surname = newSurname } ChangeBio newBio -> { model | bio = newBio } Save -> ... ChangeDogName newName -> { model | dogName = newName } ChangeBreed newBreed -> { model | breed = newBreed } ChangeDogBio newBio -> { model | dogBio = newBio } SaveDog -> ... 

Sudah pada tahap ini, Anda dapat melihat bahwa Msg berisi dua "grup" pesan. "Bakat terprogram" saya menunjukkan bahwa hal-hal seperti itu perlu disarikan. Apa yang akan terjadi ketika 5 komponen lainnya muncul? Bagaimana dengan subkomponen? Hampir tidak mungkin menavigasi dalam kode ini.


Bisakah kita memperkenalkan lapisan abstraksi tambahan ini? Tentu saja !


 type Msg = HoomanEvent HoomanMsg | DoggoEvent DoggoMsg type HoomanMsg = ChangeHoomanName String | ChangeHoomanSurname String | ChangeHoomanBio String | SaveHooman type DoggoMsg = ChangeDogName String | ChangeDogBreed String | ChangeDogBio String | SaveDog update : Msg -> Model -> Model update msg model = case msg of HoomanEvent hoomanMsg -> updateHooman hoomanMsg model DoggoEvent doggoMsg -> updateDoggo doggoMsg model updateHooman : HoomanMsg -> Model -> Model updateHooman msg model = case msg of ChangeHoomanName newName -> { model | name = newName } -- Code skipped -- updateDoggo : DoggoMsg -> Model -> Model -- Code skipped -- view : Model -> Html Msg view model = div [] [ h3 [] [ text "Hooman" ] , input [ placeholder "Name", value model.name, onInput (HoomanEvent << ChangeHoomanName) ] [] , -- Code skipped -- , button [ onClick (HoomanEvent SaveHooman) ] [ text "Save" ] , h3 [] [ text "Doggo" ] , input [ placeholder "Name", value model.dogName, onInput (DoggoEvent << ChangeDogName) ] [] , -- Code skipped -- ] 

Memanfaatkan sistem tipe Elm, kami membagi pesan kami menjadi dua jenis: manusia dan anjing. Sekarang ambang untuk memasukkan kode ini akan jauh lebih mudah. Segera setelah beberapa pengembang perlu mengubah sesuatu di salah satu komponen, ia akan dapat segera menentukan dengan tipe struktur bagian mana dari kode yang ia butuhkan. Perlu menambahkan logika ke penyimpanan informasi anjing? Lihatlah pesan-pesan itu dan mulailah mencarinya.


Bayangkan kode Anda adalah referensi yang sangat besar. Bagaimana Anda mencari informasi yang Anda minati? Menurut daftar isi (Msg dan Model). Akankah mudah bagi Anda untuk menavigasi daftar isi tanpa membagi menjadi beberapa bagian dan subbagian? Hampir tidak.


Kesimpulan


Ini adalah teknik yang sangat sederhana yang dapat digunakan di mana saja dan cukup mudah untuk ditanamkan dalam kode yang ada. Refactoring aplikasi yang ada akan sepenuhnya tidak menyakitkan, berkat pengetikan statis dan kompiler elm favorit kami.


Setelah menghabiskan hanya satu jam dari waktu Anda (kami menghabiskan kurang dari 20 menit pada setiap aplikasi pada proyek kami), Anda dapat secara signifikan meningkatkan keterbacaan kode Anda dan menetapkan standar untuk bagaimana menulisnya di masa depan. Bukan kode yang mudah dikoreksi kesalahan itu baik, tetapi kode yang melarang kesalahan dan memberikan contoh bagaimana kode harus ditulis.


Teknik yang persis sama dapat diterapkan untuk Model , menyoroti informasi yang diperlukan dalam jenis. Misalnya, dalam contoh kami, model hanya dapat dibagi menjadi dua jenis: Hooman dan Doggo , mengurangi jumlah bidang dalam model menjadi dua.


Tuhan selamatkan sistem tipe Elm.


Repositori PS dengan kode dapat ditemukan di sini jika Anda ingin melihat diff

Source: https://habr.com/ru/post/id455553/


All Articles