• בלוג
  • לפעמים קוד יותר ארוך הוא פשוט קוד יותר ארוך

לפעמים קוד יותר ארוך הוא פשוט קוד יותר ארוך

16/04/2019

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

מתכנת ניגש לעדכן את הקוד הבא שנראה קצת מסורבל:

def sum_all_numbers(*values):
    res = 0
    for v in values:
        if isinstance(v, numbers.Number):
            res += v

    return res

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


def sum_all_numbers_2(*values):
    return sum([NumericValue(x) for x in values])

מדהים נכון? רק שאז ניגשים לכתוב את NumericValue ומגיעים לזה:

class NumericValue:
    def __init__(self, val):
        if isinstance(val, numbers.Number):
            self.val = val
        else:
            self.val = 0

    def __add__(self, other):
        if isinstance(other, int):
            return self.val + other
        elif isinstance(other, NumericValue):
            return self.val + other.val
        else:
            return NotImplemented

    def __radd__(self, other):
        return self.__add__(other)

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

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

def numeric_value(v):
    return v if isinstance(v, numbers.Number) else 0

def sum_all_numbers_3(*values):
    return sum([numeric_value(v) for v in values])

print(sum_all_numbers_3(10, 20, 'f', 'g', '10', 30))

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