• בלוג
  • שלוש שעות ועשר שניות

שלוש שעות ועשר שניות

21/12/2020

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

function padded(num) {
  return num > 10 ? String(num) : '0' + num;
}

נו, מביך והכל אבל פה בבלוג מותר לדבר על הכל, אפילו על טעויות Off By One. קודם כל הבאג למי שלא ראה מיד קשור לסימן ה"גדול מ-" שהיה צריך להיות "גדול-שווה" או גדול מ-9. עשר הוא גם מספר דו-ספרתי.

אבל יותר מעניין - איך מונעים שטויות כאלה בעתיד? הנה שלושה רעיונות:

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

  2. כיוון שני יהיה להשתמש בספריה חיצונית. במקרה של padded הספריה החיצונית אפילו די מפורסמת ונקראת left-pad. הקוד היה נראה כך:

impor leftPad from 'left-pad';

function padded(num) {
    return leftPad(String(num), 2, '0');
}

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

  1. כיוון שלישי ספציפי למקרה הזה הוא להיזכר שאחרי הפארסה של left-pad כבר הוסיפו ל JavaScript את הפונקציונאליות והיום היה אפשר לכתוב את הקוד הזה:
function padded(num) {
    return String(num).padStart(2, '0');
}

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

function padded(num) {
    return ('0' + num).slice(-2);
}

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