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

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

שלושה פיצ'רים של בינג החדש שמשאירים את ChatGPT מאחור

11/03/2023

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

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

המשך קריאה

ארגונומיקה

10/03/2023

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

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

המפתחים שכותבים את Visual Studio נדרשים ליכולות שונות ולכלים שונים מאשר מפתחות הבונות משחק מחשב ואלה יצטרכו יכולות שונות ממפתחים הבונים יישום Saas. עם ההבדל הזה בראש כדאי ללכת לקרוא את הדיון המרתק בין דוד בוב לקייסי מורטורי בקישור: https://github.com/unclebob/cmuratori-discussion/blob/main/cleancodeqa.md

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

להוציא קבצים מגיט עם rm cached

09/03/2023

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

$ git add .
$ git commit -m 'fixed bug'

אופס.

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

ניסיון ראשון למחוק את התיקיה עם git rm ייכשל:

$ git rm .idea

fatal: not removing '.idea' recursively without -r

ואם אנסה להקשיב לו ולהפעיל git rm -r .idea אני אומנם אמחק את התיקיה מגיט אבל אאבד את קבצי הגדרות הפרויקט שלי.

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

  1. יש את העותק שאנחנו רואים בתיקיית העבודה.

  2. אפשר לחשוב על כל קומיט בתור עותק נוסף של הפרויקט.

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

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

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

$ git rm --cached -r .idea

rm '.idea/.gitignore'
rm '.idea/cached.iml'
rm '.idea/inspectionProfiles/profiles_settings.xml'
rm '.idea/misc.xml'
rm '.idea/modules.xml'

$ git commit -m 'removed .idea from project'

$ ls .idea
cached.iml              inspectionProfiles      misc.xml                modules.xml             vcs.xml                 workspace.xml

יצירת סיסמאות משורת הפקודה עם pwgen

08/03/2023

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

בהפעלה רגילה pwgen מדפיסה המון סיסמאות אקראיות למסך:

$ pwgen

cahhoh2G oofah7Wo Kain5pha eeKue9th Shieng9i ail5Mai3 ahgh1Woh uuQuu2oh
IVahg0ro Ahju2tah Zuox3laS ual3Iece Ohx7ua2e ib2riyoG UuYie9Oh eicuc7Ib
loh5ja7T Nen9biTh Zee5vaiw ies6AoBo eGheip3m eiyeeNg9 Aish1ohn eM6isees
oR7Zeam4 ithang7O Aing4hah eeNae6Ro ahRashi2 xo2eiVie Eew4ohp8 uusaeCh0
chaic0Vu eu2phaeJ oFee7ei8 zohBu4xe mu9iTeik oow0Ia7e Noothah5 yuuph2Ie
keiFair2 Chutoh1i ji9Quei5 OoX5Ophe yay3AeNo Ahoong3C keeS5Eih Ohbaivi4
pheiPh1A aaloof4B ahsoMai6 they7Xoo IeN1aiqu eoGhai7e ahLaqu9u EiGh3ook
kooCh3ah niGieb7E Chohpai9 uibi2Lah Aiqueiz9 the7ua1T fooS2Ohl Cha9aene
aeT9ahzi teeG8axa the9Wahy WooT0eis tieW5yoh aiYeip1l eTh0iewu azucew3A
oofoKu6h Wievei4c xoo0Quae Lah7Nue0 ieZ8ahqu Oi1ahjee OoW6eeZ3 yei1fi7A
ohb9phuN Gee5see4 eeD5jaik Figha4oo Jet2uo6e Eir9re3i OhDohk9e Yai8ahsu
Ahjaev2i ea8ohJ0e yeiHai4i Cev4Wuuh sheih9Hi akeiZa8t Aic3ahro zoo2AeCa
Ohgoong0 Bouhoo5a wai7Eih0 ZooP7eif ba5eiy3R eewooCh7 Aga2ueZ1 aiT8Shah
Aethee0h Eir9cieg Wo6zoodi iV6idohv Iezei7am chaeR5uf Ooree0ie aequa5Wi
Eeyu8uiF aibac7Li fee4Ahpe HooGo1ei pahng4Ah ohXuo9tu Eeseew0u aefes4Ph
Ea8ohnie kiyaiTh9 Lai9eifu aib4eeSa ua8aaM2o Tied3tee Lo5sooVo Ieshaiw4
pe3Aib4j HiujeeX2 teiJu0Ni geeSh7hi ieNg4oov Ua9ma1oC ahpieC9k Peit0Eih
ab9Raelo jahC6eix QuahG6to aeL7iera ze5OP9Ie uoBai7ob MohK8Ohm Ahr2eemi
loh8iGhu Iu3ahwie uDa4ia8j Quoh4iek aQu6ith0 Ahs5jaiy uech4aiS eodai7Ah
kei4Noox quooy0Ae ohnais7A jeech9Ae ob8ehaeN die4Ahth Ahg8jah3 Aishe8Yi

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

$ pwgen | cat
zo3gi3Ie

$ pwgen -1
shaiPoo2

יש מתגים שמאפשרים להפוך את הסיסמאות ליותר בטוחות, למשל המתג -y שמוסיף תווים מיוחדים ו -s שהופך את הסיסמה ליותר מסובכת לבני אדם. ואפשר גם לצרף מספר בסוף כדי לספר כמה תווים אתם רוצים:

$ pwgen -s -1 -y 30
bPcAig)mVL|\_hMpib|f.=?7$o^RQ|

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

$ pwgen 10 10 | sed 's/$/@test.com/'
ige6Eiji3i@test.com
joiC9kaes0@test.com
EiZuwofu3z@test.com
nee6Ea0eid@test.com
iye7ieJ4oh@test.com
abaeReeP4y@test.com
ebei4NiQu6@test.com
OCheil6ahr@test.com
ootheiH3tu@test.com
ei8ne6ohMi@test.com

או הסקריפט הקצר הבא שמדפיס 10 משתמשים אקראיים ל JSON כאשר כל משתמש מקבל מזהה, שם ואימייל אקראיים:

echo "["
for i in {1..10}; do
  id=$(pwgen -1 10)
  name=$(pwgen -s 2 1)
  email="${name:l}.${id}@example.com"
  if [ $i -eq 10 ]; then
    echo "{\"id\":\"$id\",\"name\":\"$name\",\"email\":\"$email\"}"
  else
    echo "{\"id\":\"$id\",\"name\":\"$name\",\"email\":\"$email\"},"
  fi
done
echo "]"

[דוקר] למה להעתיק את ה package.json לפני כל השאר?

07/03/2023

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

FROM node:16

WORKDIR /app

COPY app /app

RUN npm install

CMD ["node", "main.js"]

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

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

FROM node:16

WORKDIR /app
COPY app/package.json app/package-lock.json /app
RUN npm install

COPY app /app

CMD ["node", "main.js"]

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

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

טיפ דיבאג - שימו לב לגירסאות

06/03/2023

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

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

המשך קריאה

תנו צ'אנס לנווד - ארבע תכונות טובות של Nomad

05/03/2023

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

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

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

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

  3. פיצ'רים קטנים שעושים את ההבדל - נכון אין לו את כל הפיצ'רים המסובכים של קוברנטיס, אבל בפינוקים קטנים נומד מצטיין. לדוגמה הפקודה nomad plan תקבל קובץ מניפסט (זה נקרא Job Specification שם) ותגיד לכם בדיוק ובצורה מפורטת מה הוא הולך לעשות כשתנסו להריץ את הג'וב הזה, וכמובן תזהה בעיות לפני שהן קורות. או התמיכה ב Canary Updates שבעזרת שורת הגדרה אחת נומד יריץ את המערכת שלכם במכונה חדשה בתור קנרית ורק אם היא עלתה כמו שצריך הוא ישדרג את כל המכונות הקיימות.

  4. אינטגרציה עם שאר הכלים של HashiCorp - במקום להכניס את הכל לכלי אחד האשיקורפ יצרו אוסף כלים עצמאיים שיכולים לעבוד יחד בתור מכפיל כח. לדוגמה Terraform יודע לבנות ארכיטקטורת רשת על כל ענן שתתנו לו (וכך יהיה קל להתקין את נומד על כל ענן ולעבור בקלות בין עננים), Vault יודע לנהל סודות ולכן קלאסטרים של נומד ישתמשו בו כדי להזריק סודות לקונטיינרים ו Consul מנהל את ה Service Discovery בתוך הקלאסטר. היתרון בבחירה לחלק את המשימות לכלים יחסית קטנים ועצמאיים היא שאפשר ללמוד כל כלי בפני עצמו ולהתחיל להשתמש למשל ב Nomad בלי הכלים האחרים, אבל אז כשלומדים על Terraform מגלים כמה קל לשלב בין השניים.

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

נ.ב. נקודת התחלה טובה לעבודה איתו היא אוסף ה Tutorials באתר שלהם כאן: https://developer.hashicorp.com/nomad/tutorials/get-started.

האם ריאקט הוא סקאם?

04/03/2023

כשמישהו שואל "האם טכנולוגיה X היא Scam" הוא בדרך כלל מתכוון לשילוב של הגורמים הבאים:

  1. יש טכנולוגיות יותר פשוטות שפותרות את אותה בעיה.

  2. הרבה אנשים בוחרים בטכנולוגיה המסובכת בגלל יחסי הציבור שלה ולא בגלל הערך האמיתי.

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

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

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

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

תפסו מחסה, הדקורטורים חוזרים!

03/03/2023

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

המשך קריאה

היום למדתי: כבר מזמן לא צריך להוסיף קו תחתי אחרי exec ב Qt for Python

02/03/2023

לפמעים צריך לחכות שמשהו יהפוך ל Deprecated עד שאני אשים לב שכבר הרבה זמן הוא לא היה הכרחי. זה לפחות היה הסיפור עם PyQt ו PySide והפקודה exec.

בפייתון 2 המילה exec היתה מילה שמורה. הפקודה exec של Qt היא זאת שמפעילה את הלולאה הראשית של היישום, והשם exec הוא בדיוק שם הפונקציה ב C++, לכן ובשביל לא לבלבל יותר מדי מתכנתים שכבר מכירים Qt מ C++, בפייתון בחרו לאמץ את השם אבל להוסיף _ בסוף. תוכנית PyQt פשוטה של שלום עולם לכן נראתה כך:

import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QLabel

if __name__ == "__main__":
    app = QApplication(sys.argv)
    label = QLabel("Hello World", alignment=Qt.AlignCenter)
    label.show()
    sys.exit(app.exec_())

אבל בפייתון 3 המילה exec כבר לא היתה מילה שמורה, ולכן החל מ Qt5 אפשר להשתמש באותו exec של C++. בגירסה 6 אנחנו כבר מקבלים Deprecation Warning על ה exec עם הקו התחתי בסוף. אגב גם על sys.exit שמופיע בתוכנית הדוגמה אפשר לוותר והקוד הבא יעשה בדיוק את אותו דבר ובלי להתלונן:

import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QLabel

if __name__ == "__main__":
    app = QApplication(sys.argv)
    label = QLabel("Hello World", alignment=Qt.AlignCenter)
    label.show()
    app.exec()

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

pip install PySide6