התמודדות עם שגיאות תוכנה

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

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

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

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

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


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

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

הנה מצב שבאמת מתרחש בעולם התוכנה:
אני שרת (נעים מאוד). מישהו פותח מולי סוקט. מה אני עושה עכשיו? אחרי שעברתי מליארד דברים "עסקיים" בשרת, אשר החליטו האם לאשר את הבקשה בכלל, אני מחכה עכשיו לקבל payload.
אבל הוא עדיין לא הגיע, מה עכשיו? האם אני סוגר את החיבור? מה אם קיבלתי keep alive כחלק מTCP? כמה הזדמנויות אני צריך לתת לתעבורה להגיע אלי, עד שאני מודה שמשהו כאן לא תקין?

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

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

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

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

העניין הוא שאני רואה הרבה מערכות אשר יעלו חריגה בנושא, ויתייחסו אל זה כמשהו לא תקין.
ויותר גרוע, ראיתי שרתים קורסים בגלל זה. כן, באמת!

חריגה היא משהו שלא צריך להתרחש ובמידה וכן, צריך אליו התייחסות מיוחדת. כלומר זה משהו חריג, שלא אמור להתרחש בכלל.

למשל תוכנית ביקשה 10 מגה של זיכרון, ואין 10 מגה לספק עבורה, זה משהו שאני צריך להיות ערוך לו, אבל זו חריגה, כי התוכנית כנראה לא יכולה להמשיך בלי כמות הזיכרון הזו.

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

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

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

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

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

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

להשאיר תגובה

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

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת /  לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת /  לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת /  לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת /  לשנות )

w

מתחבר ל-%s

This site uses Akismet to reduce spam. Learn how your comment data is processed.