תקשורת בין הורים לילד באלם: OutMsg לעומת מתרגם לעומת דפוסי NoMap

כאשר האפליקציה Elm שלך תתחיל לצמוח, תרצה לפרק אותה בחלקים קטנים יותר בכדי שתוכל להרחיב אותה. כיסיתי את זה בבלוג אחר: דוגמה מובנית של TodoMVC עם Elm.

חלק אם קנה המידה הזה בסופו של דבר כרוך בצורך של שליחת Msg ממודול להורה שלו, כמו כאשר לחצני ניווט בתצוגה מסוימת צריכים לשלוח הודעה לנתב ברמה העליונה.

לאחר זמן מה התחלתי לשים לב לשלושה דפוסים שונים לטיפול בזה, ושבתי מחדש את Elm TodoMVC לכל הגישה השונה במאגר הזה, כך שתוכל להשוות אותם זה לצד זה.

תבנית OutMsg

אני מאמין שפולרטרטב היה הראשון שראיתי לכתוב על תקשורת בין הורים לילד, עמוד הבלוגים שלו מסביר גישה זו די טוב.

אבל, לסיכום, למעשה אתה מחזיר ערך נוסף בפונקציית העדכון שלך. אז במקום להחזיר את זה:

(דגם, Cmd Msg)

אתה מחזיר את זה:

(דגם, Cmd Msg, OutMsg)

לאחר מכן, פונקציית עדכון ההורים אחראית על הטיפול בהם. בדרך זו הילד אינו צריך לדעת דבר אודות ההורה שלו, אך ההורה צריך לדעת על OutMsgs של ילדו.

יישמתי את TodoMVC בגישה זו. אבל אם ברצונך לבדוק את גודל העולם האמיתי של זה, ריצ'רד פלדמן הטמיע את דוגמת ה- el-spa כך.

דוגמא נוספת שמשתמשת בגישה זו היא elm-datepicker.

דפוס המתרגם

דפוס המתרגם דומה מאוד לתבנית OutMsg, אך במקום שההורה יידע על סוגי ה- Msgs של הילד, ההורה הוא זה שעובר אשר Msgs ייווצר באמצעות מתרגם. אלכס לב מסביר את גישתו הרבה יותר טוב כאן.

בעיקרון יש לך מתרגם שהוא רשומה כזו:

סוג כינוי תרגום
  {onInternalMessage: InternalMsg -> msg
  , onPlayerWin: Int -> msg
  , onPlayerLose: msg
  }

יישמתי את TodoMVC גם בגישה זו, ואני מאמין שהשלמה אוטומטית של elm היא גם דוגמה טובה לכך.

עדכון elm-parent-child הוא ספריה העוזרת לך בעדכון הילד-הורה שנראה שעוקב אחר דפוס זה.

תבנית ה- NoMap

זה משהו ששמתי לב אליו שאני עושה. הרעיון הבסיסי הוא להימנע מביצוע Cmd.map ו- Html.map, ולכן במקום זאת כולם צריכים לדבר באותה שפה, במילים אחרות, פונקציות העדכון והתצוגה שלך יצטרכו להחזיר את סוג ה- Msg ברמה העליונה.

עם זה בטח יהיו לך מסרים כמו MsgForLogin, MsgForRouter וכו ', כך שבתצוגה שלך היית עושה משהו כמו:

לחצן [onClick (MsgForLogin SignUp)] []

כך השיבתי לראשונה את TodoMVC, למעשה, בפעם הראשונה שראיתי את OutMsg לא הבנתי את הסיבה לכך, מכיוון שלא מיפיתי את ה- MSS שלי.

עיין באפליקציית ברק-דיבור לקבלת דוגמא גדולה יותר בגישה זו. כמו כן, נראה כי יישום זה עוקב אחר דרכו של קריס ג'נקינס לבנות אפליקציות של Elm, המעדיפה גישה זו כאשר הוא מפריד בין סוגי Msgs בקובץ Types.elm.

הספרייה elm-taco משתמשת בתערובת של דפוסי OutMsg ו- NoMap על ידי "טאקו" ברמה העליונה שאליה אתה יכול לשלוח הודעות.

תצפיות והשוואות

תוך כדי מחקר ושיבוץ מחדש של אותם דפוסים, ציינתי דברים שיכולים להוות יתרונות או חסרונות בהתאם לצרכים שלך:

  • ב- NoMap פונקציית העדכון של ההורה שומרת בערך ככל שהאפליקציה שלך גדלה, ואילו ב- OutMsg ותרגום פונקצית העדכון של ההורה עשויה להיות גדולה מאוד, מכיוון שאתה צריך לטפל ב- OutMsg של כל ילד (דוגמה)
  • ב- OutMsg ותרגום המודולים המקוננים לא צריכים לייבא כלום מההורים העליונים, מה שהופך אותם למעטפים יותר, יהיה קל יותר לחלץ ולפרסם מודול משנה כלשהו כספרייה למשל.
  • כדי ש- NoMap יעבוד ה- Msgs שלך אמור לחיות בקובץ נפרד מ- Update, אחרת תהיה לך לולאת תלות. זו סיבה טובה מכריחה אתכם לפצל דברים, אך רע בעת ובעונה אחת אם ברצונכם שיהיה קובץ אחד לכל מודול (Home.elm, Login.elm, Router.elm)
  • ב- NoMap, קל יותר לשלוח את Msgs לכל מקום אחר, אך יתכן שיהיה קשה יותר לעקוב אחר כל שינויי המצב שנגרמו כתוצאה מכך.
  • כפי שנמדד ברגע כתיבת שורות אלה, עבור רפלקטורי TodoMVC, לגישה של NoMap יש 546 LOC, OutMsg 561 והמתרגם 612 אם זה חשוב לך
  • ב- NoMap בסופו של דבר עליכם להשתמש בתיק _ catch-all כדי להתעלם מ- Msgs ממקומות אחרים שאינכם רוצים לטפל בהם, כך שיש פחות עזרה מהמהדר, היא לא יכולה לדעת מה חסר לכם (תודה על @mordrax על הצבעה זה בחלל רפיון
  • ב- OutMsg ובמתרגם תוכלו פשוט לבדוק את הסוגים או המתרגמים כדי לגלות אילו תקשורת בין הורים נדרשים, כך שהמהדר יכול להנחות אתכם ליישם אותם, ואילו ב- NoMap תקשורת זו היא יותר מרומזת.
  • נראה כי גישת המתרגם היא רעיון טוב למסור את ה- Msgs שלך לרכיב חיצוני, כמו elm-autoocomplete
  • התקשיתי לעקוב אחר דפוס המתרגם וקשה יותר להבין הודעות שגיאה ממהדר Elm בזמן בנייתו
  • אם לא תשנה את התקן (דגם, Cmd Msg) תוכל להשתמש בספריית elm-return בסדר
  • יש אנשים הרואים בכך שאינם משתמשים ב- Html.map כפרקטיקה טובה להימנע מיצירת "רכיבים"
  • אתה יכול להפיק תועלת רבה מהערבוב של גישות אלה, למשל, אתה יכול פשוט להימנע מ- Html.map לצפיות, בעודך עדיין משתמש ב- OutMsg לצורך עדכונים, או שאתה יכול להשתמש ב- NoMap רק עבור Msgs ברמה העליונה, עם OutMsgs למטה, תוך עיבוד רכיב מתורגם חיצוני

משאבים

אני מאמין שתקשורת בין הורים היא לעתים קרובות יותר חשובה בעת קנה המידה והביצוע של מכוני ספא, זו הסיבה שהרבה דברים שמצאתי קראתי את הנושא האדום הזה על אפליקציות Scaling Elm:

לחיים!