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

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

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

03/03/2019

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

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

import binascii

def write_stuff_to_file(fname):
    with open(fname, 'w') as f:
        f.write('\x10')

def read_stuff_from_file(fname):
    with open(fname, 'r') as f:
        stuff = f.read()
        print(binascii.hexlify(stuff.encode('utf-8')))

write_stuff_to_file('demo.txt')
read_stuff_from_file('demo.txt')

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

b'10'

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

import binascii

def write_stuff_to_file(fname):
    with open(fname, 'w') as f:
        f.write('\x0d')

def read_stuff_from_file(fname):
    with open(fname, 'r') as f:
        stuff = f.read()
        print(binascii.hexlify(stuff.encode('utf-8')))

write_stuff_to_file('demo.txt')
read_stuff_from_file('demo.txt')

ועכשיו התוצאה:

b'0a'

מה קרה כאן? כתבתי לקובץ את המספר 13 וקיבלתי בחזרה את המספר 10. נלך לראות מה כתוב בקובץ:

$ xxd demo.txt 
00000000: 0d

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

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

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

בחזרה לתוכנית הקודמת - שינוי הפקודה open לעבודה עם מידע בינארי יבטל את המרת תווי ירידת השורה ויגרום לתוכנית לעבוד ולקרוא מהקובץ בדיוק את אותו מידע שכתבנו:

import binascii

def write_stuff_to_file(fname):
    with open(fname, 'wb') as f:
        f.write(b'\x0d')

def read_stuff_from_file(fname):
    with open(fname, 'rb') as f:
        stuff = f.read()
        print(binascii.hexlify(stuff))

write_stuff_to_file('demo.txt')
read_stuff_from_file('demo.txt')

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

fname = 'demo.txt'
with open(fname, 'r', encoding='utf-8') as f:
    pass

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

02/03/2019

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

וכשזה באמת לא הצליח אז עזבתי והלכתי לעשות משהו שאני טוב בו.

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

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

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

שאלות לא הוגנות

01/03/2019

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

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

function foo() {
    var a = b = 5;
    console.log(typeof(a));
    console.log(typeof(b));
}

foo();
console.log(typeof(a));
console.log(typeof(b));

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

function foo() {
    var a = 5;
    b = 5;

    console.log(typeof(a));
    console.log(typeof(b));
}

foo();
console.log(typeof(a));
console.log(typeof(b));

עכשיו הכל ברור. השאלה בודקת אם את יודעת את ההבדל בין הגדרת משתנה עם var להגדרה בלעדיו, ואנחנו יכולים לדבר על זה (ועל הדרך לדבר גם על let ו const ו window ו this ומתי נגדיר משתנים גלובליים, ואיזה עוד משתנים גלובליים יש בתוכנית הזאת).

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

איך לדבר עם לקוחות

27/02/2019

מה עונים ללקוח שמבקש הנחה? וללקוחה שמבקשת את הכסף בחזרה כי היא לא מרוצה מהעבודה שלכם? או ללקוח שמתעקש להוסיף עוד ועוד שינויים ופיצ'רים לפרויקט שתומחר כ Fixed Price?

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

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

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

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

מה דוקר יכול לעשות בשבילכם?

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

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

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

המשך קריאה

גזלן

25/02/2019

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

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

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

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

שלושה סוגים של Delegation

24/02/2019

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

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

המשך קריאה

אינטואיציה

23/02/2019

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

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

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

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

חדש בבלוג: ערוץ טלגרם

22/02/2019

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

כתובת הערוץ החדש ישן היא:

@tocodeil

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

  def publish_daily_post_content do
    href = App.Tocode.daily_post_url <> "/md"
    headers = []
    options = [hackney: [pool: :default]]

    {:ok, response} = HTTPoison.get(href, headers, options)
    Nadia.send_message("@tocodeil", response.body, parse_mode: "Markdown")
  end

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

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

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

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

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

https://github.com/ynonp/tocode_bot