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

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

איך ולמה להתחיל להשתמש ב Scss

25/03/2019

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

שפת Sass, שזה קיצור ל Syntactically awesome style sheets היא שפה שנועדה להוסיף מנגנונים של שימוש חוזר בחלקים מהקוד ל CSS. היא נכתבה על ידי הנרי תורנטון ונמצאת איתנו מ 2006. בזכות תאימות מלאה ל CSS קל מאוד להתחיל להשתמש בה וכך לאט לאט לשפר את קוד ה CSS שלכם. כל העבודה עם Sass מתבצעת בצד השרת לפני שהקבצים מגיעים לדפדפן ולכן מבחינת הדפדפן זה שקוף לגמרי. לגולש אין מושג אם אתם משתמשים ב CSS או ב Scss.

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

https://www.tocode.co.il/workshops/72

המשך קריאה

מוכנים הרבה יותר ממה שצריך

24/03/2019

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

אבל קודם - מה זה בכלל אומר ״מוכנים הרבה יותר ממה שצריך?״

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

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

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

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

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

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

בהצלחה.

ומה איתנו?

23/03/2019

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

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

ומה איתנו?

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

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

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

פשוט תעוף על זה

22/03/2019

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

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

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

  1. קח את הקוד הזה ותקליד אותו אצלך ותראה שעובד.

  2. קח את הקוד הזה שהקלדת ותשנה את הצבעים.

  3. קח את האפליקציה הזאת ותוסיף לה פיצ'ר.

  4. קח את הרעיון הזה ותבנה ממנו אפליקציה.

  5. פשוט תעוף על זה :)

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

מימוש יישום מרובה שפות באמצעות React Context

21/03/2019

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

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

  1. מדובר על מידע גלובאלי שכל רכיב ביישום משתמש בו.

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

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

דוגמאות נפוצות ל Context כוללות: הגדרות שפה, הגדרות עיצוב גלובאליות ו Redux Store.

המשך קריאה

הפונקציה useEffect פותרת את אחת הבעיות הישנות ביותר שאני זוכר עם ריאקט

20/03/2019

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

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

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

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

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

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

function Character(props) {
  const [data, setData] = useState({});

  useEffect(function() {
    const req = $.get(`https://swapi.co/api/people/${props.id}`, function(data) {
      setData(data);
    });
    return function() {
      req.abort();
    }
  }, [props.id]);

  return <p>id = {props.id}, name = {data.name}</p>
}

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

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

למה דווקא Git?

19/03/2019

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

  1. שהמערכת תהיה מבוזרת.

  2. שהמערכת תהיה אמינה.

  3. שהמערכת תעבוד מהר.

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

I can build something better in two weeks -- Linus Torvalds

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

המשך קריאה

מהי Callback Function ולמה שבכלל יהיה לכם אכפת ממנה?

18/03/2019

״רוצה לכתוב לי את זה כאן?״ ״לא עזוב זה ארוך... אתקשר אליך בערב״

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

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

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

בואו נפרק את זה כדי לראות את המבנה:

function myCallbackFunction() {
  $('p').text('Thanks!');
}

$('button').on('click', myCallbackFunction);

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

  1. הפונקציה on מקבלת שני פרמטרים: הראשון הוא שם האירוע והשני הוא ה Callback Function. אפשר לחשוב על זה כאילו בהפעלת הפונקציה on ביקשנו מידע - וזה באמת יהיה נכון. ביקשנו לדעת מי לחץ על הכפתור. הבעיה היחידה היא שאף אחד עדיין לא לחץ על הכפתור. לכן אני מעביר את פונקציית ה״צלצל אליי בערב״, או בשמה המקצועי את ה Callback Function. כשמישהו ילחץ על הכפתור הפונקציה on תתעורר ותפעיל את פונקציית ה Callback שלי.

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

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

והנה הקוד המפורק מתוכו:

function myCallback(data) {
  $('pre').html(JSON.stringify(data));
}

$.get('https://swapi.co/api/people/1', myCallback);

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

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

function getHairColor(id) {
  function myCallback(data) {
    $('pre').html(data.hair_color);
  }

  $.get(`https://swapi.co/api/people/${id}`, myCallback);
}

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

const hairColor = getHairColor(1);
alert("Luke's hair color is ", hairColor);

אני מקווה שעכשיו אתם כבר רואים שזה לא הולך לעבוד. הפונקציה getHairColor מחזירה את הערך לפני שהיא סיימה לקבל את המידע ב Ajax. בשביל להציג את צבע השיער מבחוץ אנחנו צריכים לשנות את המבנה שלה כך שהיא תקבל Callback Function. בדיוק כמו on. בדיוק כמו get.

הנה דרך אחת בה זה יכול לעבוד:

function getHairColor(id, fn) {
  function myCallback(data) {
    fn(data.hair_color);
  }

  $.get(`https://swapi.co/api/people/${id}`, myCallback);
}

getHairColor(1, function(hairColor) {
  alert(hairColor);
});

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

איך (ולמה) לכתוב React Hook

17/03/2019

ריאקט עברה ועוברת עדיין הרבה טלטלות מבחינת ה API, כאשר אולי הגדולה ביותר היתה ההמלצה להפסיק להשתמש ב React.createClass ולעבור להשתמש במחלקות וב Function Components כדי ליצור את הקומפוננטות.

נודה על האמת הפונקציה React.createClass היתה סוג של פשרה מהיום הראשון. הרי אם היו class-ים ב JavaScript כשריאקט התחילה כנראה לא היו צריכים לכתוב אותה. לפונקציה זו מקבילה בהרבה ספריות UI אחרות ישנות יותר כמו למשל Class.create של פרוטוטייפ או declare של dojo.

אבל משהו מאוד גדול הלך לאיבוד במעבר מ React.createClass ל class המודרני, ולמשהו הזה קוראים Mixins. מיקסינס הפכו במעבר למחלקות למבנה שנקרא Higer Order Components שהיה הרבה פחות אינטואיטיבי לרוב המפתחים. בפוסט היום ניזכר יחד מה היו מיקסינס, איך HoC אמורים היו להחליף אותם ומה Hooks מצליחים לעשות טוב יותר. מוכנים?

המשך קריאה

לא מה שחשבת

16/03/2019

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

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

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

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