האם `2.days.ago` היא דרך אלגנטית לבטא תאריך יחסי?
-
תרחיש נפוץ: עליך לחשב תאריך כערך ביחס לתאריך הנוכחי.
באמצעות ספריית moment.js הפופולרית (אם כי מעט מיושנת), ניתן לבטא זאת באופן הבא:
const twoDaysAgo = moment().subtract(2, 'days')
נֶחְמָד. קָרִיא. מַסְפִּיק.
נתקלתי לאחרונה בקטע המוזר הבא בשפת רובי:
user = User.create( email: 'user@example.com', trial_ends_at: 30.days.from_now )
משתמשי Ruby on Rails עשויים למצוא את הקוד הזה מוכר במקצת. מבחינתי זו באה בהפתעה גדולה.
לאחר ההפתעה הראשונית, ניסיתי להבין כיצד קוד זה עובד בפועל.אין מצב ששפת Ruby מציעה את
days
כמתודה שלInteger
. זה פשוט יהיה מגוחך מכדי לדמיין.מסתבר, כי רובי מאפשר (מעודד?) הרחבת טייפים מובנים של השפה, וגם נראה שזה נהיה מנהג פופולרי. בעוד שבמדינת JS - איפה שאני גר - בדרך כלל לא רואים את זה בעין יפה, ברובי (on Rails?) נראה שהנורמה היא להרחיב טייפים מובנים של השפה. יש אפילו ספרייה המיועדת במיוחד למטרה זו בשם ActiveSupport.
אז לסיכום...
days
היא מתודת הרחבה של סוגInteger
, והיא מחזירה אובייקט מסוגDuration
. לאובייקטים מסוגDuration
יש כנראה מתודה בשםago
המחזירהDate
שמוסטduration
ימים בעבר. מלהיב? יפה?בוא תראה מה יש ל-DHH (דייוויד היינמאייר הנסון, יוצר RoR) לומר על סגנון קוד כזה:
... שתי ההחלטות עדיין, עד היום, גורמות לי לחייך. אני אוהב לכתוב
people.third
בטסט או בקונסולה. לא, זה לא הגיוני. זה לא יעיל. זה אפילו יכול להיות פתולוגי. אבל זה ממשיך לגרום לי לחייך, ובכך מגשים את העיקרון, ומעשיר את חיי, עוזר להצדיק את המשך המעורבות שלי ב- Rails לאחר 12 שנות שירות.אוקיי... ¯/_(ツ)_\¯
לדעתי סגנון הקוד הזה הוא לא רק רע, הוא גם פחות קריא ובמובן מסוים מכוער יותר. "למה?" אתה יכול לשאול. ובכן בעיני, קוד אינו פרוזה. קוד מעולם לא נועד להיות פרוזה. וקוד שמתחזה לפרוזה דורש יותר אנרגיה נפשית כדי לתרגם אותו לקוד שהוא באמת.
לא מסכים? בבקשה... ספרו לי בתגובות.
-
זו דוגמה של שימוש לא הולם ב"שיטות הרחבה" גם לשיטת התומכים בהם, כי ההרחבה צריכה להיות על המחלקה duration ולא על הרכיב השולי שהוא מספר הימים. ללא ספק מי שעשה את ידע שזה לא הולם אבל בגלל התוצאה הגיקית הנחמדה שכתוב בשפה טבעית "עוד שלושים יום" בהחלט ניתן להבין את המניע ואף לסלוח על המקרה הזה.
להלן מgeekswithblogs (שנראה לא מקוון כבר, הציטוט שלי הוא מפה).What Is a Good Extension Method? Extension methods can be overused and actually begin to convolute the code, thereby negating the advantages. James Michael Hare’s blog suggests a good extension method should: * Apply to any possible instance of the type it extends. * Apply to the most specific type or interface applicable. * Simplify logic and improve readability/maintainability. * Be isolated in a namespace so that it does not pollute IntelliSense. (See more at http://geekswithblogs.net/BlackRabbitCoder.)
אם מפריע לך באופן כללי כל המושג "מתודות הרחבה" זה בהחלט נושא שנוי במחלוקת
https://daedtech.com/why-i-dont-like-c-extension-methods/
https://softwareengineering.stackexchange.com/questions/371868/when-to-write-extension-methods-for-your-own-classes -
@nigun
https://www.hamichlol.org.il/פרוזה@nigun אמר בהאם `2.days.ago` היא דרך אלגנטית לבטא תאריך יחסי?:
אולי הקוד עדיין קריא כי זה מקרה נפוץ
וגם מי שלא מכיר את רובי מבין מיד מה הוא עושהלא הבנת את הטענה שלי. ברור מיד במבט ראשון מה היעד של הקוד. קוראים את זה כמו משפט באנגלית. אבל לגמרי לא ברור איך הוא מגיע לשם. האם שם של מתודה
days
על integer הוא משהו נורמלי? מה הקשר של days ל-integer? האם מתודה בשםago
על duration יש לו שום הסבר חוץ מהרצון לסלף את הקוד כדי לקבל משפט מגניב באנגלית? האם זה הגיוני ליצור אובייקט של duration כדי לעשות חישוב של מינוס יומיים על התאריך של היום?הטענה שלי הוא שאני קורא קוד עם ראש של קריאת קוד. לא רוצה לראות גימיקים חמודים שמסבכים את הקוד.
אגב, לקחתי רק דוגמה אחת. אבל זה כבר שיטה שלימה בסביבות של Ruby ו-Laravel. וזה מעצבן אותי לראות אנשים מעלים צילום מסך של שורת קוד שנקרא כמו משפט באנגלית: "וואו, תראה כמה Laravel אלגנטי!!! זה ממש נקרא כמו משפט באנגלית!"