זה הממשק, טמבל

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

max_found = 0
for i in range(100, 1_000):
    for j in range(100, 1_000):
        product = i * j
        if str(product) == str(product)[::-1] and product > max_found:
            max_found = product

print(max_found)

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

  1. איתור כל המספרים שהם מכפלה של שני מספרים תלת ספרתיים.

  2. איתור כל המספרים מתוכם שהם פלינדרומים.

  3. חישוב המספר המקסימלי.

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

ארגון מחדש של הקוד בחשיבה על המנגנונים והממשק ביניהם נראה כך:

import itertools

three_digit_numbers = range(10, 1_000)
pairs = itertools.product(three_digit_numbers, repeat=2)
products = (i * j for (i, j) in pairs)
palindroms = (p for p in products if str(p) == str(p)[::-1])
print(max(palindroms))

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