• בלוג
  • איך פלאקס נבדל מ MVC ?

איך פלאקס נבדל מ MVC ?

07/01/2016

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

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

1. הרכיבים בארכיטקטורת MVC

טוב לפני שאפשר להשוות את פלאקס ל MVC צריך לשאול לאיזה MVC אנחנו משווים. את אמבר אני לא מכיר ולאנגולר לא הייתי ממהר לקרוא MVC (יש בה קונטרולר זה נכון, ואולי אפשר לטעון שהטמפלייט הוא ה view, אבל מיהו המודל ואיך directives משתלבים בתבנית זה לא לגמרי ברור).
נשארנו עם Backbone שהיא מספיק פשוטה כדי שאפשר להשוות בין השתיים וגם ללמוד משהו מועיל מההשואה.

ב Backbone המודל מחזיק את הלוגיקה. מודל מתקשר עם צד השרת ומעדכן את התצוגה כשמשהו משתנה באמצעות הפצת אירועים. עד כאן זה נשמע דומה מאוד ל Flux Store.

2. הסוד הוא ב Disaptcher

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

האבסטרקציה הראשונה שפלאקס מוסיף לתמונה היא ה Action שמייצגת משהו שקורה במערכת. תבנית העיצוב הזו אומרת שמספר רכיבי UI יכולים לשגר פעולה מסוימת ולכן קוד הפעולה אינו חלק מקוד ה View.

קחו לדוגמא מצב של עריכת Todo Item עבור יישום ניהול משימות. נניח שבכל סיום עריכת משימה אנו רוצים לשמור את הפריט ובנוסף לעדכן מודל של סטטיסטיקות שבוצעה פעולת עריכה. נניח גם שהממשק שלנו מורכב מכפתור ״שמירה״ ובנוסף מתפריט צד שמאפשר לעבור בין משימות, וכל פעם שמנווטים החוצה ממסך משימה יש לשמור את השינויים במשימה.

בעולם של Backbone הייתם צריכים לכתוב את אותו הקוד לעדכון שני המודלים בשני Views שונים: גם בתפריט הצד וגם במסך עריכת משימה. כתיבת הקוד המשותף במודל מייצרת תלות בין שני המודלים (מודל Todo ומודל הסטטיסטיקה) כך שפונקציית save של TodoItem קוראת לפונקציה של מודל הסטטיסטיקה לצורך הוספת המידע.

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

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

var TodosStore = Object.assign({}, Store, {
  items: [],
  editItem: function() { ... }
});

TodosStore.dispatchToken = Dispatcher.register(function(action) {
  switch(action.type) {
    case SAVE_ITEM:
      TodosStore.saveItem(action.payload);
      break;
  }
});

var StatisticsStore = Object.assign({}, Store, {
  log: function() { ... }
});

StatisticsStore.dispatchToken = Dispatcher.register(function(action) {
  switch(action.type) {
    case SAVE_ITEM:
      Dispatcher.waitFor([TodosStore.dispatchToken]);
      StatisticsStore.log(action.payload);
      break;
  }
});

עדיין יש לנו תלות בין שני הרכיבים אבל היא הפכה מתלות של ״איך״ לתלות של ״מה״: במקום שרכיב TodosStore יעדכן ישירות את רכיב StatisticsStore אנו מעבירים לשניהם את אותה הפעולה וכל רכיב מעדכן את עצמו מתוך הפעולה שהועברה. התלות מתבטאת רק בשורה 21 בפקודה waitFor. במקום שרכיב יקרא לפונקציה מתוך רכיב אחר, רכיבים מציינים לאיזה רכיבים אחרים הם מחכים. כך יש עדיין תלות של סדר אך ההחלטה איך לטפל בכל פעולה נשארת בתחומי הרכיב הרלוונטי.