שימוש ב-Assert יכול להיות פתרון נוח
ושימושי כשרוצים לוודא שה-State
שאנחנו נמצאים בו כרגע, באמת מתאים למה שאנחנו מצפים. אנחנו יכוללים
להשתמש בו בשביל לבדוק כל מיני מקרי קצה ביזארים, כל מיני מצבים ש"אין
מצב" שיקרו (על פי הלוגיקה הקיימת בקוד). כל מיני מצבים שהמשך הקוד שלנו
מסתמך על זה שהם לא אפשריים, ולא יקרו בזמן הוא רץ. בדרך כלל נקרא ל-Assert דרך המחלקה הסטאטית Debug, שעושה שימוש ב-
ConditionalAttribute
עם הערך "DEBUG", כך שאנחנו יודעים שכל הבדיקות האלו לא יעלו לנו כלום
כשנצא לגרסת ה-Release, כך שאנחנו גם לא צריכים "להתקמצן" על כל Assert
קטן בקוד שיכול לעזור לנו למצוא כל מיני מצבים לא הגיוניים בתוכנית שלנו.
ברגע שה-Assert שלנו יכשל, יופיע MessageBox גדול ויפה שיציג לנו את
ההודעה שרצינו להדפיס במידה וה-Assert נכשל, ובנוסף לכך את ה-StackTrace
הרלוונטי. הבעיה מתחילה כשאנחנו חס וחלילה.. סוגרים את החלון הזה. ופוף!
הכל נעלם. אנחנו אולי יודעים בערך איזה Assert בקוד נכשל, אבל מן הסתם
אנחנו לא זוכרים את ה-StackTrace, או חשוב מכך, את הזמן שבו ה-Assert קרה
(כך שנוכל אחר כך להתאים אותו ביחס לשאר הלוגים שהדפסנו במהלך הריצה,
למעשה להבין פחות או יותר מה היה יכול להשפיע על הכישלון הזה).
צריל לזכור ש-Assert כושל
לא יגרור זריקת Exception. כל מה שהוא
יעשה זה לעבור על כל ה-TraceListener'ים שהוצמדו ל-Debug, ופשוט לקרוא
לפונקצית ה-Fail שלהם. כברירת מחדל ה-Listener היחיד שמוצמד הוא ה-
DefaultTraceListener. שרק מדפיס ל-Output את ההודעה, ובנוסף מציג את ההודעה בחלון ה-MessageBox המוכר (במידה והערך הנמצא בשדה
AssertUiEnabled מאפשר לו לעשות זאת).
מכאן, שלא משנה בכמה Try-Catch'ים עטפנו את הקוד שלנו, הכשלון הזה לא
יתפס, ואנחנו יכולים למצוא עכשיו את עצמנו מגששים באפלה אחר סיבות אפשריות
לכישלון בבדיקה.
אולם, המצב לא חייב להיות כך. ואנחנו יכולים לדאוג שכל כשלון כזה יטופל
כמו כל שגיאה אחרת, וישמר אוטומטית בלוג של התוכנית שלנו. נוסף על כך, אם
נרצה נוכל גם להכריח את התוכנית להסגר, במידה ואנחנו לא מעוניינים שהיא
תמשיך לעבוד במצב זומבי שכזה, בו אנחנו בין כה וכה לא יודעים מה קורה
איתה, ומצפים שהיא תקרוס בקרוב בגלל איזו תופעת לוואי שנגרמה כתוצאה
מה-State הלא צפוי אליו היא נכנסה.
הפתרון הוא פשוט למדי, כל מה שעלינו לעשות זה ליצור TraceListener חדש
משלנו, ולהשתמש בו. אנחנו יכולים ליצור מחלקה חדש שתרש מהמחלקה האבסטרקטית
TraceListener, ותדרוס את המימוש של הפונקציה Fail. בתוך המימוש החדש,
נשאר לנו רק לשמור ללוג את ההודעה + ה-StackTrace שמעניין אותנו, וזה הכל.
מעכשיו כל Assert כושל שיתרחש אצלנו, ישמר אוטומטית ללוג.
מאחר וה-Listener'ים מופעלים בצורה סינכרונית, אחד אחרי השני. אפשר וכדאי
לדאוג שה-Listener שלנו יהיה הראשון שמופעל, כך שלא נבזבז זמן על זה שחלון
ה-MessageBox מוצג, או שבטעות מישהו יסגור את התוכנית לפני שנספיק לשמור
את השגיאה ללוג שלנו (באותה מידה אפשר גם לדאוג שה-Listener שלנו יהיה
היחיד שקיים, ואז בסוף ה-Fail לזרוק למשל שגיאה ... בכל אופן, לא חסרות
דרכים להתמודד עם הבעיה).