MVC

10 בDecember 2012

7 תגובות

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

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

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

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

התרשים הברור ביותר ייראה כך (בתור התחלה)

 
























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

כהסבר בסיסי נגיד שהמודל שמבחינתי מייצג עכשיו את הכל חוץ מאשר הUI

ז”א הגדרת יישויות , Dal, BL , ואילו הUI הוא משהו פשוט שכל מה שהוא מכיר זה הקונטרולר ודרכו הוא מדבר עם שאר
העולם,  מה זה נותן לי? ובכן שימוש חוזר
החלפת
UI  לUI עדכני יותר,

שמירה על מבנה שכבות, ועוד ועוד.

 אבל זה ברמה בסיסית, ברמה
מורכבת יותר גם ה
View יכול להכיראת הModel , אמנם הוא לא פונה אליו אבל הוא יכול לדוגמא
ליירט
Events  שנורים ע”י שכבה כלשהי במערכת שלנו (המודל
נניח),

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

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

של שכבות בתכנית נניח Dal=>BL=>UI עדיין ישנה בעייתיות
גדולה מי מכיר את מי ואיך המודולים

מתקשרים ביניהם! , בוואקום הזה נדחפת MVC  ומציעה פתרון
לתקשורת בין השכבות שתקרא 
controllerController
ה 
 מכיר
את כולם, והוא
singletone , כולם מכירים אותו והכל
דופק נפלא.

את
הבעיות של
MVC  אני לא אציג כאן כדי לא להרוס את החגיגה, מה שכן
אני אציג מיני אפליקציה שמדגימה את התבנית, בהמשך (פוסט הבא) אציג דוגמא מוחשית
יותר (
Real World Sample) שתציג את ASP MVC כפי שמוטמעת היום בVisual
Studio
וזה סוג של סטנדרט.

דוגמא:

       אני אבנה את הדוגמא לפי עיקרון ה Inversion of control שמוכר גם כ IOC, ויזכה לפוסט נפרד בעתיד
בינתיים ניתן להחכים קצת באמצעות
Depndency Injection  שזה חלק מIOC

 

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

   public
interface IController

    {

       void
AddItem(Item item);

       List<Item> GetItems();

    }

 

2.       אני מגדיר דבר ראשון חוזה Imodel שיכיל את מה שהמודל יודע
לעשות

public interface IModel

    {

       void
AddItem(Item item);

       IEnumerable<Item> GetItems();

    }

 

 

3.      
נגדיר
חוזה ל
Iview,  רק
נזכור שכל
view שירוץ אצלינו צריך להיות מסוג IView,

חשוב
לשים לב לחתימה
InjectController שארחיב עליה עוד מעט.

public interface IModel

    {

       void
AddItem(Item item);

       IEnumerable<Item> GetItems();

       void InjectController(IController controller);

 

    }

 

 

לפני
שנמשיך באותה רמה של החוזים נגדיר את האובייקט שהמודל מטפל בו, קראתי לו

אייטם
והוא נראה כך:

    public class Item

    {

        public string name { get; set; }

    }

 

4.       אני מגדיר אובייקט מודל שבשבילי זה כל מה שיושב בצד שרת גם הלוגיקה
וגם הנתונים, והוא כמובן המימוש של
Imodel.

public class Model
:IModel

    {

        public Model()

        {

 

        }

        List<Item> Items = new List<Item>();

 

        public void AddItem(Item item)

        {

            if (!Items.Contains(item))

               
Items.Add(item);

        }

     

        public IEnumerable<Item> GetItems()

        {

            ReadOnlyCollection<Item>
returendList = new      ReadOnlyCollection<Item>(Items);

            return returendList;

        }

    }

 

5.      
 

נגדיר את
המימוש הקונקרטי של הקונטרולר, הוא יכיל אינסטנסים מסוג
Iview ו Imodel

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

public sealed class
Contreoller : IController

    {

        public Contreoller(IView view, IModel model)

        {

            _View = view;

            _Model = model;

        }

 

        private IView _View;

        private IModel _Model;

 

 

        public List<Item> GetItems()

        {

            return _Model.GetItems().ToList();

        }

 

        public void AddItem(Item item)

        {

           
_Model.AddItem(item);

        }

    }

 

6.      
מה נשאר
לנו? כמובן
VIEW.. מפאת עצלנותי לא אגדיר עכשיו טפסי UI

אני
מגדיר קלאס גאוני שעובד מול
console ומבחינתי עכשיו הוא הVIEW  וכמובן הוא

המימוש
של
Iview,

לא לפספס
נקודה חשובה:  ה
View מחזיק אינסטנס של controller וגם הcontroller
מחזיק אינסטנס של ה
view
זה הגיוני מאוד כי אני רוצה לשלוח בקשות ולקבל תשובות,

התשובות
האלה הם בעצם ה
CallBack
של הקונטרולר לצד ה
UI.

בכל מקרה
כך ייראה ה
View :

public class DeomView
: IView

    {

        IController _controller;

 

        public DeomView()

        {

        }

 

        public void ShowItems(List<Item>
list)

        {

            if(_controller != null)

            foreach (var item in list)

            {

                Console.WriteLine(item.name);

            }

        }

 

        public void addItem()

        {

            if (_controller != null)

            {

                Console.WriteLine(“enter
Name for new item”
);

                Item item = new Item() { name = Console.ReadLine()
};

               
_controller.AddItem(item);

            }

        }

 

 

        public void InjectController(IController controller)

        {

           this._controller = controller;

        }

    }

 

 

7.        וזהו, בוא נריץ את העניינים,
על הדרך פתרנו בעיה מעיקה מי מרים את מי, ז”א ברור לנו מי מכיר את מי אבל אני
לא הייתי רוצה שהקונטרולר ירים את המודל או ה
View ירים את הקונטרולר,

במצב
הנוכחי אני משתמש ב
console שיוצר את כולם ושולח להם
את המופעים הרלוונטיים.

class
Program

    {

        static void Main(string[] args)

        {

            IView view = new DeomView();

            IModel model = new
Model();

 

            IController control = new
Contreoller(view, model);

 

           
view.InjectController(control);

            view.addItem();

            view.addItem();

           
view.ShowItems(control.GetItems());

        }

    }

 

8.      
הערה
אחרונה(למבוגרים בלבד) וממש חשובה, זוכרים את הפתיחה אודות
IOC
 וDependency Injection  ??
אז הפונקציה של ה
View שנקראת InjectController זה המחשה מצוינת לבעיה ולפתרונה, כאמור
אמרנו שה
view מכיר controller וגם להיפך הcontroller מכיר view אבל איך אני מוודא שיש לי
אינסטנסים שלהם בזמן ריצה?

ז”א
אם נבקש בקונסטרקטור של ה
view מופע של controller, לא יהיה לי מה לשלוח כי

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

מצער
מאוד אה? יפה לכן הוספנו פונקציה של
injection שנקרא לה דבר ראשון לפני
שנשתמש ביכולת של ה
view והיא “מזריקה”
לתוך ה
view את הקונטרולר והכל מסודר.

מסובך?
קצת.. תקראו שוב מהתחלה זה יהיה יותר טוב.. (אצלי זה עבד)

 

 

 

הוסף תגובה
facebook linkedin twitter email

Leave a Reply to יוש Cancel reply

Your email address will not be published. Required fields are marked *

7 תגובות

  1. יוש10 בDecember 2012 ב 15:57

    מדהים! פשוט ומשעשע , תמשיך, פעם ראשונה הבנתי מה זה MVC

    Reply
  2. עודד10 בDecember 2012 ב 15:58

    Good Work, and Fun too..

    Reply
  3. רולי01210 בDecember 2012 ב 15:59

    יש קשר בין IOC ל ASP MVC???

    Reply
  4. תלמיד11 בDecember 2012 ב 2:54

    תגיד – אתה מורה? אם לא זה ברכה לבטלה!!

    Reply
  5. אוריאל11 בDecember 2012 ב 5:07

    מורה בשעות הפנאי
    תודה

    Reply
  6. Dimma16 בDecember 2012 ב 4:44

    yes it is. great Post !

    Reply
  7. רן23 בDecember 2012 ב 10:37

    וואלה הרב דוט נט השני..

    Reply