ToCode
1.43K subscribers
3.95K links
טיפים קצרים למתכנתים מאת ינון פרק
Download Telegram
📌 מה לוקח זמן בפיתוח עם AI

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

מנגנונים עודפים

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

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

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

מנגנונים חסרים

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

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

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

ארגון מחדש של החלטות עקומות של AI

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

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

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

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

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

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

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

סינון שטויות ש AI מסביר

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

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

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

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

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

אופטימיזציה לפרומפטים וקריאות AI

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

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

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

תחזוקה ושיפור עבודת הסוכן

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

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

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

נ.ב. שורה תחתונה חשובה מכל הרשימה כאן - כשאתם שומעים שמישהו פיתח אפליקציה מדהימה רק באמצעות AI ולא צריך מפתחים יותר, בקשו לראות את הקוד. בתוכנה יש מרחק גדול בין משהו שנראה עובד למוצר מוכן לפרודקשן.
👏2👍1
📌 מה למדתי מלקרוא את הקוד

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

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

כשהוא מתחיל להסביר לי על התיקון שהוא בנה שמפענח טוב יותר את ההודעות שחוזרות מהסוכן אני שואל "ולמה לא השתמשנו לפני כן ב Structured Output"?

כשהוא מדבר בשבחי מנגנון ה Cache שהוא הוסיף עכשיו כדי שהמידע יחזור מהשרת מהר יותר אני שואל "אבל למה השאילתה עד עכשיו לקחה כל כך הרבה זמן"?

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

כל תיקון כשלעצמו אולי הכי מדויק שיכול להיות - אבל במערכת טובה זו התמונה המלאה שקובעת.
📌 נקודות כשל (או: אולי כבר לא צריך ללמוד פייתון)

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

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

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

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

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

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

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

https://he.langlets.app/courses/president-franklin-d-roosevelt-declares-war-on-jap-lk8gygg0dke/lessons/peaceful-relations-and-deception?a=4

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

def word_order_phrases(phrases)
phrase_list = phrases.is_a?(ActiveRecord::Relation) ? phrases.to_a : phrases
phrase_list.select do |phrase|
words = phrase.text_l1.to_s.split(/\s+/).reject(&:empty?)
words.any? && words.size <= MAX_WORD_ORDER_WORDS
end
end


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

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

מצד אחד לא צריך לדעת לכתוב לולאות ב Ruby ולא צריך לזכור אם זה filter או select או reject ואם צריך לבדוק שמערך גדול מאפס או שיש פונקציה בשם any? שמחזירה את זה ואפילו לא יקרה כלום אם נדלג על ה to_a או התנאי בשורה הראשונה. אבל פיצול שורה למילים לפי רווחים כבר ישבור את ההגיון הפנימי של המערכת וזו החלטה לא נכונה. גם אם זה יעבוד היום זה מהר מאוד יישבר.
(ושלא תתחילו עם "פשוט תכניס את כל החוכמה הזאת ל AGENTS.md. הגיון של החלטות משתנה ויש כל הזמן החלטות חדשות. ברור שצריך להשתמש ב AGENTS.md אבל הוא לא מחליף את קריאת הקוד).

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

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

לדוגמה נתון קובץ טקסט עם השורות הבאות:

line1
line2
line3
line4
line.txt


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

$ grep line3 demo.txt


ונקבל את השורה.

בשביל לבדוק אם קיימת בו השורה line.txt מפתה לכתוב גם:

$ grep line.txt demo.txt


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

line-txt
line_txt
line2txt


אותה פקודת grep תחזיר את כל השורות:

grep line.txt demo.txt
line.txt
line-txt
line_txt
line2txt


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

$ fgrep line.txt demo.txt
line.txt


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

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

2+4
2229


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

$ grep '2+' demo.txt
2+4


אבל זו רק הטעיה כי אם מוסיפים לה \ לפני הפלוס היא חוזרת להתיחס אליו כמו תו של ביטויים רגולאריים:

$ grep '2\+' demo.txt
2+4
2229
👍2
📌 בואו נערבב merge ו rebase כדי לשבור את גיט

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

עכשיו בואו נשבור את זה.

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

* 45cfa5d (main) main: 3 commits ahead
* 51c18b4 main: 2 commits ahead
* dfad935 main: 1 commit ahead
| * fa37287 (HEAD -> merge-feature1) Merge feature1 into old main (RESOLVED CONFLICT)
|/|
| * 2392145 (feature1) feature1: add HTML report part 2
| * 6b24764 feature1: add HTML report part 1
* | 9961b60 main: added some changes
|/
* d4d0727 fixed stuff
* 9155d8f initial commit


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

(merge-feature1) $ git rebase main
Auto-merging main.py
CONFLICT (content): Merge conflict in main.py
error: could not apply 6b24764... feature1: add HTML report part 1
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Recorded preimage for 'main.py'
Could not apply 6b24764... # feature1: add HTML report part 1


קיבלתי קונפליקט על קומיט 6b24764, כלומר קונפליקט שכבר פתרתי ב Merge Commit. היה לי רעיון טוב להקדים תרופה למכה ולמזג את השינויים מ main לפני שאני מסיים לעבוד על הבראנץ' אבל בסוף זו היתה עבודה מיותרת כי ריבייס מתעלם מהקונפליקטים שפתרתי.

מה עושים? קודם כל כדאי לזכור שקשה להזיז merge commit ולכן עדיף לחשוב לפני שאתם מתחילים merge איפה אתם רוצים שה merge commit שלכם ישב. אם בכל זאת תבקשו מאיזה קלוד להתעקש הוא ימזג חזרה את main העדכני לתוך merge-feature1, ימחק את main ואז יבנה קומיט חדש עם git write-tree שיש לו רגל אחת על אותו ענף צד ורגל שניה איפה שהיה פעם main.
👍2
📌 גם אתם צריכים מדיניות LLM

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

אלה הדברים המרכזיים שמדיניות LLM צריכה להגדיר:

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

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

Showing LLM output to another human without solicitation is likely banned


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

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

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

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

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

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

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

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

גיוס ו AI

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

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

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

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

הפרמטר החשוב

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

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

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

השאלה היא לא כמות המשימות

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

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

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

תפקיד הג'וניורים

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

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

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

פיטורים בהייטק

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

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

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

יהיו פיטורים. יהיו חברות שייסגרו. יהיו אנשים שיחליטו לצאת לגמרי מהתעשייה ויהיו את אלה שיפרחו וחדשים שייכנסו. אני לא יודע מה יהיה העתיד ובטח לא מה יהיה העתיד האישי שלי או של מי מכם, אבל בהערכה אחת אני די בטוח - יותר קוד גורם ליותר בעיות ודורש יותר מתכנתים. מהאמת הזו אי אפשר לברוח.
3👍2
📌 כזה ניסיתי: Vercel Agent Browser

תמיד חלמתם לראות את Chrome Devtools MCP בגרסת ה CLI? אם כן ורסל התנדבו לסגור את הפער ופיתחו כלי שליטה בדפדפן משורת הפקודה בקוד פתוח, זהו Vercel Agent Browser. מתקינים כאן:

https://agent-browser.dev

למה

כלי שורת פקודה מספקים שני יתרונות על MCP:

1. חסכון בטוקנים כי אני לא צריך לשלוח לסוכן את רשימת הכלים בכל בקשה או להתקין אותם בסוכן הקידוד. מספיק להתקין את הסקיל ולשכוח מזה, או אפילו לצרף לפרומפט איזה "use agent browser CLI"
2. חסכון בטוקנים אם הסוכן יצירתי כי אז הוא יכול לשלב מספר פעולות לתוך סקריפט שורת פקודה, למשל במקום לחפש אלמנט על העמוד באמצעות קבלת snapshot של כל האלמנטים וחיפוש בה הסוכן יוכל להעביר את הפלט של ה snapshot ל grep וכך כל הטוקנים של העמוד אפילו לא נכנסים לחלון הקונטקסט.

במקרה של agent browser אנחנו מקבלים עוד מספר יתרונות:

1. מחשבה על הסוכן ולא על הדפדפן - היכולות ששולבו ב agent browser הן תוצאה של מחשבה על תהליך העבודה של פיתוח באמצעות סוכן ולא בהכרח של הכפתורים בכלי הפיתוח בדפדפן. כך יש כלי diff שמראה את ההבדל בין שני snapshots של העמוד, או אפשרות לקבל snapshot רק של האלמנטים האינטרקטיביים בעמוד, או קבלת הפלט.
2. אפשרות חיבור לדפדפנים אחרים לדוגמה יש להם חיבור לסימולטור של ios או מנוע בשם lightpanda
3. חיבור מובנה למקור הדף כך ש agent-browser יכול להציג לסוכן את מקור הקומפוננטות על העמוד וכך הרבה יותר קל לנהל פיתוח ריאקט ולראות את התוצאה.

איך

הכי קל בעולם - מתקינים מהאתר שלהם עם:

npm install -g agent-browser


דוגמה

אחרי התקנה אני מפעיל:

ynonp@ynons-MacBook-Air ~/tmp $ agent-browser open  http://localhost:5173

✓ frontend
http://localhost:5173/
ynonp@ynons-MacBook-Air ~/tmp $ agent-browser snapshot
- generic [ref=e1] clickable [onclick]
- generic
- generic
- image "React logo"
- image "Vite logo"
- heading "Get started" [level=1, ref=e2]
- paragraph
- StaticText "Edit "
- code
- StaticText "src/App.tsx"
- StaticText " and save to test "
- code
- StaticText "HMR"
- button "Count is 0" [ref=e3]
- StaticText "Count is 0"
- generic
- generic
- heading "Documentation" [level=2, ref=e4]
- paragraph
- StaticText "Your questions, answered"
- list
- listitem [level=1]
- link "Explore Vite" [ref=e6]
- StaticText "Explore Vite"
- listitem [level=1]
- link "Learn more" [ref=e7]
- StaticText "Learn more"
- generic
- heading "Connect with us" [level=2, ref=e5]
- paragraph
- StaticText "Join the Vite community"
- list
- listitem [level=1]
- link "GitHub" [ref=e8]
- StaticText "GitHub"
- listitem [level=1]
- link "Discord" [ref=e9]
- StaticText "Discord"
- listitem [level=1]
- link "X.com" [ref=e10]
- StaticText "X.com"
- listitem [level=1]
- link "Bluesky" [ref=e11]
- StaticText "Bluesky"


אפשר גם להפעיל:

agent-browser dashboard start


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

שורה תחתונה

סך הכל אהבתי את הכלי הוא עובד מהר ונראה שהושקעה מחשבה ביצירת Workflows יעילים לסוכנים. בינתיים אני לא עובד איתו מספיק זמן בשביל להגיד אם התוצאה טובה יותר או פחות מ Devtools MCP אבל חייב להודות שאני אוהב את המעבר שהתעשייה עושה מכלי MCP לכלי CLI - זה גם כיף לסוכנים וגם כיף למשתמשים שיכולים בקלות להפעיל משורת הפקודה את אותן פקודות שהסוכן מפעיל ולראות את התוצאות.
1
📌 היום למדתי: מספרים גדולים ב JavaScript

ל JavaScript יש טיפוס נתונים שנקרא number לייצוג מספרים:

> typeof(12)
'number'


משתנה מסוג number הוא בגודל 64 ביט אבל JavaScript עצמה לא משתמשת בכל 64 הביטים כדי לייצג מספרים שלמים. הערכים שמותר לייצג כמספרים הם הטווח:

> Number.MIN_SAFE_INTEGER
-9007199254740991
> Number.MAX_SAFE_INTEGER
9007199254740991


ל JavaScript יש גם טיפוס נתונים בשם bigint שיודע לייצג מספרים הרבה יותר גדולים ואנחנו יוצרים ערך מסוג bigint בעזרת הסיומת n בסוף מספר:

> typeof(12n)
'bigint'


הגודל של bigint מוגבל רק בכמות הזכרון שיש לכם על המחשב. מה קורה כשיוצאים מחוץ לטווח הבטוח? שימו לב:

> Number.MAX_SAFE_INTEGER + 1
9007199254740992
> Number.MAX_SAFE_INTEGER + 2
9007199254740992
> Number.MAX_SAFE_INTEGER + 3
9007199254740994
> Number.MAX_SAFE_INTEGER + 4
9007199254740996

> 9007199254740992 == 9007199254740993
true


נו זה היה כיף. במספרים גדולים זה כמובן לא היה קורה:

> 9007199254740992n == 9007199254740993n
false


אז למה לא להשתמש ב bigint כל הזמן? בגלל JSON כמובן:

> JSON.stringify(9007199254740992)
'9007199254740992'
> JSON.stringify(9007199254740992n)
Uncaught TypeError: Do not know how to serialize a BigInt
at JSON.stringify (<anonymous>)


בשביל ש JavaScript יהפוך מספר גדול ל JSON הוא יצטרך לכתוב ערך שאף אחד לא יוכל לקרוא. מה עושים? הופכים למחרוזת וזוכרים להמיר ל BigInt בחזרה:

BigInt(JSON.parse(JSON.stringify(90071992547409932n.toString())))
90071992547409932n


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