Learning Validation Application Block with Strippers: Using Bussiness Entities with Validator Attributes
סדרת לומדים Validation Application Block עם חשפניות
1. קדם דבר: למה צריך וולידציה? (או: "קופים. פשוט קופים."), פורסם ב-26.6.2007
2. חלק ראשון: הפתרון הקיים והמצוי ב-Winforms, Console ו-ASP.Net (או: "איך קוראים לך ובת כמה את?"), פורסם ב-8.7.2007
3. חלק שני: שימוש ישיר ב-Validatorים של VAB (או: "איך לגרום לקוד יחסית קריא להפוך להיות ארוך ומעיק"), יפורסם ב-9.7.2007
4. חלק שלישי: הכנסת נתוני הוולידטורים לתוך מחלקות (או: "ממלכתי עבור וולידטור ג'נארי"), פורסם ב-10.7.2007
5. חלק רביעי: אינטגרציה בסיסית עם ה-GUI ו-וולידציה מתוך קבצי קונפיוגרציה (או: "קצת יותר Drag&Drop, קצת פחות קוד"), יפורסם ב-11.7.2007
6. המשך יבוא.
חלק שלישי: הכנסת נתוני הוולידטורים לתוך מחלקות (או: "ממלכתי עבור וולידטור ג'נארי")
נוסיף מחלקה חדשה. (גם באנגלית: Class)
ניצור פרוייקט חדש מסוג Class Library ונקרא לו BL:
נוסיף מחלקה חדשה בשם Stripper ואת ה-refernces של VAB. (בנוסף, נמחוק את ה-references של VAB משאר הפרוייקטים עד כה)
נדאג להוסיף references לפרוייקט הזה משאר הפרוייקטים.
נדאג לבצע Add reference מכל פרוייקט אחר שלנו (Console, Winforms ו-ASP.Net) לפרוייקט שנקרא BL וכרגע ריק יחסית.
נוסיף שני מאפיינים (גם באנגלית: Properties) למחלקת החשפנית שלנו.
אחד שייצג את שם החשפנית והשני שייצג את גיל החשפנית.
בנוסף, גם נוסיף קונסטרקטור (גם באנגלית: Constructor) שמקבל את שני הפרמטרים הנ"ל.
בנקודה זו אני רוצה לשלב תמונה של חשפנית כי כבר הרבה מאוד קוד לא ראינו אישה חצי עירומה.
נמשיך.
עכשיו ניקח את הקוד הבא שהוא הקוד המעודכן של ה-Console שלנו ונחליף אותו ככה שיעבוד עם אותו מחלקהת Stripper שכרגע יצרנו.
יהפוך ל-
וכנ"ל נשנה גם את הקוד של גיל החשפנית שיכנס ל-Stripper.Age.
מה שכן, נכון לעכשיו בשלב זה של המאמר - נפסיק לבדוק אם הקלט הוא אכן מספר. נחזור לבדוק את זה בשלבים הרבה יותר מאוחרים של המאמר שקשורים לאינטגרציה (סוג של ממתק סובייטי) עם ה-GUI (שזה סוג של כלב הולדני).
הקוד הבא אחרי שנניח כי הקלט הוא תמיד מספר יהפוך מ-
לקוד הבא:
ובשימוש עם המחלקת Stripper שלנו נקבל:
אז למה התחלנו לעבוד עם מחלקה? הרי לא חסכנו כאן שום קוד!
אז בואו נראה אחד מהפיצ'רים האדירים של VAB, נכתוב בתוך המחלקה שלנו איזה וולידציה מתבצעת עליה.
אמרנו הרי שאת Name אנחנו רוצים לבדוק שהוא לפחות באורך תו 1 ולא יותר מ-100 תווים, ואת Age אנחנו רוצים לבדוק שהוא בין 18 ל-int.MaxValue.
בואו פשוט נכתוב את זה בקוד שלנו של המחלקה!!!
אמרנו ככה: Name הוא בין 1 ל-100 תווים, ו-Age הוא מספר בין 18 ל-int.MaxValue ("כולל" 8 ו-int.MaxValue ולכן ציינו Inclusive).
עכשיו נעשה משהו קיצוני לקוד של ה-Console. הקוד הבא:
יהפוך ל:
נעבור על זה שורה-שורה.
העפנו את כל אתחול ה-Validatorים הפרימיטיביים מהקוד שלנו. הרי הם כבר כתובים במחלקה.
אז כל מה שנשאר זה לאתחל את מחלקת ה-Stripper שלנו.
יצרנו מופע של משהו שנקרא <Validator<Stripper. קראנו שם לאיזה ValidationFactory.CreateValidator שמקבל כפרמטר ג'נארי את ה-T שאנחנו רוצים לקבל את ה-Validator שלו.
נחשוב ביחד על המשמעות של זה - הרי עכשיו למעשה ה-Stripper שלנו מכילה את כל הוולידטורים שלנו והיא בעצמה וולידטור!
אם אמרנו שעכשיו יש לנו Validator עם כל המידע שיושב על Stripper הרי מספיק לנו לשלוח לוולידטור הזה מופע (גם באנגלית: Instance) של Stripper והוא כבר יגיד לנו מה לא בסדר איתו.
קיבלנו בחזרה ValidationResults שזה אוסף (גם באנגלית: Collection) של כל כשלון בביצוע הוולידציה.
אם זה אוסף אז אפשר לבצע על זה foreach? בטח שאפשר.
עברנו על התוצאות והדפסנו משהו. לא ברור מה בדיוק הדפסנו ומה הולך כאן עם ההדפסה, אבל נריץ ונראה איך כל זה רץ.
נראה את זה מולנו:
קיבלנו שיש בעיה עם הוולידציה של Name כי השם צריך להיות בין אות 1 ל-100 אותיות.
וגם קיבלנו שיש בעיה עם הוולידציה של Age כי הערך צריך להיות בין 18 ל-int.MaxValue.
נשנה את ההודעות שגיאה האלו למשהו קצת יותר ידידותי.
אם הוולידטורים יושבים על Stripper אז נשנה את Stripper כך שהודעות השגיאה יופיעו גם בו. הקוד הבא של Stripper יהפוך מ-
יהפוך ל-
נראה את זה בהרצה:
ניקח את הקוד שכתבנו עד כה ב-Console ונעתיק אותו לתוך Winforms ו-ASP.Net. הקוד הנוכחי שלנו ב-Console יהפוך מ-
לקוד הבא ב-Winforms ו-ASP.Net:
ובהרצה של Winforms:
ובהרצה של ASP.Net:
עדיין יש לי בעיה עם הקוד הזה:
הוא חוזר על עצמו ולפי דעתי מיותר לגמרי.
נחליף אותו בקוד הבא:
החבר'ה הטובים ברדמונד חשבו כבר על זה שאנחנו לא רוצים להיות אלו שמאתחלים כל מיני וולידטורים ובאמצעות Validation.Validate העלימו אותם לגמרי.
כל מה שאנחנו עושים בנקודה הזו זה להוסיף את הוולידטורים על המחלקה ולשלוח אותו לאיזה מתודת Validation.Validate קסומה שמחזירה לנו ValidationResults עם כל מה שאנחנו צריכים. (אגב, מאחורי הקלעים כל מה שמתבצע שם זה זה קריאה ל-ValidationFactory עבורנו + Caching זה ה-Validatorים).
אז עכשיו ככה נראה הקוד שלנו ב-Winforms וב-ASP.Net עם VAB:
וככה הוא נראה עם וולידציה ישר בתוכו:
וככה נראה הקוד שלנו ב-Console עם VAB כרגע:
במקום הקוד המקורי ב-Console:
אפשר לראות שה-GUIים השונים שלנו כבר לא מכירים יותר את כללי הוולידציה, אלא רק יודעים לעבוד עם איזה מנגנון כללי שהוא זה שאחראי לביצוע הוולידציה בפועל.
אז כבר אנחנו לא כותבים יותר קוד שבודק את הקלט של המשתמש.
עכשיו אנחנו:
1. אומרים ל-VAB מה לבדוק (בצורה של Attributes על Properties של המחלקה)
2. שולחים ל-VAB מחלקות לבדיקה
3. מתייחסים לתוצאות של הבדיקה.
מה שכן מוזר לי מאוד שאנחנו נאלצים ב-Winforms וב-ASP.Net לדאוג להציג את התוצאות של הוולידציה בעצמנו.
הרי מדובר גם במשימה מאוד פשוטה ונפוצה יחסית.
הרי תחת ההנחה שכל שדה ב-GUI מתכתב למאפיין במחלקה שלנו אפשר בקלות מאוד לבצע וולידציה פר-שדה.
כלומר, עכשיו אנחנו צריכים לנסות לראות איך נוכל להוריד את הלולאת foreach על כל התוצאות שלנו.