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

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

המלצה על פרויקט - Helm Dashboard

20/03/2023

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

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

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

אתם יכולים למצוא את כל הפרטים על הפרויקט בקישור כאן: https://www.facebook.com/groups/frontendistim/permalink/913268943434540/

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

19/03/2023

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

בהרבה מערכות אחרות המידע הדינמי של העמוד הוא חלק בלתי נפרד ממנו, אבל בשביל לאפשר Scale גדול נבחר עדיין להשתמש בקבצי HTML/CSS/JS סטטיים, שימשכו את המידע הדינמי מהשרת בעליה דרך API. ההנחה היא שבמקרי קיצון משיכת מידע מ API תעמיס פחות על השרתים מאשר ייצור של Template מלא של ה HTML, ובנוסף קל יותר לפתח את המערכת עם הפרדה ברורה בין צוות ה Front End לצוות ה Back End.

בהרבה מערכות נוספות המידע הדינמי של העמוד הוא חלק בלתי נפרד ממנו אבל בגלל שהצוות קטן ומורכב ממתכנתי Full Stack, או שלא מתוכנן עומס של אלפי בקשות בשניה על ה API, שווה לנו לוותר על ה HTML הסטטי וליצור את ה HTML דינמית מתוך קוד צד שרת (לדוגמה קוד Rails או Django). דף HTML כזה שחוזר לדפדפן מכיל בטעינה הראשונית גם את כל המידע הדינמי של העמוד ואז הדפדפן יכול להציג את התוכן מיד איך שמקבל את התשובה לבקשה הראשונה. נכון, הפסדנו את היכולת להפיץ את ה HTML דרך CDN, אבל חסכנו צורך בבקשת רשת נוספת בשביל המידע הדינמי של העמוד.

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

תאכל תאכל

18/03/2023

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

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

הרעבה (באנגלית: Starvation) היא בעיה הנוצרת בסביבה המאפשרת ריבוי משימות (Multitasking), כאשר מתהליך מסוים נמנעת גישה לאחד ממשאבי המערכת כך שהתהליך לעולם לא יצליח לסיים את משימתו.

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

המשך קריאה

מיתוסים על קוד ישן

17/03/2023

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

  1. הקוד הישן מכוער ולא גמיש.

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

  3. בקוד הישן אין באגים כי כולם כבר תוקנו.

  4. כל בעיות האבטחה של המערכת הן בגלל הקוד הישן.

  5. הקוד הישן הוא הגורם העיקרי לאיטיות.

  6. בשביל לתקן באג בקוד הישן צריך למחוק את כולו ולכתוב הכל מחדש.

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

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

כשההגיון שלך וההגיון של המחשב לא תואמים

16/03/2023

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

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

תרגום טקסטים בפייתון עם AWS

15/03/2023

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

$ aws configure

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

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

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

$ pip install boto3

ואז להריץ סקריפט כמו זה:

import boto3

client = boto3.client('translate')

response = client.translate_text(
    Text='hola mundo',
    SourceLanguageCode='es',
    TargetLanguageCode='en',
)

print(response["TranslatedText"])

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

בונוס למתקדמים - אם יש לכם הרבה טקסטים לתרגם, אפשר להעלות אותם ל S3 ולשלוח את התרגומון לרוץ על כל הקבצים ולתרגם את כולם. זה יכול לעזור כשצריך לבנות כרטיסיות מתוך רשימה ארוכה של מילים שאספתם. מידע נוסף על הפיצ'ר אפשר למצוא בתיעוד של בוטו בקישור: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/translate/client/starttexttranslation_job.html

החשיבות של כללים

14/03/2023

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

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

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

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

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

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

היום למדתי: לא הופכים OpenStruct ל JSON

13/03/2023

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

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

3.1.1 :001 > d = {foo: 10, bar: 20}
 => {:foo=>10, :bar=>20}
3.1.1 :002 > d[:foo]
 => 10
3.1.1 :003 >

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

3.1.1 :005 > require 'ostruct'
 => true
3.1.1 :007 > dd = OpenStruct.new(d)
 => #<OpenStruct foo=10, bar=20>
3.1.1 :008 > dd.foo
 => 10
3.1.1 :009 > dd.bar
 => 20

עד לפה הכל טוב ואפשר גם להפעיל to_json ולקבל את כל השדות בחזרה בתור JSON:

3.1.1 :002 > require 'ostruct'
 => true
3.1.1 :003 > require 'json'
 => true
3.1.1 :004 > OpenStruct.new({ foo: 10, bar: 20 })
 => #<OpenStruct foo=10, bar=20>
3.1.1 :005 > OpenStruct.new({ foo: 10, bar: 20 }).to_json
 => "\"#<OpenStruct foo=10, bar=20>\""

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

3.1.1 :001 > OpenStruct.new({ foo: 10, bar: 20 }).to_json
 => "{\"table\":{\"foo\":10,\"bar\":20}}"

מאיפה הגיע לשם ה table???

חיפוש ב Stack Overflow הביא אותי לתשובה הזאת. מסתבר שבמימוש של OpenStruct כל הפריטים נשמרים בתור ערכים של משתנה מחלקה בשם table, והקידוד ל JSON של ריילס פשוט מקודד את כל משתני המחלקה.

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

3.1.1 :077 > OpenStruct.new({a: 10, b: 20}).to_h.to_json
 => "{\"a\":10,\"b\":20}"

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

בעיות שכבר אין בפיתוח תוכנה

12/03/2023

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

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

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

  1. הפצת תוכנה - לפני 20 שנה היה מאוד קשה לכתוב אפליקציה אחת שתרוץ גם על Windows וגם על Mac. כשהאייפון הראשון יצא אי אפשר היה לדמיין פיתוח מערכת שתרוץ גם על מחשב וגם על טלפון, וכשאנדרואיד התחיל לתפוס תאוצה המצב רק נהיה יותר מבלבל. אבל אז האינטרנט השתלט והגיעו חנויות האפליקציות וכלי ה Cross Platform, ופתאום כל אחד יכול לשבת בבית ולכתוב אפליקציה קטנה שכולם בכל העולם יוכלו להפעיל.

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

  3. אבטחת מידע בסיסית - ב 2005 אפשר היה להיכנס לבסיס הנתונים של 90% מהאתרים ברשת עם פירצה מאוד בסיסית שנקראה SQL Injection. ב 2012 אפשר היה לשבור את רוב הרשת עם פירצה שנקראה XSS. טכנולוגיות חדשות הפכו את שתי הפריצות האלה ופריצות פשוטות רבות נוספות ללא רלוונטיות. נכון עדיין יש האקרים ועדיין צריך לאבטח את המוצרים שלנו, אבל הסיכון בפריצה למוצר שלכם (אם כתבתם בפריימוורק מודרני) הוא הרבה יותר נמוך ממה שהיה פעם.

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

ועכשיו שזה מאחורינו, מה עוד עוצר אותך?

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

11/03/2023

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

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

המשך קריאה