• בלוג
  • התיקון הלא נכון (או: למה הוובינר הופיע בשעה הלא נכונה)

התיקון הלא נכון (או: למה הוובינר הופיע בשעה הלא נכונה)

רבים מכם שמו לב שהוובינר באתר הופיע בשני מקומות שונים בשתי שעות שונות: בדף רשימת הוובינרים הוא הופיע בשעה הנכונה (עשר בבוקר), אבל בדף האירוע עצמו הוא הופיע בשעה שמונה בבוקר.

בואו נראה למה זה קרה ומה אפשר ללמוד מזה.

1. למה זה קרה: אזורי זמן

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

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

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

<% @workshops.each do |wi| %>
  <% ldate = wi.date.in_time_zone("Jerusalem") %>

  ...

  <%= ldate.strftime("%b") %>

המשתנה ldate הוא קיצור של המילה local_date ומחזיק את התאריך והשעה בצירוף אזור זמן.

2. אז מה הבעיה?

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

לא צריך להתאמץ בדמיון כדי להבין מה קרה הלאה. בדף הוובינר היה לי את הקוד הבא:

<% wi = @workshop_instance %>
<% date = wi.date.strftime('%d/%m/%Y') %>
<% start_time = wi.date.strftime('%l:%M%P') %>
<% end_time = (wi.date + (wi.workshop&.duration || 0).hours).strftime('%l:%M%P') %>

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

3. התיקון

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

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

config.time_zone = "Jerusalem"

לקובץ config/application.rb.

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