Exceptions are NOT Evil
כן כן הכותרת באה לעשות פרפרזה על Extends is Evil וGetters and Setter are evil - שני המאמרים המבריקים של אלן Holub.(ראו הפנייה בהודעה של ייוני על מאמרים) אז ככה, יש האומרים (וביניהם יווני) שExceptions are Evil או בלשון העם אל תשתמש בהם כלל. הטענה שלהם מתבססת על הגדרה אשר אומרת כאשר אנו פונה לאובייקט אשר מיישם Interface מסויים, הוא צריך לעבוד, ושלא יעשה לי הצגות. טענה זו נכונה ומעניינת, אבל בעיני סותרת רעיון בסיסי של AGILE. יסוד ההגדרה של AGILE - בעיני היא "אני לא יודע הכל, אני לא יודע מה יהיה, אני רק יודע מה אני צריך עכשיו, ומה היה קודם (ונבדק על ידי הUNIT TESTS). בעיני השימוש בExceptions מאפשר למתכנת לטפל במקרים שהוא חשב עליהם, ולהיות שקט שאם יגיע מקרה שהוא לא לקח בחשבון - המערכת לא תתנהג בצורה לא צפוייה אלא תודיע לו, כאן ועכשיו. דוגמא טובה לכך היא ממשקים, קריאה של XML וקבצים חיצוניים וכו... אני אדגים נגיד שאני מתממשק לWEBSRVICE אשר מחזיר לי איזה שהוא STATUS ID (כן ייוני אני יודע שאתה לא אוהב שזה מחזיר, אבל זו הדוגמא). לאותו סטטוס ID יש כרגע שני ערכים קבועים - 1 הצליח, 2 נכשל. הקוד שלי יהיה משהו כזה
כן כן הכותרת באה לעשות פרפרזה על Extends is Evil וGetters and Setter are evil - שני המאמרים המבריקים של אלן Holub.(ראו הפנייה בהודעה של ייוני על מאמרים) אז ככה, יש האומרים (וביניהם יווני) שExceptions are Evil או בלשון העם אל תשתמש בהם כלל. הטענה שלהם מתבססת על הגדרה אשר אומרת כאשר אנו פונה לאובייקט אשר מיישם Interface מסויים, הוא צריך לעבוד, ושלא יעשה לי הצגות. טענה זו נכונה ומעניינת, אבל בעיני סותרת רעיון בסיסי של AGILE. יסוד ההגדרה של AGILE - בעיני היא "אני לא יודע הכל, אני לא יודע מה יהיה, אני רק יודע מה אני צריך עכשיו, ומה היה קודם (ונבדק על ידי הUNIT TESTS). בעיני השימוש בExceptions מאפשר למתכנת לטפל במקרים שהוא חשב עליהם, ולהיות שקט שאם יגיע מקרה שהוא לא לקח בחשבון - המערכת לא תתנהג בצורה לא צפוייה אלא תודיע לו, כאן ועכשיו. דוגמא טובה לכך היא ממשקים, קריאה של XML וקבצים חיצוניים וכו... אני אדגים נגיד שאני מתממשק לWEBSRVICE אשר מחזיר לי איזה שהוא STATUS ID (כן ייוני אני יודע שאתה לא אוהב שזה מחזיר, אבל זו הדוגמא). לאותו סטטוס ID יש כרגע שני ערכים קבועים - 1 הצליח, 2 נכשל. הקוד שלי יהיה משהו כזה
public void UseWebService() { int result = WebService(); if (result ==1) DoSuccessStuff(); else DoFailStuff(); }
עכשיו אותו WEBSERVICE החליט להוסיף סטטוס נוסף, 3 - שיהיה הצלחתי וחייבתי את הלקוח הקוד שלי לא יעבוד - אני אצתרך להתחיל לחפש לה הקוד מחזיר כשלון במקרים שהלקוח אומר לי שהיתה הצלחה, ואז אני צריך לרוץ, ואחרי זמן לא מבוטל לגלות שהספק הוסיף ערך קבוע נוסף (3). לעומת זאת אם הקוד היה כתוב כך:public void UseWebService() { int result = WebService(); switch (result) { case "1": DoSuccessStuff(); break; case "2": DoFailStuff(); break; default: throw new Exception ("UnKnow result code = "+result.ToString()); } }
הקוד הזה, יודיע לי מייד ברגע שהוא נתקל במקרה שלא ידעתי עליו, ולא חשבתי עליו על שגיאה. אשר אותה אוכל לתקן. מקרה נוסף שזה עוזר בו, זה כאשר אני מתממשק עם גורם שלא מתועד כמו שצריך. מה שעושים אז, זה מסתכלים על דוגמאות ונסים לפענח אותן. נגיד שהגעתי למסקנה ששדה A הוא סטטטוס -1 הוא הצלחה ו2 הוא כשלון, ולא נתקלתי במקרה של 3. מה שיקרא עם הקוד הראשון, כאשר יהיה מקרה של 3 הדרך היחידה שלי להבין את זה תהייה פענוח של התוצאות אשר גרמו לו להתנבהג כמו 2 - והיכולת שלי למצא את צומת ההחלטה הזו מהר. במקרה השני, ברגע שאני נתקל בערך לא מוכר - הקוד מודיע לי, היי מקרה לא מוכר (חריג) כלומר Exception אשמח לשמוע את דעתכם בנושא