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

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

ציד באגים

19/04/2018

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

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

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

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

חרדיות בהייטק

18/04/2018

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

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

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

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

חרדת ביצוע

17/04/2018

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

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

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

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

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

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

תיקונים

16/04/2018

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

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

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

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

ונעבור לחלק המקצועי

15/04/2018

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

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

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

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

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

משוררים ושרברבים

14/04/2018

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

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

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

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

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

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

tr -cs A-Za-z '\n' |
tr A-Z a-z |
sort |
uniq -c |
sort -rn |
sed ${1}q

כשהמציאות והתיעוד לא מסכימים

13/04/2018

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

use strict;

my %h = (
  foo => 10,
  bar => 20,
  buz => 30,
  has => 40,
  bil => 50,
  boo => 60,
);

print join(', ', values(%h)), "\n";

לא משנה כמה פעמים תריצו את הקוד הזה הוא תמיד ידפיס את המספרים 10,20,30,40,50,60 באותו הסדר. ועדיין התיעוד של פרל ציין במפורש שסדר המספרים שיודפסו במקרה כזה הוא מקרי אז אל תסתמכו עליו. אבל אנחנו הסתמכנו.

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

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

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

נ.ב. בנושא Push Notifications על אנדרואיד כדאי לקרוא כאן: https://medium.freecodecamp.org/why-your-push-notifications-never-see-the-light-of-day-3fa297520793

תרבות עבודה

12/04/2018

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

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

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

מסקנות?

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

תבניות מחשבה ושפות תכנות

11/04/2018

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

public class a {
  public static String checkSecurity(String [] people) {
    String found = "";
    int i=0;
    while (i < people.length && found.equals("")) {
      if (people[i].equals("Don")) {
        // report Don
        found = "Don";
      }
      if (people[i].equals("John")) {
        // report John
        found = "John";
      }
      i += 1;
    }
    return found;
  }

  public static void main(String [] args) {
    String res = checkSecurity(args);
    System.out.println(String.join(", ", args));
    if (res != "") {
      System.out.println("Found intruder: " + res);
    }
  }
}

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

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

interface StringPredicate {
  boolean check(String candidate);
}

public class b {
  public static String find_first(String [] people, StringPredicate p) {
    for (int i=0; i < people.length; i++) {
      if (p.check(people[i])) {
        return people[i];
      }
    }
    return null;
  }

  public static String checkSecurity(String [] people) {
    return find_first(people, (name) -> (name.equals("John") || name.equals("Don")));
  }

  public static void main(String [] args) {
    String res = checkSecurity(args);
    System.out.println(String.join(", ", args));
    if (res != "") {
      System.out.println("Found intruder: " + res);
    }
  }
}

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

def find_first(items)
  items.each do |item|
    break item if yield(item)
  end
end

found = find_first(ARGV) { |name| %w[John Don].include?(name) }
puts "Found Intruder: #{found}"

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

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

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

10/04/2018

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

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

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

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

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

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

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