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

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

איך לעקוף אפליה לפי גיל

26/04/2018

סקוט ג'ונסון העלה השבוע את קורות חיפוש העבודה שלו בחצי קיטור חצי הזדמנות לפרסם מוצר שפיתח. אני חושב שכדאי לכם לקרוא את הסיפור כאן: http://fuzzyblog.io/blog/jobhound/2018/04/24/ten-things-i-learned-from-a-job-hunt-for-a-senior-engineering-role.html

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

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

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

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

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

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

יש לכם עוד רעיונות? אשמח לשמוע בתגובות או במייל.

עיצוב תוכנה בתנועה

25/04/2018

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

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

את המערכת השניה עיצב מתכנת שלא תיכנן על מערכת גדולה וקצת יצא לו בטעות. כל העיצוב היה בנוי על 2-3 מחלקות שנלקחו מאיזה פרויקט Hello World שפשוט יצא מפרופורציה והפך למיליוני שורות קוד כמעט בלי שינוי של מבנה המחלקות. פונקציות באורך מאות שורות קוד היו מחזה נפוץ.

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

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

מיתוסים על מיומנות

24/04/2018

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

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

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

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

ולשאלות- האם אתם יודעים מה רמת המיומנות שלכם? יש לכם מושג מה האחרים בצוות שלכם חושבים על רמת המיומנות שלכם? והאם אתם מרגישים שרמת המיומנות שלכם השתפרה בשנים האחרונות (או התדרדרה)?

3 מטרות

23/04/2018

בואו נדבר על 3 מטרות של קורסים:

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

  2. הקניית ידע - הקורס מלמד איך להשתמש בכלי מסוים.

  3. שיפור מיומנות (טכניקה).

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

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

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

חדש מאתר ToCode: תוכנית המנויים

22/04/2018

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

אל תבלעו Exceptions. זה לא טעים.

21/04/2018

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

System test integration requires Rails >= 5.1 and has a hard dependency
on a webserver and `capybara`, please add capybara to
your Gemfile and configure a webserver
(e.g. `Capybara.server = :webrick`) before attempting to use system tests.

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

לפני שנגיע לזה בואו נלך לקוד של rspec-rails, הספריה ממנה הגיעה הודעת השגיאה. כך נראה הבלוק הבעייתי:

      included do |other|
        begin
          require 'capybara'
          require 'action_dispatch/system_test_case'
        # rubocop:disable Lint/HandleExceptions
        rescue LoadError
          # rubocop:enable Lint/HandleExceptions
          abort """
            System test integration requires Rails >= 5.1 and has a hard
            dependency on a webserver and `capybara`, please add capybara to
            your Gemfile and configure a webserver (e.g. `Capybara.server =
            :webrick`) before attempting to use system tests.
          """.gsub(/\s+/, ' ').strip
        end

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

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

# from: https://www.python.org/download/releases/2.2.3/descrintro/
class defaultdict(dict):

    def __init__(self, default=None):
        dict.__init__(self)
        self.default = default

    def __getitem__(self, key):
        try:
            return dict.__getitem__(self, key)
        except KeyError:
            return self.default

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

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

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

נ.ב. 2 - אצלי Capybara לא עלה בגלל חוסר תאימות בין ריילס 5.1 ל Capybara 3. ברגע ששינמכתי ל Capybara 2 הכל התחיל לעבוד.

נ.ב. 3 - קפיברה (בנוסף להיותה המכרסם הגדול ביותר) היא ספריית בדיקות אוטומטיות ב Ruby.

קוד כניסה (פייתון)

20/04/2018

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

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

import sys
class CodePanel:
    def __init__(self, code):
        self.code = code
        self.guess = Buffer(len(code))

    def check(self):
        if self.guess.get_as_string() == self.code:
            print('welcome')
            sys.exit(0)
        else:
            print('wrong code. try again')
            self.guess = Buffer(self.guess.size)

    def type_char(self, ch):
        self.guess.write(ch)
        if self.guess.is_full():
            self.check()

class Buffer:
    def __init__(self, size):
        self.buf = [''] * size
        self.at = 0
        self.size = size

    def write(self, ch):
        self.buf[self.at] = ch
        self.at += 1

    def is_full(self):
        return self.at == self.size

    def get_as_string(self):
        return ''.join(self.buf)


panel = CodePanel('13579')
code = '123413579'
for ch in code:
    panel.type_char(ch)

בכל פעם שמשתמש לוחץ על כפתור תיקרא הפונקציה CodePanel#type_char ותוסיף את האות לחוצץ עד שהחוצץ מתמלא, ורק אז נבדוק את הקוד ונדפיס הודעה. אפשר לראות שניסיתי להקליד את הרצף 123413579 ונשארתי בחוץ.

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

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

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

1
1, 2
1, 2, 3
1, 2, 3, 4
1, 2, 3, 4, 1
3, 2, 3, 4, 1
3, 5, 7, 9, 1

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

import sys

class CircularBuffer:
    def __init__(self, size):
        self.size = size
        self.buf  = [''] * size
        self.at   = 0

    def write(self, ch):
        self.buf[self.at] = ch
        self.at = (self.at + 1) % self.size

    def get_as_string(self):
        res = []
        for i in range(self.size):
            res.append(self.buf[(self.at + i) % self.size])
        return ''.join(res)

class CodePanel:
    def __init__(self, code):
        self.code = code
        self.guess = CircularBuffer(5)

    def check(self):
        if self.guess.get_as_string() == self.code:
            print(f'welcome: {self.guess.get_as_string()}')
            sys.exit(0)

    def type_char(self, ch):
        self.guess.write(ch)
        self.check()


panel = CodePanel('13579')
code = input()
for ch in code:
    panel.type_char(ch)

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

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

class CircularBuffer:
    def __init__(self, size):
        self.size = size
        self.buf  = deque([''], size)
        self.at   = 0

    def write(self, ch):
        self.buf.append(ch)

    def get_as_string(self):
        return ''.join(list(self.buf))

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

ציד באגים

19/04/2018

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

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

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

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

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

18/04/2018

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

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

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

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

חרדת ביצוע

17/04/2018

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

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

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

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

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

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