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

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

מתי ואיך אני משתמש ב AI

01/04/2025

שאלה אמיתית - אתם מרגישים שאתם מרגישים יותר מדי או פחות מדי ב AI? ואם פחות מדי, למה אתם לא משתמשים בו יותר? הנה רשימת המקרים בהם אני משתמש ב AI במהלך הפיתוח ו Best Practices שמצאתי לכל מקרה:

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

  2. כשאני כותב קוד ויודע מה אני רוצה - אם אני בונה סכימה לדריזל ואני יודע איזה טבלה אני רוצה ואיזה עמודות זה זמן מושלם ללחוץ Command I ב VS Code ולבקש מ Copilot לכתוב את הבלוק שמוסיף את הטבלה לסכימה, וכך חוסך לי לבדוק מה השם המדויק של הפונקציה.

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

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

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

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

  7. כתיבת תיעוד, בדיקות והודעות קומיט.

  8. קבלת Code Review - לפני קומיט אני מפעיל git diff ושולח את הפלט ל AI כדי לקבל סיכום מסודר של מה שעשיתי והצעות לשיפור או תיקונים.

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

נ.ב. הג'מיני החדש באמת מטורף.

פיתרון Advent Of Code יום 6 ב Ruby - היום לגמרי לא ראיתי את זה

31/03/2025

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

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

המשך קריאה

זה לא תורמוס

30/03/2025

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

fibonacci = lambda n, a=0, b=1: [a := b, b := a + b][0] if n else None

נראה יופי אבל כמו התורמוס, התוצאה אינה מספר מסדרת פיבונאצ'י.

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

from functools import lru_cache

fib = lru_cache(None)(lambda n: n if n < 2 else fib(n-1) + fib(n-2))

print(fib(10))  # Output: 55

ואז הצעה נוספת ש"משתמשת באיטרציות כדי לשפר ביצועים":

fib = lambda n, a=0, b=1: a if n == 0 else fib(n-1, b, a+b)

print(fib(10))  # Output: 55

ואתם צודקים, אין פה איטרציות ובהשוואה ל LRU Cache גם אין פה שיפור ביצועים.

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

ניסוי AI - בואו נכתוב Tools

29/03/2025

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

המשך קריאה

היום נתתי ל Aider לכתוב פיצ'ר חדש לאתר

27/03/2025

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

https://www.youtube.com/watch?v=thSABbP1rF4&feature=youtu.be

עכשיו הסיכום:

  1. אני לא חושב ש AI ייקח לנו את העבודה בזמן הקרוב.

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

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

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

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

הצעה לפרומפט - איך לשבור את הקוד

25/03/2025

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

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

Let's play a game - the code below has a hidden bug, but it will be triggered if we add a specific feature. What new feature will break this code?

אני נתתי לו בשביל הדוגמה את הקוד ריאקט הזה והוא קלע בול לפיצ'ר שהיה צריך בשביל לראות את הבאג:

function ColorPalette({ start }: {
  start: ColorInput,
}) {
  const [deletedBoxes, setDeletedBoxes] = useState(new Set());

  const removeBox = useCallback((e: React.MouseEvent) => {
    console.log(`deleted boxes = ${deletedBoxes.size}`);

    const id = (e.target as HTMLDivElement).dataset.id;
    deletedBoxes.add(Number(id));
    setDeletedBoxes(new Set(deletedBoxes));
  }, [deletedBoxes, setDeletedBoxes]);

  const colors = [];
  for (let i=-360; i < 360; i++) {
    if (deletedBoxes.has(i)) continue;

    colors.push(
      <ColorBox
        key={i}
        start={start}
        spin={i}
        onClick={removeBox}
        id={i}
      />
    );
  }
  return colors;
}

(וכן כנראה שאפשר להוריד את התחילית Let's play a game, אבל אני מוצא שהתשובות של AI יותר נחמדות כשהוא חושב שהוא במשחק).

ואם המידלוור לא ירוץ?

24/03/2025

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

import { withMiddlewareAuthRequired } from "@auth0/nextjs-auth0/edge";

export default withMiddlewareAuthRequired();

export const config = {
  matcher: ["/protected", "/admin"],
};

הקוד מגדיר שגישה לנתיבי protected ו admin מותרת רק למשתמשים מאומתים. אתם רואים את הבעיה נכון? אם המידלוור לא רץ הגישה פתוחה לכולם.

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

export const getUserProfileData = async (): Promise<Claims> => {
  const session = await getSession();

  if (!session) {
    throw new Error(`Requires authentication`);
  }

  const { user } = session;

  return user;
};

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

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

טיפ JavaScript - שימוש ב matchMedia במקום resize

23/03/2025

פקודת matchMedia היא טריק חמוד שמאפשר לנו לקבל אירוע כל פעם ש"התאמת המסך ל Media Query" מסוים משתנה. זה מנגנון הרבה יותר יעיל מאירועי resize כי רוב הזמן מה שמעניין אותנו זה לא שמשתמש שינה את גודל החלון אלא שגודל החלון נהיה מספיק קטן כדי להתיחס אליו כמו לטלפון, או מספיק גדול כדי להציג עליו יותר מידע. זאת בעצם גירסת ה JavaScript של Media Queries ב CSS.

הנה דוגמה קצרה ל Hook ריאקטי שבודק אם אנחנו על מכשיר מובייל:


const MOBILE_BREAKPOINT = 768

export function useIsMobile() {
  const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)

  React.useEffect(() => {
    const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
    const onChange = () => {
      setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
    }
    mql.addEventListener("change", onChange)
    setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
    return () => mql.removeEventListener("change", onChange)
  }, [])

  return !!isMobile
}