DCSIMG
מה הפואנטה של MVVM ? - אלעד כץ | Elad Katz
Sign in | Join | Help

אלעד כץ | Elad Katz

לגו של גדולים

מה הפואנטה של MVVM ?

פורסם בתאריך Jan 19 2011, 10:29 PM על ידי eladkatz | ישנם 9 תגובות

למה אני צריך את זה בכלל?!

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

התיעוד של פריזם מספקת דוגמא מאוד טובה לבעייתיות שאליה אני מתכוון... - רוב רובו של התיעוד בנוי כך - בשביל לממש A יש לבצע B, בשביל לממש C יש לבצע D.. בהרבה מאוד מקומות שמתמשים בפריזם נופלים ללא מעט טעויות בגלל שאת השאלה הבסיסית, למה, שוכחים טיפה לשאול. (וזה חבל היות וסה"כ פריזם היא לא פריימוורק רע.. פשוט משתמשים בו מאוד רע ברוב המקרים)

הרעיון שלי בסדרת הפוסטים הבאים זה לא לתת עוד הסבר של איך לממש MVVM בדוגמא טריוויאלית, אלא לנסות באמת לתת את הדגשים של "העולם האמיתי", וזו תהייה האוריינטציה של רוב הפוסטים. יחד עם זאת, אי אפשר להקיף כל סיטואציה אפשרית, ולכן חייבים לפני כל דבר אחר להבין מה ה"שוס" של MVVM, ובמילים אחרות - למה אני צריך את זה בכלל?!

מה MVVM נותן לי?

MVVM דומה מאוד לMVC, רק שהוא טוב ממנו בכל פרמטר (MVVM זה לא רק MVC לWPF, זה שדרוג מאוד משמעותי של MVC). MVVM נותן לי כל מה שMVC נותן לי, רק יותר טוב.

טוב, אז מה MVC נותן לי? (או: תשמעו שאלה מטופשת)

אז מה באמת MVC נותן לי? אם התשובה שנתת לעצמך בראש היא "הפרדה של שכבות" או משהו דומה, אני רוצה להציע את השאלה המעניית הבאה:

עקרונית, בMVC אנו נפריד את הקוד שלי לשלוש שכבות נפרדות - Model, View, Controller.

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

הView, זה החלק שמכיל את כל הגדרות הUI באפליקציה, והקונטרולר זה ה"מוח" של האפליקציה, מה שמחבר את כל הרכיבים ביחד. כדוגמא, לחיצה על כפתור בView, נתפסת ע"י הקונטרולר, שמבקש מהDAL רשימת מוצרים ולאחר מכן שם אותם בתוך הView. גם הView וגם המודל פאסיביים למדי, והקונטרולר הוא זה שעושה את העבודה הקשה (זה תיאור מפושט משהו, אבל הוא מספיק לנו כרגע).

אז... לכאורה לממש MVC זה כבר בילט אין בWPF!

הXAML זה הView.

הCodeBehind זה הקונטרולר,

והDAL יהיה המודל!

השאלה לא כל כך טריוויאלית כמו שהיא נראית, למרות שהיא בפירוש שגויה.

אז כמובן שזו טעות. זה בפירוש לא MVC. אבל.. למה?

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

MVC מספק לי שלושה דברים חשובים

1. יכולת תחזוקה קלה ויעילה של הקוד. קוד של לוגיקה לא מעורב בקוד של UI ולכן הרבה יותר קל לכתוב פרוייקט מורכב, והרבה יותר קל לתחזק אותו/ לדבג אותו.

2. יכולת להריץ טסטים אוטומאטיים (UT) על הלוגיקה של האפליקציה (על הקונטרולר והמודל, כל אחד בנפרד).

3. יכולת נוחה יותר של עבודה עם שכבת הUI, היות וVisual Studio יצליח יותר בקלות להציג לנו את הView בDesign Time - היות ואין שם באמת קוד - רק XAML. (ספציפית לWPF/SL, למרות שזה נכון גם בwinforms).

שלושת היכולות החשובות הללו - תחזוקה קלה, הרצת טסטים, תמיכה טובה יותר לDesigner של Visual Studio - הן למעשה מושגים מאוד חשובים בעולם ארכיטקטורת הUI -

Maintainability, Testability, Blendability

1. Maintainability - יכולת תחזוקה קלה.

2. Testability - היכולת להריץ מבחנים אוטומאטיים (UT)

3. Blendability - היכולת לעבוד עם Cider, הdesigner של Visual Studio, או עם Expression Blend (ומכאן מגיע השם).

הסיבה שCode Behind הוא לא מימוש באמת טוב של MVC זה בעיקר בגלל סעיפים 1 ו2. CodeBehind לא נותן הפרדה טובה, ולכן יש קושי רב בבניית אפליקציות שקל לתחזק, ושקל להריץ עליהם מבחנים אוטומאטיים. זה נובע מכך שההפרדה בין הXAML לCodeBehind היא לא באמת הפרדה. הם שניהם חלק מאותה המחלקה, מה שאומר ש:

1. הצימוד ביניהם (הCoupling ביניהם) מאוד גבוה. אי אפשר להפריד ביניהם, ולמעשה אין לי כאן הפרדה טובה בין קוד של UI לקוד של הלוגיקה של האפליקציה.

2. נובע מ(1) - אין לי אפשרות להרים מופע של הCode Behind ללא ה XAML, ולפיכך אין לי שום יכולת להריץ עליו UnitTesting בנפרד (Unit Testing => המטרה היא לבחון כל רכיב בפני עצמו בלבד, לפני כל מבחן אחר), ובנוסף להריץ UT על XAML די בלתי אפשרי... (יש אפשרות לבצע UI Testing אבל זהו נושא אחר..)

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

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

MVVM הולך בגישה שונה והרבה יותר חזקה.

אם נחזור לדוגמא של XAML וCodeBehind, ההפרדה שם כבר יחסית די טובה.. הבעיה היא שהCodeBehind ניגש ישירות לXAML על מנת לשלוט בו, ובנוסף הXAML מכיל לא מעט קישורים לCodeBehind (כדוגמא, רישום של Events). שני החלקים מאוד תלויים אחד בשני, מה שלמעשה הורס את כל ההפרדה. יחד עם זאת, יש לנו כאן כבר חצי פיתרון - כל מה שאנחנו צריכים זה להפריד את שני החלקים. אם נחליט שאסור לגשת לXAML מהCodeBehind, ואסור לXAML להכיל קישור ישיר לCodeBehind, למעשה נקבל הפרדה מאוד טובה, ואפילו יותר טובה מMVC!

יש רק בעיה אחת... אם אסור להם לגשת ישירות אחד לשני.. אז איך הם אמורים לתקשר?

כאן נכנסים שני פיצ'רים מאוד חזקים של WPF/SL - Binding ו Commands.

Binding - יעביר מידע בין הCodeBehind לXAML.

Commands - יאפשרו הרמת אירועים מהXAML לCodeBehind, רק שאלו Weak Events (עוד על זה בהמשך). Commands מאוד דומים לEvents, רק שהם מהווים קישור יותר קל, היות וEvent שמוגדר בXAML - אם אין לו Event Handler ב CodeBehind יגרור זריקה של שגיאה, בעוד Commands לא יזרקו שגיאה.

למעשה, CodeBehind וXAML שלא מדברים ישירות בכלל אחד עם השני מהווים הפרדה מאוד מאוד טובה. כל כך טובה, שאפשר לשים את הCodeBehind במחלקה אחרת (נקרא לה ViewModel לצורך העניין).

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

הפואנטה של MVVM

1. Blendability - ברמות שMVC יכול רק לחלום עליו. אנו נראה בהמשך שזו תכונה חשובה מאין כמוה, המאפשרת כתיבה הרבה יותר מהירה וקלה מאי פעם.

2. Maintainability - תחזוקת הקוד יותר קלה בMVVM היות ובViewModel אין גישה ישירה לView, ולפיכך MVVM שומר על עקרון ה SRP (Single Responsibility Principle - אחריות אחת בלבד לכל רכיב) יותר טוב בהרבה. הContoller בMVC ניגש גם לModel וגם לView, ולפיכך מפר עיקרון זה.

3. Testability - בניגוד לMVC, שמצריך שימוש בInterface על מנת להפריד בין הקונטרולר ובין הView, ובכך לאפשר בדיקה של הController בפני עצמו (וזה סיפור די מסורבל ומציק סה"כ - להגדיר interface לכל view...) MVVM הרבה יותר אלגנטי.

הViewModel לא מכיל שום קישור לView, ולכן מוכן אוטומאטית לUnitTesting. אלגנטיות במיטבה :-)

מתי נשתמש בMVVM?

Blendability, Maintainability, Testability - שלושתן יכולות מאוד חזקות ומאוד חשובות שמתאפשרות ע"י ההפרדה של השכבות בMVVM, וככל שהפרוייקט יותר גדול ככה הכוח שלהן יותר משמעותי.

אבל.

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

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

אז מה הלאה?

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

רשימת תגובות

# re: מה הפואנטה של MVVM ?

פורסם בתאריך Thursday, January 20, 2011 10:12 AM על ידי Jasper  

מה זה "פיצ'רים" ??

"כאן נכנסים שני פיצ'רים מאוד חזקים של WPF/SL - Binding ו Commands"

# re: מה הפואנטה של MVVM ?

פורסם בתאריך Thursday, January 20, 2011 2:32 PM על ידי Rotem Bloom  

אחלה של סידרת מאמרים שנושא מאוד חשוב.

תודה על השיתוף

# ???????????? ??? ?????????? ?????????? ?????????????????????? ???????????????? [21-01-11] | Newsgeek

פורסם בתאריך Friday, January 21, 2011 6:39 PM על ידי ???????????? ??? ?????????? ?????????? ?????????????????????? ???????????????? [21-01-11] | Newsgeek  

Pingback from  ???????????? ??? ?????????? ?????????? ?????????????????????? ???????????????? [21-01-11] | Newsgeek

# http://newsgeek.co.il/blogeek-21-01-11/

פורסם בתאריך Saturday, January 22, 2011 2:04 AM על ידי TrackBack  

# re: מה הפואנטה של MVVM ?

פורסם בתאריך Sunday, January 23, 2011 9:02 AM על ידי שחר אלדד  

פוסט מעולה - מסכם את כל השיעור האחרון שלנו ב- 10 דקות של קריאה.

תודה :)

# איך מממשים MVVM ? זה הרבה יותר פשוט ממה שחושבים.

פורסם בתאריך Friday, February 04, 2011 6:08 PM על ידי Lego for grownups  

לממש MVVM הרבה יותר קל ממה שנשמע. משום מה יצא לDesign Pattern הזה שם של Design Pattern מורכב, ולפי דעתי

# re: מה הפואנטה של MVVM ?

פורסם בתאריך Thursday, August 11, 2011 1:44 AM על ידי zvi  

שאלה - אם ככה אלעד למה בכלל ציך את הקוד בהיינד? למה זה משמש? האם יש לו שימוש בארכיטקטורת MVVM

# re: מה הפואנטה של MVVM ?

פורסם בתאריך Tuesday, August 16, 2011 10:43 PM על ידי eladkatz  

zvi:

You don't need the code behind. MSs original thought (2001) was that code behind gives us a strong-enough separation between logic and ui. turns out it doesn't.

I'm not saying that you should never ever use codebehind, but that codebehind tends to become bad code and therefor u should try to avoid it.

# re: מה הפואנטה של MVVM ?

פורסם בתאריך Tuesday, December 27, 2011 7:47 AM על ידי חן  

מאמר מעולה !

ממתין למאמרים נוספים בנושא

תודה,

חן

שלח תגובה

(שדה חובה) 
(שדה חובה) 
(אופציונלי)
(שדה חובה) 

Enter the numbers above: