ChatGPT, GitHub Copilot, Cursor, ובני דודיהם יכולים כעת לפלוט קומפוננטת React עוד לפני שסיימתם להקליד את הפרומפט. לחבר נתיב (route) של Next.js ל-Supabase? זה מוכן תוך שניות. לעשות refactor לכלי TypeScript מסורבל? הנה שלוש אפשרויות, כולל type guards. עבור כל מי שעובד עם web stacks מודרניים, החוויה יכולה להרגיש כמעט קסומה.

אני משתמש בכלים האלה מדי יום. ה-stack שלי הוא Next.js, TypeScript ו-Supabase, וה-AI יושב ממש שם בעורך שלי, מוכן לבנות custom hooks, לייצר שאילתות מסד נתונים, או לנקות לוגיקה מותנית מבולגנת. בפרטים הקטנים, הוא מתפקד כמו מפתח ג'וניור מהיר מאוד. הוא מכיר את הסינטקס בעל פה. הוא זוכר שטחי API שאני צריך לחפש בגוגל. הוא לא מתעייף מכתיבת boilerplate.

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

התשובה היא שיצירת סינטקס ובניית תוכנה הן לא אותה עבודה.

סינטקס הוא לא ארכיטקטורה

AI מטפל בטוקנים (tokens) בצורה יוצאת דופן. בקשו ממנו לכתוב useEffect hook שמקשיב לערוץ real-time של Supabase, ותקבלו משהו שמתקמפל. הוא יכול להפוך קובץ JavaScript ללא טיפוסים ל-TypeScript קשיח, או להקים קומפוננטת טופס עם ולידציה של Zod עוד לפני שהספקתם לשתות את הקפה.

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

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

שתי נקודות החיכוך

כשאני נותן ל-AI לכתוב קטעי קוד גדולים יותר ללא guardrails קשיחים, אני מבחין בשתי אותן בעיות שעולות שוב ושוב.

ראשית, הוא מתעלם מדפוסי העיצוב (design patterns) שכבר קבעתם. אולי הצוות שלכם מוציא את כל שליפת הנתונים (data fetching) לשכבה ייעודית של custom hooks. אולי יש לכם מוסכמה קשיחה לאופן שבו מדיניות ה-RLS של Supabase מתאימה ל-frontend helpers. ל-AI לא אכפת. הוא יזרוק supabase.from().select() גולמי ישר לתוך ה-onClick של כפתור אם זה פותר את הפרומפט המיידי. הקוד רץ. הוא אפילו נראה נקי. אבל הוא חריג (outlier) ב-codebase שלכם, וכל חריג הוא מס של refactoring בעתיד. שישה חודשים לאחר מכן, מישהו יצטרך למצוא את המחט הזו, להבין למה היא קיימת, ולהחזיר אותה בעדינות לשורה.

שנית, הוא שואף למורכבות כשפשטות הייתה מספיקה. הכלי אומן על מאגרים (repositories) גדולים מספיק כדי להזדקק ל-abstract factories, דפוסי reducer מורכבים, ו-higher-order components רב-שכבתיים. כשאתם מבקשים ממנו לבנות טופס יצירת קשר פשוט, הוא בהחלט עלול להגיש לכם state machine, context provider, והפשטה של custom hook שמתפרסת על פני שלושה קבצים. הפתרון אינו שגוי מבחינה טכנית. הוא פשוט כבד. כל שכבה מיותרת מוסיפה חוב קוגניטיבי (cognitive debt). לא דילגתם על העבודה; דחיתם אותה, עם ריבית.

מלכודת המהירות

יש כאן לולאת משוב מסוכנת. ה-AI מאפשר לכם לבנות פיצ'רים פי שניים מהר יותר, אבל הקשב האנושי לא גדל באותו אופן. אם אתם משיקים (shipping) בחצי מהזמן, האם אתם מבלים פי שניים זמן ב-code review? האם אתם כותבים יותר טסטים, או פחות?

בפועל, קל להפליא לסמוך על קוד שנוצר כי הוא נראה סמכותי. הוא משתמש בסינטקס מודרני. הערות מפוזרות בדיוק במקומות הנכונים. שמות המשתנים נשמעים מקצועיים. באגים עדינים מסתתרים בתוך הגימור הזה. מערך תלות (dependency array) ב-hook שמשמיט setter. טיפוס TypeScript שהוא נכון טכנית אך מאפשר מצב null ששכחתם לטפל בו. שאילתת Supabase ששוכחת להתחשב בשורות שנמחקו רך (soft-deleted) בסכימה הספציפית שלכם. אתם עוברים על הקוד במהירות במקום לקרוא כל שורה, כי קצב המסירה מחייב זאת. המהירות מרגישה נהדרת ביום שני. מפגש הדיבאגינג ביום שישי נמשך עד חצות.

העלות האמיתית

האנשים שמשלמים על זה הם לא המפתחים. הם המשתמשים הקצה.

תוכנה מרגישה מסורבלת יותר מכיוון שהמורכבות גדלה מהר יותר מהיכולת של צוותים לנהל אותה. אנחנו בונים אפליקציות גדולות יותר עם צוותים קטנים יותר, חמושים בכלים שגורמים לנו להרגיש בלתי מנוצחים. כשמפתח אחד יכול להקים dashboard שלם בשעות אחר הצהריים, הארגון מצפה לשלושה dashboards עד יום רביעי. צמיחה (Scale) ללא תשומת לב מייצרת מערכות שבירות. ה-State מתנפח. גודלי ה-bundle עולים בהדרגה. Race conditions מתרבים. הממשק עשוי להיראות מודרני, אבל הוא מאתחל את עצמו כשמשתמש לוחץ על כפתור ה"חזור", או שהוא לוקח ארבע שניות לבצע hydration כי לאף אחד לא היה זמן לבצע profiling ל-waterfall של data fetches שנוצרו על ידי AI.

לעבוד עם המכונה, לא עבורה

אף אחד מהדברים האלה לא אומר שאתם צריכים לזרוק את ה-AI מהעורך שלכם. זה אומר שאתם זקוקים לגבולות.

השתמשו בו במה שהוא טוב בו. תנו לו לכתוב את הדברים המשעממים: TypeScript interfaces חוזרים על עצמם, boilerplate Supabase queries, ו-Jest setup.