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

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

מילים שקשה להגיד

28/09/2020

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

לכל פונקציה ב JavaScript יש מאפיין משם length שמחזיר כמה פרמטרים הפונקציה מצפה לקבל. ב Python קצת יותר קשה לגלות את זה אבל עדיין אפשרי עם חבילת inspect, ב Ruby יש לכל פונקציה מאפיין בשם arity שמחזיר את הערך וב Clojure אנחנו צריכים לקפוץ שמיניות באוויר בשביל למצוא אותו.

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

a = { a: 10, c: 30 }
b = { a: 5, b: 20 }
res = a.merge(b) {|k, v1, v2| v1 + v2 }

# now res is: { a: 15, b: 20, c: 30 }

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

a = { 'a': 10, 'c': 30 }
b = { 'b': 20 }
res = dict(**a, **b)
# now res is: { 'a': 10, 'b': 20, 'c': 30 }

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

ויש עוד מאות כעסים קטנים כאלה בכל מעבר בין שפות, וזה בסדר. שווה לזכור שבכל מעבר כזה בין שפות מאוד קל למצוא חבילות שסוגרות את הפער. גם אם ל JavaScript אין את random.randint של פייתון, אנחנו עדיין יכולים לקבל פונקציונאליות זהה מ lodash; חבילת mergedict של פייתון מאפשרת לשלב בצורה אלגנטית בין מילונים ולקבוע מה לעשות עם ערכים מתנגשים בקלות ממש כמו ב Ruby.

ההבדלים האמיתיים בין שפות הם לא בפונקציה מסוימת שנמצאת או לא, אלא בגישה ובהשקפת עולם שונה: האם יש Type System? האם הוא מחייב? האם יש Class-ים? האם יש הגבלה על עומק הרקורסיה? איך בונים קוד מקבילי או מבוזר? האם זה מתקמפל? האם זה רץ על המכונה אליה אני מכוון?

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

לעצור את הטובים

27/09/2020

אחת הטכניקות הטפשיות (אך מפתות) של אבטחת מידע היא לבנות מנגנונים שיהיה קל מאוד לעקוף אותם ויעצרו רק את האנשים שאין להם כח להתאמץ יותר מדי. השבוע למדתי במקרה על דרך קלה לזהות גולשים שמשתמשים בסלניום כדי להפעיל בצורה אוטומטית אתרים: מסתבר שסלניום או יותר נכון ה chromedriver שהוא מפעיל מוסיף Cache לכל דף - אני לא לגמרי בטוח מה הוא שומר ב Cache הזה - אבל את ה Cache הוא שומר במפתח עם שם מוזר שמתחיל ב $cdc. לסקרנים שביניכם הנה הקוד שיוצר את ה cache בכרומדרייבר:

function getPageCache(opt_doc, opt_w3c) {
  var doc = opt_doc || document;
  var w3c = opt_w3c || false;
  // |key| is a long random string, unlikely to conflict with anything else.
  var key = '$cdc_asdjflasutopfhvcZLmcfl_';
  if (w3c) {
    if (!(key in doc))
      doc[key] = new CacheWithUUID();
    return doc[key];
  } else {
    if (!(key in doc))
      doc[key] = new Cache();
    return doc[key];
  }
}

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

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

זום

26/09/2020

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

המשך קריאה

חידת פנדס: לאן נעלמו הערכים?

25/09/2020

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

בגלל שכל אחד שילם מחיר קצת שונה היה נוח לחלק את המחירים לקבוצות עם pd.cut וכך הגעתי לקוד הבא:

import pandas as pd

url = 'https://raw.githubusercontent.com/guipsamora/pandas_exercises/master/07_Visualization/Titanic_Desaster/train.csv'
titanic = pd.read_csv(url)

s=pd.cut(titanic['Fare'], bins=[0, 10, 20, 50, 100, 1000], right=True)
data = s.value_counts()

print(data)

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

(0, 10]        321
(20, 50]       216
(10, 20]       179
(50, 100]      107
(100, 1000]     53
Name: Fare, dtype: int64

והנה מאפייני הטיטאניק:

In: titanic['Fare'].describe()
Out:

count    891.000000
mean      32.204208
std       49.693429
min        0.000000
25%        7.910400
50%       14.454200
75%       31.000000
max      512.329200
Name: Fare, dtype: float64

קל לראות שבחלוקה לסלים בשביל לצייר את הגרף איבדנו 15 נתוני כרטיסים.

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

תרגיל פייתון פשוט

24/09/2020

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

המשך קריאה

לפעמים זה משעמם

23/09/2020

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

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

בקישור הזה: https://github.com/ossu/computer-science

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

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

פיתוח מערכת פלאגינים פשוטה ב Python

22/09/2020

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

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

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

המשך קריאה

שינוי שם ענף ברירת המחדל ב git

21/09/2020
git

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

בינתיים בכל מקרה וכהכנה לאירוע שני טיפים קשורים-

הראשון הוא שאתם יכולים (ותמיד יכולתם) לבחור מה יהיה שם הענף הראשון במקום master, פשוט באמצעות יצירת ענף ראשון חדש לפני הקומיט הראשון:

$ git init
$ git checkout -b main

והשני הוא שאתם יכולים (מיולי האחרון) לבחור מה יהיה שם ענף ברירת המחדל במאגרים מקומיים חדשים שאתם יוצרים באמצעות שינוי קונפיגורציה פשוט. הרצת הפקודה הבאה מ cmd (כרגיל בלי הדולר שבהתחלה) תשנה את שם ענף ברירת המחדל ל main בכל מאגר מקומי חדש שלכם:

$ git config --global init.defaultBranch main

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

במורד מחילת הארנב

20/09/2020

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

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

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

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

וכן CSS - אני מסתכל עליך...

עבודה עם מספר מאגרים מרוחקים ב Git במקביל

19/09/2020
git

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

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

המשך קריאה