הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

שי חלוד

18/09/2025

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

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

ומצד שני אי אפשר בכלל להשוות את הפופולריות של npm מול rubygems. לא מפתיע ששחקנים זדוניים לא מנסים להשתלט על ריילס במתקפות נגד שרשרת האספקה באותה עוצמה וכמות כמו שתוקפים את npm. גם אליקסיר, php, קלוז'ר וכלים לא פופולריים רבים נוספים "נהנים" מהיותם מטרה פחות מלהיבה. קצת כמו ש Desktop Linux די חסין לוירוסים, פשוט בגלל שהוא לא מטרה מספיק מלהיבה.

לקחים מעשיים מהסיפור? כמו במקרים דומים כדאי לשים לב ל Best Practices של פיתוח מאובטח:

  1. לא להתקין גירסאות חדשות של ספריות חיצוניות מיד כשעולות לאוויר.

  2. להוריד הרשאה על מפתחות גישה, לא לערבב בין מפתחות גישה של פיתוח ושל פרודקשן.

  3. להפריד בין רכיבים במערכת ובין מערכות שונות, כולל משתמשים שונים לכל מערכת.

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

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

  6. להתקין פחות ספריות JavaScript. הרבה דברים אפשר לפתור היום לבד או עם מימוש קטן של AI.

תקציר דוגמאות הוובינר מחר

17/09/2025

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

המשך קריאה

רק AI היה יכול לחשוב על זה, חלק 2

16/09/2025

מאחר ול AI אין בעיה להקליד הרבה אנחנו הרבה פעמים מקבלים PR-ים עם המון קוד שבמבט ראשון לא נראה נורא ואולי אפילו נותן הרגשה של "וואו איזה כיף שיש AI כי לי היה לוקח המון זמן להקליד את כל זה" אבל במבט יותר מעמיק אנחנו מבינים שבני אדם מראש לא היו מקלידים את הכל. דוגמה? בטח.

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

items = [
    { id: 'a', name: 'one', next: 'b' },
    { id: 'b', name: 'two', prev: 'a', next: 'c' },
    { id: 'c', name: 'three', prev: 'b', next: 'd' },
    { id: 'd', name: 'four', prev: 'c' }
]

וביקשתי מ AI לכתוב בדיקות ללוגיקה.

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

expected = [{id: 'a', name: 'one'}]
assert_equal expected, build_list

רואים כבר את הבעיה? תכף היא תהיה ברורה.

הפיצ'ר הבא למימוש היה שינוי שהמזהים יהיו אקראיים, כך שעכשיו הפונקציה build_list עדיין מחזירה מבנה נתונים בדיוק באותו מבנה אבל במקום a, b, c ו d היא משתמשת ב uuid. מבחינת הקוד זה היה שינוי של דקה אבל הבדיקה (כלומר כמה מאות שורות של בדיקות) לא שרדה.

בן אדם שהיה מקבל משימה לכתוב בדיקות היה קודם כל חושב "מה בעצם חשוב לי בבדיקה הזאת", מבין שמה שחשוב זה שה next ו prev תמיד מכילים את המזהים של מה שבא לפניהם ואחריהם וכותב בדיקה גמישה שלוקחת את המזהים מהרשימה שנוצרה ומוודאת שהקשר בין הפריטים נכון. ל AI אין ולא יכולה להיות ההבנה הזאת.

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

נשים לב - בקידוד עם AI יש לנו הזדמנות להקליד פחות ומחויבות לחשוב יותר. זה שני דברים טובים במכה אחת.

רק AI היה יכול לחשוב על זה

15/09/2025

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

item
  .select { |item| !item["id"] }
  .each_with_index do |item, index|
    item["id"] = "item_#{index + 1}"
  end

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

מה שמעניין שלקלוד אין בעיה לזהות את הכשל הלוגי שהוא יצר. מספיק לבקש ממנו לעשות Code Review לקטע הקוד בשביל לקבל מיד הסבר מלא לבעיה הלוגית. אבל זה לא עוזר כי Code Review של AI לא עובד בסקייל גדול.

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

היום למדתי: המחלקה StringScanner ב Ruby

14/09/2025

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

המשך קריאה

הפיתרונות של אתמול

13/09/2025

הכפתור הכי חשוב במשחק Spelling Bee הוא "הפיתרונות של אתמול".

לא כי בפיתרונות של אתמול יש רמזים לחידה של היום (ממילא כל יום יש אותיות אחרות).

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

כל הדברים שלא הספקתי

12/09/2025

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

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

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

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

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

מותר לשנות את דעתכם

11/09/2025

לפני 10 שנים DHH עלה על הבמה ב Rails World וסיפר כמה הוא אוהב בדיקות End To End, כמה זה הדבר הכי חשוב במערכת, איך כל סוגי הבדיקות האחרים מיותרים ואיך ריילס תעודד מפתחים לכתוב רק בדיקות מערכת מקצה לקצה.

השנה הוא עלה לבמה ב Rails World וסיפר על ההחלטה למחוק אצלם במוצר כמעט את כל בדיקות המערכת (נשארו 10) ולהתמקד בבדיקות יחידה כיוון שבדיקות מערכת לא מוצאות מספיק באגים, נשברות לעתים קרובות והם מבזבזים המון זמן בתיקון בעיות פיקטיביות - בעיות שקורות רק בבדיקות. החל מהגירסה הבאה של ריילס ברירת המחדל לא תהיה ליצור בדיקת End To End לכל קוד חדש שאתם כותבים.

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

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

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

מה ה Use Case

10/09/2025

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

מהר מאוד הבנתי איזה Use Case ראיתי, ואיזה Use Case-ים פספסתי:

  1. המחבת שלי היתה בדיוק בגודל שהתאים לארון. את המחבת הגדולה אין איפה לשים.

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

  3. מחבת גדולה צריכה מכסה גדול, אבל המכסה שהיה לי התאים רק למחבת הישנה.

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

תגיד מה כן

09/09/2025

משפט פשוט שעובד טוב כשבונים הרצאה מול קהל, כשמעצבים ממשקי משתמש, כשמדברים עם הילדים ואפילו בשיחות עם AI.

תגידו מה כן לעשות.

פקודת git checkout יודעת להדפיס לכם לעבור לגירסה החדשה יותר git switch, ואם חזרתם אחורה לקומיט גיט יכתוב לכם שאתם במצב detached head ותשימו לב להיזהר מהקומיט הבא.

בתיעוד של פקודת with ב MDN יש פיסקה שמסבירה שפקודה זו כבר לא רצויה והמלצה במה להשתמש במקום.

כשאני מנסה להריץ פקודה ב Ubuntu והפקודה לא מותקנת אני אקבל שגיאה שמציעה לי להתקין את אותה הפקודה.

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

במקום "לא כתבת בדיקות" נכתוב "תוסיף בדיקת יחידה לוודא שדברים עובדים גם אם היתה שגיאת תקשורת".

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

במקום "אל תשכפל את אותו קוד ב-3 מקומות שונים" נכתוב "הוצא את הקוד המשותף לפונקציה".

וכן ברור שיותר קל לראות מה לא בסדר מלהמליץ מה כן לעשות. כדאי לזכור ש״לא להחליט״ זה פשוט לתת למישהו אחר (אולי פחות מוכשר) להחליט בשבילנו.