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

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

הגדרת תלויות ב docker-compose עלולה להסתיר באג במערכת

14/02/2026

נתבונן בדוקר קומפוז הבא:

services:
  db:
    image: postgres:15
    container_name: my_postgres

  api:
    build: ./api
    container_name: my_api
    depends_on:
      - db

קלאסי נכון? שרת API שתלוי בבסיס נתונים והגדרת depends_on בדוקר קומפוז כדי לוודא שבסיס הנתונים עולה קודם.

אבל בעצם... למי אכפת מה עולה קודם?

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

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

איך לשמור שיחות ב LangGraph

13/02/2026

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

from langgraph.graph import StateGraph, MessagesState, START, END
from google.colab import userdata

from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import HumanMessage

# --- setup ---
api_key = userdata.get("GEMINI_API_KEY")

llm = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    temperature=1.0,
    google_api_key=api_key,
)

class GraphState(MessagesState):
    pass


# --- graph node ---
async def chat_node(state: GraphState):
    response = await llm.ainvoke(state["messages"])
    return {
        "messages": [response]
    }


# --- build graph ---
graph = StateGraph(GraphState)
graph.add_node("chat", chat_node)

graph.add_edge(START, "chat")
graph.add_edge("chat", END)

app = graph.compile()


# --- interactive loop (Colab-safe) ---
state: GraphState = {"messages": []}

try:
    while True:
        user_input = input("You: ").strip()

        state = await app.ainvoke(
            {"messages": [HumanMessage(content=user_input)]},
            state
        )

        print("AI:", state["messages"][-1].content)

except KeyboardInterrupt:
    print("\nExiting chat. Goodbye!")

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

המשך קריאה

השוואה בין Claude Code, Copilot CLI ו Cursor CLI

12/02/2026

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

המשך קריאה

מתי בכל זאת כדאי לכתוב קוד בלי סוכן קידוד

11/02/2026

זוכרים את כל אלה שמסבירים שאנחנו צריכים לתת לסוכן קידוד לכתוב 100% מהקוד או שאצלם סוכני קידוד כותבים 80% או 99% מהקוד? אז השאלה שהייתי רוצה לשאול אותם היא איזה קוד הם בכל זאת כותבים לבד בלי סוכן קידוד. מה זה האחוז הנותר או ה 20% הנותרים.

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

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

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

cleanStaleFiles()
cleanStaleFiles()

אולי הוא אפילו ייתן איזו הערה שמסבירה שהפונקציה מנקה עד 20 קבצים כל הפעלה ובעולם האמיתי היא מופעלת מ cron job ולכן זה לא בעיה אבל אנחנו פה בקוד של בדיקה ושם יכולים להיות גם 30 קבצים שצריכים ניקוי אז פעמיים מבטיחות לו שיימחקו עד 40 קבצים. ב Code Review של מאות שורות זה משהו שאני בקלות יכול לסלוח עליו.

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

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

טיפ: סוכני קידוד וקבצי הזכרון שלהם

10/02/2026

נתתם לקלוד לבנות פיצ'ר, המימוש לא היה משהו, מחקתם את מה שהוא כתב עם git restore . && git clean -f -d והמשכתם הלאה בחיים.

סוף סיפור? לא בדיוק.

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

הזכרון של קלוד קוד מוסבר בדף התיעוד הזה:

https://code.claude.com/docs/en/memory

הרבה פעמים שווה להגדיר CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 ולוותר על יצירת הזכרונות תוך כדי תנועה ובמקום זה להסתמך על קבצי הוראות.

הזכרונות עצמם נשמרים בתיקיית ~/.claude/projects//memory/. תיקייה אחת למעלה תוכלו למצוא את כל השיחות הקודמות שעשיתם עם קלוד. מדי פעם מומלץ:

  1. לכתוב /memory בתוך קלוד קוד, לבקש עריכה של קובץ הזכרון ולנקות אותו.

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

הבנה לעומת שימוש

08/02/2026

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

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

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

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

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

קוד ידידותי לבני אדם

07/02/2026

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

// Create workflow in account 1
$messageIds1 = $this->createSeriesMessages(2);
$template1 = $this->generateSeriesLogicJsonTemplate(2);
$result1 = $this->createSeriesAutomationWithMessages(
    $this->accountId,
    $this->listId,
    $template1,
    array_combine(range(0, count($messageIds1) - 1), $messageIds1)
);
$workflowId1 = $result1['workflowId'];

// Add subscribers to account 1
$subscriberIds1 = array_slice($this->subscriberIds, 0, 3);
$this->seedUserEnterList($this->listId, $subscriberIds1, $this->accountId);
$this->runAutomationHandler($this->accountId);

// Create second account
$this->secondAccount = $this->createSecondAccount(5);

// Create workflow in account 2
$messageIds2 = [];
for ($i = 0; $i < 2; $i++) {
    $messageIds2[] = $this->createMessageForAccount(
        $this->secondAccount['accountId'],
        $this->secondAccount['listId'],
        $this->secondAccount['senderId'],
        "Account2 Message " . ($i + 1),
        "Account2 Subject " . ($i + 1)
    );
}
// ... skip more code ...
$workflowId2 = $responseData2['createdId'];

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

המשך קריאה

מה זה אומר "יודע לתכנת"

05/02/2026

ראיתי את המשפט הזה באיזו פרסומת:

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

שלחתי אותו ל ChatGPT כדי שיסביר מה זה אומר וקיבלתי את סט המיומנויות הבא שלטענת ChatGPT משקף את המיומנויות הכי קריטיות למתכנתים:

  1. להבין מה הבעיה האמיתית (ולא מה שנכתב בטיקט)
  2. לפרק רעיון עמום ל-spec חד ובר־בדיקה
  3. לבחור פשרות נכונות: ביצועים מול פשטות, מהירות מול חוב טכני
  4. לזהות מתי הפתרון “נראה עובד” אבל מסוכן בקנה מידה (הוא התכוון לכתוב פה Scale, אני לא בטוח שהתרגום "קנה מידה" מדויק בהקשר הזה)
  5. ולחבר קוד למוצר, לביזנס, ולמשתמשים אמיתיים

אני חותם על כל מילה פה, רק שימו לב מה אין בה - אין בה MCP, אין Tools, אין Context Engineer, אין Prompt Enginnering, אין Agent Skills, אין בחירת מודלים ואפילו לא איך עובד מודל שפה גדול. מסתבר שבעולם ה"חדש" הדברים שאנחנו צריכים בשביל לשרוד הם אותם הדברים שהיינו צריכים בעולם הישן.

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

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