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

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

תסמונת המתחזה

15/12/2018

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

  1. אנחנו שואלים פחות שאלות, כדי שלא יחשבו שלא הבנו.

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

  3. אנחנו מסתירים כשלונות וחוסר ידע כולל באמצעות שקרים.

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

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

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

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

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

אתה לא חולה (או: שתי המלצות על פודקסטים)

14/12/2018

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

https://www.akimbo.me/blog/s-2-e-6-origin-stories

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

https://soundcloud.com/einatnathan/ep17

האזנה מהנה, ינון

לא יודע

13/12/2018

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

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

רק בבקשה אל תעצרו ב"לא יודע". זה לא בריא לכם וזה לא בריא לקוד שלכם.

מימוש סינגלטון ב Ruby

12/12/2018

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

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

class Critter
  @@instance = Critter.new
  def self.instance
    @@instance
  end

  def val
    5
  end
end

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

c = Critter.instance
d = Critter.instance

puts c == d # true

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

require 'singleton'

class Critter
  include Singleton
  def val
    5
  end
end

c = Critter.instance
d = Critter.instance

puts c.val
puts d == c

הבעיות מתחילות כשננסה להסתיר את הפונקציה new. כאן לרובי יש סוג של פיתרון באמצעות הפונקציה private_class_method. כך נראה Critter שמסתיר את פונקציית new שלו:

class Critter
  include Singleton
  def val
    5
  end
  private_class_method :new
end

ובאמת מי שינסה לקרוא עכשיו ל Critter.new יקבל את השגיאה:

NoMethodError: private method `new' called for Critter:Class

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

require 'singleton'

class Critter
  include Singleton
  def val
    5
  end
  private_class_method :new
end

c = Critter.instance
d = Critter.send(:new)

puts d.val # print 5
puts d == c # false

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

טיפ רובי: בואו נחליף את הסוף של המחרוזת

11/12/2018

ל Bash יש פיצ'ר מדליק שמחליף במהירות את הסוף של מילה, מה שעוזר לנו לכתוב סקריפטים שמשנים שמות של קבצים. הקוד הבא ב Bash יחליף במהירות את כל הקבצים שמסתיימים ב old לסיומת new:

for fname in *.old
do
    mv "$fname" "${fname%old}new"
done

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

בקוד זה נראה כך:

glob("*.old").each do |fname|
    File.rename(fname, fname.chomp("old") + "new")
end

קסם נוסף שיש ל Bash בשרוול הוא מחיקת קטע מהתחלה של מחרוזת עם סימן הסולמית - אבל לא הצלחתי למצוא מקבילה טובה ברובי אליו.

מה שהלקוח רוצה

10/12/2018

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

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

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

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

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

טיפ קצר: בואו נגדיר קבועים ב Node.JS

09/12/2018

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

נתחיל עם מה שעובד - כל עוד אנחנו בקובץ יחיד אפשר להשתמש ב const כדי לתת שם לערך קבוע:

const MESSAGE_SIZE = 48;

ומכאן ועד סוף הקובץ לא משנה מה תעשו השם MESSAGE_SIZE תמיד יתייחס למספר הקבוע 48. אבל העסק מסתבך מהר מאוד כשאנחנו רוצים לשתף מידע בין מספר קבצים. נניח שהקובץ utils.js מגדיר הפעם את הקבוע ומייצא אותו:

// utils.js
const MESSAGE_SIZE = 48;
exports.MESSAGE_SIZE = MESSAGE_SIZE;

והקובץ app.js מייבא את הקבוע:

const { MESSAGE_SIZE } = require('./utils');
console.log(MESSAGE_SIZE);

זה עבד לא רע והדפיס 48, אבל הולך להישבר די בקלות. נסו לכתוב במקום את הקוד הבא ב app.js:

const utils = require('./utils');
utils.MESSAGE_SIZE = 999;

console.log(utils.MESSAGE_SIZE);

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

מה אפשר לעשות? אז אומנם const לא תעזור לשמור על שדות של אוביקטים משינויים, אבל Object.freeze דווקא כן. אם נפעיל אותה לפני ה export נוכל לקבל קבועים של ממש.

החליפו את תוכן הקובץ utils.js עם הקוד הבא:

module.exports = Object.freeze({
  MESSAGE_SIZE: 48,
});

ועכשיו בלי לשנות את app אפשר להריץ אותו שוב ולקבל את ערך הקבוע 48. מספר זה לא ישתנה לא משנה מה נכתוב בקבצים שטוענים אותו.

איך להגיב לשאלה שאת כבר מכירה בראיון עבודה?

08/12/2018

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

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

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

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

דוגמא? יאללה בשמחה-

המראיין: מהי בעיית N+1 בעת שליפת נתונים מ DB, ואיך היית מתמודד איתה?

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

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

שבוע אחר כך ועם הקוד הלא נכון

07/12/2018

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

אבל כמובן שזה משנה.

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

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

בלוקים ב Ruby

06/12/2018

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

המשך קריאה