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

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

שתי מוטיבציות

24/02/2023

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

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

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

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

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

23/02/2023

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

המשך קריאה

חדש ב Ruby: אוביקט מידע

22/02/2023

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

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

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

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

User = Data.define(:name, :email)

u1 = User.new(name: 'dave', email: 'dave@e.com')
u2 = User.new(name: 'john', email: 'john@e.com')

puts u1.email

puts "u1 == u2 ? #{u1 == u2}"

עד לפה הכל קל ודומה ל Struct, אבל יש שני הבדלים מרכזיים:

  1. אוביקטי Data לא מגדירים את to_a לכן אי אפשר להמיר Data Object למערך של כל הערכים שבו (כמובן שאין בעיה להפעיל to_h כדי לקבל Hash)

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

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

נכשלתי במבחן פישינג (או: למה לינקים במייל זה כל כך מסובך)

21/02/2023

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

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

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

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

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

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

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

  2. עדכונים על PR בגיטהאב מגיעים למייל עם לינק ל PR.

  3. ניוזלטרים שנשלחים למייל מגיעים מלאים בלינקים, ואנחנו רגילים ללחוץ על לינקים למאמרים שמעניינים אותנו.

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

  5. חברות רבות ישלחו חשבונית בתור קובץ מצורף, אבל חברות רבות אחרות ישלחו אותה בתור לינק לקובץ PDF ברשת.

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

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

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

פיתרון תרגיל Advent Of Code יום 7 בעזרת Datomic

20/02/2023

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

המשך קריאה

כשיש לך פטיש

19/02/2023

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

וכאן יש גם שתי הזדמנויות ללמידה-

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

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

קטנה על שאילתות ב Datomic

18/02/2023

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

המשך קריאה

כן, לשכפל

16/02/2023

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

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

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

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

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

  1. כשאני רק בונה פיצ'ר חדש, ועדיין לא בטוח מה הוא צריך לכלול.

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

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

  4. כשכל אבסטרקציה שאני מנסה לבנות לא ממש "מסתדרת" ומשאירה המון פינות ומקרי קצה.

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