שלום אורח התחבר

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

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

מעדיפים לקרוא מהטלגרם? בקרו אותנו ב:@tocodeil

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

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

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

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

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

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

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

מסלול בוטקמפ ללימוד ריאקט ייפתח בתאריך 14.06.2020 למשך שלושה שבועות. מפגשי העבודה יתקיימו בימי ראשון ורביעי בין השעות 9:00 ל-11:00 בבוקר בתאריכים: 14/06, 17/06, 21/06, 24/06, 28/06, 01/07. מחיר הקורס 970 ש"ח וזה כולל חודש מנוי לתקופה של הקורס (אם אתם כבר מנויים החודש הזה יתווסף לכם אוטומטית לתקופת המנוי). הצטרפות לבוטקמפ בקישור: https://www.tocode.co.il/quickjoin2?term=15.

מסלול בוטקמפ ללימוד פייתון יפתח בתאריך 14.06.2020 למשך שלושה שבועות. מפגשי העבודה יתקיימו בימי ראשון ורביעי בין השעות 13:00 ל-15:00 בצהריים בתאריכים: 14/06, 17/06, 21/06, 24/06, 28/06, 01/07. מחיר הקורס 970 ש"ח וזה כולל חודש מנוי לתקופה של הקורס (אם אתם כבר מנויים החודש מתווסף אוטומטית לתקופת המנוי). הצטרפות לבוטקמפ פייתון בקישור: https://www.tocode.co.il/quickjoin2?term=16.

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

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

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

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

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

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

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

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

class ColorChanger {
  constructor(root) {
    this.el = document.createElement('div');
    root.appendChild(this.el);
    this.el.style.width = '100px';
    this.el.style.height = '100px';
    this.el.style.border = '2px solid';
  }

  red() {
    this.el.style.backgroundColor = 'red';
  }

  blue() {
    this.el.style.backgroundColor = 'blue';
  }

  yellow() {
    this.el.style.backgroundColor = 'yellow';
  }
}

const c = new ColorChanger(document.body);

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

c.red();

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

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

class ColorChanger {
  constructor(root) {
    this.el = document.createElement('div');
    root.appendChild(this.el);
    this.el.style.width = '100px';
    this.el.style.height = '100px';
    this.el.style.border = '2px solid';
  }
}

for (let clr of ['red', 'blue', 'yellow']) {
  ColorChanger.prototype[clr] = function() {
    this.el.style.backgroundColor = clr;
  };
}

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

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

הנה תוכן המייל בשבילכם:

ינון שלום, כחלק ממערך האבטחה של רייד נסרקים מידי יום תכנים ומידע על פריצות אבטחה באפליקציות כגון, Wordpress, Joomla ועוד, אתרך כנראה נפרץ על ידי גורמים עויינים ואנטישמים - נתגלתה באתרף פירצה מסוג Defacement, כתובת הפריצה שנסרקה: qtcollege.co.il

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

if ($_POST['url']) {
        $uploaddir = $_POST['url'];
}
 
$first_filename = $_FILES['uploadfile']['name'];
$filename = md5($first_filename);
$ext = substr($first_filename, 1 + strrpos($first_filename, '.'));
$file = $uploaddir . basename($filename . '.' . $ext);
 
if (move_uploaded_file($_FILES['uploadfile']['tmp_name'], $file)) {
        echo basename($filename . '.' . $ext);
} else {
        echo 'error';
}

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

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

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

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

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

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

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

הרבה פעמים אני בטוח שהבעיה שלי היא שאני לא יודע איך-

  • אני לא יודע איך לכתוב קוד Python בשביל לענות על השאלות בראיון עבודה

  • אני לא יודע איך לכתוב אפליקציה שתהיה מספיק פופולרית כדי שאוכל להתפרנס ממנה

  • אני לא יודע איך לבנות תיק עבודות שיגרום ללקוחות למצוא אותי ולהתקשר אליי

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

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

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

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

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

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

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

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

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

function debug_log(msg) {
  if (DEBUG_MODE) {
    console.log(msg);
  }
}

אפשר להשתמש בפונקציה בתוכנית בצורה הבאה:

const DEBUG_MODE = false;

function debug_log(msg) {
  if (DEBUG_MODE) {
    console.log(msg);
  }
}

debug_log("hello world");

אבל - יש עם זה די הרבה בעיות:

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

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

debug_log(`1 + 1 = ${1+1}`);

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

מה אפשר לעשות במקום? מאחר ו DEBUG_MODE לא אמור להשתנות לאורך ריצת התוכנית אפשר להתחיל מלחשב את הפונקציה debug_log פעם אחת, כלומר לכתוב את הקוד הבא:

const DEBUG_MODE = false;

if (DEBUG_MODE) {
  function debug_log(msg) {
    console.log(msg);
  }
} else {
  function debug_log(msg) {}
}


debug_log("hello world");

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

const DEBUG_MODE = true;

if (DEBUG_MODE) {
  function debug_log(msg) {
    console.log(msg());
  }
} else {
  function debug_log(msg) {}
}


debug_log(() => "hello world");

נ.ב. אם אתם משתמשים ב Webpack יש די הרבה פלאגינים שימחקו את כל ה console.log-ים לפני מעבר לפרודקשן ואני חושב שזו הדרך המומלצת ביותר. הפלאגין נקרא terser והאופציה הרלוונטית נקראת drop_console.

נמאס לי מזום.

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

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

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

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

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

איפה מצטרפים? שמח ששאלתם: https://www.tocode.co.il/workshops/97. נתראה בחמישי בעשר בבוקר.

הנה קוד JavaScript קצר ולגמרי מומצא שתפקידו לספור ביקורים באתר. כל פעם שאתם מגיעים לאתר עם הקוד הזה משתנה ב local storage יעלה ב-1, ויוצג על המסך בתוך ה body:

const visits = localStorage.getItem('visits');
if (visits == null) {
  localStorage.setItem('visits', 1);
} else {
  localStorage.setItem('visits', Number(visits) + 1);
}

document.body.textContent = Number(visits) + 1;

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

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

ככה זה נראה אחרי תיקון:

let visits = localStorage.getItem('visits');

if (visits == null || isNaN(Number(visits))) {
  visits = 1;
} else {
  visits = Number(visits) + 1;
}

localStorage.setItem('visits', visits);
document.body.textContent = visits;

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

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

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

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

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