ההמלצה ה"קלה יותר" של Claude הסתירה עלויות אמיתיות. שאלה חוזרת אחת חשפה הכול.
עבדתי על smarts — אפליקציית Rails שמרנדרת חוזים חכמים של Ethereum כ"תיעוד למפתחים". לפני כמה ימים נתקלתי בבעיה ישנה: חוזים מתעדכנים. אם המערכת מרנדרת חוזה proxy שעבר שדרוג עם ABI מיושן, היא משקרת למשתמש.
ביקשתי מ-Claude לתכנן איתי מנגנון לזיהוי שדרוגי proxy. הוא הוציא תוכנית טכנית מסודרת, כולל תאימות ל-EIP-1967, ל-Beacon proxies ול-ZeppelinOS. כשהגענו ל"מתי להפעיל את הבדיקה", הוא הניח שתי אפשרויות:
# אפשרות A: להוסיף last_proxy_check_at בבסיס הנתונים, throttle של 5 דקות
if @contract.last_proxy_check_at.nil? || @contract.last_proxy_check_at < 5.minutes.ago
CheckProxyUpgradeJob.perform_later(@contract)
end
# אפשרות B: throttle דרך Solid Cache, קליל יותר
unless Rails.cache.exist?("proxy_check:#{@contract.id}")
Rails.cache.write("proxy_check:#{@contract.id}", true, expires_in: 5.minutes)
CheckProxyUpgradeJob.perform_later(@contract)
end
המשפט הסוגר שלו:
B פשוט יותר, אין צורך להוסיף עמודה.
בהיתי בשני הקטעים רגע. B אכן היה פשוט יותר, בלי migration, רק קריאות cache, מאוד אידיומטי ל-Rails. אבל משהו לא ישב לי.
הקלדתי חמישה תווים והקשתי enter:
ממליץ a?
התשובה שלו (כמה בלוקי קוד נחתכו):
משנה דעה — ממליץ על A.
הסיבה: כל המטרה של זיהוי proxy היא לא לסמוך על הטריות של ה-ABI. אם נעשה throttle דרך Solid Cache, אנחנו שמים שוב את "כבר בדקנו?" באחסון נדיף:
- אחרי deploy / cache wipe כל החוזים נכנסים בו-זמנית למצב "לא נבדקו" → גל הגישה הבא מפעיל סופת בדיקות
- אי אפשר לענות על "כמה זמן עבר מאז שהחוזה הזה נבדק שוב?"
- אי אפשר לעשות רשת ביטחון מתוזמנת: חוזים קרים יכולים לעבור שבועות בלי תנועה, ו-trigger בעצלות לא יופעל אף פעם
מה ההוספה של עמודת
last_proxy_check_atפותחת:
- trigger בעצלות (אותה לוגיקה כמו B)
- רשת מתוזמנת דרך recurring.yml שמכניסה לתור באצווה חוזים שעברו 24 שעות, ללא תלות בתנועת המשתמשים
- הצגת טריות ב-UI: "Implementation verified 12 min ago"
מחיר: migration אחת +
update_columnאחד פר job (בלי callbacks, כמעט בחינם).בקצרה: B נראה "יותר Rails-native, קליל יותר", אבל חסרה לו שכבת יכולת. A היא האפשרות שבאמת מממשת את ה"אנחנו לא סומכים על טריות ה-ABI".
שים לב מה קרה בין שתי ההמלצות:
בין שני המעברים לא נכנסה אף עובדה חדשה. נפח קוד, אידיומים של Rails, סמנטיקת cache — הכול נשאר אותו דבר. מה שהשתנה זה מאיזה שכבה הוא העריך.
המעבר הראשון השווה נפח קוד. השני השווה "האם השינוי הזה באמת פותר את הבעיה שהצבנו?".
כשהקלדתי "ממליץ a?" לא ניסיתי לדחוף אותו לשום מקום. פשוט נתקעתי על הקוד של B, ובאופן אינסטינקטיבי שאלתי שוב מה הוא מעדיף.
אבל האפקט היה למשוך אותו מ"בחר אחת משתיים" חזרה ל"למה בכלל אנחנו עושים את זה?". הפער הזה הוא כל הסיפור.
כשמודלי שפה ממליצים, הם כמעט תמיד יוצאים מאופטימום מקומי: איזה diff קטן יותר, איזה snippet יותר אידיומטי, איזה מימוש קורא נקי יותר. אלה צירים אמיתיים. אבל הם לעיתים קרובות לא מתחברים למה שה-PR הזה באמת בא לפתור.
A ו-B שווים בציר "throttle של 5 דקות". אבל A פותח גם שלושה דברים ש-B לא יודע — רשת מתוזמנת, צפיוּת, טריות ב-UI. אם מסתכלים רק על שכבת ה-throttle, B מנצח. אם אכפת לך למה ה-job הזה קיים, A מנצח.
Claude לא ראה את השכבה הזו בפעם הראשונה לא כי הוא לא מסוגל. זה כי המסגרת ברירת המחדל ל"השווה את האפשרויות האלה" היא שכבת תחביר/Rails. שאלה חוזרת אחת משכה אותו לשכבת הבעיה, ומשם הוא חישב לבד את העלות של B.
כמה התאמות קטנות שהכנסתי לתהליך שלי:
כש-Claude סוגר ב"פשוט יותר / קליל יותר / יותר native", תסתכל פעם שנייה. אלה מילים אסתטיות, לא מילים של שיפוט. הן מתארות את מה שקורא טוב, לא את מה שמחזיק מעמד.
עלות שאלה חוזרת היא אפס. "ממליץ X?" — חמישה תווים. Claude נאלץ להעריך מזווית שלא לקח. גם אם ינחת על אותה המלצה, ההנמקה תהיה מוצקה יותר, מספיק כדי שתחליט אם לסמוך עליה.
גרום לו לפרוש את העלויות, לא רק את ההמלצה. מה שעשה את זה טוב כאן זה לא שלחצתי על A — זה ש-Claude כתב את העלויות הנסתרות של B (סופה אחרי cache wipe, חוסר צפיוּת, מבוי סתום למשימות מתוזמנות). אף אחת מהן לא ניסחתי בעצמי לפני שהוא עשה זאת.
הוצאתי לפועל את A: הוספתי את העמודה last_proxy_check_at, trigger בעצלות בתוספת רשת מתוזמנת ל-24 שעות, וב-UI מוצגת עכשיו שורה Implementation verified 12 min ago. שלושה ימים אחר כך, בעבודה לא קשורה, העמודה הזו אפשרה לי לכתוב שאילתה Contract.where("last_proxy_check_at < ?", 24.hours.ago).find_each — שאילתה שפשוט לא הייתה יכולה להתקיים אם הייתי בוחר ב-B.
חמישה תווים של שאלה חוזרת, שווים בערך refactor של שבוע אחר כך.