Komunikimi i prindërve të fëmijëve në Elm: OutMsg vs Translator vs Modelet NoMap

Kur aplikacioni juaj Elm të fillojë të rritet, do të doni ta ndani atë në copa më të vogla për të qenë në gjendje të shkallëzoni. Unë e mbulova këtë në një blogpost tjetër: Strukturuar shembull TodoMVC me Elm.

Pjesë nëse kjo shkallëzim përfundimisht përfshin nevojën e dërgimit të një Msg nga një modul tek prindi i saj, si kur butonat navigues në një pamje specifike duhet të dërgoni një mesazh në Ruterin e nivelit të lartë.

Pas ca kohësh fillova të vëreja 3 modele të ndryshme për trajtimin e kësaj, dhe unë refaktova Elm TodoMVC për të gjitha ato qasje të ndryshme në këtë depo, kështu që ju mund t'i krahasoni ato krah për krah.

Modeli OutMsg

Unë besoj se Folkertdev ishte i pari që pashë të shkruaja për komunikimin fëmijë-prindër në Elm, blogposti i tij e shpjegon mjaft mirë këtë qasje.

Por, për ta përmbledhur, në thelb i ktheni një vlerë shtesë në funksionin tuaj të azhurnimit. Kështu që në vend që ta ktheni këtë:

(Model, Cmd Msg)

Ju e ktheni këtë:

(Model, Cmd Msg, OutMsg)

Pastaj, funksioni i azhurnimit të prindit është përgjegjës për trajtimin e atyre. Në këtë mënyrë fëmija nuk ka nevojë të dijë asgjë për prindin e tij, por prindi duhet të dijë për OutMsgs së fëmijës së tij.

Unë e kam implementuar TodoMVC duke përdorur këtë qasje. Por nëse doni të kontrolloni një shkallë të botës reale të kësaj, Richard Feldman zbatoi shembullin e elm-spa në këtë mënyrë.

Një shembull tjetër që përdor këtë qasje është elm-datepicker.

Modeli i Përkthyesit

Modeli i Përkthyesit është shumë i ngjashëm me atë OutMsg, por në vend që prindi të dijë për llojet Msgs të fëmijës, është prindi që kalon të cilin Msgs do të gjenerohet, përmes një përkthyesi. Alex Lew shpjegon qasjen e tij shumë më mirë këtu.

Në thelb ju keni një përkthyes i cili është një rekord si ky:

shkruani pseudonimin PërkthimDhkrimi msg =
  {onInternalMessage: InteriorMsg -> msg
  , onPlayerWin: Int -> msg
  , nëPlayerLose: msg
  }

Unë kam zbatuar edhe TodoMVC duke përdorur këtë qasje, dhe besoj se autokomotiva e plotë është gjithashtu një shembull i mirë.

Përditësimi i prindërve-prind-fëmijë është një bibliotekë që ju ndihmon me azhurnimin fëmijë-prind i cili duket se ndjek këtë model.

Modeli NoMap

Kjo është diçka që vura re që po bëja. Ideja themelore është të shmangni bërjen e Cmd.map dhe Html.map, kështu që në vend të kësaj, të gjithë duhet të flasin të njëjtën gjuhë, me fjalë të tjera, funksionet tuaja të azhurnimit dhe shikimit do të duhet të kthejnë llojin e nivelit të lartë Msg.

Me këtë ju me siguri do të keni Msgs si MsgForLogin, MsgForRouter, etj, kështu që në pamjen tuaj do të bëni diçka si:

butoni [onClick (Signs MsgForLogin)] []

Kjo është se si unë së pari e refaktova TodoMVC, në fakt, herën e parë që pashë OutMsg nuk e kuptova arsyen e kësaj, sepse nuk po hartoja Msgs time.

Shikoni programin e bisedave rrufe për një shembull më të madh me këtë qasje. Gjithashtu, kjo aplikacion duket se ndjek mënyrën e strukturimit të aplikacioneve Elm të Kris Jenkins, e cila favorizon këtë qasje ndërsa ai ndan llojet e Msgs në një skedar Types.elm.

Libri i bibliotekës elm-taco përdor një përzierje të modeleve OutMsg dhe NoMap duke pasur një "taco" të nivelit të lartë, të cilit mund t'i dërgoni mesazhe.

Vëzhgime dhe krahasime

Ndërsa hulumtova dhe rindërtoja për ato modele, unë shënova disa gjëra, të cilat mund të jenë avantazhe ose disavantazhe në varësi të nevojave tuaja:

  • Në NoMap, funksioni i azhurnimit të prindit vazhdon të jetë i njëjtë ndërsa rritet aplikacioni juaj, ndërsa në OutMsg dhe Përkthimi funksioni i azhurnimit të prindit mund të bëhet shumë i madh, pasi ju duhet të trajtoni OutMsg të çdo fëmije (shembull)
  • Në OutMsg dhe Përkthimi i moduleve të foleve nuk ka nevojë të importoni asgjë nga prindërit e sipërm, duke i bërë ata më të kapsuluar, do të ishte më e lehtë të ekstraktoni dhe publikoni disa nën-modul si një bibliotekë për shembull
  • Që NoMap të punojë Msg tuaj duhet të jetojë në një skedar të veçantë nga Azhurnimi, ose përndryshe do të keni një lak varësie. Kjo është shkaku i mirë që ju detyron të ndani gjërat, por keq në të njëjtën kohë nëse doni të keni një skedar të vetëm për secilin modul (Home.elm, Login.elm, Router.elm)
  • Në NoMap, është më e lehtë të dërgosh Msgs kudo tjetër, por mund të jetë më e vështirë të ndiqni të gjitha ndryshimet e shtetit të shkaktuara nga ai.
  • Si e matur në momentin e këtij shkrimi, për refaktorët e TodoMVC, qasja NoMap ka 546 LOC, OutMsg 561 dhe Translator 612 nëse kjo ka rëndësi për ju
  • Në NoMap përfundimisht duhet të përdorni çështjen _ kapur-për të injoruar Msgs nga vendet e tjera që nuk doni të trajtoni, kështu që ka më pak ndihmë nga përpiluesi, nuk mund të tregojë se çfarë ju mungon (faleminderit për @mordrax për tregimin që në elm slack)
  • Në OutMsg dhe Translator ju thjesht mund të shikoni në llojet ose përkthyesit për të zbuluar se cilat komunikime fëmijë-prindër janë të nevojshme, kështu që përpiluesi mund t'ju udhëzojë në zbatimin e tyre, ndërsa në NoMap kjo komunikim është më e nënkuptuar
  • Qasja e përkthyesit duket të jetë një ide e mirë për të dhënë Msg tuaj në një përbërës të jashtëm, si autokomplete elm
  • Unë e pashë modelin e përkthyesit të vështirë për t'u ndjekur me vështirësi për të kuptuar mesazhe gabimi nga përpiluesi Elm ndërsa ndërtimin e tij
  • Nëse nuk e modifikoni standardin (Model, Cmd Msg) mund të përdorni bibliotekën e kthimit të mirë të bërrylave
  • Disa njerëz konsiderojnë të mos kenë Html.map si një praktikë të mirë për të shmangur krijimin e "komponentëve"
  • Mund të përfitoni shumë nga përzierja e atyre metodave, për shembull, thjesht mund të shmangni Html.map për shikime, ndërsa ende përdorni OutMsg për azhurnime, ose mund të përdorni NoMap vetëm për Msgs të nivelit të lartë, me OutMsg poshtë, ndërsa jepni një komponent të jashtëm të Përkthyer

burime

Unë besoj se Komunikimi i Prindërve të Fëmijëve shpesh është më i rëndësishëm kur shkallëzoni dhe bëni SPA, kjo është arsyeja pse shumë sende që gjeta po lexonin këtë fije të kuqe për Shkallëzimin e Aplikacioneve të Elmave:

Cheers!