משתנים שאינם משתנים

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

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

workerSalary = baseSalary * 0.18;

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

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

אז הפתרון שלנו הוא כמובן להגדיר את המספרים האילו, שאנחנו קוראים להם “מספרי קסם” כי הם כאילו מופיעים להם בתוכנית בלי שום הסבר, כקבועים. משהו כזה, בג’אווה למשל –

final double VAT_RATE = 0.18;

או ככה ב-C:

const double VAT_RATE = 0.18;

ואז שורת הקוד הבעייתית הופכת לברורה יותר –

workerSalary = baseSalary * VAT_RATE;

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

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

final double VAT_RATE = 18;

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

workerSalary = baseSalary * (VAT_RATE / HUNDRED) ;

על זה הייתי שואל: אה? HUNDRED? איזה ערך אנחנו מקבלים מלהחליף את המספר 100 בשם HUNDRED? התשובה – שום ערך. אין לזה שום משמעות. במקרה כזה פשוט תשאירו את זה 100, זה יהיה יותר ברור ככה. אגב, אפשר כמובן להתחכם ולכתוב משהו כמו

final int THE_WHOLE_PART_OF_PERCENTAGE = 100;

אני משאיר לכם את השאלה מה עדיף….

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

circlePerimeter = 2 * 3.14 * radius;