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

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

השיטה הבטוחה להפוך למתכנתים טובים יותר

30/03/2018

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

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

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

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

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

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

סיפור אחר לגמרי

29/03/2018

כמעט בכל המכללות היום מעודדים סטודנטים להשתמש בגיטהאב ולהעלות פתרונות לתרגילים לפרופיל שלהם שם. כן גם אני חוטא בזה בחלק מהקורסים כאן באתר ולראיה יש 190,118 מאגרים בגיטהאב ששמם datasciencecoursera. יש גם מיליון מאגרים בשם hello-world ועוד מיליון שנקראים test. אבל לתרום קוד לפרויקט קוד פתוח זה סיפור אחר לגמרי. לפני כמה חודשים הורדתי את הקוד של gcompris. הבן שלי עף על המשחקים האלה וכל הקוד כתוב ב QML אז חשבתי שיהיה נחמד לכתוב משחק בעצמי. הקוד לא התקמפל בגלל חוסר תאימות למק ב CMakeLists.txt. אני יודע CMake ומהר מאוד תיקנתי את הבעיה, קימפלתי והרצתי. השלב הבא היה לשלוח Pull Request בחזרה ל gcompris עם התיקון כדי שגם אחרים יהנו. בתגובה החברים שם אמרו שאם כבר באתי אולי אני יכול לעזור להם בעוד כמה בעיות שקשורות בתאימות למק ושעדיף להוסיף גם אותן לאותו Pull Request, ושהם גם לא יכולים לקבל ממני PR כי צריכים את השם המלא והחשבון גיטהאב שלי היה בשם ynonp. בסוף אחרי שלושה חודשים התיקון שלי (באורך שתי שורות) כן נכנס לפרויקט הרשמי. לתרום קוד לפרויקט קוד פתוח דורש יכולת לעבוד עם אנשים, להבין את העולם מנקודת המבט שלהם, להיות מוכן להיכנס לדיאלוג ולשפר את העבודה שלך עד שהיא תהיה ברמה מספיק טובה כדי שיקבלו אותה. במקום לעודד אנשים לפתוח עוד ריפוזיטורי בגיטהאב עדיף להתאמץ ולעזור להם לשלוח Pull Request, כל הדרך עד שמתקבל.

איוון יו

28/03/2018

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

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

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

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

אתם לא צריכים עוד קורס

27/03/2018

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

לא, אתם לא צריכים עוד קורס. אתם צריכים להתחיל ללמוד.

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

סגנון אחר

26/03/2018

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

...

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

...

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

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

על תבונה ורגישות (של מחשבים)

25/03/2018

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

print(sum(n * n for n in range(100)))
print(sum([n * n for n in range(100)]))

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

ב Ruby שתי השורות האלה אולי נראות דומה אבל השניה תכשיל את כל התוכנית (גם אם יש פונקציה בשם max שהוגדרה לפני כן):

puts max(2, 3)
puts max (2, 3)

וב Bash שתי הפקודות האלה עשויות למצוא קבצים אחרים לגמרי:

find . -name '*.c'
find . -name *.c

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

שתי דרכים לכתוב קוד לשימוש חוזר

24/03/2018

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

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

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

  2. אפשר להתחיל עם מימוש אחד בלי חשיבה מתוחכמת על שימוש חוזר והיררכיית מחלקות. גם המימוש השני והשלישי יהיו פיתוח מאפס עם הרבה copy/paste ורק במימוש הרביעי לחפש את המשותף, לבנות ספריה גנרית ואיתה לכתוב מחדש את שלושת המימושים הראשונים.

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

שבעה הרגלים של מתכנתים יעילים במיוחד

23/03/2018

  1. לחשוב לפני שמתחילים לכתוב.

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

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

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

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

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

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

הודעות שגיאה

22/03/2018

הקוד הזה בפייתון כותב את הטקסט Hello World לקובץ בשם out.txt:

def run(myfile, text):
    myfile.write(text)

f = open('out.txt', 'w')
run(f, 'Hello World\n')
f.close()

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

import multiprocessing as mp

def run(myfile, text):
    myfile.write(text)

f = open('out.txt', 'w')

p = mp.Process(target=run, args=(f, 'hello world'))
p.start()
p.join()

f.close()

הבעיה? הקובץ הפעם נשאר ריק.

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

כשאתם כותבים קוד תשתית שגם אנשים אחרים הולכים להשתמש בו, צפו לזה שאנשים אחרים לא חכמים כמוכם ואולי לא מבינים איך כל דבר בקוד שלכם עובד. אם מישהו משתמש במנגנון שכתבתם בצורה לא נכונה כדאי להגיד לו את זה בצורה ברורה. אין לי בעיה שאתה לא יכול להעביר File Object בין Processes. אפשר ורצוי לזרוק Exception כך שאני לא אהיה מופתע שהתוכנית הסתיימה ״בהצלחה״ והקובץ נשאר ריק.

מה חשוב השם

21/03/2018

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

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

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

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