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

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

יום 1 - מספיק Rust בשביל שנוכל לקודד

27/12/2022

הי חברים,

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

מוכנים? הדקו חגורות ומיד ממריאים.

המשך קריאה

למה אנחנו לא בוחרים ב X

26/12/2022

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

  1. אין לי שום בעיה ש X פותר (שנים אנשים כתבו jQuery בלי לדעת שיש להם בעיה. שנים אנשים המשיכו להשתמש ב SVN בלי לשים לב ש git היה משפר את המצב שלהם).

  2. אני לא מאמין ש X יוכל לפתור לי את הבעיה.

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

  4. גם ל X יש בעיות. לעבור אליו זה בסך הכל להחליף בעיה אחת באחרת. אני מעדיף להישאר עם הבעיות שאני מכיר.

  5. אני לא מכיר אף אחד שמשתמש ב X (או: המערכת שלי שונה מכל המערכות שבונים אנשים שמשתמשים ב X).

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

לקחים מהחלפת כמה עשרות סיסמאות (ועוד מחשבות על הפירצה האחרונה ל lastpass)

25/12/2022

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

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

המשך קריאה

אם הם רק היו עקביים...

24/12/2022

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

>>> 5 in range(0, 5)
False

ב JavaScript, עם lodash:

_.range(0, 5)
Array(5) [ 0, 1, 2, 3, 4 ]

ב Clojure:

user=> (range 0 5)
(0 1 2 3 4)

ב Rust:

for i in 0..5 {
    print!("{}", i)
}
// prints: 01234

אבל אז יש את השפות בהן האיבר האחרון הוא כן חלק מ Range. למשל Elixir:

iex(2)> Enum.member?(0..5, 5)
true

או Bash:

$ echo {0..5}
0 1 2 3 4 5

ואז יש את רובי, שמציעה שתי דרכים ליצור Range:

3.1.1 :001 > (0..5).include?(5)
 => true

3.1.1 :002 > (0...5).include?(5)
 => false

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

מאחורי כל שאלת "איך"

23/12/2022

מאחורי כל שאלת "איך" מתחבאת שאלת "למה", ובדרך כלל ה"למה" היא הרבה יותר מעניינת.

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

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

מעבר בין "חשבונות" באפליקציית Redux

22/12/2022

אחד האתגרים בעבודה עם Redux הוא ניהול אוביקט המידע, במיוחד כשהמידע שאנחנו מנהלים לא ממש מסתדר טוב עם העקרונות של רידאקס, ובמיוחד אם אנחנו מדברים על שינוי מערכת קיימת. דוגמה? בואו. ניקח מערכת Todo פשוטה שצריכה להציג רשימת משימות, מאפשרת למשתמשים למחוק משימות ולעדכן שמשימות בוצעו. אפשר ליצור כזאת בשניה וחצי ב code sandbox עם הטמפלייט redux-toolkit-typescript. הנה קישור עם קוד לסקרנים:

https://codesandbox.io/s/eager-thompson-ijimne

המשך קריאה

קוד נכון

21/12/2022

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

שתי דוגמאות מהימים האחרונים ואז שורה תחתונה-

  1. פה באתר כפתור "אחורה" בדפדפן לא עבד בחלק מהדפים. הבאג נגרם בגלל השורה:
window.history.replaceState(null, null, url.toString());

בשביל לתקן בסך הכל היה צריך להחליף את השורה ל:

window.history.replaceState(window.history.state, null, url.toString());

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

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

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

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

ואיך זה ישפיע על הפיתוח בעתיד?

20/12/2022

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

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

  2. איזה בדיקות חדשות אצטרך להריץ בכל סבב?

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

  4. איך זה יישבר?

  5. איזה פיצ'רים אחרים במערכת יושפעו?

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

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

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

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