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

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

ככה לא כותבים בדיקות תקינות

27/08/2018

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

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

$ hebcal 4 2059
4/1/2059 Pesach IV (CH''M)
4/2/2059 Pesach V (CH''M)
4/3/2059 Pesach VI (CH''M)
4/4/2059 Pesach VII
4/5/2059 Pesach VIII
4/10/2059 Yom HaShoah
4/13/2059 Rosh Chodesh Iyyar
4/14/2059 Rosh Chodesh Iyyar
4/16/2059 Yom HaZikaron
4/17/2059 Yom HaAtzma'ut
4/27/2059 Pesach Sheni

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

$ hebcal 99999 2059
Segmentation fault: 11

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

https://github.com/hebcal/hebcal

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

startAbs = greg2abs(tempDate);
tempDate.dd = MonthLengths[LEAP(theYear)][theMonth];
endAbs = greg2abs(tempDate);

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

 theMonth = atoi(remain[0]);

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

       if (theMonth > 12)
               die("The month must be less than 13", "");

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

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

tempDate.dd = MonthLengths[LEAP(theYear)][theMonth];

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

int getMonthLength(int year, int month)
{
    if (month < 0 || month > 13)
    {
        return 0;
    }
    return MonthLengths[LEAP (year)][month];
}

עכשיו אפשר יהיה לשנות את שאר הקוד בתוכנית כך שכל הגישות למערך MonthLengths יהיו דרך הפונקציה.

אפשר לראות את השינויים המלאים שהצעתי לפרויקט ב Pull Request שהעליתי כאן:

https://github.com/hebcal/hebcal/pull/157/files

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

רעיונות לא טובים

26/08/2018

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

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

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

אל תשכחו למלא מים

25/08/2018

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

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

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

נ.ב. הפוסט הזה לא באמת היה על מגהצים. טוב אולי קצת.

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

רוצים לזכות במנוי לשנה במתנה לאתר?

24/08/2018

ברור שכן! יש אחלה קורסים ובעיקר הקלטות מעולות מהוובינרים שאנחנו מעבירים.

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

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

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

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

מחכה לשמוע מכם ינון

פתוח-סגור

23/08/2018

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

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

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

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

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

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

למה אנשים לא רוצים לגייס פרילאנסרים (ומה בכל זאת אפשר לעשות)

22/08/2018

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

והעניין שלנו היום בהליכי גיוס הוא היחס לפרילאנסרים.

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

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

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

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

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

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

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

זחילת פיצ'רים

21/08/2018

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

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

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

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

0 7 * * 0,1,2,3,4,5 /home/ynon/bin/cron/daily_blog.sh
0 21 * * 6 /home/ynon/bin/cron/daily_blog.sh

למי שעדיין לא לקח את קורס Linux שלנו (איך עדיין לא לקחתם את קורס Linux?! הוא מעולה. קחו את קורס Linux) המשמעות היא שבימים ראשון עד שישי המייל יישלח בשבע בבוקר וביום שבת בתשע בערב אחרי צאת שבת.

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

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

חידת גיט קצרה

20/08/2018

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

את תיקיית הפרויקט עם מאגר הגיט אפשר להוריד מהקישור:

http://www.tocode.co.il/system/uploads/git-ex.zip

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

בהצלחה!

יותר מדי חומר

19/08/2018

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

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

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

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

ושוב

18/08/2018

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

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

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