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

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

טיפ גיט: הצילו מחקתי את תיקוני הקונפליקט

27/11/2025

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

אני יוצר פרויקט עם שלושה קומיטים בשלושה ענפים, ענף main, ענף b וענף c:

* fb6d328 (HEAD -> c) c
| * fc29558 (b) b
|/
* c3482e6 (main) a

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

<<<<<<< HEAD
**The Clockmaker’s friend**
=======
**The Clockmaker’s bug**
>>>>>>> b

ענף c שנקרא HEAD מכיל את המחרוזת העליונה וענף b שאותו ניסיתי למזג מכיל את המחרוזת התחתונה ואני צריך לבחור. עד פה אין חדש. אנחנו גם יודעים לסדר את הקונפליקט, לעשות git add ואז קומיט שוב וליצור Merge Commit. אבל מה קורה אם אחרי ה add התבלבלתם והרצתם:

$ git merge --abort

פקודת merge abort מבטלת את המיזוג ומוחקת את כל השינויים המקומיים כך שהעולם חוזר להיות כמו לפני המיזוג. אבל רגע - מה קרה לתיקונים שלי? מה קרה לקונפליקט שפתרתי? הקובץ שהיה בקונפליקט עכשיו חזר להיות כמו בענף c לפני המיזוג. האם המאמץ שלי בפתרון הקונפליקט ירד לטמיון? האם אפשר לשחזר את הקובץ או שחייבים לפתור את הקונפליקט שוב?

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

git fsck --cache --no-reflogs --lost-found --unreachable HEAD

ומקבל רשימה של שטויות שהלכו לאיבוד:

unreachable tree 606ee30389b8548213f2f11596605040a54fe4e0
unreachable tree 72c93914a344c812fcf5fa7216cfd1e464bd9cc3
unreachable tree f85d50eb6572db3613432d0608b5338120883acb
unreachable blob 5c7cfc2892118a24ebbc3f8511010899e6d09781
unreachable blob dd0221c310613ea89104ce0fede8f10bf6df626a
unreachable blob 1be3a6878600782668ffaf33ff9b8843078a06cd
unreachable commit fc295586d6e98fea615ebec979850bd13b8441c3

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

$ git cat-file blob dd0221c310613ea89104ce0fede8f10bf6df626a
**The Clockmaker’s friend**
**The Clockmaker’s bug**

הבלוב dd0221c מכיל בדיוק את הקובץ אחרי ה add ולפני שזרקתי הכל עם merge --abort. כדי לקבל חזרה את הקובץ אני מריץ:

git cat-file blob dd0221c3106 > a.txt

בלי ידיים (שני קסמים)

26/11/2025

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

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

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

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

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

  1. ההתקדמות היא לא לינארית. בהתחלה לוקח המון זמן להגיע להישגים קטנים ולא מורגשים.

  2. יש קפיצות, אבל הן לא לפי הזמנה.

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

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

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

לקחים שלמדתי על עלויות

25/11/2025

  1. לתקן קוד יותר זול מלשכתב מערכת.

  2. יותר זול לבחור שפת תכנות שאני מכיר מאשר שפת תכנות שאני רוצה ללמוד.

  3. יותר זול לבחור שפת תכנות שהרבה אנשים מכירים משפה שרק אני מכיר.

  4. מונוליט יותר זול ממיקרו סרביסס.

  5. שרת יותר זול מ Serverless.

  6. מוצר מדף בתשלום הרבה פעמים יותר זול מפתרון חינמי.

  7. המחיר לשעה של פרילאנסר לא אומר הרבה על איכות הקוד.

  8. פיתוח פתרון לבעיה שאני מכיר יותר זול מפיתוח פתרון גנרי.

  9. לעבוד נכון יותר זול מלעבוד מהר.

ומה שלכם?

אתה דווקא לא נראה כמו אחד שמשתמש ב AI

24/11/2025

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

זה יעבור.

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

Real Programmers

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

להשתמש ב AI כדי לחסוך זמן אומר שה AI יכתוב לי סקריפט שמשנה מרכאות כפולות לגרש בודד בקבצי YAML, מריץ אותו על ערימה של קבצים ואז מתקן את הסקריפט כי הוא פספס כמה מקרי קצה וממשיך באיטרציה עד שכל הקבצים נכונים. כן יכולתי לכתוב את הסקריפט הזה לבד אבל יש לי דברים יותר טובים לעשות בשעה הזאת. או למפות בכל הקודבייס איזה חלקים מפעילים פונקציה מסוימת ובאיזה תנאים היא תופעל (כי יש בדרך המון if-ים). זה גם יכול להיות לקבל הסבר על פונקציה מסוימת או צורת כתיבה מסוימת במקום ללכת לחפש בגוגל ולראות מהר חלופות שיתאימו לסטנדרטים של הקוד. כמובן לקבל תקציר של שינויים ב diff מסוים ואפילו לתרגם מ Options API ל Composition API ב vue.

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

כת הקוד הקדוש

23/11/2025

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

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

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

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

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

ואם זה נכשל?

22/11/2025

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

let (feature_values, _) = features
    .append_with_names(&self.config.feature_names)
    .unwrap();

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

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

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

if save_data(items):
    report_success()

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

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

נ.ב. זה הסיפור המלא של קלאודפלייר לסקרנים. הוא מרתק: https://blog.cloudflare.com/18-november-2025-outage/

הדברים שלא אמרתי בוובינר היום על Prompt Engineering

21/11/2025

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

אבל האמת שכל אלה הם לא הדברים החשובים.

הנדסת פרומפטים היא לא ספר מתכונים שאם רק תעקוב צעד צעד אחרי המדריך תקבל תוצאות יותר טובות, אלא היא תפיסת עולם ושיטת עבודה. תפיסת עולם שאומרת שפרומפט הוא חלק מהקוד, שאנחנו יכולים וצריכים להסתכל על הביצועים של ה Prompt שלנו בקונטקסט המלא של האפליקציה ושל הקלטים מהמשתמשים וכמו שיש לנו בדיקות אוטומטיות לקוד כך אנחנו צריכים ליצור Datasets ו Evals, שעובדים כמו בדיקות אוטומטיות לפרומפטים. ככל שהמודלים מתקדמים כך ה"טכניקות" מתחלפות במדע והאתגר הוא לא ליישם כללי אצבע גנריים אלא להבין איך להתאים את הפרומפט למערכת שלך. הנדסת פרומפטים היא החיבור בין היכרות עמוקה עם Problem Domain, יצירתיות והרבה סבלנות.

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

אפשר למצוא סיכום של הנקודות המרכזיות שדיברנו עליהן בוידאו סיכום כאן: https://youtu.be/TQPZZawYW34?si=EUZWzmlW-7NYh2Z2

שבוע הבא נדבר על Cursor וגם שם יש הרבה חידושים אז שווה לקפוץ להגיד שלום. לכניסה אפשר להירשם דרך העמוד הזה:

https://www.tocode.co.il/talking_ai

בואו נדבר עוד פעם על הודעות קומיט

20/11/2025

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

אלה התירוצים שאני שומע הכי הרבה מחברים וחברים לעבודה:

  1. ממילא אף אחד לא יקרא את זה.

  2. זה רק לבדיקה כדי שאוכל לדחוף את השינוי.

  3. תסתכל בשינויים בקוד למה צריך הסבר גם בהודעה.

והתשובות בקצרה:

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

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

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

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

יותר טוב מ ChatGPT - תרגיל שיפור קוד בפייתון

19/11/2025

נתון הקוד הבא:

import sys

def print_1(text):
    print(f"*{text}*")

def print_2(text):
    print(text)

def print_3(text):
    print(f"# {text}")

def handle(output_type, text):
    method_name = f"print_{output_type}"
    globals()[method_name](text)

if __name__ == "__main__":
    handle(*sys.argv[1:])

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

המשך קריאה

אילוצים

18/11/2025

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

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

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

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