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

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

פקודת Bash קצרה לפתרון Spelling Bee

06/07/2025

דבורת האיות הוא משחק חמוד המכיל אות אחת באמצע ועוד 6 אותיות מסביב והמשימה שלנו היא למצוא כמה שיותר מילים מהאותיות האלה עם הכללים:

  1. האות שבאמצע חייבת להופיע.

  2. אורך המילה לפחות 4 אותיות.

אפשר לשחק בו כאן: https://6mal5.com/wortendo/

ובטח בעוד המון מקומות ברשת.

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

אתחיל עם הפיתרון שלי והוא נראה כך:

#!/bin/bash -e

center=$1
rest=$2

cat /usr/share/dict/words | grep $center | grep .... | egrep "^[${rest}{$center}]+$" | awk '{ print length "\t" $0 }' | sort -n | cut -f2-

וכן זה שורה אחת:

  1. לוקחים קובץ מילים.
  2. משאירים רק את המילים עם האות שבאמצע.
  3. משאירים רק מילים עם 4 אותיות.
  4. משאירים רק מילים שמורכבות אך ורק מהאותיות של המשחק.
  5. מסדרים את הכל לפי האורך כך שמילים ארוכות יופיעו בתחתית הרשימה (שיהיה קל לראות אותן).

מיטיבי לכת יכולים להוסיף שם head -1 כדי לקבל רק רמז אחד.

ועכשיו למימוש של קלוד:

#!/bin/bash -e

center=$1
rest=$2

# Check if arguments are provided
if [ -z "$center" ] || [ -z "$rest" ]; then
    echo "Usage: $0 <center_letter> <other_letters>"
    echo "Example: $0 a bcdefg"
    exit 1
fi

# Combine all available letters
all_letters="${center}${rest}"

# Convert to lowercase for consistency
center=$(echo "$center" | tr '[:upper:]' '[:lower:]')
rest=$(echo "$rest" | tr '[:upper:]' '[:lower:]')
all_letters=$(echo "$all_letters" | tr '[:upper:]' '[:lower:]')

# Word list file (common locations)
word_files=(
    "/usr/share/dict/words"
    "/usr/dict/words"
    "/usr/share/dict/american-english"
    "/usr/share/dict/web2"
)

word_file=""
for file in "${word_files[@]}"; do
    if [ -f "$file" ]; then
        word_file="$file"
        break
    fi
done

if [ -z "$word_file" ]; then
    echo "Error: No word dictionary found. Please install a word list."
    echo "On Ubuntu/Debian: sudo apt-get install wamerican"
    echo "On macOS: Word lists are usually in /usr/share/dict/"
    exit 1
fi

echo "Solving Spelling Bee with center letter: $center"
echo "Available letters: $all_letters"
echo "Using word list: $word_file"
echo "----------------------------------------"

# Find valid words
valid_words=()
total_score=0

while IFS= read -r word; do
    # Convert word to lowercase and remove any non-alphabetic characters
    clean_word=$(echo "$word" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z]//g')

    # Skip if word is less than 4 letters
    if [ ${#clean_word} -lt 4 ]; then
        continue
    fi

    # Check if word contains the center letter
    if [[ "$clean_word" != *"$center"* ]]; then
        continue
    fi

    # Check if word only uses available letters
    valid=true
    for ((i=0; i<${#clean_word}; i++)); do
        letter="${clean_word:$i:1}"
        if [[ "$all_letters" != *"$letter"* ]]; then
            valid=false
            break
        fi
    done

    if [ "$valid" = true ]; then
        # Calculate score
        word_length=${#clean_word}
        if [ $word_length -eq 4 ]; then
            score=1
        else
            score=$word_length
        fi

        # Check if it's a pangram (uses all letters)
        is_pangram=true
        for ((i=0; i<${#all_letters}; i++)); do
            letter="${all_letters:$i:1}"
            if [[ "$clean_word" != *"$letter"* ]]; then
                is_pangram=false
                break
            fi
        done

        if [ "$is_pangram" = true ]; then
            score=$((score + 7))
            echo "$clean_word ($score points) - PANGRAM!"
        else
            echo "$clean_word ($score points)"
        fi

        valid_words+=("$clean_word")
        total_score=$((total_score + score))
    fi
done < "$word_file"

echo "----------------------------------------"
echo "Found ${#valid_words[@]} valid words"
echo "Total score: $total_score points"

נשים לב להמון דברים כאן:

  1. קלוד חישב ניקוד של כל המילים שהוא מצא. זה מאוד סיבך לו את המימוש.

  2. קלוד השתמש רק בפקודות bash לסינונים בעוד שאני שמחתי להשתמש ב grep.

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

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

Use a one line pipeline giving just word suggestions (without score)

עכשיו אני מקבל מקלוד את הסקריפט:

#!/bin/bash -e

center=$1
rest=$2

grep -E "^[${center}${rest}]+$" /usr/share/dict/words | grep "$center" | awk 'length >= 4' | sort -u

שכבר מאוד דומה לפיתרון שלי מלבד סדר הפעולות, המיון בסוף, והבחירה להשתמש ב awk במקום ב grep כדי לבדוק אורך.

לא עומד בקצב

05/07/2025

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

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

  1. איך לבנות פרומפט.

  2. איך לחלק את העבודה עם ה AI.

  3. איזה דברים AI יודע לעשות טוב, ומה עדיף לעשות לבד.

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

  5. למה חשוב לשים לב בקוד ש AI מייצר.

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

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

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

היום למדתי: פרוטוטייפ ופונקציות חץ

04/07/2025

עזרתי לחבר עם איזה באג שהביא אותי לקוד הבא מתוך ספריית JavaScript ישנה:

/**
 * Used to determine we'll call be calling React.createElement on the component of if this is a
 * generator function used return a function that takes props to return a React element
 * @param component
 * @returns {boolean}
 */
function generatorFunction(component) {
  if (!component.prototype) {
    return false;
  }

  // es5 or es6 React Component
  return !component.prototype.isReactComponent;
}

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

  1. העברת React Component ל API.

  2. העברת פונקציה שמחזירה React Component ל API.

האנטי תבנית כאן היא ברורה - שפת JavaScript לא עושה חיים קלים למי שרוצה להבדיל בין טיפוסים בזמן ריצה. כן יש את typeof אבל גם את Array.isArray וגם את Number.isNaN ויש הרבה כללים לזכור. ועכשיו נסו להבדיל בין "פונקציה שהיא React Component" ל"פונקציה שמחזירה React Component". לא ככה מתכננים API.

עכשיו מה היה הבאג? שימו לב:

> generatorFunction(function() { 10 })
true
> generatorFunction(() => 10)
false

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

טיפ רובי: דיג במקום סוגריים מרובעים

03/07/2025

הקוד הזה היה נראה כמו רעיון טוב בזמנו:

x[:foo].presence || 9

הוא אומר שאם המפתח :foo קיים באוביקט x אז יש להשתמש בערך שלו (אפילו אם הוא 0, כי אנחנו ברובי ולא ב JavaScript), ואם הוא לא קיים ניקח את ערך ברירת המחדל 9.

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

זה עובד:

3.3.5 :003 > x = {foo: 0, bar: 20}
 => {:foo=>0, :bar=>20}
3.3.5 :004 > x[:foo].presence || 9
 => 0

וגם זה עובד:

3.3.5 :006 > x = {bar: 20}
 => {:bar=>20}
3.3.5 :007 > x[:foo].presence || 9
 => 9

אבל זה כבר לא:

3.3.5 :008 > x = nil
 => nil
3.3.5 :009 > x[:foo].presence || 9
(langlets):9:in `<main>': undefined method `[]' for nil (NoMethodError)

x[:foo].presence || 9

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

3.3.5 :011 > x = 10
 => 10
3.3.5 :012 > x&.abs
 => 10
3.3.5 :013 > x = nil
 => nil
3.3.5 :014 > x&.abs
 => nil

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

> x&.[:foo]

אבל זו שגיאת תחביר ברובי.

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

3.3.5 :017 > x = {foo: 10, bar: 20}
 => {:foo=>10, :bar=>20}
3.3.5 :018 > x&.dig(:foo)
 => 10
3.3.5 :019 > x = {foo: {foo: {foo: 10}}, bar: 20}
 => {:foo=>{:foo=>{:foo=>10}}, :bar=>20}
3.3.5 :020 > x&.dig(:foo, :bar, :foo)
 => nil
3.3.5 :021 > x&.dig(:foo, :foo, :foo)
 => 10
3.3.5 :023 > x = nil
 => nil
3.3.5 :024 > x&.dig(:foo, :bar)
 => nil

עבודת יד

02/07/2025

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

ועכשיו היא הגיעה לקוד.

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

כמה תובנות להשאיר בראש:

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

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

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

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

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

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

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

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

זה לא תיקון סינטקס (חידוד ההערה של תומאס דומקה)

01/07/2025

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

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

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

  1. בקשו מ AI לייצר Security Review על קוד והוא בטוח ימצא דברים. לפעמים הדברים האלה הם בעיות אבטחה אמיתיות בקוד (במיוחד אם זה בעיות מאוד בולטות), לפעמים זה פשוט Best Practices שלא לקחת ולפעמים זה פשוט קוד שנראה קצת חשוד או לא שגרתי. כן אני יכול להשתמש ב AI כדי לקבל כיוון ולהציף דברים שיכולים להיות בעייתיים, אבל בשום אופן לא הייתי נותן לו להחליט איזה בעיית אבטחה היא אמיתית ודורשת תיקון ואיזה רק נראית כמו בעיה.

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

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

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

כזה ניסיתי: קלוד קוד

30/06/2025

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

  1. יצרתי איתו מוצר אחד בשיטת Vibe Code כלומר מאפס רק עם פרומפטים ונתתי לו לבנות פיצ'רים לכמה מוצרים בשלים יותר.

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

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

אז מה בכל זאת היו הבעיות ולמה אני לא מתכנן להמשיך איתו?

  1. נרשמתי למסלול של ה 20$ בחודש וסיימתי אותו ב-3 ימים. הבנתי שיש מסלול יותר מתקדם של 100$ בחודש שאמור להספיק לכל החודש אבל זה פי 10 מקופיילוט ופי 5 מקרסר.

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

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

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

לטיפים נוספים על פיתוח יעיל יותר בעזרת AI מוזמנים להצטרף לוובינרים החינמיים שאני מעביר בימי חמישי בבוקר:

https://www.tocode.co.il/talking_ai

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

חדש ב JavaScript: פונקציות עזר לאיטרטורים

29/06/2025

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

new Array(100).fill(0).map(i => Math.floor(Math.random() * 100)).find(p => p > 50)

אבל עדיין יש פה משהו צורם בקוד - בשביל מה היית צריך להמשיך להגריל מספרים אחרי שמצאת את הראשון שגדול מ-50? כתיב השורה אחת צריך לעבוד יותר קשה מכתיב הלולאה המקביל:

for (let i=0; i < 100; i++) {
  const r = Math.floor(Math.random() * 100)
  if (r > 50) { console.log(r); break; }
}

מה עושים? מתקנים את JavaScript כמובן כדי שאפשר יהיה לכתוב את כל הלולאות בשורה אחת ובלי עבודה מיותרת בעזרת פונקציות עזר לאיטרטורים - פיצ'ר חדש שנכנס כבר לכל הדפדפנים והתקבל לאיפיון של ES2025, וזה נראה ככה:

  1. הפונקציה values של מערך מחזירה איטרטור.
  2. לאיטרטור יש פונקציות כמו map, filter, take, drop שמשפיעות על מהלך האיטרציה.
  3. לאיטרטור יש פונקציית next שמחזירה את הערך הבא ממנו.

ולכן הלולאה נראית כך:

new Array(100).values().map(() => Math.floor(Math.random() * 100)).filter(i => i > 50).take(1).next().value

שורה אחת, מגרילה עד 100 מספרים ומחזירה את הראשון שגדול מ-50.

ואם אני רוצה את ה-3 מספרים הראשונים שגדולים מ-50? אין שום בעיה פשוט נשתמש ב toArray במקום ב next:

new Array(100).values().map(() => Math.floor(Math.random() * 100)).filter(i => i > 50).take(3).toArray()

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

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator

שינוי קצב

28/06/2025

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

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

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

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

  2. קצב מהיר זה ה Vibe Coding, ה Agent Mode, ה Yolo. כמה Issues אני מצליח לפתור בשעה, קומיט אחרי קומיט, ריכוז גבוה, אנדרנלין, מצב Flow, זזים מהר ושוברים דברים.

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

האם שרתי MCP הם ההזדמנות הבאה לגנבי הביטקוין?

27/06/2025

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

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

  1. מי יכול להריץ את שרת ה MCP? שרתי MCP יכולים לרוץ בתור סקריפט מקומי (דרך stdio) או בתור שרת HTTP. מסתבר שבתור שרת HTTP שרתים רבים מאזינים לכתובת 0.0.0.0 מה שהופך אותם לנגישים לכל המכונות ברשת ולא רק לקופיילוט שרץ אצלכם ב VS Code.

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

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

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

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

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