והנה המשחק - גם אם סוכן הקידוד יכול לקחת כל דרישה שלי בנפרד ולתת לה פתרון מושלם (זה עדיין לא המצב אבל אפשר לדמיין עתיד בו זה יהיה), עדיין אין דרך לבנות פתרון אחד שיפתור את כל הדרישות יחד.
קבלת החלטות הופכת הרבה יותר מסובכת ככל שאנחנו מדברים על מערכות גדולות יותר. בגלל שאין תשובה נכונה, בגלל שאין פתרון בית ספר, אנחנו חייבים להבין את האילוצים והאפשרויות הרבה יותר לעומק. במערכת אמיתית לא נוכל להגיד לסוכן קידוד "תכתוב פתרון מאובטח עם ביצועים טובים", כי המלים האלה לא אומרות כלום.
יותר מזה, שום סוכן קידוד לא יוכל לחשוב מחוץ לקופסה כי מנגנון קבלת ההחלטות של סוכני קידוד מתוכנן להציע את הפתרונות ההגיוניים ביותר, וחשיבה מחוץ לקופסה היא בדיוק החיפוש אחרי הפתרונות שלא נראים הגיוניים. סוכני קידוד לעולם לא היו יכולים להמציא את Rails למרות ש Rails הופך את העבודה שלהם להרבה יותר קלה. כש DHH המציא את ריילס הוא היה תקוע בין פרויקטי PHP מבולגנים ורצון ללמוד רובי. לסוכן קידוד אין רצון ללמוד שום דבר ואל מול פרויקט מבולגן הוא רק ינסה לשמור על תאימות אחורה ולאמץ את הבלאגן גם לקוד החדש.
פה המקום לפתוח סוגריים ולהתייחס להערה שאני שומע מדי פעם שאומרת "אולי כבר לא צריך חדשנות". יש לנו ריילס ויש לנו next.js ויש לנו ריאקט ו vue ויש לנו Web Assembly וגם Rust ו Docker. די מספיק. חדשנות או אבסטרקציות מאפשרות לנו לכתוב מערכות גדולות יותר בפחות קוד, אבל ל AI אין בעיה של כמות קוד. אפשר לזרוק הכל ולתת ל AI לכתוב כל מערכת מאפס באסמבלי.
התשובה שלי לזה היא לא אידאולוגית אלא אמפירית. עד היום לא ראיתי שום ראיה שסוכני קידוד מסוגלים להתמודד עם מערכות תוכנה בלי אבסטרקציות. למעשה בעבודה מאוד אינטנסיבית שלי עם סוכני קידוד אני רואה שוב ושוב את אותן תבניות - כשהאבסטרקציות טובות הסוכן נותן תוצאות יעילות ובונה קוד טוב. כשהאבסטרקציות גרועות או לא מספיק טובות הקוד שהסוכן יכתוב יהיה גרוע ולא יעבוד. זה לא סתם ש Lovable נותנים לסוכן שלהם תבנית בסיס וספריות קוד מובנות ולא מבקשות ממנו לבנות כל מערכת מאפס. אולי בעתיד נראה את סוכני הקידוד המופלאים שמצליחים לבנות מערכות מורכבות ללא אבסטרקציות וללא חלוקה לשכבות, כרגע אנחנו בכלל לא בכיוון לשם.
איך מתאמנים על קבלת החלטות טובות בתוכנה
זיהיתי קודם שש נקודות שעוזרות ליכולת לקבל החלטות טובות יותר. בואו נפתח אותן כדי להבין איך להתאמן על כל אחת.
התחלנו עם היכרות עם פתרונות קיימים. זה נשמע מוזר בעידן ה AI כי בעצם ה AI יכול להציג לי כמה פתרונות שאני ארצה לכל בעיה אז בשביל מה אני צריך להכיר אותם, אבל הסיפור פה מטעה. ה AI מציג את הפתרונות הצפויים ואת אלה שאני מבקש ממנו, גם אם זה לא נראה שביקשתי. במילים אחרות הפתרון שה AI יציג יהיה הפתרון שהכי מתאים לפרומפט שכתבתי לפי נתוני האימון של ה AI ובאיזושהי הסתברות ממושקלת. כדי לקבל יותר פתרונות אני צריך או לשאול את אותה שאלה שוב ושוב מספיק פעמים עד שפתרון אחר יעלה בגורל, או מה שיותר פרקטי לשאול שאלה אחרת שעבורה הפתרון השני יהיה בעל הסתברות גבוהה יותר.
בדוגמה של פונקציית פייתון שסופרת שורות בקובץ לא משנה כמה פעמים אני אבקש אותה אף סוכן קידוד לא יגיד לי "בעצם עדיף לך class". דבר שני בגלל האינטגרציה של סוכני קידוד עם כלי פיתוח הרבה פעמים אפילו אם AI ירצה להציע כמה פתרונות ה VS Code או Cursor יבחר רק אחד מהם וכבר יכתוב אותו בתוך הקוד כך שאני לא אראה את זה.
לכן הדבר הראשון שאנחנו חייבים לעשות הוא להמשיך לחפש בעיות ופתרונות גם מעולם התוכן שלנו וגם מעולמות תוכן אחרים - מישקו הברה, היוצר של אנגולר לא היה מתכנת FrontEnd והגיע מעולם של Java כשהוא יצר את אנגולר. הוא הגיע עם ראייה של פתרונות מהעולם של תכנות מונחה עצמים וזה לדעתי מאוד עזר לו לראות בעיות ופתרונות שאנשי פרונטאנד פספסו. קריאת ספרים, היכרות עם מערכות קיימות, עבודה על עוד פרויקטים, קריאת בלוגים ואפילו קורסים מקצועיים כולם יעזרו לכם להכיר טוב יותר את עולם התוכן, את היסודות, את הבעיות והפתרונות הקיימים. כדאי גם לפתח הרגל במקום להסתכל על תרגיל ולחפש את הפתרון שלו אתם רוצים להסתכל על תרגיל ולחפש כמה שיותר פתרונות אפשריים.
קבלת החלטות הופכת הרבה יותר מסובכת ככל שאנחנו מדברים על מערכות גדולות יותר. בגלל שאין תשובה נכונה, בגלל שאין פתרון בית ספר, אנחנו חייבים להבין את האילוצים והאפשרויות הרבה יותר לעומק. במערכת אמיתית לא נוכל להגיד לסוכן קידוד "תכתוב פתרון מאובטח עם ביצועים טובים", כי המלים האלה לא אומרות כלום.
יותר מזה, שום סוכן קידוד לא יוכל לחשוב מחוץ לקופסה כי מנגנון קבלת ההחלטות של סוכני קידוד מתוכנן להציע את הפתרונות ההגיוניים ביותר, וחשיבה מחוץ לקופסה היא בדיוק החיפוש אחרי הפתרונות שלא נראים הגיוניים. סוכני קידוד לעולם לא היו יכולים להמציא את Rails למרות ש Rails הופך את העבודה שלהם להרבה יותר קלה. כש DHH המציא את ריילס הוא היה תקוע בין פרויקטי PHP מבולגנים ורצון ללמוד רובי. לסוכן קידוד אין רצון ללמוד שום דבר ואל מול פרויקט מבולגן הוא רק ינסה לשמור על תאימות אחורה ולאמץ את הבלאגן גם לקוד החדש.
פה המקום לפתוח סוגריים ולהתייחס להערה שאני שומע מדי פעם שאומרת "אולי כבר לא צריך חדשנות". יש לנו ריילס ויש לנו next.js ויש לנו ריאקט ו vue ויש לנו Web Assembly וגם Rust ו Docker. די מספיק. חדשנות או אבסטרקציות מאפשרות לנו לכתוב מערכות גדולות יותר בפחות קוד, אבל ל AI אין בעיה של כמות קוד. אפשר לזרוק הכל ולתת ל AI לכתוב כל מערכת מאפס באסמבלי.
התשובה שלי לזה היא לא אידאולוגית אלא אמפירית. עד היום לא ראיתי שום ראיה שסוכני קידוד מסוגלים להתמודד עם מערכות תוכנה בלי אבסטרקציות. למעשה בעבודה מאוד אינטנסיבית שלי עם סוכני קידוד אני רואה שוב ושוב את אותן תבניות - כשהאבסטרקציות טובות הסוכן נותן תוצאות יעילות ובונה קוד טוב. כשהאבסטרקציות גרועות או לא מספיק טובות הקוד שהסוכן יכתוב יהיה גרוע ולא יעבוד. זה לא סתם ש Lovable נותנים לסוכן שלהם תבנית בסיס וספריות קוד מובנות ולא מבקשות ממנו לבנות כל מערכת מאפס. אולי בעתיד נראה את סוכני הקידוד המופלאים שמצליחים לבנות מערכות מורכבות ללא אבסטרקציות וללא חלוקה לשכבות, כרגע אנחנו בכלל לא בכיוון לשם.
איך מתאמנים על קבלת החלטות טובות בתוכנה
זיהיתי קודם שש נקודות שעוזרות ליכולת לקבל החלטות טובות יותר. בואו נפתח אותן כדי להבין איך להתאמן על כל אחת.
התחלנו עם היכרות עם פתרונות קיימים. זה נשמע מוזר בעידן ה AI כי בעצם ה AI יכול להציג לי כמה פתרונות שאני ארצה לכל בעיה אז בשביל מה אני צריך להכיר אותם, אבל הסיפור פה מטעה. ה AI מציג את הפתרונות הצפויים ואת אלה שאני מבקש ממנו, גם אם זה לא נראה שביקשתי. במילים אחרות הפתרון שה AI יציג יהיה הפתרון שהכי מתאים לפרומפט שכתבתי לפי נתוני האימון של ה AI ובאיזושהי הסתברות ממושקלת. כדי לקבל יותר פתרונות אני צריך או לשאול את אותה שאלה שוב ושוב מספיק פעמים עד שפתרון אחר יעלה בגורל, או מה שיותר פרקטי לשאול שאלה אחרת שעבורה הפתרון השני יהיה בעל הסתברות גבוהה יותר.
בדוגמה של פונקציית פייתון שסופרת שורות בקובץ לא משנה כמה פעמים אני אבקש אותה אף סוכן קידוד לא יגיד לי "בעצם עדיף לך class". דבר שני בגלל האינטגרציה של סוכני קידוד עם כלי פיתוח הרבה פעמים אפילו אם AI ירצה להציע כמה פתרונות ה VS Code או Cursor יבחר רק אחד מהם וכבר יכתוב אותו בתוך הקוד כך שאני לא אראה את זה.
לכן הדבר הראשון שאנחנו חייבים לעשות הוא להמשיך לחפש בעיות ופתרונות גם מעולם התוכן שלנו וגם מעולמות תוכן אחרים - מישקו הברה, היוצר של אנגולר לא היה מתכנת FrontEnd והגיע מעולם של Java כשהוא יצר את אנגולר. הוא הגיע עם ראייה של פתרונות מהעולם של תכנות מונחה עצמים וזה לדעתי מאוד עזר לו לראות בעיות ופתרונות שאנשי פרונטאנד פספסו. קריאת ספרים, היכרות עם מערכות קיימות, עבודה על עוד פרויקטים, קריאת בלוגים ואפילו קורסים מקצועיים כולם יעזרו לכם להכיר טוב יותר את עולם התוכן, את היסודות, את הבעיות והפתרונות הקיימים. כדאי גם לפתח הרגל במקום להסתכל על תרגיל ולחפש את הפתרון שלו אתם רוצים להסתכל על תרגיל ולחפש כמה שיותר פתרונות אפשריים.
❤1
נקודה שניה היא הבנת אותם פתרונות. זה שיש 10 פתרונות לבעיה לא אומר שכולם טובים ושכולם מתאימים לאותן נסיבות. פה בהחלט אפשר להתאמן יחד עם ה AI ולשחק "מה קורה אם" - מה קורה אם השורות מאוד ארוכות? מה קורה אם קריאה מקובץ היא איטית מאוד כי הקובץ נמצא על כונן רשת? מה קורה אם הדרישות ישתנו ונצטרך לספור שורות בלי שורות כותרת או בקובץ בפורמט אחר? מה החסרונות של כל גישה? האתגר שלנו הוא להתנתק מתפיסת העולם של "איך פותרים את הבאג" ולעבור לתפיסה של "מה הסיפור פה" ו"מה הסיבות הבסיסיות שגרמו לבאג".
נקודה שלישית היתה תשומת לב לפרטים. אני חושב שזה משהו שקשה מאוד להתאמן עליו אבל הוא הכרחי לכל עבודת פיתוח ואולי פה ה AI דווקא יכול להיות חבר טוב ולשחק את פרקליט השטן. ככל שאני עובד יותר עם AI אני מגלה שאני קורא קוד בזכוכית מגדלת הרבה יותר מבעבר כי יש לי את מי לשאול. בכל שורת קוד אני עוצר לשאול "מה עושה השורה הזאת כאן", "איך עוד אפשר היה לכתוב את זה", "מה ההשלכות של השורה הזאת על הביצועים של המערכת", "איזה בעיות אבטחת מידע היא עלולה ליצור", "איך בודקים אותה?", "מה יקרה אם דרישה מסוימת תשתנה", "האם יש דרך חדשה יותר לכתוב את הקוד הזה", "האם הייתי יכול לחשוב על אבסטרקציה אחרת שהיתה גורמת לשורה הזאת להיראות אחרת". ככל שאני מבלה יותר זמן עם הקוד כך אני שם לב ליותר פרטים, וככל שאני מקפיד לחזור על זה עם כל קוד שאני קורא כך אני שם לב לפרטים מהר יותר.
נקודה רביעית היתה טעם טוב ופה עליי לאכזב שוב את אלה שמחפשים פתרונות מהירים. טעם טוב לוקח שנים לפתח. עלינו להיות מעורבים במערכות קיימות, לקרוא קוד, לקרוא ספרים על קוד, להבין את השיקולים בעד או נגד שיטת כתיבה מסוימת. זו דרך ללא סוף.
הנקודה החמישית היתה מודעות לאילוצים ולמגבלות ופה האימון שלנו הוא שוב משחק בכאילו ויציאה מכסא המפתח כדי להבין טוב יותר את החברה והמודל העסקי. מפתחים טובים יודעים איזה פיצ'רים הולכים להגיע לפני שפרודקט העביר אותם כי אנחנו מבינים לאן דברים הולכים. בדוגמה דומה מישהו שאל בפייסבוק "עברתי מכתיבת אתרים ב Wordpress ל next.js ועכשיו חשבון האחסון שלי קפץ, מה עושים?". בתור מפתחים שמודעים למגבלות אנחנו רוצים לשים לב לעלויות האחסון כבר בשלב הפיתוח, להתלבט על SEO וזמני טעינה עם כל שורת קוד. וכן לשלב את כל זה בשיקולים על לוחות זמנים ויכולת לעבוד בצוות או בשיתוף פעולה עם צוותים אחרים בחברה.
טריק קטן שעוזר להשתפר גם בתשומת לב לפרטים וגם במודעות לאילוצים הוא ממש לכתוב אחרי כל פיצ'ר מה אתם חושבים שיהיו הפיצ'רים הבאים, באיזה מצבים אתם חושבים שהקוד הזה הולך להשתנות. לכתוב מכריח אותנו לחשוב ואחרי זה תמיד כיף לפתוח את הפתקים האלה ולהבין כמה היינו בכיוון (ואם לא, לנסות לחשוב איך לשפר את התחזיות לפעם הבאה).
נקודה שישית וסופר חשובה היא החשיבה מחוץ לקופסה. האתגר שלנו הוא להסתכל על בעיה ולהבין איזה דברים היו יכולים להיות אחרת כדי שהבעיה הזאת בכלל לא תהיה בעיה. זה היה הטריק של אדם וואתן עם Tailwind - אדם הסתכל על אלמנט HTML ולא ידע להגיד איזה CSS משפיע עליו, הוא הסתכל על קוד ה CSS שלו ולא ידע להגיד איזה חלקים בו בכלל פעילים. בעוד ש AI היה עשוי להציע לסרוק את המערכת ולמפות מה קשור למה אדם הסתכל צעד קדימה והבין שהפתרון הוא לכתוב את כל ה CSS בתוך קוד ה HTML. אבל אדם לא היה לבד, באותו זמן שהוא יצר את טיילווינד זו היתה תקופה של פריחה לספריות של CSS-In-JS שהציעו לכתוב את קוד ה CSS בתוך קוד הקומפוננטות של ריאקט. חשיבה מחוץ לקופסה דורשת גם היא שינוי תפיסה, במקום לנסות לפתור את הבעיה בכלים הקיימים לחפש כלים אחרים שיגרמו לבעיה לא להתקיים.
האתגר העיקרי - מוטיבציה
תמיד קשה לדבר על העתיד אבל היציבות של סוכני הקידוד בהיבט של מנגנון קבלת ההחלטות שלהם, מנגנון שלא השתנה מאז הגרסה הראשונה של ChatGPT, מלמדת אותנו שמפתחים אנושיים ימשיכו להיות קריטיים לתעשייה לפחות בעשור הקרוב וכנראה הרבה מעבר.
אבל היכולות המדהימות של סוכני הקידוד בייצור קוד ובבחירת פתרון עובד פועלות לרעתנו. מתכנתים בתחילת הדרך מסתכלים על העולם ושואלים את עצמם "אם כל מה שאני יכול לעשות ה AI עושה טוב יותר, בשביל מה להתאמץ?". אני מבין את זה. פעם לימוד פייתון נתן לך יכולות מסוימות. אחרי שלמדת פייתון יכלת לכתוב סקריפט שסופר שורות בקובץ. היום? אפשר לכתוב את הסקריפט הזה בלי לדעת פייתון כלל. אפשר לכתוב משחקים בלי לדעת כלום על פיתוח משחקים, אתרי אינטרנט בלי לדעת כלום על HTML. איך נשכנע אנשים ללמוד תכנות אם אין שום "גמול" מיידי בסוף הקורס, אם הלימוד לא ייתן להם מיומנות חדשה?
נקודה שלישית היתה תשומת לב לפרטים. אני חושב שזה משהו שקשה מאוד להתאמן עליו אבל הוא הכרחי לכל עבודת פיתוח ואולי פה ה AI דווקא יכול להיות חבר טוב ולשחק את פרקליט השטן. ככל שאני עובד יותר עם AI אני מגלה שאני קורא קוד בזכוכית מגדלת הרבה יותר מבעבר כי יש לי את מי לשאול. בכל שורת קוד אני עוצר לשאול "מה עושה השורה הזאת כאן", "איך עוד אפשר היה לכתוב את זה", "מה ההשלכות של השורה הזאת על הביצועים של המערכת", "איזה בעיות אבטחת מידע היא עלולה ליצור", "איך בודקים אותה?", "מה יקרה אם דרישה מסוימת תשתנה", "האם יש דרך חדשה יותר לכתוב את הקוד הזה", "האם הייתי יכול לחשוב על אבסטרקציה אחרת שהיתה גורמת לשורה הזאת להיראות אחרת". ככל שאני מבלה יותר זמן עם הקוד כך אני שם לב ליותר פרטים, וככל שאני מקפיד לחזור על זה עם כל קוד שאני קורא כך אני שם לב לפרטים מהר יותר.
נקודה רביעית היתה טעם טוב ופה עליי לאכזב שוב את אלה שמחפשים פתרונות מהירים. טעם טוב לוקח שנים לפתח. עלינו להיות מעורבים במערכות קיימות, לקרוא קוד, לקרוא ספרים על קוד, להבין את השיקולים בעד או נגד שיטת כתיבה מסוימת. זו דרך ללא סוף.
הנקודה החמישית היתה מודעות לאילוצים ולמגבלות ופה האימון שלנו הוא שוב משחק בכאילו ויציאה מכסא המפתח כדי להבין טוב יותר את החברה והמודל העסקי. מפתחים טובים יודעים איזה פיצ'רים הולכים להגיע לפני שפרודקט העביר אותם כי אנחנו מבינים לאן דברים הולכים. בדוגמה דומה מישהו שאל בפייסבוק "עברתי מכתיבת אתרים ב Wordpress ל next.js ועכשיו חשבון האחסון שלי קפץ, מה עושים?". בתור מפתחים שמודעים למגבלות אנחנו רוצים לשים לב לעלויות האחסון כבר בשלב הפיתוח, להתלבט על SEO וזמני טעינה עם כל שורת קוד. וכן לשלב את כל זה בשיקולים על לוחות זמנים ויכולת לעבוד בצוות או בשיתוף פעולה עם צוותים אחרים בחברה.
טריק קטן שעוזר להשתפר גם בתשומת לב לפרטים וגם במודעות לאילוצים הוא ממש לכתוב אחרי כל פיצ'ר מה אתם חושבים שיהיו הפיצ'רים הבאים, באיזה מצבים אתם חושבים שהקוד הזה הולך להשתנות. לכתוב מכריח אותנו לחשוב ואחרי זה תמיד כיף לפתוח את הפתקים האלה ולהבין כמה היינו בכיוון (ואם לא, לנסות לחשוב איך לשפר את התחזיות לפעם הבאה).
נקודה שישית וסופר חשובה היא החשיבה מחוץ לקופסה. האתגר שלנו הוא להסתכל על בעיה ולהבין איזה דברים היו יכולים להיות אחרת כדי שהבעיה הזאת בכלל לא תהיה בעיה. זה היה הטריק של אדם וואתן עם Tailwind - אדם הסתכל על אלמנט HTML ולא ידע להגיד איזה CSS משפיע עליו, הוא הסתכל על קוד ה CSS שלו ולא ידע להגיד איזה חלקים בו בכלל פעילים. בעוד ש AI היה עשוי להציע לסרוק את המערכת ולמפות מה קשור למה אדם הסתכל צעד קדימה והבין שהפתרון הוא לכתוב את כל ה CSS בתוך קוד ה HTML. אבל אדם לא היה לבד, באותו זמן שהוא יצר את טיילווינד זו היתה תקופה של פריחה לספריות של CSS-In-JS שהציעו לכתוב את קוד ה CSS בתוך קוד הקומפוננטות של ריאקט. חשיבה מחוץ לקופסה דורשת גם היא שינוי תפיסה, במקום לנסות לפתור את הבעיה בכלים הקיימים לחפש כלים אחרים שיגרמו לבעיה לא להתקיים.
האתגר העיקרי - מוטיבציה
תמיד קשה לדבר על העתיד אבל היציבות של סוכני הקידוד בהיבט של מנגנון קבלת ההחלטות שלהם, מנגנון שלא השתנה מאז הגרסה הראשונה של ChatGPT, מלמדת אותנו שמפתחים אנושיים ימשיכו להיות קריטיים לתעשייה לפחות בעשור הקרוב וכנראה הרבה מעבר.
אבל היכולות המדהימות של סוכני הקידוד בייצור קוד ובבחירת פתרון עובד פועלות לרעתנו. מתכנתים בתחילת הדרך מסתכלים על העולם ושואלים את עצמם "אם כל מה שאני יכול לעשות ה AI עושה טוב יותר, בשביל מה להתאמץ?". אני מבין את זה. פעם לימוד פייתון נתן לך יכולות מסוימות. אחרי שלמדת פייתון יכלת לכתוב סקריפט שסופר שורות בקובץ. היום? אפשר לכתוב את הסקריפט הזה בלי לדעת פייתון כלל. אפשר לכתוב משחקים בלי לדעת כלום על פיתוח משחקים, אתרי אינטרנט בלי לדעת כלום על HTML. איך נשכנע אנשים ללמוד תכנות אם אין שום "גמול" מיידי בסוף הקורס, אם הלימוד לא ייתן להם מיומנות חדשה?
השתמשו ב AI כמו בוס
בעבודה עם סוכני קידוד יש לכם רק שתי אפשרויות ורק אחת טובה.
1. האפשרות הטובה - לדעת מראש מה ה AI הולך לכתוב. להסתכל על הקוד שנכתב. לוודא שזה מתאים למה שציפיתם. אם אפילו שורה או אות לא במקום להבין למה זה שם, מה היה לא נכון בציפיה שלכם (או בקוד שה AI יצר), ליצור מחדש עם פרומפט יותר ברור.
2. האפשרות שתוביל לאבדון - לבקש מ AI לכתוב פיצ'ר שאתם צריכים, לנסות להבין מה הוא עשה, לתקן אם זה לא עובד.
מתכנתים וותיקים לא צריכים את התזכורת הזו. אבל אם אתם ג'וניורים ורוצים לסיים את המשימות מהר כדי להשאיר רושם טוב שימו לב, גם אם תסיימו את המשימות מהר לאורך זמן המיומנות שלכם תישחק במקום לצמוח ואתם תישחקו איתה. אין דבר יותר משעמם מלהיות בייביסיטר של AI.
לכתוב קוד מהר זה לא הדבר החשוב כרגע. ספק אם אי פעם זה היה.
בעבודה עם סוכני קידוד יש לכם רק שתי אפשרויות ורק אחת טובה.
1. האפשרות הטובה - לדעת מראש מה ה AI הולך לכתוב. להסתכל על הקוד שנכתב. לוודא שזה מתאים למה שציפיתם. אם אפילו שורה או אות לא במקום להבין למה זה שם, מה היה לא נכון בציפיה שלכם (או בקוד שה AI יצר), ליצור מחדש עם פרומפט יותר ברור.
2. האפשרות שתוביל לאבדון - לבקש מ AI לכתוב פיצ'ר שאתם צריכים, לנסות להבין מה הוא עשה, לתקן אם זה לא עובד.
מתכנתים וותיקים לא צריכים את התזכורת הזו. אבל אם אתם ג'וניורים ורוצים לסיים את המשימות מהר כדי להשאיר רושם טוב שימו לב, גם אם תסיימו את המשימות מהר לאורך זמן המיומנות שלכם תישחק במקום לצמוח ואתם תישחקו איתה. אין דבר יותר משעמם מלהיות בייביסיטר של AI.
לכתוב קוד מהר זה לא הדבר החשוב כרגע. ספק אם אי פעם זה היה.
👍1
בואו נלמד Git Worktree בעזרת AI
לימוד באמצעות AI הוא נחמד כי ה AI מסוגל להתאים את עצמו לסגנון שלנו ולייצר בדיוק את המידע שאנחנו צריכים בשביל להבין את הנושא. מצד שני קל לטעות ולקבל ממנו חומר יותר מדי קל לעיכול כך שנרגיש שאנחנו מבינים משהו למרות שבפועל רק קראנו וכל הידע יישכח כמה דקות אחרי.
אני רוצה בפוסט הזה להראות דוגמה ללימוד אפקטיבי בעזרת AI, לתעד את התהליך ולשים לב אם דברים מסתבכים ואיפה.
פרומפט 1 - הצגת הנושא
החלטתי ללמוד Git Worktree כי VS Code התחיל להקפיץ לי הודעות שסוכן ה AI שלו צריך לעבוד ב Worktree והוא רוצה לדעת מה לעשות עם השינויים שלי לפני שהוא מתחיל לעבוד. אני מתחיל עם הפרומפט (בעברית):
> כתוב פוסט לבלוג של tocode המסביר מה זה git worktree ואיך זה עוזר לסוכני AI שעובדים על הפרויקט
התשובה הסבירה לי בגדול מה זה worktree ואיך זה עוזר לסוכני AI וגם כללה דוגמת הרצה קצרה שהסבירה לי איך ליצור worktree משורת הפקודה. זה לא רע. הוא סיים בהצעה:
אם רוצים, אני יכול גם לכתוב גרסה קלה יותר לקריאה עם דיאגרמות והסבר ויזואלי, שמתאימה במיוחד לבלוג של ToCode עם קטעי קוד ואיורים שמראים worktree בפעולה. זה יהפוך את הפוסט ליותר “חי” ואינטראקטיבי.
ואני עונה:
> כן תוסיף בבקשה דיאגרמות והסברים
אהבתי גם שהוא תרגם את branch ל"סניף" (אבל זה כבר סיפור אחר):
אפשר לראות את השיחה בלינק הזה:
https://chatgpt.com/share/69664d32-ad5c-8009-b4b1-b1e892858436
פרומפט 2 - מעבר מהפרטי לכללי
מתוך השיחה הקודמת הבנתי למה VS Code ממליץ לי להשתמש ב Worktree אבל עדיין לא היה מספיק ברור השימוש הכללי בפיצ'ר זה - מאיפה הוא נולד, האם יש עוד מצבים בהם נרצה להשתמש בו, חוץ מיצירה של worktree מה עוד אפשר לעשות עם זה. אפשר להגיד שהגעתי לשיחה עם נקודת כניסה מסוימת ועכשיו אני רוצה לקחת צעד אחורה ולהרחיב את ההבנה.
אני ממשיך עם הפרומפט הבא:
> כתוב מדריך טכני שמסביר לעומק:
> 1. מה זה git subtree
> 2. מה המגבלות שלו
> 3. איך הוא ממומש, איך זה עובד מתחת לפני השטח
> 4. מהן כל האפשרויות לכתיבה משורת הפקודה כולל אפשרויות שאנשים לא מכירים
> 5. באיזה עוד מקרים חשוב להשתמש בו
> 6. באיזה מקרים אנשים משתמשים בו בטעות והיה עדיף להם להשתמש במנגנונים אחרים
עכשיו השיחה הלכה לכיוונים מאוד מעניינים ולא תמיד נכונים, למשל מהר מאוד אני מזהה משפט חשוד ברשימת המגבלות של subtree:
> שכפול נתונים כל commit של סאבטרי נכנס למאגר הראשי. אם המאגר החיצוני ענק, המאגר הראשי גם הוא מתנפח.
רגע, מה? ברור שכל קומיט יישלח למאגר הראשי. זה לא אומר שנתונים שוכפלו. המטרה שלנו בשלב הזה היא לזהות את הבעיות האלה, כי דווקא דרך הוויכוחים וחוסר ההסכמה עם ה AI אנחנו יכולים לשפר את ההבנה שלנו. כל פעם שמצאנו משהו אפשר לכתוב ל AI כדי להרחיב עליו לדוגמה:
> כתבת "שכפול נתונים" כל commit של סאבטרי נכנס למאגר הראשי. אם המאגר החיצוני ענק, המאגר הראשי גם הוא מתנפח. זאת לא המשמעות של שכפול נתונים - הקומיט לא משוכפל לכמה מאגרים הוא פשוט נשמר פעם אחת במאגר הראשי
פרומפט 3 - זמן לעבוד
אחרי שקראתי והתווכחתי מגיע הזמן לעבוד. אפשר באותה שיחה או בשיחה חדשה להפוך את כל הידע לתרגול אינטרקטיבי:
> צור דף תרגילים בסגנון התרגולים באתר טוקוד שלוקחת אותי צעד צעד ממתחיל עד למישהו שמבין טוב איך להשתמש ב worktree
> כל תרגיל צריך להיבנות על ולהרחיב את הקודם והתרגילים יהיו ברמת קושי עולה
> את התרגילים אני אבצע על ריפו שלי ובסוף כל תרגיל כתוב לי איך אני בודק את עצמי
> דף התרגול מכיל 10 תרגילים
> בתרגילים יש להתמקד בתרחישים מהעולם האמיתי, לדוגמה לדמות מספר סוכני קידוד שעובדים במקביל על פרויקט או משיכה של גרסה ובנייתה בלי לפגוע בקבצים שכבר יש לי בתיקיית העבודה
זאת רשימת התרגילים שנוצרה:
1. יצירת worktree בסיסי
2. עבודה מקבילה על שני סניפים
3. משיכת שינויים מסניף חיצוני בלי לפגוע בקבצים
4. מחיקת worktree
5. יצירת מספר worktrees מקבילים
6. סנכרון שינויים מ־feature2 ל־main
7. עבודה על סניפים מרוחקים במקביל
8. ניהול קונפליקטים בין worktrees
9. שימוש ב־worktree עם תיקיות Nested
10. תרחיש סוכני AI מורכב
עכשיו אתם
אם עדיין לא נכנסתם לשיחה התחנה הבאה היא הקישור הזה:
לימוד באמצעות AI הוא נחמד כי ה AI מסוגל להתאים את עצמו לסגנון שלנו ולייצר בדיוק את המידע שאנחנו צריכים בשביל להבין את הנושא. מצד שני קל לטעות ולקבל ממנו חומר יותר מדי קל לעיכול כך שנרגיש שאנחנו מבינים משהו למרות שבפועל רק קראנו וכל הידע יישכח כמה דקות אחרי.
אני רוצה בפוסט הזה להראות דוגמה ללימוד אפקטיבי בעזרת AI, לתעד את התהליך ולשים לב אם דברים מסתבכים ואיפה.
פרומפט 1 - הצגת הנושא
החלטתי ללמוד Git Worktree כי VS Code התחיל להקפיץ לי הודעות שסוכן ה AI שלו צריך לעבוד ב Worktree והוא רוצה לדעת מה לעשות עם השינויים שלי לפני שהוא מתחיל לעבוד. אני מתחיל עם הפרומפט (בעברית):
> כתוב פוסט לבלוג של tocode המסביר מה זה git worktree ואיך זה עוזר לסוכני AI שעובדים על הפרויקט
התשובה הסבירה לי בגדול מה זה worktree ואיך זה עוזר לסוכני AI וגם כללה דוגמת הרצה קצרה שהסבירה לי איך ליצור worktree משורת הפקודה. זה לא רע. הוא סיים בהצעה:
אם רוצים, אני יכול גם לכתוב גרסה קלה יותר לקריאה עם דיאגרמות והסבר ויזואלי, שמתאימה במיוחד לבלוג של ToCode עם קטעי קוד ואיורים שמראים worktree בפעולה. זה יהפוך את הפוסט ליותר “חי” ואינטראקטיבי.
ואני עונה:
> כן תוסיף בבקשה דיאגרמות והסברים
אהבתי גם שהוא תרגם את branch ל"סניף" (אבל זה כבר סיפור אחר):
/project
├── main/ <- סניף main
└── experiment/ <- סניף experiment
אפשר לראות את השיחה בלינק הזה:
https://chatgpt.com/share/69664d32-ad5c-8009-b4b1-b1e892858436
פרומפט 2 - מעבר מהפרטי לכללי
מתוך השיחה הקודמת הבנתי למה VS Code ממליץ לי להשתמש ב Worktree אבל עדיין לא היה מספיק ברור השימוש הכללי בפיצ'ר זה - מאיפה הוא נולד, האם יש עוד מצבים בהם נרצה להשתמש בו, חוץ מיצירה של worktree מה עוד אפשר לעשות עם זה. אפשר להגיד שהגעתי לשיחה עם נקודת כניסה מסוימת ועכשיו אני רוצה לקחת צעד אחורה ולהרחיב את ההבנה.
אני ממשיך עם הפרומפט הבא:
> כתוב מדריך טכני שמסביר לעומק:
> 1. מה זה git subtree
> 2. מה המגבלות שלו
> 3. איך הוא ממומש, איך זה עובד מתחת לפני השטח
> 4. מהן כל האפשרויות לכתיבה משורת הפקודה כולל אפשרויות שאנשים לא מכירים
> 5. באיזה עוד מקרים חשוב להשתמש בו
> 6. באיזה מקרים אנשים משתמשים בו בטעות והיה עדיף להם להשתמש במנגנונים אחרים
עכשיו השיחה הלכה לכיוונים מאוד מעניינים ולא תמיד נכונים, למשל מהר מאוד אני מזהה משפט חשוד ברשימת המגבלות של subtree:
> שכפול נתונים כל commit של סאבטרי נכנס למאגר הראשי. אם המאגר החיצוני ענק, המאגר הראשי גם הוא מתנפח.
רגע, מה? ברור שכל קומיט יישלח למאגר הראשי. זה לא אומר שנתונים שוכפלו. המטרה שלנו בשלב הזה היא לזהות את הבעיות האלה, כי דווקא דרך הוויכוחים וחוסר ההסכמה עם ה AI אנחנו יכולים לשפר את ההבנה שלנו. כל פעם שמצאנו משהו אפשר לכתוב ל AI כדי להרחיב עליו לדוגמה:
> כתבת "שכפול נתונים" כל commit של סאבטרי נכנס למאגר הראשי. אם המאגר החיצוני ענק, המאגר הראשי גם הוא מתנפח. זאת לא המשמעות של שכפול נתונים - הקומיט לא משוכפל לכמה מאגרים הוא פשוט נשמר פעם אחת במאגר הראשי
פרומפט 3 - זמן לעבוד
אחרי שקראתי והתווכחתי מגיע הזמן לעבוד. אפשר באותה שיחה או בשיחה חדשה להפוך את כל הידע לתרגול אינטרקטיבי:
> צור דף תרגילים בסגנון התרגולים באתר טוקוד שלוקחת אותי צעד צעד ממתחיל עד למישהו שמבין טוב איך להשתמש ב worktree
> כל תרגיל צריך להיבנות על ולהרחיב את הקודם והתרגילים יהיו ברמת קושי עולה
> את התרגילים אני אבצע על ריפו שלי ובסוף כל תרגיל כתוב לי איך אני בודק את עצמי
> דף התרגול מכיל 10 תרגילים
> בתרגילים יש להתמקד בתרחישים מהעולם האמיתי, לדוגמה לדמות מספר סוכני קידוד שעובדים במקביל על פרויקט או משיכה של גרסה ובנייתה בלי לפגוע בקבצים שכבר יש לי בתיקיית העבודה
זאת רשימת התרגילים שנוצרה:
1. יצירת worktree בסיסי
2. עבודה מקבילה על שני סניפים
3. משיכת שינויים מסניף חיצוני בלי לפגוע בקבצים
4. מחיקת worktree
5. יצירת מספר worktrees מקבילים
6. סנכרון שינויים מ־feature2 ל־main
7. עבודה על סניפים מרוחקים במקביל
8. ניהול קונפליקטים בין worktrees
9. שימוש ב־worktree עם תיקיות Nested
10. תרחיש סוכני AI מורכב
עכשיו אתם
אם עדיין לא נכנסתם לשיחה התחנה הבאה היא הקישור הזה:
ChatGPT
ChatGPT - Git Worktree לסוכני AI
ChatGPT helps you get answers, find inspiration, and be more productive.
https://chatgpt.com/share/69664d32-ad5c-8009-b4b1-b1e892858436
קראו את כל תשובות ה AI לפרומפטים שלי, בצעו את 10 המשימות שהוא כתב וספרו לי אחרי זה מה ההרגשה שלכם לגבי git worktree והיכולת להשתמש בהם.
אחרי זה מוזמנים להצטרף לוובינר בחמישי הקרוב, שם אדבר גם על הדוגמה הזאת וגם על רעיונות נוספים ללימוד באמצעות AI, כולל על השאלות מה ללמוד ואיך ללמוד. אפשר להצטרף כאן:
https://tocode.ravpage.co.il/tocodeai
קראו את כל תשובות ה AI לפרומפטים שלי, בצעו את 10 המשימות שהוא כתב וספרו לי אחרי זה מה ההרגשה שלכם לגבי git worktree והיכולת להשתמש בהם.
אחרי זה מוזמנים להצטרף לוובינר בחמישי הקרוב, שם אדבר גם על הדוגמה הזאת וגם על רעיונות נוספים ללימוד באמצעות AI, כולל על השאלות מה ללמוד ואיך ללמוד. אפשר להצטרף כאן:
https://tocode.ravpage.co.il/tocodeai
ChatGPT
ChatGPT - Git Worktree לסוכני AI
ChatGPT helps you get answers, find inspiration, and be more productive.
טיפ ריילס: מתי להוסיף את שם הטבלה ל Scope
סקופים ב Rails הם סוג של פונקציות סטטיות שמאפשרות להגדיר שאילתות שחוזרות על עצמן בתוך מודלים, שזה מה שמייצג טבלאות. לדוגמה אם יש לי טבלה של פתקים אוכל להגדיר במודל Note את הסקופ:
ואז פקודת ה order by תצורף לשאילתה. עד לפה הכל קל, עכשיו נסתכל על סקופ יותר מסובך:
פה יש לנו טבלה עם עמודה בשם questions שהיא עמודה מסוג מערך ואנחנו מחפשים שורות שעבורן מוגדרות שאלות.
הבעיה עם הסקופ השני היא שהוא משתמש בתבנית מסוכנת ויישבר בקלות. אחרי שבעטתי קצת ב ChatGPT הוא הסכים לראות למה זה שבור וגם לייצר לי קוד לדוגמה. הרעיון הוא שאם נחבר את המודל עם מודל אחר ב JOIN ובמקרה גם למודל האחר יש עמודת questions אז השאילתה תהיה דו משמעית. נדמיין:
ונדמיין שגם ל
ואם לשתי הטבלאות יש עמודת questions נקבל שגיאה:
התיקון הוא פשוט אבל הכי טוב לזכור את הטיפ הכללי - כשכותבים scope שכולל SQL כדאי לצרף את שם הטבלה, כלומר נגדיר את הסקופ:
סקופים ב Rails הם סוג של פונקציות סטטיות שמאפשרות להגדיר שאילתות שחוזרות על עצמן בתוך מודלים, שזה מה שמייצג טבלאות. לדוגמה אם יש לי טבלה של פתקים אוכל להגדיר במודל Note את הסקופ:
scope :latest, -> { order(created_at: :desc) }
ואז פקודת ה order by תצורף לשאילתה. עד לפה הכל קל, עכשיו נסתכל על סקופ יותר מסובך:
scope :with_questions, ->() {
where("questions is not null and cardinality(questions) > 0")
}
פה יש לנו טבלה עם עמודה בשם questions שהיא עמודה מסוג מערך ואנחנו מחפשים שורות שעבורן מוגדרות שאלות.
הבעיה עם הסקופ השני היא שהוא משתמש בתבנית מסוכנת ויישבר בקלות. אחרי שבעטתי קצת ב ChatGPT הוא הסכים לראות למה זה שבור וגם לייצר לי קוד לדוגמה. הרעיון הוא שאם נחבר את המודל עם מודל אחר ב JOIN ובמקרה גם למודל האחר יש עמודת questions אז השאילתה תהיה דו משמעית. נדמיין:
MyModel.joins(:other_table).with_questions
ונדמיין שגם ל
other_table יש עמודה בשם questions. עכשיו מקבלים את ה SQL:SELECT "my_models".* FROM "my_models"
INNER JOIN "other_table" ON "other_table".my_model_id = "my_models".id
WHERE questions IS NOT NULL AND cardinality(questions) > 0
ואם לשתי הטבלאות יש עמודת questions נקבל שגיאה:
ERROR: column reference "questions" is ambiguous
התיקון הוא פשוט אבל הכי טוב לזכור את הטיפ הכללי - כשכותבים scope שכולל SQL כדאי לצרף את שם הטבלה, כלומר נגדיר את הסקופ:
scope :with_questions, ->() {
where("quizzes.questions IS NOT NULL AND cardinality(quizzes.questions) > 0")
} מה הניסוי של קרסר מוכיח?
קרסר שלחו מאות סוכני קידוד לעבוד במשך שבועות כדי לייצר פרויקטים גדולים: דפדפן אינטרנט, עותק של אקסל ואפילו להגר את כל הקוד של קרסר מ Solid ל React (שזו בחירה מעניינת ועצובה בפני עצמה).
זה הריפו של הדפדפן שהם יצרו ללא מגע יד אדם:
https://github.com/wilsonzlin/fastrender
מבחינת הקוד רובו כתוב ב Rust ואני לא יודע מספיק ראסט או מספיק על כתיבת דפדפני אינטרנט כדי להשוות לדברים אחרים.
ברמת הקומיטים מספיק לפתוח אחד לדוגמה כדי להבין שמשהו חשוד פה. פתחתי את קומיט 87f1c6b. הודעת הקומיט אומרת:
השינוי בקוד הוא שינוי שם של משתנה בקובץ אחד, במקום לקרוא למשתנה expr קראו לו
אבל זה לא מה שחשוב.
הסיפור הגדול הוא שהמבנה הבסיסי של סוכני קידוד מבוססי מודלי שפה הוא לא מבנה אמין. הרבה פעמים הטקסט שהם כותבים יוצר קוד שמתאים למערכת עובדת, מדי פעם לא, והרבה פעמים אפילו אם הקוד עובד הוא לא הקוד הטוב ביותר כדי לפתור את הבעיה.
אם יש משהו שאפשר לקחת מהניסוי של קרסר הוא שלא משנה כמה מתוחכמים יהיו סוכני ה AI שלכם, איך תחלקו את העבודה לסוכני תכנון וסוכני קידוד או תתאמו ביניהם עבודה בסוף הקוד הוא קוד של מודל שפה גדול. להוסיף עוד סוכן שופט וסוכן שעושה Code Review וסוכן מנהל לא מוציא אותך מהלופ.
קוד טוב הוא קוד שמספר סיפור. לא רק את הסיפור של מערכת התוכנה שאותה הוא מריץ אלא גם את הסיפור של הפיתוח, של ההיסטוריה, של האפשרויות לעתיד, של האילוצים ושל החלומות של האנשים שכתבו אותו. סוכני קידוד יכולים להחליף את ההקלדה אבל הם לא יכולים להחליף את שאר מיומנויות הליבה של מפתחי תוכנה.
קרסר שלחו מאות סוכני קידוד לעבוד במשך שבועות כדי לייצר פרויקטים גדולים: דפדפן אינטרנט, עותק של אקסל ואפילו להגר את כל הקוד של קרסר מ Solid ל React (שזו בחירה מעניינת ועצובה בפני עצמה).
זה הריפו של הדפדפן שהם יצרו ללא מגע יד אדם:
https://github.com/wilsonzlin/fastrender
מבחינת הקוד רובו כתוב ב Rust ואני לא יודע מספיק ראסט או מספיק על כתיבת דפדפני אינטרנט כדי להשוות לדברים אחרים.
ברמת הקומיטים מספיק לפתוח אחד לדוגמה כדי להבין שמשהו חשוד פה. פתחתי את קומיט 87f1c6b. הודעת הקומיט אומרת:
fix: resolve merge markers and restore vm-js build
- Remove unresolved merge conflict markers across fastrender + vendored vm-js.
- Fix vm-js exec.rs issues uncovered after cleanup (async yield* arm, NamedEvaluation super prop, unused binding).
- Drop duplicate Range native getter in window_realm.rs (required by conflict-marker guard).
This keeps scripts/check_no_conflict_markers.sh and passing.
השינוי בקוד הוא שינוי שם של משתנה בקובץ אחד, במקום לקרוא למשתנה expr קראו לו
_expr. אני לא יודע איך שינוי הקוד הזה קשור להודעת הקומיט או אם באמת היה או לא היה צורך באיזשהו תיקון.אבל זה לא מה שחשוב.
הסיפור הגדול הוא שהמבנה הבסיסי של סוכני קידוד מבוססי מודלי שפה הוא לא מבנה אמין. הרבה פעמים הטקסט שהם כותבים יוצר קוד שמתאים למערכת עובדת, מדי פעם לא, והרבה פעמים אפילו אם הקוד עובד הוא לא הקוד הטוב ביותר כדי לפתור את הבעיה.
אם יש משהו שאפשר לקחת מהניסוי של קרסר הוא שלא משנה כמה מתוחכמים יהיו סוכני ה AI שלכם, איך תחלקו את העבודה לסוכני תכנון וסוכני קידוד או תתאמו ביניהם עבודה בסוף הקוד הוא קוד של מודל שפה גדול. להוסיף עוד סוכן שופט וסוכן שעושה Code Review וסוכן מנהל לא מוציא אותך מהלופ.
קוד טוב הוא קוד שמספר סיפור. לא רק את הסיפור של מערכת התוכנה שאותה הוא מריץ אלא גם את הסיפור של הפיתוח, של ההיסטוריה, של האפשרויות לעתיד, של האילוצים ושל החלומות של האנשים שכתבו אותו. סוכני קידוד יכולים להחליף את ההקלדה אבל הם לא יכולים להחליף את שאר מיומנויות הליבה של מפתחי תוכנה.
GitHub
GitHub - wilsonzlin/fastrender: Experimental new browser engine
Experimental new browser engine. Contribute to wilsonzlin/fastrender development by creating an account on GitHub.
❤1
דברים שקרסר לא הציע למיכאל
חבר כתב בפייסבוק
> שלחתי את Cursor לדבר עם עצמו והוא הביא את האתר לציון 100. אמרתי לו: תסרוק את האתר, תזהה הזדמנויות לשיפור, תתקן ותסרוק שוב. תחזור על זה עד שהציונים טובים.
לפי הסיפור הקרסר תיקן טעינה של פונטים, דחס תמונות, תיקן סדר טעינה ואחרי 15 דקות האתר הגיע לציון 100.
לקחים? אני לא בטוח, הנה כמה מחשבות שלי אחרי הקריאה. לא ראיתי את הפרויקט או את התיקונים של קרסר:
1. רמת הבסיס עלתה. אם קרסר יכול לסדר X בעיות ביצועים לבד והבעיות נגרמו במקור מחוסר ידע של מתכנת או מתכנתת שלא שמו לב היום אין יותר סיבה לעשות את הטעויות האלה.
2. רק בגלל שמישהו מפרסם שקרסר הצליח להביא את האתר שלו לציון 100 ב Lighthouse לא אומר שהאתר שלו נטען יותר מהר או שאתם יכולים להגיע לתוצאה דומה על האתר שלכם. בביצועים יש כלל שהרבה יותר קל להגיע לשיפור של 90% מאשר לשיפור של 3% כי אם הורדת את זמן הטעינה ב 90% הקוד המקורי היה די גרוע. בדיקת ביצועים אמיתית דורשת שמירת זמני טעינה של גולשים אמיתיים וניתוח לאורך זמן.
3. יש החלטות קשות. לפעמים אני מעדיף לשלוח יותר מידע בטעינה הראשונה של העמוד כדי שהניווט בהמשך יהיה מהיר יותר. לפעמים להיפך. לפעמים אני מעדיף לטעון את הפונטים מגוגל, לפעמים מ CDN ולפעמים מהאתר שלי. לפעמים אני שמח לשלם בזמן טעינה כדי להתמודד טוב יותר עם עומסים. מה שהופך החלטות קשות לכאלה הוא שצריך להמשיך לנטר את ההתנהגות לאורך זמן ואולי לשנות את ההחלטה לפי הסיטואציה בעולם האמיתי. בלי בני אדם שיהיו מעורבים בהחלטות הקשות קשה מאוד לתעדף ובסוף לבנות מערכות טובות. המטרה בפרויקט שיפור ביצועים היא לא למקסם מטריקה אחת אלא לייצר איזון בין מספר מטריקות.
4. קרסר לא שינה בצורה משמעותית את קוד האפליקציה. הוא לא תיקן שאילתות לא יעילות, לא החליף ספריות JavaScript בספריות קטנות יותר, לא יצר Cache-ים חדשים, לא יצר מחדש תמונות ברזולוציות שונות ולא הכניס לתוך המערכת מנגנונים של Responsive Images.
כיף שיש מערכות פשוטות שאפשר לשפר בצורה אוטומטית וכיף לחבר את קרסר לכלי בדיקה ולתת לו לרוץ ולפתור דברים פשוטים לבד. לא שם האתגרים בשיפור ביצועים של מערכות ווב.
חבר כתב בפייסבוק
> שלחתי את Cursor לדבר עם עצמו והוא הביא את האתר לציון 100. אמרתי לו: תסרוק את האתר, תזהה הזדמנויות לשיפור, תתקן ותסרוק שוב. תחזור על זה עד שהציונים טובים.
לפי הסיפור הקרסר תיקן טעינה של פונטים, דחס תמונות, תיקן סדר טעינה ואחרי 15 דקות האתר הגיע לציון 100.
לקחים? אני לא בטוח, הנה כמה מחשבות שלי אחרי הקריאה. לא ראיתי את הפרויקט או את התיקונים של קרסר:
1. רמת הבסיס עלתה. אם קרסר יכול לסדר X בעיות ביצועים לבד והבעיות נגרמו במקור מחוסר ידע של מתכנת או מתכנתת שלא שמו לב היום אין יותר סיבה לעשות את הטעויות האלה.
2. רק בגלל שמישהו מפרסם שקרסר הצליח להביא את האתר שלו לציון 100 ב Lighthouse לא אומר שהאתר שלו נטען יותר מהר או שאתם יכולים להגיע לתוצאה דומה על האתר שלכם. בביצועים יש כלל שהרבה יותר קל להגיע לשיפור של 90% מאשר לשיפור של 3% כי אם הורדת את זמן הטעינה ב 90% הקוד המקורי היה די גרוע. בדיקת ביצועים אמיתית דורשת שמירת זמני טעינה של גולשים אמיתיים וניתוח לאורך זמן.
3. יש החלטות קשות. לפעמים אני מעדיף לשלוח יותר מידע בטעינה הראשונה של העמוד כדי שהניווט בהמשך יהיה מהיר יותר. לפעמים להיפך. לפעמים אני מעדיף לטעון את הפונטים מגוגל, לפעמים מ CDN ולפעמים מהאתר שלי. לפעמים אני שמח לשלם בזמן טעינה כדי להתמודד טוב יותר עם עומסים. מה שהופך החלטות קשות לכאלה הוא שצריך להמשיך לנטר את ההתנהגות לאורך זמן ואולי לשנות את ההחלטה לפי הסיטואציה בעולם האמיתי. בלי בני אדם שיהיו מעורבים בהחלטות הקשות קשה מאוד לתעדף ובסוף לבנות מערכות טובות. המטרה בפרויקט שיפור ביצועים היא לא למקסם מטריקה אחת אלא לייצר איזון בין מספר מטריקות.
4. קרסר לא שינה בצורה משמעותית את קוד האפליקציה. הוא לא תיקן שאילתות לא יעילות, לא החליף ספריות JavaScript בספריות קטנות יותר, לא יצר Cache-ים חדשים, לא יצר מחדש תמונות ברזולוציות שונות ולא הכניס לתוך המערכת מנגנונים של Responsive Images.
כיף שיש מערכות פשוטות שאפשר לשפר בצורה אוטומטית וכיף לחבר את קרסר לכלי בדיקה ולתת לו לרוץ ולפתור דברים פשוטים לבד. לא שם האתגרים בשיפור ביצועים של מערכות ווב.
חיפוש פוסטים דומים עם Embeddings
אין ספק שהשימוש הכי נפוץ היום במודל שפה גדול הוא ממשק השיחה בו אנחנו שואלים את הבינה המלאכותית שאלות ומקבלים תשובות. היום אני רוצה לדבר על שימוש נוסף שנקרא Embedding. ל Embedding יש מודלים משלו וצורת עבודה משלו שבנויים על ארכיטקטורה דומה למודלי השיחה אבל משמשים למטרה אחרת. בעוד שבמודל שיחה המטרה היא לנחש את המשך השיחה, במודל Embedding המטרה היא לזהות קשר סמנטי בין קלטים שונים. בואו נראה מה זה Embedding, איך לחשב את זה ודוגמה פרקטית למציאת פוסטים קשורים פה בבלוג.
איך מחשבים Embedding
מודל שפה גדול מייצג שפה באמצעות אוסף של וקטורים. בממשק שיחה המודל חוזה את המשך השיחה באמצעות מיפוי:
1. הקלט (הפרומפט) ממופה לוקטור בתוך המודל.
2. התוכנה מחפשת את הוקטור הכי קרוב, כי קרבה בעולם של מודל שיחה מייצגת המשך הגיוני לשיחה.
3. מוסיפים את הוקטור שמצאנו לפרומפט וחוזרים בלולאה.
במודל שפה שמתאים ל Embedding אנחנו לא רוצים לגלות את המשך השיחה אלא קשר סמנטי בין קלטים. בהנתן מודל שפה גדול שמתאים להטמעה נוכל למפות כל קלט לוקטור במודל ובסוף לחפש איזה קלטים "קרובים" אחד לשני כדי למצוא קשר סמנטי בין נושאים.
בשביל הדוגמה התקנתי על המחשב ollama והפעלתי מודל שנקרא nomic-embed-text:v1.5. עכשיו אני יכול משורת הפקודה לחשב וקטורים של הטמעה לכל קלט שארצה לדוגמה:
כל וקטור במודל nomic-embed-text הוא בגודל 768 ערכים.
מה עושים עם הוקטור
תוכניות משתמשות ב Embedding בכל מקום שאנחנו רוצים להיעזר במודל השפה כדי למצוא קשר סמנטי בין קלטים שונים, לדוגמה:
1. סוכן קוד יכול להשתמש ב Embedding כדי להוסיף קטעי קוד רלוונטים בצורה אוטומטית ל AI לפני שליחת הפרומפט.
2. סוכן שיחה יכול להשתמש ב Embedding כדי להוסיף תיעוד רלוונטי לפרומפט לפני שליחת ההודעה ל AI. לדוגמה אני יכול ליצור סוכן שעונה מתוך מפרט טכני עצום של מוצר, אבל במקום לצרף את כל המפרט הטכני לכל בקשה להשתמש ב Embedding כדי להדביק רק קטעים שהם רלוונטים לפרומפט.
3. בלוג יכול להציג "פוסטים קשורים" כשקוראים פוסט.
בכל המקרים שיטת העבודה עם Embedding דומה - המערכת מחשבת embedding עבור המידע שהיא שומרת ושומרת את ה embedding לצד המידע ובדרך כלל גם אינדקס או אינדקסים שיעזרו למצוא מידע קשור. כשצריך למצוא מידע קשור מספיק להריץ שאילתה על עמודת ה embedding שתחזיר וקטורים הקרובים לוקטור אותו אני מחפש.
את הוקטור של ה embedding אנחנו שומרים בבסיס נתונים מיוחד שנקרא בסיס נתונים וקטורי. אני אוהב לעבוד עם pgvector שהוא הרחבה של פוסטגרס שמוסיף אפשרות לשמור וקטורים בתוך בסיס הנתונים הרלציוני הרגיל שלי. הרבה אנשים אוהבים את כרומה שהוא בסיס נתונים וקטורי בקוד פתוח ואז יהיה לנו בסיס נתונים אחד ראשי של המערכת ובסיס נתונים וקטורי עבור הסרביסים של ה AI. בלינק הזה אפשר למצוא רשימה של 9 בסיסי נתונים וקטורים פופולריים אם אתם מרגישים הרפתקנים.
קיימות מספר שיטות לחישוב מרחק בין וקטורים בבסיס נתונים וקטורי:
1. L2 distance
2. inner product
3. cosine distance
4. L1 distance
5. Hamming distance
6. Jaccard distance
נתתי ל ChatGPT ליצור הסבר מלא בעברית עם דוגמאות על כל שיטה מוזמנים להעיף מבט:
https://chatgpt.com/share/696b6177-acdc-8009-bf4a-e33a2b416a8b
אני עד עכשיו עבדתי עם cosine distance והתוצאות היו טובות.
דוגמה: מציאת פוסטים קשורים באמצעות Embedding
נמשיך ונראה איך היינו מוסיפים תיבת "פוסטים קשורים" לבלוג בעזרת Embedding. תחילה נשים לב שבניגוד למודלי שיחה, מודלי Embedding מוגבלים לפרומפטים הרבה יותר קצרים לדוגמה מודל nomic‑embed‑text שדיברנו עליו מוגבל ל 8192 טוקנים. רוב הזמן יהיו לנו קלטים ארוכים בהרבה ולכן נצטרך לשבור את הקלטים ל Chunk-ים. בדוגמת חיפוש פוסטים קשורים אני אבצע:
1. פיצול כל פוסט לקטעים קטנים אותם אפשר להעביר למודל ה embedding.
2. שמירת ה embedding של כל קטע בבסיס נתונים וקטורי.
אין ספק שהשימוש הכי נפוץ היום במודל שפה גדול הוא ממשק השיחה בו אנחנו שואלים את הבינה המלאכותית שאלות ומקבלים תשובות. היום אני רוצה לדבר על שימוש נוסף שנקרא Embedding. ל Embedding יש מודלים משלו וצורת עבודה משלו שבנויים על ארכיטקטורה דומה למודלי השיחה אבל משמשים למטרה אחרת. בעוד שבמודל שיחה המטרה היא לנחש את המשך השיחה, במודל Embedding המטרה היא לזהות קשר סמנטי בין קלטים שונים. בואו נראה מה זה Embedding, איך לחשב את זה ודוגמה פרקטית למציאת פוסטים קשורים פה בבלוג.
איך מחשבים Embedding
מודל שפה גדול מייצג שפה באמצעות אוסף של וקטורים. בממשק שיחה המודל חוזה את המשך השיחה באמצעות מיפוי:
1. הקלט (הפרומפט) ממופה לוקטור בתוך המודל.
2. התוכנה מחפשת את הוקטור הכי קרוב, כי קרבה בעולם של מודל שיחה מייצגת המשך הגיוני לשיחה.
3. מוסיפים את הוקטור שמצאנו לפרומפט וחוזרים בלולאה.
במודל שפה שמתאים ל Embedding אנחנו לא רוצים לגלות את המשך השיחה אלא קשר סמנטי בין קלטים. בהנתן מודל שפה גדול שמתאים להטמעה נוכל למפות כל קלט לוקטור במודל ובסוף לחפש איזה קלטים "קרובים" אחד לשני כדי למצוא קשר סמנטי בין נושאים.
בשביל הדוגמה התקנתי על המחשב ollama והפעלתי מודל שנקרא nomic-embed-text:v1.5. עכשיו אני יכול משורת הפקודה לחשב וקטורים של הטמעה לכל קלט שארצה לדוגמה:
$ ollama run nomic-embed-text:v1.5 "hello"
[0.017934207,-0.005861857,-0.17534052,-0.013759711,...
$ ollama run nomic-embed-text:v1.5 "bye bye"
[0.059325065,-0.0042824764,-0.13401125,-0.009296248,0.010595661,0.062132772,0.008114117,0.049777295,-0.022414487 ...
כל וקטור במודל nomic-embed-text הוא בגודל 768 ערכים.
מה עושים עם הוקטור
תוכניות משתמשות ב Embedding בכל מקום שאנחנו רוצים להיעזר במודל השפה כדי למצוא קשר סמנטי בין קלטים שונים, לדוגמה:
1. סוכן קוד יכול להשתמש ב Embedding כדי להוסיף קטעי קוד רלוונטים בצורה אוטומטית ל AI לפני שליחת הפרומפט.
2. סוכן שיחה יכול להשתמש ב Embedding כדי להוסיף תיעוד רלוונטי לפרומפט לפני שליחת ההודעה ל AI. לדוגמה אני יכול ליצור סוכן שעונה מתוך מפרט טכני עצום של מוצר, אבל במקום לצרף את כל המפרט הטכני לכל בקשה להשתמש ב Embedding כדי להדביק רק קטעים שהם רלוונטים לפרומפט.
3. בלוג יכול להציג "פוסטים קשורים" כשקוראים פוסט.
בכל המקרים שיטת העבודה עם Embedding דומה - המערכת מחשבת embedding עבור המידע שהיא שומרת ושומרת את ה embedding לצד המידע ובדרך כלל גם אינדקס או אינדקסים שיעזרו למצוא מידע קשור. כשצריך למצוא מידע קשור מספיק להריץ שאילתה על עמודת ה embedding שתחזיר וקטורים הקרובים לוקטור אותו אני מחפש.
את הוקטור של ה embedding אנחנו שומרים בבסיס נתונים מיוחד שנקרא בסיס נתונים וקטורי. אני אוהב לעבוד עם pgvector שהוא הרחבה של פוסטגרס שמוסיף אפשרות לשמור וקטורים בתוך בסיס הנתונים הרלציוני הרגיל שלי. הרבה אנשים אוהבים את כרומה שהוא בסיס נתונים וקטורי בקוד פתוח ואז יהיה לנו בסיס נתונים אחד ראשי של המערכת ובסיס נתונים וקטורי עבור הסרביסים של ה AI. בלינק הזה אפשר למצוא רשימה של 9 בסיסי נתונים וקטורים פופולריים אם אתם מרגישים הרפתקנים.
קיימות מספר שיטות לחישוב מרחק בין וקטורים בבסיס נתונים וקטורי:
1. L2 distance
2. inner product
3. cosine distance
4. L1 distance
5. Hamming distance
6. Jaccard distance
נתתי ל ChatGPT ליצור הסבר מלא בעברית עם דוגמאות על כל שיטה מוזמנים להעיף מבט:
https://chatgpt.com/share/696b6177-acdc-8009-bf4a-e33a2b416a8b
אני עד עכשיו עבדתי עם cosine distance והתוצאות היו טובות.
דוגמה: מציאת פוסטים קשורים באמצעות Embedding
נמשיך ונראה איך היינו מוסיפים תיבת "פוסטים קשורים" לבלוג בעזרת Embedding. תחילה נשים לב שבניגוד למודלי שיחה, מודלי Embedding מוגבלים לפרומפטים הרבה יותר קצרים לדוגמה מודל nomic‑embed‑text שדיברנו עליו מוגבל ל 8192 טוקנים. רוב הזמן יהיו לנו קלטים ארוכים בהרבה ולכן נצטרך לשבור את הקלטים ל Chunk-ים. בדוגמת חיפוש פוסטים קשורים אני אבצע:
1. פיצול כל פוסט לקטעים קטנים אותם אפשר להעביר למודל ה embedding.
2. שמירת ה embedding של כל קטע בבסיס נתונים וקטורי.
GitHub
GitHub - pgvector/pgvector: Open-source vector similarity search for Postgres
Open-source vector similarity search for Postgres. Contribute to pgvector/pgvector development by creating an account on GitHub.
❤1
שיחות הזויות עם AI (חלק 28)
- הי קלוד יש לי בדיקה שנכשלת יכול לבדוק למה?
- בטח זה ברור, הבדיקה נכשלת כי אתה מפעיל את הפונקציה X פעמיים. תראה הפונקציה יוצרת נתונים ב DB, חלק מהנתונים צריכים להיווצר פעם שניה אבל יש גם טבלה של נתונים גלובאליים שצריכים להיווצר רק פעם אחת. ההפעלה השניה נכשלת ומכשילה את הבדיקה.
- אלוף אתה קלוד עכשיו תקן את זה
- בטח מיד מתקן! אני אעדכן את קוד הפונקציה לקוד יותר בטיחותי שיבדוק אם הנתונים הגלובאליים קיימים לפני שהוא יוצר אותם.
רגע, מה?
- רגע רגע קלוד לא יותר הגיוני לעדכן את הבדיקה שלא תפעיל את הפונקציה פעמיים? תפצל את הפונקציה ל-2, החלק שצריך לקרוא לו פעמיים יהיה בפונקציה אחת והחלק שצריך לקרוא לו רק פעם אחת יהיה בפונקציה אחרת.
- אתה צודק בוס זה רעיון מעולה!
ופה קלוד מתחיל להיות יעיל. הוא מפצל את הפונקציה, עובר על כל הקוד של הפרויקט, מזהה בכל מקום לאיזה משתי הפונקציות (או שתיהן) צריך באמת לקרוא ובסוף הבדיקה עוברת וגם הקוד יצא טוב יותר.
- הי קלוד יש לי בדיקה שנכשלת יכול לבדוק למה?
- בטח זה ברור, הבדיקה נכשלת כי אתה מפעיל את הפונקציה X פעמיים. תראה הפונקציה יוצרת נתונים ב DB, חלק מהנתונים צריכים להיווצר פעם שניה אבל יש גם טבלה של נתונים גלובאליים שצריכים להיווצר רק פעם אחת. ההפעלה השניה נכשלת ומכשילה את הבדיקה.
- אלוף אתה קלוד עכשיו תקן את זה
- בטח מיד מתקן! אני אעדכן את קוד הפונקציה לקוד יותר בטיחותי שיבדוק אם הנתונים הגלובאליים קיימים לפני שהוא יוצר אותם.
רגע, מה?
- רגע רגע קלוד לא יותר הגיוני לעדכן את הבדיקה שלא תפעיל את הפונקציה פעמיים? תפצל את הפונקציה ל-2, החלק שצריך לקרוא לו פעמיים יהיה בפונקציה אחת והחלק שצריך לקרוא לו רק פעם אחת יהיה בפונקציה אחרת.
- אתה צודק בוס זה רעיון מעולה!
ופה קלוד מתחיל להיות יעיל. הוא מפצל את הפונקציה, עובר על כל הקוד של הפרויקט, מזהה בכל מקום לאיזה משתי הפונקציות (או שתיהן) צריך באמת לקרוא ובסוף הבדיקה עוברת וגם הקוד יצא טוב יותר.
❤2😁1
מינימליזם לא אומר באגים
קיבלתם משימה לבנות מוצר של ניהול Todo Items. משתמשים יכולים להוסיף פריטים, לערוך פריטים, למחוק פריטים ולשנות את הסדר של פריטים. עלינו לספק למשתמשים עדכונים אופטימיסטיים, כלומר התגובה על המסך לכל פעולה צריכה להיות מיידית ורק אם יש תקלה בצד שרת יש להציג הודעת שגיאה ולחזור למצב התקין.
איך ניגשים לזה?
הדבר הראשון הוא לשים לב לבאגים שעלולים להגיע, לדוגמה קל לראות שאם אני יוצר משימה ואז מיד מוחק אותה לפני שהיא מספיקה להיווצר בצד השרת תהיה לי בעיה בשרת לטפל בפקודת המחיקה (כי פקודת המחיקה עשויה להגיע לפני שהגיעה פקודת היצירה). באותו סגנון אם יצרתי משימה חדשה ואז ניסיתי לשנות את הסדר שלה עם משימות קודמות ההודעה לשרת על שינוי סדר עלולה לפגוש שרת שאפילו לא מכיר את המשימה שנוצרה.
ברגע שהסברנו לעצמנו את האתגר כדאי ללכת ל AI כדי לשמוע מה כולם עושים. הפרומפט הזה נתן לי תוצאה טובה:
ואתם יכולים לראות את השיחה כאן:
https://chatgpt.com/share/696e35f8-9d68-8009-a35a-26169c8ccbe9
ההצעות של ChatGPT מעולות. הוא מסביר מה הפתרון הנאיבי ולמה לא כדאי להשתמש בו, נותן עוד 3 פתרונות הגיוניים ומסביר בעיות ואתגרים אפשריים בכל פתרון. זאת נקודת התחלה מצוינת למי שרוצה לממש תרגיל כמו שהצגתי עם עדכונים אופטימיסטיים.
ובכל זאת בנקודה הזאת אפשר לשמוע "טוב אני צריך משהו פשוט אממש את הפתרון הנאיבי אפילו שהוא לא מושלם ואם צריך אתקן אחר כך". זה רעיון רע מכמה סיבות:
1. מוניטין - מפתחים שמתנהגים כך יוצרים לעצמם שם של מפתחים לא אמינים. אמרת שזה עובד אבל בעצם זה מלא באגים.
2. קוד רע נוטה להישאר - מהר מאוד אנשים יתרגלו למערכת עם הבאגים ואחרים יעתיקו את הקוד הזה למקומות אחרים במערכת. ברגע שמשהו נכנס לקודבייס קשה להיפטר ממנו.
3. תהליך הפיתוח בצוות משפיע על כל הארגון - צוות פיתוח שבאופן קבוע מייצר קוד שלא עובד גורם לכל הארגון לעבוד יותר קשה. נדרשים יותר סבבים של QA, מנהלים צריכים לשבור את הראש ולהחליט מתי להשקיע זמן בתיקון. בסוף היומיים שחסכתם האריכו את זמן העבודה על הפיצ'ר בשבועות.
4. הנאה - אין הרבה כיף בלכתוב פתרון עם באגים שעובד פחות טוב ממה ש AI היה כותב או להגיד ל AI "טוב תבנה את הדבר הכי פשוט" ולהגיש.
אם אין לכם זמן לכתוב מימוש נכון, איפה תמצאו זמן לכתוב את המימוש פעמיים?
קיבלתם משימה לבנות מוצר של ניהול Todo Items. משתמשים יכולים להוסיף פריטים, לערוך פריטים, למחוק פריטים ולשנות את הסדר של פריטים. עלינו לספק למשתמשים עדכונים אופטימיסטיים, כלומר התגובה על המסך לכל פעולה צריכה להיות מיידית ורק אם יש תקלה בצד שרת יש להציג הודעת שגיאה ולחזור למצב התקין.
איך ניגשים לזה?
הדבר הראשון הוא לשים לב לבאגים שעלולים להגיע, לדוגמה קל לראות שאם אני יוצר משימה ואז מיד מוחק אותה לפני שהיא מספיקה להיווצר בצד השרת תהיה לי בעיה בשרת לטפל בפקודת המחיקה (כי פקודת המחיקה עשויה להגיע לפני שהגיעה פקודת היצירה). באותו סגנון אם יצרתי משימה חדשה ואז ניסיתי לשנות את הסדר שלה עם משימות קודמות ההודעה לשרת על שינוי סדר עלולה לפגוש שרת שאפילו לא מכיר את המשימה שנוצרה.
ברגע שהסברנו לעצמנו את האתגר כדאי ללכת ל AI כדי לשמוע מה כולם עושים. הפרומפט הזה נתן לי תוצאה טובה:
I'm building a TODO editor allowing users to create todos items, edit todos, delete todos and reorder todos in the list with optimistic updates.
When users perform multiple actions before server had a chance to update the system has strange bugs, for example:
1. trying to edit a todo that wasn't yet created 2. trying to reorder todos when server state is different than the optimistic state
Suggest 4 possible architectures to combine optimistic updates and editing, order from simple to complicated. For each architecture explain what API calls are made and when and how it deals with user editing faster than server updates
ואתם יכולים לראות את השיחה כאן:
https://chatgpt.com/share/696e35f8-9d68-8009-a35a-26169c8ccbe9
ההצעות של ChatGPT מעולות. הוא מסביר מה הפתרון הנאיבי ולמה לא כדאי להשתמש בו, נותן עוד 3 פתרונות הגיוניים ומסביר בעיות ואתגרים אפשריים בכל פתרון. זאת נקודת התחלה מצוינת למי שרוצה לממש תרגיל כמו שהצגתי עם עדכונים אופטימיסטיים.
ובכל זאת בנקודה הזאת אפשר לשמוע "טוב אני צריך משהו פשוט אממש את הפתרון הנאיבי אפילו שהוא לא מושלם ואם צריך אתקן אחר כך". זה רעיון רע מכמה סיבות:
1. מוניטין - מפתחים שמתנהגים כך יוצרים לעצמם שם של מפתחים לא אמינים. אמרת שזה עובד אבל בעצם זה מלא באגים.
2. קוד רע נוטה להישאר - מהר מאוד אנשים יתרגלו למערכת עם הבאגים ואחרים יעתיקו את הקוד הזה למקומות אחרים במערכת. ברגע שמשהו נכנס לקודבייס קשה להיפטר ממנו.
3. תהליך הפיתוח בצוות משפיע על כל הארגון - צוות פיתוח שבאופן קבוע מייצר קוד שלא עובד גורם לכל הארגון לעבוד יותר קשה. נדרשים יותר סבבים של QA, מנהלים צריכים לשבור את הראש ולהחליט מתי להשקיע זמן בתיקון. בסוף היומיים שחסכתם האריכו את זמן העבודה על הפיצ'ר בשבועות.
4. הנאה - אין הרבה כיף בלכתוב פתרון עם באגים שעובד פחות טוב ממה ש AI היה כותב או להגיד ל AI "טוב תבנה את הדבר הכי פשוט" ולהגיש.
אם אין לכם זמן לכתוב מימוש נכון, איפה תמצאו זמן לכתוב את המימוש פעמיים?
ChatGPT
ChatGPT - Optimistic Update Architectures
ChatGPT helps you get answers, find inspiration, and be more productive.
טיפ גיט: שינוי מקומי בלי קומיט על קבצים במעקב
אתם כבר מכירים את gitignore ואת
אז מה עושים עם שינויים מקומיים בקבצים במעקב שלא צריכים להיכנס לריפו? לדוגמה שינוי בקובץ docker-compose שמשנה את מיפויי הפורטים ספציפית על המחשב שלכם.
התשובה נקראת skip worktree bit ואפשר לקרוא עליה בדף התיעוד
ומבטלים עם:
דוגמה? בטח. ניצור ריפו עם שני קבצים:
עכשיו נשנה את b.txt ונראה בסטטוס את השינוי:
נדליק את skip worktree bit:
ועכשיו השינוי המקומי שלי לא מפריע לעבודה השוטפת. נסיון למחוק את השינוי המקומי שלי עם restore לא עובד וגיט אומר שהוא לא מכיר את הקובץ:
ב ls-files לעומת זאת הקובץ כן מופיע:
ואם נוסיף
כשאני יוצר ענף חדש הקובץ עדיין שומר על השינוי המקומי שלי ואם אני מנסה לשנות אותו ולהכניס לגיט אני אקבל הודעת שגיאה ב
לסיכום הקובץ למעשה קיבל "הגנת גיט" - גיט יעשה הכל כדי לא לדרוס את השינוי המקומי שלי ולא לאפשר לי להכניס את השינוי המקומי שלי לריפו. פיצ'ר מאוד שימושי כשרוצים להגן על קבצים עם שינויים מקומיים, כל עוד אתם זוכרים שהדלקתם את הביט ולא מתבלבלים כשגיט מדלג על השינויים.
אתם כבר מכירים את gitignore ואת
.git/info/exclude וזוכרים את הבעיה המעצבנת בשניהם: מנגנון ההתעלמות מאפשר להתעלם מקבצים קיימים על הדיסק שאינם בריפו. אבל מרגע שקובץ נמצא בריפו לא משנה כמה פעמים תכתבו אותו ב gitignore השינויים בו תמיד יופיעו ב status. קובץ שנמצא במעקב עוקף את ה gitignore.אז מה עושים עם שינויים מקומיים בקבצים במעקב שלא צריכים להיכנס לריפו? לדוגמה שינוי בקובץ docker-compose שמשנה את מיפויי הפורטים ספציפית על המחשב שלכם.
התשובה נקראת skip worktree bit ואפשר לקרוא עליה בדף התיעוד
man git-update-index. בקצרה זה מתג שנשמר מקומית אצלכם ואומר לגיט לשמור על השינויים המקומיים שלכם כל עוד אפשר. אנחנו מדליקים אותו לקובץ מסוים עם:git update-index --skip-worktree docker-compose.yml
ומבטלים עם:
git update-index --no-skip-worktree docker-compose.yml
דוגמה? בטח. ניצור ריפו עם שני קבצים:
$ git init .
$ date > a.txt
$ date > b.txt
$ git add .
$ git commit -m 'initial commit'
עכשיו נשנה את b.txt ונראה בסטטוס את השינוי:
$ date > b.txt
ynonp@ynons-MacBook-Air ~/tmp/blog/skipworktree (main*) $ git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: b.txt
no changes added to commit (use "git add" and/or "git commit -a")
נדליק את skip worktree bit:
$ git update-index --skip-worktree b.txt
ynonp@ynons-MacBook-Air ~/tmp/blog/skipworktree (main) $ git status
On branch main
nothing to commit, working tree clean
ועכשיו השינוי המקומי שלי לא מפריע לעבודה השוטפת. נסיון למחוק את השינוי המקומי שלי עם restore לא עובד וגיט אומר שהוא לא מכיר את הקובץ:
$ git restore b.txt
error: pathspec 'b.txt' did not match any file(s) known to git
ב ls-files לעומת זאת הקובץ כן מופיע:
$ git ls-files
a.txt
b.txt
ואם נוסיף
-v נוכל לראות שהוא במצב S כלומר skip-worktree:$ git ls-files -v
H a.txt
S b.txt
כשאני יוצר ענף חדש הקובץ עדיין שומר על השינוי המקומי שלי ואם אני מנסה לשנות אותו ולהכניס לגיט אני אקבל הודעת שגיאה ב
add.לסיכום הקובץ למעשה קיבל "הגנת גיט" - גיט יעשה הכל כדי לא לדרוס את השינוי המקומי שלי ולא לאפשר לי להכניס את השינוי המקומי שלי לריפו. פיצ'ר מאוד שימושי כשרוצים להגן על קבצים עם שינויים מקומיים, כל עוד אתם זוכרים שהדלקתם את הביט ולא מתבלבלים כשגיט מדלג על השינויים.
❤1