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

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

שלום GraphQL חלק 2: חיבור אפליקציית ריאקט עם Relay

14/09/2020

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

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

המשך קריאה

שלום GraphQL

13/09/2020

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

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

המשך קריאה

להוריד את הגלגלי עזר

12/09/2020

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

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

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

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

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

טיפ פנדס: איך להתעלם מטעויות Encoding בקובץ

11/09/2020

הפקודה read_csv של פנדס היא מופלאה. רוב קבצי ה CSV שאנחנו מוצאים בדוגמאות באינטרנט כתובים בקידוד UTF8 וזה בדיוק גם קידוד ברירת המחדל של read_csv.

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

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

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

>> pd.read_csv('053cea08-09bc-40ec-8f7a-156f0677aff3.csv', '|')

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xee in position 0: invalid continuation byte

עד לפה לא מבהיל מדי כי תמיד אפשר להעביר Encoding לפנדס. אבל הפעם גם זה לא עבד:

>> pd.read_csv('053cea08-09bc-40ec-8f7a-156f0677aff3.csv', encoding='iso8859-8')

UnicodeDecodeError: 'charmap' codec can't decode byte 0xd2 in position 127430: character maps to <undefined>

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

>> fd = open('053cea08-09bc-40ec-8f7a-156f0677aff3.csv', encoding='iso8859-8', errors='replace')
>> df = pd.read_csv(fd, '|')

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

df.groupby('tozeret_nm').size().sort_values(ascending=False)

tozeret_nm
מזדה יפן         299175
יונדאי קוריאה    228002
קיה קוריאה       205592
טויוטה יפן       189340
סקודה צ'כיה      173473

לדעת ריאקט בלי רידאקס

10/09/2020

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

אבל-

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

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

המספר בקפה

09/09/2020

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


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

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

ובכל פעם, האתגר הסודי שלי היה לקוות שאקבל את אחד המספרים האהובים עליי: 7 או 22.

ולמה זה אתגר?

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

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

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

בקפה הם אף פעם לא אמרו לי לא.

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

הדרך הטובה ביותר לקבל את מה שאתם רוצים היא פשוט לבקש.

זה לא קל כמו שזה נראה ; זה דורש תרגול.

מהו הדבר הקטן, או הגדול, שאתם הולכים להרשות לעצמכם לבקש היום? מה הדבר הכי גרוע, והכי טוב, שיכול לקרות בגלל זה?

מי נתן לך את זה ב 35 ?

08/09/2020

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

אם קניתי קילו מלפפונים ב 10 ש"ח, וחודש אחרי אני מגיע לחנות ואני רואה שהמחיר הוא 20, אני אחשוב פעמיים לפני שאקנה (למרות שאולי אם כבר בביקור הראשון המחיר היה 20 ש"ח הייתי קונה בשמחה).

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

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

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

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

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

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

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

עזבו אדומות, בואו נגלה מי הערים הירוקות בעזרת פייתון

07/09/2020

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

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

https://www.gov.il/he/Departments/DynamicCollectors/cities-ramzor

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

https://www.gov.il/he/api/DataGovProxy/GetDGResults

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

המשך קריאה

איך לקרוא קובץ CSV למערך של מפות ב Clojure

06/09/2020

בתיעוד על ספריית העבודה עם CSV של Clojure מצאתי את קטע הקוד הבא, שהופך קובץ CSV למערך של מפות:

(defn csv-data->maps [csv-data]
  (map zipmap
       (->> (first csv-data)
            repeat)
      (rest csv-data)))

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

המשך קריאה

פייתון, פסיק ושגיאות לא הגיוניות

05/09/2020

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

def first_letter(text):
    return text[0]

text = "I can see a mountain",
print(first_letter(text))

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

$ python3 ouch.py 
I can see a mountain

את כל הטקסט??? פייתון...

הבעיה היא כמובן הפסיק בסוף שורת ההשמה:

text = "I can see a mountain",

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

וזאת אולי הסיבה המרכזית שכדאי להוסיף Type Hints לקוד שלכם. הכתיב הבא:

def first_letter(text: str):
    return text[0]

text = "I can see a mountain",
print(first_letter(text))

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

$ python3 -m mypy ouch.py
ouch.py:5: error: Argument 1 to "first_letter" has incompatible type "Tuple[str]"; expected "str"
Found 1 error in 1 file (checked 1 source file)

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