השאלה היא לא כמה אחוז מהקוד ה AI כותב
כשרוצים להטמיע AI בארגון פיתוח מנהלים היו מנסים למדוד כמה אחוז מהקוד נכתב על ידי AI. אבל זאת מטריקה גרועה.
אם AI כותב 100% מהקוד והתוצאה היא בעיות אבטחה, ביצועים גרועים, פיצ'רים שאי אפשר לממש ובאגים שלא משתחזרים או אז לא עשינו כלום. גם אם AI כותב 100% מהקוד וקיבלנו מערכת שאף בן אנוש לא יצליח לתחזק אחרי לא עשינו כלום.
הנה כמה מטריקות טובות יותר לשילוב AI במהלך הפיתוח:
1. כמה אחוז מהקוד נכנס למערכת בלי שאף אחד קרא אותו?
2. כמה אחוז מהקוד ש AI כותב הרגשנו בנוח לזרוק לפח?
3. מה אנחנו עושים היום טוב יותר או אחרת ממה שעשינו בעבר בזכות ה AI?
4. כמה גרסאות שונות אני בודק לכל פיצ'ר לפני שאני מתקדם?
5. כמה תהליכי עבודה מבוססי AI חדשים בנינו בארגון?
דוגמה? בטח. לקוח או פרודקט מבקש לקבל דוח חדש ממערכת CRM. מפתחים שעובדים עם AI בצורה חכמה עוד באותו יום יכולים להוציא 3 גרסאות של הדוח הזה כדי שהלקוח יבחר. בזמן שהלקוח מתלבט הם קוראים את שלושת הגרסאות שה AI כתב כדי להבין מה מקרי הקצה, מה האתגרים, מה החלקים שצריכים להתחבר. כשהלקוח בוחר את העיצוב המפתחים יוצרים פרומפט חדש שמשלב את מה שהם למדו משלושת הגרסאות ומוסיף בדיקות אוטומטיות. כשה AI כותב את הקוד החדש אנחנו כבר יודעים למה לצפות, יכולים לקרוא כל שורה ולהבין שאנחנו לא מכניסים שטויות למערכת.
אם ה AI כתב 100% או 80% מהקוד זה לא הדבר החשוב, מה שחשוב זה איך אנחנו עובדים היום ואיך תהליך העבודה השתפר בזכות שימוש בכלי AI.
כשרוצים להטמיע AI בארגון פיתוח מנהלים היו מנסים למדוד כמה אחוז מהקוד נכתב על ידי AI. אבל זאת מטריקה גרועה.
אם AI כותב 100% מהקוד והתוצאה היא בעיות אבטחה, ביצועים גרועים, פיצ'רים שאי אפשר לממש ובאגים שלא משתחזרים או אז לא עשינו כלום. גם אם AI כותב 100% מהקוד וקיבלנו מערכת שאף בן אנוש לא יצליח לתחזק אחרי לא עשינו כלום.
הנה כמה מטריקות טובות יותר לשילוב AI במהלך הפיתוח:
1. כמה אחוז מהקוד נכנס למערכת בלי שאף אחד קרא אותו?
2. כמה אחוז מהקוד ש AI כותב הרגשנו בנוח לזרוק לפח?
3. מה אנחנו עושים היום טוב יותר או אחרת ממה שעשינו בעבר בזכות ה AI?
4. כמה גרסאות שונות אני בודק לכל פיצ'ר לפני שאני מתקדם?
5. כמה תהליכי עבודה מבוססי AI חדשים בנינו בארגון?
דוגמה? בטח. לקוח או פרודקט מבקש לקבל דוח חדש ממערכת CRM. מפתחים שעובדים עם AI בצורה חכמה עוד באותו יום יכולים להוציא 3 גרסאות של הדוח הזה כדי שהלקוח יבחר. בזמן שהלקוח מתלבט הם קוראים את שלושת הגרסאות שה AI כתב כדי להבין מה מקרי הקצה, מה האתגרים, מה החלקים שצריכים להתחבר. כשהלקוח בוחר את העיצוב המפתחים יוצרים פרומפט חדש שמשלב את מה שהם למדו משלושת הגרסאות ומוסיף בדיקות אוטומטיות. כשה AI כותב את הקוד החדש אנחנו כבר יודעים למה לצפות, יכולים לקרוא כל שורה ולהבין שאנחנו לא מכניסים שטויות למערכת.
אם ה AI כתב 100% או 80% מהקוד זה לא הדבר החשוב, מה שחשוב זה איך אנחנו עובדים היום ואיך תהליך העבודה השתפר בזכות שימוש בכלי AI.
👍1
מתנות חינם
בשביל Rails, Laravel ו Django החיים די קלים. כולם יודעים מה יש באפליקציית ווב מונוליטית, כולם לוקחים פיצ'רים אחד מהשני וההבדלים ביניהם הם יותר של סגנון כתיבת ותפיסת עולם מאשר של פיצ'רים. בסוף אפילו Django הוסיפו רכיב להרצת משימות ברקע. חלק גדול מהיציבות של ספריות אלה הוא תוצאה של יציבות הפלטפורמה - ריילס יודע מה מערכת ההפעלה נותנת ויכול להתקדם עם זה.
בעולם של ספריות לפיתוח סוכנים חכמים המשחק שונה לגמרי: הממשק מול המודל מתפתח כל הזמן, אגרגטורים כמו Bedrock, Open Router ו Copilot Models עוטפים את ה API הבסיסי ויכולים לספק פונקציונאליות נוספת או כפולה, סביבות להרצת סוכנים כמו Vertex AI Engine או Agent Core מספקות עוד יכולות וכל אלה משתנים כל הזמן. כך יש לנו היום כלים מובנים בתוך ה API של OpenAI, כלים מובנים ב AgentCore, שער של אייג'נט קור להרצת כלים או חיבור שרתי MCP וספריית פיתוח סוכנים שבעצמה מתחברת לשרתי MCP.
גם בצד השני ציפיות המשתמשים מספריות לפיתוח סוכנים חכמים משתנות חדשות לבקרים וכל פיצ'ר חדש באחת הספריות יוצר ציפיות חדשות מכל האחרות והכל צריך לעבוד אתמול.
ומתוך הבנה של תנאי העבודה השונים כדאי לאמץ גישה שונה למתנות שאנחנו מקבלים מכל עולם:
1. כשהעולם יציב, כשברור מה צריך לבנות ומה היכולות יהיה לנו חשוב להשקיע ולהבין את כל המנגנונים והיכולות של הפריימוורק. לכל מנגנון בריילס יש סיבה, מישהו היה צריך את זה.
2. כשהעולם כמרקחה המנגנונים המובנים בכל ספריה יכולים להכנס לשם כי באמת מישהו היה צריך אותם, אבל גם כי אנחנו בדיוק בוחנים רעיון או כי מישהו הציע משהו או כי פריימוורק אחר הכניס את זה ואי אפשר להישאר מאחור.
בתקופה שיכולות חדשות נכנסו לדפדפנים חדשות לבקרים היה קשה מאוד ללמוד JavaScript Frameworks. כל פריימוורק הגיע עם יכולות שונות, אילוצים שונים, הבטחות שונות ומתנות שונות ואפשר היה לבלות שעות ללמוד אבסטרקציות שאחרי חודש כבר לא היו רלוונטיות בגלל יכולת חדשה שנכנסה לדפדפן. רק כשדפדפנים הפסיקו לרוץ גם הפריימוורקים יכלו למצוא שלווה. אני חושד שבעתיד נראה תופעה דומה גם לספריות פיתוח הסוכנים. בינתיים כדאי לקחת אוויר כי השנים הבאות יהיו מטלטלות.
בשביל Rails, Laravel ו Django החיים די קלים. כולם יודעים מה יש באפליקציית ווב מונוליטית, כולם לוקחים פיצ'רים אחד מהשני וההבדלים ביניהם הם יותר של סגנון כתיבת ותפיסת עולם מאשר של פיצ'רים. בסוף אפילו Django הוסיפו רכיב להרצת משימות ברקע. חלק גדול מהיציבות של ספריות אלה הוא תוצאה של יציבות הפלטפורמה - ריילס יודע מה מערכת ההפעלה נותנת ויכול להתקדם עם זה.
בעולם של ספריות לפיתוח סוכנים חכמים המשחק שונה לגמרי: הממשק מול המודל מתפתח כל הזמן, אגרגטורים כמו Bedrock, Open Router ו Copilot Models עוטפים את ה API הבסיסי ויכולים לספק פונקציונאליות נוספת או כפולה, סביבות להרצת סוכנים כמו Vertex AI Engine או Agent Core מספקות עוד יכולות וכל אלה משתנים כל הזמן. כך יש לנו היום כלים מובנים בתוך ה API של OpenAI, כלים מובנים ב AgentCore, שער של אייג'נט קור להרצת כלים או חיבור שרתי MCP וספריית פיתוח סוכנים שבעצמה מתחברת לשרתי MCP.
גם בצד השני ציפיות המשתמשים מספריות לפיתוח סוכנים חכמים משתנות חדשות לבקרים וכל פיצ'ר חדש באחת הספריות יוצר ציפיות חדשות מכל האחרות והכל צריך לעבוד אתמול.
ומתוך הבנה של תנאי העבודה השונים כדאי לאמץ גישה שונה למתנות שאנחנו מקבלים מכל עולם:
1. כשהעולם יציב, כשברור מה צריך לבנות ומה היכולות יהיה לנו חשוב להשקיע ולהבין את כל המנגנונים והיכולות של הפריימוורק. לכל מנגנון בריילס יש סיבה, מישהו היה צריך את זה.
2. כשהעולם כמרקחה המנגנונים המובנים בכל ספריה יכולים להכנס לשם כי באמת מישהו היה צריך אותם, אבל גם כי אנחנו בדיוק בוחנים רעיון או כי מישהו הציע משהו או כי פריימוורק אחר הכניס את זה ואי אפשר להישאר מאחור.
בתקופה שיכולות חדשות נכנסו לדפדפנים חדשות לבקרים היה קשה מאוד ללמוד JavaScript Frameworks. כל פריימוורק הגיע עם יכולות שונות, אילוצים שונים, הבטחות שונות ומתנות שונות ואפשר היה לבלות שעות ללמוד אבסטרקציות שאחרי חודש כבר לא היו רלוונטיות בגלל יכולת חדשה שנכנסה לדפדפן. רק כשדפדפנים הפסיקו לרוץ גם הפריימוורקים יכלו למצוא שלווה. אני חושד שבעתיד נראה תופעה דומה גם לספריות פיתוח הסוכנים. בינתיים כדאי לקחת אוויר כי השנים הבאות יהיו מטלטלות.
אני מבין מה עשית שם
תנאי מקדים לקריאת קוד ול Code Review אפקטיבי הוא בסך הכל המשפט "אני מבין מה עשית שם". רוב הזמן בקריאת קוד של AI אני צריך לעבוד בשביל להגיע למצב הזה.
הנה רובי:
הפונקציה פותחת חיבור ל Rabbitmq ומחזירה את החיבור שנפתח. נתעלם רגע מהשאלה אם צריך פונקציה בשביל זה (אני חושב שלא), אבל השאלה היותר חשובה היא מה ה tap עושה שם? הנה הקוד בצורה הכי מפורשת שלו:
עכשיו זה יותר ברור, קלוד רצה להפעיל start וגם להחזיר את אוביקט ה connection והכל בשורה אחת. הוא הסתבך בגלל שאם היה כותב:
אז הפונקציה היתה מחזירה את מה ש start מחזירה ואולי זה משהו אחר ממה ש new מחזירה. פה המקום לשים לב לנטיה של AI לעבוד בתבניות - קלוד לא בדק מה start מחזירה. אם הוא היה בודק הוא היה רואה שהיא מחזירה בדיוק את אוביקט החיבור כי מי שכתב את Bunny כבר חשב על מנגנון הקריאה הזה. כלומר ה tap מיותר לגמרי שם.
אני מבין מה ניסית לעשות שם, אבל זו טעות. עכשיו אפשר לתקן.
תנאי מקדים לקריאת קוד ול Code Review אפקטיבי הוא בסך הכל המשפט "אני מבין מה עשית שם". רוב הזמן בקריאת קוד של AI אני צריך לעבוד בשביל להגיע למצב הזה.
הנה רובי:
def create_connection
Bunny.new(@connection_config[:url]).tap(&:start)
end
הפונקציה פותחת חיבור ל Rabbitmq ומחזירה את החיבור שנפתח. נתעלם רגע מהשאלה אם צריך פונקציה בשביל זה (אני חושב שלא), אבל השאלה היותר חשובה היא מה ה tap עושה שם? הנה הקוד בצורה הכי מפורשת שלו:
def create_connection
conn = Bunny.new(@connection_config[:url])
conn.start
return conn
end
עכשיו זה יותר ברור, קלוד רצה להפעיל start וגם להחזיר את אוביקט ה connection והכל בשורה אחת. הוא הסתבך בגלל שאם היה כותב:
def create_connection
Bunny.new(@connection_config[:url]).start
end
אז הפונקציה היתה מחזירה את מה ש start מחזירה ואולי זה משהו אחר ממה ש new מחזירה. פה המקום לשים לב לנטיה של AI לעבוד בתבניות - קלוד לא בדק מה start מחזירה. אם הוא היה בודק הוא היה רואה שהיא מחזירה בדיוק את אוביקט החיבור כי מי שכתב את Bunny כבר חשב על מנגנון הקריאה הזה. כלומר ה tap מיותר לגמרי שם.
אני מבין מה ניסית לעשות שם, אבל זו טעות. עכשיו אפשר לתקן.
👍1
עולם ללא קוד
כבר היום אני לא בטוח שכדאי לאנשים ללמוד את החשיבות של HTML סמנטי, את ההבדלים בין section ל article ומתי להשתמש ב nav במקום ב div. אם זה חשוב אנחנו מצפים ש AI ישתמש בזה כשנבקש ממנו לכתוב HTML.
כבר היום אני לא בטוח שכדאי לאנשים ללמוד לכתוב Shell Scripts. ממילא כמעט לא נכתבו Shell Scripts ארוכים ואת כל הקצרים ה AI יכול לכתוב, לקרוא ולתחזק טוב יותר מרוב האנשים שכתבו סקריפטים בעבר.
מה לגבי node.js ואקספרס? או ראסט? או Java?
מה שמיוחד ב HTML-ים וב Shell Scripts הוא שהממשק שלהם פשוט. אפשר להוסיף עוד מהם בלי להכיר את הקיימים. קובץ HTML גרוע יכול לשבור רק את עצמו. סקריפט גרוע ישבור רק את עצמו.
הנה מה שכתב rupayanc ברדיט בנוגע ל PR-ים שהוא מקבל על פרויקטי קוד פתוח שלו:
> The other half compile but introduce subtle bugs because the model doesn't understand the actual design constraints of the project.
מילת המפתח היא understand. סוכני קידוד לא מבינים אלא משלימים תבניות ולכן בפרויקטים גדולים יש פערים. אני רואה פה שתי דרכים קדימה בשביל להיפטר מהקוד:
1. אפשר לבנות עולם בו יותר דברים מתנהגים כמו קבצי HTML. מיקרו סרביסס זו ארכיטקטורה שמתארת כזה נסיון - הסוכנים בונים המון דברים קטנים ומחברים אותם.
2. אפשר לחבר סוכני קידוד ל"צוות AI", לשפר פרומפטים, לעודד אותם שיעדכנו את הפרומפטים של עצמם ולבנות צבא של סוכנים שמסוגל לדמות למידה ולחלק לעצמו את המשימות לחלקים קטנים שהוא יכול לפתור.
שני המקרים משפיעים מאוד על מה אנחנו רוצים ללמוד כמהנדסי תוכנה וסט המיומנויות שנצטרך לעתיד וגם חושפים אמת שקשה להתעלם ממנה: עולם בלי קוד דורש עולם של קוד שיפעיל אותו. מישהו צריך לבנות את הצבא של הסוכנים ואת מנגנוני שיתוף הפעולה ביניהם, או את כללי העבודה באקוסיסטם בתוכה הסוכנים יתפקדו.
כשהקוד הופך זול מאוד אין צורך להבין תחביר. לא צריך לדעת לקרוא מבנה של List Comprehension בפייתון או מה ההבדל בין פונקציה אנונימית לפונקציית חץ ב JavaScript.
כבר היום אני לא בטוח שכדאי לאנשים ללמוד את החשיבות של HTML סמנטי, את ההבדלים בין section ל article ומתי להשתמש ב nav במקום ב div. אם זה חשוב אנחנו מצפים ש AI ישתמש בזה כשנבקש ממנו לכתוב HTML.
כבר היום אני לא בטוח שכדאי לאנשים ללמוד לכתוב Shell Scripts. ממילא כמעט לא נכתבו Shell Scripts ארוכים ואת כל הקצרים ה AI יכול לכתוב, לקרוא ולתחזק טוב יותר מרוב האנשים שכתבו סקריפטים בעבר.
מה לגבי node.js ואקספרס? או ראסט? או Java?
מה שמיוחד ב HTML-ים וב Shell Scripts הוא שהממשק שלהם פשוט. אפשר להוסיף עוד מהם בלי להכיר את הקיימים. קובץ HTML גרוע יכול לשבור רק את עצמו. סקריפט גרוע ישבור רק את עצמו.
הנה מה שכתב rupayanc ברדיט בנוגע ל PR-ים שהוא מקבל על פרויקטי קוד פתוח שלו:
> The other half compile but introduce subtle bugs because the model doesn't understand the actual design constraints of the project.
מילת המפתח היא understand. סוכני קידוד לא מבינים אלא משלימים תבניות ולכן בפרויקטים גדולים יש פערים. אני רואה פה שתי דרכים קדימה בשביל להיפטר מהקוד:
1. אפשר לבנות עולם בו יותר דברים מתנהגים כמו קבצי HTML. מיקרו סרביסס זו ארכיטקטורה שמתארת כזה נסיון - הסוכנים בונים המון דברים קטנים ומחברים אותם.
2. אפשר לחבר סוכני קידוד ל"צוות AI", לשפר פרומפטים, לעודד אותם שיעדכנו את הפרומפטים של עצמם ולבנות צבא של סוכנים שמסוגל לדמות למידה ולחלק לעצמו את המשימות לחלקים קטנים שהוא יכול לפתור.
שני המקרים משפיעים מאוד על מה אנחנו רוצים ללמוד כמהנדסי תוכנה וסט המיומנויות שנצטרך לעתיד וגם חושפים אמת שקשה להתעלם ממנה: עולם בלי קוד דורש עולם של קוד שיפעיל אותו. מישהו צריך לבנות את הצבא של הסוכנים ואת מנגנוני שיתוף הפעולה ביניהם, או את כללי העבודה באקוסיסטם בתוכה הסוכנים יתפקדו.
כשהקוד הופך זול מאוד אין צורך להבין תחביר. לא צריך לדעת לקרוא מבנה של List Comprehension בפייתון או מה ההבדל בין פונקציה אנונימית לפונקציית חץ ב JavaScript.
❤1
כזה ניסיתי: Opencode ומודלי קוד פתוח מ Ollama
המודלים הפתוחים מתקדמים כל הזמן ויחד איתם גם סוכני הקידוד שיודעים להפעיל אותם. סוכני הקידוד המרכזיים שעובדים עם מודלים חופשיים הם:
1. Droid
2. Opencode
3. Kilocode
4. Aider
5. Cline
6. Roo Code
7. Claude Code
לכבוד הפוסט היום רציתי לנסות לכתוב משחק סנייק עם מודל קוד פתוח ולראות מה מצבם ואם הם מצליחים לעמוד במשימה. התוצאה הפתיעה אותי לטובה ומאז הניסוי עברתי לעבוד עם מודל פתוח גם בפרויקטים אמיתיים עם תוצאות מעולות. אבל תחילה פרטי הניסוי.
בואו נבנה משחק סנייק
התקנתי opencode ו ollama, נרשמתי לשירות הפרמיום של ollama שמאפשר להריץ שאילתות מול המודלים הפתוחים בענן שלהם (עשרים דולר בחודש. המחשב שלי לא מספיק טוב בשביל להריץ מודלים), והפעלתי את אופןקוד עם תיקיית בסיס של פרויקט next.js ריק והדבקתי את הפרומפט הבא:
בשביל להפעיל אופןקוד עם מודל קוד פתוח דרך ollama כותבים משורת הפקודה:
את הניסוי הרצתי עם שלושה מודלים:
1. kimi-k2.5
2. minimax-m2.5
3. glm-5
התוצאות בגיטהאב בקישורים:
https://github.com/ynonp/math-snake-foss-models/tree/opencode-glm5
https://github.com/ynonp/math-snake-foss-models/tree/opencode-kimi
https://github.com/ynonp/math-snake-foss-models/tree/opencode-minimax
איך זה עבד
שלושת המודלים הצליחו ליצור את המשחק. קימי הצליח בנסיון הראשון ו glm ו minimax היו צריכים פרומפט המשך כי הגרסה הראשונה שלהם היתה עם שגיאה.
שלושת המודלים יצרו גם משחק וגם בדיקות. בכולם הבדיקות בדקו את הלוגיקה של המשחק בלי לבדוק UI. כל השלושה ניסו להפריד בין פונקציות הלוגיקה לקוד הממשק כדי שיוכלו לבדוק את הלוגיקה.
שלושת המודלים סיימו תוך דקות והגבלת הטוקנים של ollama מאוד נדיבה כך שנראה שגם אם הייתי מריץ סוכן קידוד מסביב לשעון לא היו נגמרות לי הבקשות.
מבחינת התוצאות הכי אהבתי את הקוד של minimax. הקוד פשוט, הנחש מצויר עם CSS Grid, אין כמעט שימוש ביכולות של ריאקט (אין hooks, יש שני אפקטים עבור לולאת המשחק וטיפול בקלט). והקוד מאוד קריא. לדוגמה זו לולאת המשחק:
שזה מעולה כיוון שכל הלוגיקה בפונקציית tick היא חיצונית לריאקט ואפשר בקלות לבדוק אותה.
קימי יצר תוכנית מצוינת אבל לקח כיוון מסורבל בקוד. במקום להשתמש ב div-ים הוא יצר canvas. זה לא סוף העולם אבל זה אומר שהבדיקות שלו הרבה פחות טובות כיוון שיש המון לוגיקה שקשורה לציור אותה הוא לא בדק. מבחינת ההבדלים בינו לבין minimax אז הנה דוגמה קטנה הקוד של קימי שבדק אם תשובה לתרגיל חשבון היא נכונה הוא:
המודלים הפתוחים מתקדמים כל הזמן ויחד איתם גם סוכני הקידוד שיודעים להפעיל אותם. סוכני הקידוד המרכזיים שעובדים עם מודלים חופשיים הם:
1. Droid
2. Opencode
3. Kilocode
4. Aider
5. Cline
6. Roo Code
7. Claude Code
לכבוד הפוסט היום רציתי לנסות לכתוב משחק סנייק עם מודל קוד פתוח ולראות מה מצבם ואם הם מצליחים לעמוד במשימה. התוצאה הפתיעה אותי לטובה ומאז הניסוי עברתי לעבוד עם מודל פתוח גם בפרויקטים אמיתיים עם תוצאות מעולות. אבל תחילה פרטי הניסוי.
בואו נבנה משחק סנייק
התקנתי opencode ו ollama, נרשמתי לשירות הפרמיום של ollama שמאפשר להריץ שאילתות מול המודלים הפתוחים בענן שלהם (עשרים דולר בחודש. המחשב שלי לא מספיק טוב בשביל להריץ מודלים), והפעלתי את אופןקוד עם תיקיית בסיס של פרויקט next.js ריק והדבקתי את הפרומפט הבא:
Let's scaffold a math snake game
It's a regular snake game but whenever you eat an apple show a math exercise about multiplication table (multiply 2 numbers, user types
the result)
Create the project in next.js fullstack app with server components using multiple files and industry best practices
dev server is already running on http://localhost:3001/ with hot reloading so you can just change the code and check the result in the
browser
Plan the game, its UI and its tests and then let's code
בשביל להפעיל אופןקוד עם מודל קוד פתוח דרך ollama כותבים משורת הפקודה:
ollama launch opencode --model <model-name>
את הניסוי הרצתי עם שלושה מודלים:
1. kimi-k2.5
2. minimax-m2.5
3. glm-5
התוצאות בגיטהאב בקישורים:
https://github.com/ynonp/math-snake-foss-models/tree/opencode-glm5
https://github.com/ynonp/math-snake-foss-models/tree/opencode-kimi
https://github.com/ynonp/math-snake-foss-models/tree/opencode-minimax
איך זה עבד
שלושת המודלים הצליחו ליצור את המשחק. קימי הצליח בנסיון הראשון ו glm ו minimax היו צריכים פרומפט המשך כי הגרסה הראשונה שלהם היתה עם שגיאה.
שלושת המודלים יצרו גם משחק וגם בדיקות. בכולם הבדיקות בדקו את הלוגיקה של המשחק בלי לבדוק UI. כל השלושה ניסו להפריד בין פונקציות הלוגיקה לקוד הממשק כדי שיוכלו לבדוק את הלוגיקה.
שלושת המודלים סיימו תוך דקות והגבלת הטוקנים של ollama מאוד נדיבה כך שנראה שגם אם הייתי מריץ סוכן קידוד מסביב לשעון לא היו נגמרות לי הבקשות.
מבחינת התוצאות הכי אהבתי את הקוד של minimax. הקוד פשוט, הנחש מצויר עם CSS Grid, אין כמעט שימוש ביכולות של ריאקט (אין hooks, יש שני אפקטים עבור לולאת המשחק וטיפול בקלט). והקוד מאוד קריא. לדוגמה זו לולאת המשחק:
const handleTick = useCallback(() => {
setGameState(prev => tick(prev));
}, []);
שזה מעולה כיוון שכל הלוגיקה בפונקציית tick היא חיצונית לריאקט ואפשר בקלות לבדוק אותה.
קימי יצר תוכנית מצוינת אבל לקח כיוון מסורבל בקוד. במקום להשתמש ב div-ים הוא יצר canvas. זה לא סוף העולם אבל זה אומר שהבדיקות שלו הרבה פחות טובות כיוון שיש המון לוגיקה שקשורה לציור אותה הוא לא בדק. מבחינת ההבדלים בינו לבין minimax אז הנה דוגמה קטנה הקוד של קימי שבדק אם תשובה לתרגיל חשבון היא נכונה הוא:
const handleMathSubmit = (e: React.FormEvent) => {
e.preventDefault();
const userAnswer = parseInt(answer, 10);
const correct = userAnswer === gameState.currentMathProblem?.answer;
if (correct) {
setGameState((prev) => ({
...prev,
snake: growSnake(prev.snake),
apple: generateApple(prev.snake),
score: prev.score + SCORE_PER_APPLE,
speed: Math.max(MIN_SPEED, prev.speed - SPEED_DECREMENT),
status: 'PLAYING',
currentMathProblem: null,
}));
} else {
const newLives = gameState.lives - 1;
if (newLives <= 0) {
setGameState((prev) => ({ ...prev, status: 'GAME_OVER', lives: 0 }));
} else {
setGameState((prev) => ({
...prev,
snake: shrinkSnake(prev.snake),GitHub
GitHub - ynonp/math-snake-foss-models at opencode-glm5
Contribute to ynonp/math-snake-foss-models development by creating an account on GitHub.
❤1
apple: generateApple(prev.snake),
status: 'PLAYING',
currentMathProblem: null,
lives: newLives,
}));
}
}
setAnswer('');
};
זו פונקציה שמוגדרת בתוך קומפוננטה שמפעילה setState מכמה מקומות שונים לפי הנסיבות. לי קשה לקרוא אותה או לעקוב אחריה ובטח לבדוק אותה.
מינימקס הפריד את זה ל-2, החלק בתוך הקומפוננטה הוא בסך הכל:
const handleAnswerSubmit = (answer: number) => {
setGameState(prev => submitAnswer(prev, answer));
};
והלוגיקה בקובץ נפרד לא קשורה לריאקט ולכן אפשר בקלות לבדוק אותה:
export function submitAnswer(state: GameState, userAnswer: number): GameState {
if (!state.mathProblem) return state;
const isCorrect = userAnswer === state.mathProblem.answer;
if (isCorrect) {
const newSpeed = Math.max(MIN_SPEED, state.speed - SPEED_DECREASE);
return {
...state,
score: state.score + POINTS_PER_ANSWER,
speed: newSpeed,
isPaused: false,
mathProblem: null,
apple: generateApple(state.snake),
};
}
const newLives = state.lives - 1;
if (newLives <= 0) {
return {
...state,
lives: 0,
isGameOver: true,
isPaused: true,
mathProblem: null,
};
}
return {
...state,
lives: newLives,
isPaused: false,
mathProblem: null,
apple: generateApple(state.snake),
};
}
המודל האחרון glm לקח גישה היברידית, הוא גם השתמש בגריד כמו מינימקס אבל אצלו שוב המשחק נכתב בתוך Hook ולכן היתה הרבה לוגיקה שלא נבדקה. גלם גם הוסיף טעינה דינמית של לוח המשחק מאיזושהי סיבה:
'use client';
import dynamic from 'next/dynamic';
const GameBoard = dynamic(
() => import('@/components/Game/GameBoard').then((mod) => mod.GameBoard),
{ ssr: false }
);
export function Game() {
return <GameBoard />;
}
ובדוגמת בדיקת התרגיל הוא כתב:
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const userAnswer = parseInt(answer, 10);
if (isNaN(userAnswer)) {
setError(true);
return;
}
if (userAnswer === problem.answer) {
onCorrect();
} else {
onWrong();
}
};
const handleChange = (value: string) => {
setAnswer(value);
setError(false);
};
// in hook file
const handleCorrectAnswer = useCallback(() => {
setCurrentProblem(null);
setGameState('PLAYING');
}, []);
const handleWrongAnswer = useCallback(() => {
setLives((prev) => {
const newLives = prev - 1;
if (newLives <= 0) {
setGameState('GAME_OVER');
}
return newLives;
});
setCurrentProblem(null);
if (lives > 1) {
setGameState('PLAYING');
}
}, [lives]);
שזה דוגמה נפלאה לקוד שנראה יפה אבל בעצם קשה להבנה כי יש לנו יותר מדי משתני סטייט ויותר מדי פונקציות מפוזרות בכמה קבצים בלי סיבה אמיתית להפרדה.
סך הכל בעקבות הניסוי אני מודה שהתאהבתי ב minimax התחלתי גם להשתמש בו ליצירת קוד בפרויקטים אמיתיים ואני מאוד מרוצה בינתיים.
יש לי הזדמנות
המטלה הכי שנואה על מפתחים בעולם החדש היא קריאת הקוד ש AI כותב. קריאת קוד של אחרים זה תמיד כאב ראש ובמקרה של AI הקושי כפול כי אנחנו צריכים להתרכז ולחפש איפה ה AI פספס דברים בסיסיים שיסבכו אותנו בהמשך.
אחת הדרכים להקל על העומס היא לגשת למשימה בראש אחר. במקום "אני צריך למצוא מה ה AI פספס" ננסה את הגישה "יש לי הזדמנות ללמוד".
במקום לחפש "איפה ה AI פספס" נחפש "איך הקוד החדש פותר את הבעיה"
במקום לחפש "מה ה AI לא ראה" נשאל "מאיפה התבנית הזאת הגיעה?"
במקום להתאמץ ולמצוא שגיאות הגיון ננסה למצוא את ההגיון ולעקוב אחר חוט המחשבה שהיה יכול להיות שם.
במקום לחשוש לפתוח את הקוד כי "מי יודע מה אמצא שם" כדאי לזכור שהקוד הזה ממילא לא עלה לי כלום וכמו שהוא נכתב מהר אפשר גם להעיף אותו מהר ולייצר הכל מחדש עם פרומפט קצת יותר טוב.
במקום לחשוש שאני אצא טמבל ולא אבין דברים בסיסיים כדאי להזכר - יש לי הזדמנות ללמוד. כל מה שלא אבין אוכל לשאול את אותו AI. מעולם לא היה יותר קל ללמוד טריקים חדשים על קוד. מעולם לא היה יותר חשוב להבין.
המטלה הכי שנואה על מפתחים בעולם החדש היא קריאת הקוד ש AI כותב. קריאת קוד של אחרים זה תמיד כאב ראש ובמקרה של AI הקושי כפול כי אנחנו צריכים להתרכז ולחפש איפה ה AI פספס דברים בסיסיים שיסבכו אותנו בהמשך.
אחת הדרכים להקל על העומס היא לגשת למשימה בראש אחר. במקום "אני צריך למצוא מה ה AI פספס" ננסה את הגישה "יש לי הזדמנות ללמוד".
במקום לחפש "איפה ה AI פספס" נחפש "איך הקוד החדש פותר את הבעיה"
במקום לחפש "מה ה AI לא ראה" נשאל "מאיפה התבנית הזאת הגיעה?"
במקום להתאמץ ולמצוא שגיאות הגיון ננסה למצוא את ההגיון ולעקוב אחר חוט המחשבה שהיה יכול להיות שם.
במקום לחשוש לפתוח את הקוד כי "מי יודע מה אמצא שם" כדאי לזכור שהקוד הזה ממילא לא עלה לי כלום וכמו שהוא נכתב מהר אפשר גם להעיף אותו מהר ולייצר הכל מחדש עם פרומפט קצת יותר טוב.
במקום לחשוש שאני אצא טמבל ולא אבין דברים בסיסיים כדאי להזכר - יש לי הזדמנות ללמוד. כל מה שלא אבין אוכל לשאול את אותו AI. מעולם לא היה יותר קל ללמוד טריקים חדשים על קוד. מעולם לא היה יותר חשוב להבין.
👍4
ממובן למובן מאליו
מובן כלומר ״ברור״, ״נתפס בשכל״. כשאני אומר על משהו שהוא מובן אני מתכוון שאני כבר מקבל אותו או שהוא בנוי בצורה כזאת שאנשים אחרים יוכלו לקבל אותו, יוכלו להבין אותו.
כשמשהו מובן מאליו זה אומר שהוא מובן ללא כל הסבר נוסף או ללא כל מאמץ נוסף. אי אפשר להתכחש למובנות שלו.
תרגול, חשיפה ועבודה בתבניות עוזרות להפוך קוד ממובן למובן מאליו, כלומר מכזה שדורש רגע לעצור כדי להבין מה רצו שם לכזה שאפשר לראות ולהמשיך. דוגמה? בטח הנה דיפסיק מדפיס 10 מספרים ראשונים בסדרת פיבונאצ'י:
מובן לגמרי ואפילו עם הערה שעוזרת להבין למה מתחילים מ-2 אבל דורש קריאה וקצת ריכוז.
והנה מינימקס פותר את אותה בעיה:
גם הוא מעמיס הערות אבל הפעם ברור שאין בהן צורך. את התבנית:
מכיר כל מי שכתב פיבונאצ'י בפייתון.
כל עוד קריאת קוד היא חלק משמעותי מהחיים שלנו, ונראה שלשנים הקרובות היא רק הולכת והופכת יותר משמעותית, שווה להתאמץ ולהשתפר בזה. מצד אחד באמצעות שיפור מיומנות ויצירת ציפיות ומצד שני באמצעות השפעה על ה AI שיבנה את הקוד שיתאים לציפיות שלנו.
מובן כלומר ״ברור״, ״נתפס בשכל״. כשאני אומר על משהו שהוא מובן אני מתכוון שאני כבר מקבל אותו או שהוא בנוי בצורה כזאת שאנשים אחרים יוכלו לקבל אותו, יוכלו להבין אותו.
כשמשהו מובן מאליו זה אומר שהוא מובן ללא כל הסבר נוסף או ללא כל מאמץ נוסף. אי אפשר להתכחש למובנות שלו.
תרגול, חשיפה ועבודה בתבניות עוזרות להפוך קוד ממובן למובן מאליו, כלומר מכזה שדורש רגע לעצור כדי להבין מה רצו שם לכזה שאפשר לראות ולהמשיך. דוגמה? בטח הנה דיפסיק מדפיס 10 מספרים ראשונים בסדרת פיבונאצ'י:
def print_fibonacci():
first = 0
second = 1
count = 2 # We already have two elements: 0 and 1
while count < 10:
next_num = first + second
sequence.append(next_num)
first, second = second, next_num
count += 1
print(' '.join(map(str, sequence)))
מובן לגמרי ואפילו עם הערה שעוזרת להבין למה מתחילים מ-2 אבל דורש קריאה וקצת ריכוז.
והנה מינימקס פותר את אותה בעיה:
def print_fibonacci(count=10):
a, b = 0, 1 # start with the first two numbers
for _ in range(count):
print(a, end=' ')
a, b = b, a + b # move to the next pair
print() # final newline
גם הוא מעמיס הערות אבל הפעם ברור שאין בהן צורך. את התבנית:
a, b = b, a + b
מכיר כל מי שכתב פיבונאצ'י בפייתון.
כל עוד קריאת קוד היא חלק משמעותי מהחיים שלנו, ונראה שלשנים הקרובות היא רק הולכת והופכת יותר משמעותית, שווה להתאמץ ולהשתפר בזה. מצד אחד באמצעות שיפור מיומנות ויצירת ציפיות ומצד שני באמצעות השפעה על ה AI שיבנה את הקוד שיתאים לציפיות שלנו.
שתי נקודות או שלוש נקודות ב git diff
שתי הפקודות האלה נראות דומות ועושות משהו דומה ואולי בגלל הדמיון בתחביר הן כל כך מבלבלות:
רואים את ההבדל? נכון זו רק נקודה.
נתונים שני ענפים dev ו main והם התקדמו במקביל. בעבר dev יצא מ main כדי לפתח פיצ'ר ומאז main התקדם עם תיקוני באגים קטנים. עכשיו אנחנו רוצים לראות מה ההבדל ביניהם:
1. פקודת diff עם שתי נקודות תראה לי את ההבדל בין המצב העדכני ביותר בענף dev למצב העדכני ביותר בענף main.
2. פקודת diff עם שלוש נקודות תראה לי את ההבדל בין המצב העדכני ביותר בענף dev לבין הקומיט ב main ממנו הוא יצא, כלומר בלי אותם קומיטים חדשים ב main שנכתבו אחרי שהתחלתי לכתוב את הפיצ'ר.
מתי נשתמש בכל אחת? ברגע שהבנו את ההבדל גם השימוש הוא ברור: לפני מיזוג או ריבייס כשאני רוצה למפות פערים אני אשתמש ב diff שתי הנקודות. כך אני יכול לדעת כמה אני רחוק מהקוד הראשי. בזמן העבודה על dev אני אשתמש ב diff שלוש הנקודות כדי לראות מה בדיוק עשיתי, אם צריך לערוך קומיטים או לנקות קוד. בעבודה עם AI אני אוהב לעשות Code Review עם diff שלוש הנקודות, כך אני יכול לראות בדיוק את השינויים שסוכן הקידוד הכניס בלי להתבלבל בגלל שינויים אחרים חדשים יותר בענף הראשי.
שתי הפקודות האלה נראות דומות ועושות משהו דומה ואולי בגלל הדמיון בתחביר הן כל כך מבלבלות:
* 1. two dots diff *
git diff dev..main
* 2. three dots diff *
git diff dev...main
רואים את ההבדל? נכון זו רק נקודה.
נתונים שני ענפים dev ו main והם התקדמו במקביל. בעבר dev יצא מ main כדי לפתח פיצ'ר ומאז main התקדם עם תיקוני באגים קטנים. עכשיו אנחנו רוצים לראות מה ההבדל ביניהם:
1. פקודת diff עם שתי נקודות תראה לי את ההבדל בין המצב העדכני ביותר בענף dev למצב העדכני ביותר בענף main.
2. פקודת diff עם שלוש נקודות תראה לי את ההבדל בין המצב העדכני ביותר בענף dev לבין הקומיט ב main ממנו הוא יצא, כלומר בלי אותם קומיטים חדשים ב main שנכתבו אחרי שהתחלתי לכתוב את הפיצ'ר.
מתי נשתמש בכל אחת? ברגע שהבנו את ההבדל גם השימוש הוא ברור: לפני מיזוג או ריבייס כשאני רוצה למפות פערים אני אשתמש ב diff שתי הנקודות. כך אני יכול לדעת כמה אני רחוק מהקוד הראשי. בזמן העבודה על dev אני אשתמש ב diff שלוש הנקודות כדי לראות מה בדיוק עשיתי, אם צריך לערוך קומיטים או לנקות קוד. בעבודה עם AI אני אוהב לעשות Code Review עם diff שלוש הנקודות, כך אני יכול לראות בדיוק את השינויים שסוכן הקידוד הכניס בלי להתבלבל בגלל שינויים אחרים חדשים יותר בענף הראשי.
👍3
טוב לפתוח יומנים יש תוכנית וובינרים עד סוף מאי
https://www.tocode.co.il/talking_ai
אל תדאגו יצא על זה גם פוסט מסודר
https://www.tocode.co.il/talking_ai
אל תדאגו יצא על זה גם פוסט מסודר