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

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

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

13/03/2026

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

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

allowed_non_write_users: "*"
claude_args: >-
  --allowedTools "Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch"
prompt: |
  **Issue:** #${{ github.event.issue.number }}
  **Title:** ${{ github.event.issue.title }}

ראיתם את הבעיה? אני בטוח שכן. לוקחים את ה title של ה Issue ושולחים אותו לסוכן שיכול להריץ פקודות Shell ולגשת לאינטרנט.

עכשיו להגנתם הסוכן רץ על מכונה של Github Actions בלי הרשאות לעשות שום דבר. ופה אני שומע בראש את השאלה שבטח גם הם חשבו "מה כבר יכול להישבר?". נו, מסתבר שגם מכונת גיטהאב אקשן בלי הרשאות יכולה לעשות נזק והתוצאה היתה גירסה מלוכלכת של cline שעלתה ל npm.

הסיפור הטכני המלא למתעניינים נמצא בלינק הזה: https://neciudan.dev/cline-ci-got-compromised-here-is-how#what-is-openclaw-and-why-should-you-care

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

הצפנה ב Rails - הטוב, הרע והמכוער

12/03/2026

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

Add this entry to the credentials of the target environment:

active_record_encryption:
  primary_key: YehXdfzxVKpoLvKseJMJIEGs2JxerkB8
  deterministic_key: uhtk2DYS80OweAPnMLtrV2FhYIXaceAy
  key_derivation_salt: g7Q66StqUQDQk9SJ81sWbYZXgiRogBwS

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

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

len   = ActiveSupport::MessageEncryptor.key_len
salt  = SecureRandom.random_bytes(len)
key   = ActiveSupport::KeyGenerator.new('password').generate_key(salt, len) # => "\x89\xE0\x156\xAC..."
crypt = ActiveSupport::MessageEncryptor.new(key)                            # => #<ActiveSupport::MessageEncryptor ...>
encrypted_data = crypt.encrypt_and_sign('my secret data')                   # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
crypt.decrypt_and_verify(encrypted_data)

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

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

secret_key = Rails.application.key_generator.generate_key("my-secret", 32)

encryptor = ActiveSupport::MessageEncryptor.new(secret_key)

# Encrypt + sign
encrypted = encryptor.encrypt_and_sign("Hello world")

# Decrypt + verify
decrypted = encryptor.decrypt_and_verify(encrypted)

puts encrypted
puts decrypted

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

secret_key_base = Rails.application.secret_key_base

# Derive a key
key_len = ActiveSupport::MessageEncryptor.key_len
salt = "my-encryption-salt"
key = ActiveSupport::KeyGenerator.new(secret_key_base).generate_key(salt, key_len)

encryptor = ActiveSupport::MessageEncryptor.new(key)

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

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

אם קוד נכתב ביער ואף אחד לא משתמש בו

11/03/2026

בפרויקט בשם chatwoot (ריילס) מצאתי את הקוד הבא:

class Api::V1::Accounts::WorkingHoursController < Api::V1::Accounts::BaseController
  before_action :check_authorization
  before_action :fetch_webhook, only: [:update]

  def update
    @working_hour.update!(working_hour_params)
  end

  private

  def working_hour_params
    params.require(:working_hour).permit(:inbox_id, :open_hour, :open_minutes, :close_hour, :close_minutes, :closed_all_day)
  end

  def fetch_working_hour
    @working_hour = Current.account.working_hours.find(params[:id])
  end
end

הקוד לא עובד מכמה סיבות:

  1. הפונקציה fetch_webhook לא קיימת. אי אפשר להפעיל אותה לפני update.

  2. הפונקציה check_authorization מחפשת קובץ בשם working_hours_policy.rb שגם לא קיים.

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

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

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

טיפ פייתון: לא צריך לכתוב את כל הקוד ב init

10/03/2026

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

import mymodule

print(mymodule.add(10, 20))

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

mymodule/
    __init__.py
    utils.py

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

import mymodule.utils

print(mymodule.utils.add(10, 20))

העצלנים יותר ישתמשו ב alias ויכתבו ביבוא:

import mymodule.utils as mymodule

print(mymodule.add(10, 20))

אבל זה לא נראה נכון ועדיין מעצבן את המשתמשים.

כותבים מודולים יצירתיים יודעים לשים את הקוד בקובץ ה __init__.py של החבילה, וכך לא צריכים אפילו להמציא שם לקובץ המקור האמיתי והכל מסתדר עם היבוא, כלומר יהיה לנו בצד של החבילה:

mymodule/
  __init__.py

ובתוך הקובץ __init__.py תופיע הגדרת הפונקציה add, ואז משתמשים של החבילה יוכלו שוב לכתוב:

import mymodule

print(mymodule.add(10, 20))

אבל כותבים חבילות יותר יצירתיים דווקא מעדיפים להשתמש בשם קובץ מסודר עבור הקודם שלהם. במצב כזה נכתוב קובץ utils.py עם הגדרת הפונקציה add, וקובץ __init__.py שיכיל רק את פקודת היבוא והיצוא מחדש:

from .utils import add

ושוב הכל עובד אבל עכשיו גם מסודר - משתמשים יכולים לייבא את המודול mymodule ולקרוא לפונקציה add ישירות דרך היבוא, אפילו שהפונקציה מוגדרת בקובץ פנימי mymodule/utils.py בתוך החבילה.

כן הקוד שלי

09/03/2026

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

https://antman-does-software.com/i-will-never-use-ai-to-code-or-write

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

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

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

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

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

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

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

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

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

נ.ב. עלויות של AI

08/03/2026

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

בחודשים שאחרי כבר נזהרתי יותר בשימוש בג'מיני פרו ובמאי שילמתי להם רק 3 ש"ח, יוני 25 ש"ח, יולי 76 ש"ח ואוגוסט 50. חלק מזה קשור לאופטימיזציה במערכת שהיתה צריכה פחות AI כדי ליצור את השיעורים, חלק קשור לזה שהעברתי חלקים מהקוד לעבוד עם מודלים יותר זולים וחלק לזה שפשוט היה לי פחות זמן לעבוד על הפלטפורמה. סך הכל לפני אופטימיזציה שילמתי בערך 20 ש"ח לעבודה על וידאו אחד ואחרי אופטימיזציה זה ירד ל 2-3 ש"ח לוידאו.

מאז גוגל השיקו את ג'מיני פלאש לייט 3.1 ואולמה השיקו את תוכנית Ollama Cloud. שילוב שני אלה הוריד את העלות של יצירת וידאו לפחות מאגורה, ללא שינוי בקוד.

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

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

גם ה GPL כנראה לא ישרוד

07/03/2026

אני מבין איך מרגיש מארק פילגרים.

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

ואני גם מבין איך מרגיש דן בלנשרד. עוד ב 2014 הוא ראה ש chardet הוא בסך הכל מימוש מחדש בפייתון של קוד ישן של מוזילה ולכן ממילא היה צריך להיות רשום ב MPL. בלנשרד הוא המתחזק של הפרויקט מ 2014, כלומר ב 12 השנים האחרונות. בלנשרד הוא זה שקיבל פניות ממשתמשים שרוצים להשתמש ב chardet ולא יכולים בגלל הרישיון כי אצלם בחברה אסור להשתמש ב LGPL, או כי הם משתמשים ב pyinstaller, וזה מייצר קובץ exe ולכן כל המודולים חייבים להיות חופשיים. ב 2021 היה זה בלנשרד שניסה לקדם את שינוי הרישיון שוב וראה איך ספריית requests הפופולרית נפרדת ב chardet בדיוק בגלל נושא זה.

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

https://github.com/chardet/chardet/issues/327

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

האם Test Driven Development עדיין רלוונטי?

06/03/2026

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

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

האלטרנטיבה של TDD בה גם אני משתמש וגם אני רואה בתעשייה היא PDD, כלומר Prompt Driven Development. כותבים פרומפט, נותנים ל AI לייצר קוד ובדיקות, קוראים את הבדיקות והקוד, אם אוהבים שומרים ואם לא אוהבים מנקים ומתקנים את הפרומפט.

לדוגמה עבור משחק איקס עיגול ב TDD אני מתחיל עם קובץ בדיקות כזה:

import pytest
import GameUI


def test_first_player_plays(game_logic):
    game_logic.play(0, 0)
    assert not game_logic.game_over()
    assert game_logic.winner() is None

def test_second_player_plays_in_taken_square(game_logic):
    game_logic.play(0, 0)

    with pytest.raises(Exception):
        game_logic.play(0, 0)

def test_player1_wins_first_row(game_logic):
    game_logic.play(0, 0)
    game_logic.play(1, 0)

    game_logic.play(0, 1)
    game_logic.play(1, 1)

    game_logic.play(0, 2)
    assert game_logic.game_over()
    assert game_logic.winner() == game_logic.players[0]

def test_player2_wins_diagonal(game_logic):
    game_logic.play(0, 1)
    game_logic.play(0, 0)

    game_logic.play(1, 0)
    game_logic.play(1, 1)

    game_logic.play(1, 2)
    game_logic.play(2, 2)
    assert game_logic.game_over()
    assert game_logic.winner() == game_logic.players[1]

def test_cant_play_after_win(game_logic):
    game_logic.play(0, 1)
    game_logic.play(0, 0)

    game_logic.play(1, 0)
    game_logic.play(1, 1)

    game_logic.play(1, 2)
    game_logic.play(2, 2)

    with pytest.raises(Exception):
        game_logic.play(2, 0)


def test_show_empty_board(game_logic, capsys):
    GameUI.print_current_game(game_logic)
    printed_text = capsys.readouterr().out
    assert printed_text == """Waiting for player X
. . .
. . .
. . .
"""

def test_show_board_after_play(game_logic, capsys):
    game_logic.play(0, 0)
    game_logic.play(1, 1)
    game_logic.play(2, 0)

    GameUI.print_current_game(game_logic)
    printed_text = capsys.readouterr().out
    assert printed_text == """Waiting for player O
X . .
. O .
X . .
"""

def test_show_draw(game_logic, capsys):
    game_logic.play(0, 0) # X
    game_logic.play(1, 1) # O

    game_logic.play(2, 0) # X
    game_logic.play(1, 0) # O

    game_logic.play(1, 2) # X
    game_logic.play(2, 1) # O

    game_logic.play(0, 1) # X
    game_logic.play(0, 2) # O

    game_logic.play(2, 2) # X

    GameUI.print_current_game(game_logic)
    printed_text = capsys.readouterr().out
    assert printed_text == """Game Over. It's a draw
X X O
O O X
X O X
"""

def test_show_player_1_won(game_logic, capsys):
    game_logic.play(0, 0)
    game_logic.play(1, 0)
    game_logic.play(0, 1)
    game_logic.play(1, 1)
    game_logic.play(0, 2)

    GameUI.print_current_game(game_logic)
    printed_text = capsys.readouterr().out
    assert printed_text == """Bravo! X Won
X X X
O O .
. . .
"""

def test_read_move_from_player(game_logic, monkeypatch, capsys):
    monkeypatch.setattr("builtins.input", lambda _: "0, 0")
    next_move = GameUI.read_next_move(game_logic)
    game_logic.play(*next_move)

    capsys.readouterr() # clear the buffer
    GameUI.print_current_game(game_logic)
    printed_after = capsys.readouterr().out
    assert printed_after == """Waiting for player O
X . .
. . .
. . .
"""

ואז בפרומפט מאוד פשוט מקבל את GameLogic שבדיוק מתאים לממשק שהגדרתי.

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

ההבדלים המרכזיים בין הגישות:

  1. ב TDD אני לוקח שליטה על הקוד. אני יודע מה אני כותב ומה צריך להיכתב. אני קובע את המבנה של הקוד ויודע בדיוק איך יראה הקוד שה AI יבנה. כמעט לא הולך לי זמן על לחכות לסוכן הקידוד או לקרוא את הקוד שלו.

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

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

create a text based tic tac toe game in python with pytest. use uv
Use multiple modules for game logic and display
Implement pytest tests for both logic and display

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

def test_render_board_with_markers(self):
    board = Board()
    board.place_marker("A1", "X")
    board.place_marker("B2", "O")
    rendered = Display.render_board(board)
    assert "X" in rendered
    assert "O" in rendered

נראה ש glm עבד מאוד קשה רק בשביל לא להשתמש ב capsys של pytest והפך את קוד המשחק ליותר מסורבל.

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

סיכום וובינר מודלים פתוחים

05/03/2026

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

עכשיו בואו נזכר מה היה לנו בשבוע שעבר.

המשך קריאה

המעמד החברתי של המודל

04/03/2026

פרומפט-

create a vue component that takes a flat JSON object as "model" (just key/value and value has to be string) and provide an editable form for it

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

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

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

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

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