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

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

יבוא מעגלי ו Redux Tolkit

10/04/2023

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

המשך קריאה

טיפ פייתון: שימו לב ל b

09/04/2023

המודול base64 בפייתון מציע דרך פשוטה לפענח מחרוזת מקודדת ל base64. לדוגמה:

>>> import base64
>>> base64.b64decode("bmluamE=")
b'ninja'
>>> base64.b64decode("bW9ua2V5")
b'monkey'
>>> base64.b64decode("bG92ZQ==")
b'love'
>>>

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

import base64
import sys

enc = sys.argv[1]

users = ["monkey", "love", "ninja"]

if base64.b64decode(enc) in users:
    print("welcome")

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

אופציה 1:

import base64
import sys

enc = sys.argv[1]

users = [b"monkey", b"love", b"ninja"]

if base64.b64decode(enc) in users:
    print("welcome")

אופציה 2:

import base64
import sys

enc = sys.argv[1]

users = ["monkey", "love", "ninja"]

if base64.b64decode(enc).decode("utf-8") in users:
    print("welcome")

למה לא נשלח מייל הבוקר (או: מה בא אחרי I)

08/04/2023

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

hebcal | head -10
1/3/2023 Asara B'Tevet
1/23/2023 Rosh Chodesh Sh'vat
2/6/2023 Tu B'Shvat
2/18/2023 Shabbat Shekalim
2/21/2023 Rosh Chodesh Adar
2/22/2023 Rosh Chodesh Adar
3/4/2023 Shabbat Zachor
3/6/2023 Ta'anit Esther
3/7/2023 Purim
3/8/2023 Shushan Purim

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

evenings_ok=(
"Pesach I"
"Pesach VII"
"Shavuot I"
"Tish'a B'Av"
"Rosh Hashana II"
"Yom Kippur"
"Sukkot I"
"Shmini Atzeret"
)

for send_in_evening in "${evenings_ok[@]}"
do
        # echo "^[0-9/]+ ${send_in_evening}"
        if hebcal $(date +"%m %d %Y") | egrep -v "CH''M" | egrep "^[0-9/]+ ${send_in_evening}" >& /dev/null
        then
                if (( $(date +%"_H") < 20 ))
                then
                        exit 1
                fi
        fi
done

אז מה שבור כאן? הפסח כמובן. המחרוזת Pesach I שמייצגת את חג הפסח באמת מתאימה לטקסט Pesach I שיודפס באותו יום, אבל היא מתאימה גם ל Pesach II:

hebcal | grep 'Pesach I'
4/6/2023 Pesach I
4/7/2023 Pesach II
4/8/2023 Pesach III (CH''M)
4/9/2023 Pesach IV (CH''M)

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

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

$ hebcal | grep 'Pesach I$'
4/6/2023 Pesach I

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

evenings_ok=(
"Pesach I$"
"Pesach VII"
"Shavuot I$"
"Tish'a B'Av"
"Rosh Hashana II"
"Yom Kippur"
"Sukkot I"
"Shmini Atzeret"
)

no_emails=(
"Rosh Hashana"
)

no_emails_erev=(
"Erev Pesach"
"Erev Shavuot"
"Erev Rosh Hashana"
"Erev Sukkot"
"Erev Yom Kippur"
)


for send_in_evening in "${evenings_ok[@]}"
do
        # echo "^[0-9/]+ ${send_in_evening}"
        if hebcal $(date +"%m %d %Y") | egrep -v "CH''M" | egrep "^[0-9/]+ ${send_in_evening}" >& /dev/null
        then
                if (( $(date +%"_H") < 20 ))
                then
                        exit 1
                fi
        fi
done

for holiday in "${no_emails[@]}"
do
        if hebcal $(date +"%m %d %Y") | egrep "^[0-9/]+ ${holiday}" >& /dev/null
        then
                exit 1
        fi
done



for erev_holiday in "${no_emails_erev[@]}"
do
        if hebcal $(date +"%m %d %Y") | egrep "^[0-9/]+ ${erev_holiday}" >& /dev/null && [$(date +"_H") > 19]
        then
                exit 1
        fi
done

טיפ פייתון: פיתוח עם docker compose

07/04/2023

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

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

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

בשביל לפתח על המחשב שלנו קוד פייתון עם docker-compose נצטרך להתמודד עם האתגרים הבאים:

  1. נרצה שהקוד בתוך הקונטיינר יהיה זהה לקוד בספריית הפיתוח.

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

  3. נרצה לאפשר לקוד לתקשר עם בסיס נתונים שגם יעלה מתוך ה compose.

  4. נעדיף לא לבנות אימג' בשביל הפיתוח כדי לחסוך פעולות build.

המשך קריאה

פתוחים לרעיונות חדשים

06/04/2023

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

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

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

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

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

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

משחקים עם React Server Components

05/04/2023

פיצ'ר Server Components של ריאקט הוא חלק מריאקט 18 ומאפשר סוג של Server Side Rendering לקומפוננטות ספציפיות. בגירסה 13 של Next.JS התווספה תמיכה ב Server Components מה שהפך את העבודה איתם להרבה יותר פשוטה. בואו נראה איך זה עובד ומה היתרונות שלהם על פני פיתוח ריאקט רגיל או על פני Server Side Rendering.

המשך קריאה

הסיבות בגללן בחרנו Micro Services

04/04/2023

יש לא מעט סיבות שיכולות לשכנע אנשים לבחור בארכיטקטורת Micro Services, ביניהן:

יכולת גדילה אופקית - כשסרביס מסוים עמוס אפשר להוסיף עוד מופעים שלו

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

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

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

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

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

הבעיה שבהרבה מקרים הבחירה בארכיטקטורת Micro Services לא מביאה לתוצאה הרצויה: אי אפשר באמת להוסיף עוד עותקים של סרביס מסוים כי המקביליות גורמת לנעילות, כשסרביס נופל הסרביסים האחרים נכנסים ל Retry Loop ושוברים את כל המערכת כמו דומינו, סרביסים משתפים מידע דרך בסיס נתונים משותף ולכן אי אפשר באמת לשנות אחד בלי לשבור אחרים ואפילו ה Deployments נשארו מסובכים כי צריך להעלות גירסה של כמה סרביסים במקביל. כל זה לפני שדיברנו על הקושי להקים סביבת עבודה מקומית או היכולת לבדוק גירסה מסוימת של המערכת (או באופן כללי לדבר על "גירסה" של מערכת בעולם של מיקרו סרביסים).

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

גיט add הכל הוא הרגל רע

03/04/2023

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

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

במהלך הפיתוח ובמיוחד בתוך רצף עבודה מאוד מפתה להשתמש בפקודות:

$ git add .
$ git commit

או בגירסה המתונה יותר git commit -a. הבעיה בשתי הגירסאות נובעת משילוב שני גורמים:

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

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

מה עושים במקום? האפשרות המועדפת עליי היא להפעיל git status ו git diff לפני שמתחילים להכניס דברים לקומיט, ואז להכניס את השינויים לקומיט בצורה מבוקרת - או באמצעות הוספת קבצים מלאים או אפילו באמצעות git add -i שמאפשר לבחור איזה שורות בקובץ צריכות להיכנס לקומיט.

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

צעדים ראשונים עם neo4j

02/04/2023

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

המשך קריאה

הזמן הכי טוב לקחת קורס

01/04/2023

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

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

האם תוך כדי הפרויקט, כדי לא לבזבז זמן?

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

בפיתוח תוכנה - כל התשובות נכונות.

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

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

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

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