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

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

הי, ראית כבר את...

13/04/2020

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

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

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

דוגמא דומה להבדל הזה מ TypeScript היא ההבדל בין האופרטור ?. ל Assertion Functions. הראשון עוזר לקצר קטעי קוד כאלה שכמעט כולם כותבים:

let x;
if (foo != null) {
    if (foo.bar != null) {
        if (foo.bar.buz != null) {
            x = foo.bar.buz();
        }
    }
}

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

וכמובן האהוב עליי משפת פייתון הוא סימן הקו-תחתי שמאפשר לנו לכתוב:

x = 1_000_000

כדי לשים את המספר מיליון במשתנה x בלי להתבלבל באפסים.

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

לימודים בתקופה של אי וודאות

12/04/2020

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

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

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

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

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

כמה דוגמאות? ברור בשביל זה אנחנו פה:

  1. טוטוריאל פיתוח משחק פלאפי בירדס מלא בעשר דקות

  2. פרויקט אוילר

  3. אדוונט אוף קוד

  4. קראקמיס

  5. וים בייסיקס בשמונה דקות

  6. ובאותו נושא וים אדוונצ'רס

  7. פלקסבוקס צפרדעים

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

ארבע תבניות לקומפוננטות React מתורגמות ל ClojureScript ו Reagent

11/04/2020

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

המשך קריאה

ביי ביי swapi.co

10/04/2020

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

אז למי שלא הכיר (ועכשיו כבר לעולם לא יכיר), swapi.co היה אתר ששמר בסיס נתונים על כל הדמויות במלחמת הכוכבים. אבל זה לא בסיס נתונים כמו ב imdb שמכריח אותך לקרוא את הכל מהאתר שלהם, אלא בסיס נתונים עם API פתוח.

גלישה לדוגמא לכתובת https://swapi.co/api/people/1/ היתה מביאה לכם בחזרה אוביקט JSON עם כל הפרטים שיכולתם לדמיין על Luke Skywalker. פניה לכתובת https://swapi.co/api/starships/12/ היתה מחזירה דף מידע מפורט על ה X-Wing, כולל כל הפרטים הטכניים על החללית ורשימת כל הדמויות שהטיסו אותה.

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

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

תודה פול על שש שנים נפלאות.

איך נוצרים פערי ידע

09/04/2020

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

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

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

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

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

תבנית בסיס ליישומי Rails ו ClojureScript

08/04/2020

ריילס מגיע עם תמיכה מובנית בהמון ספריות JavaScript ותבניות פרויקטים בזכות ג'ם שנקרא webpacker. הצרות התחילו כשניסיתי לחבר אותו עם ClojureScript מאחר וקלוז'רסקריפט משתמש בקומפיילר משלו. אז יצרתי תבנית פשוטה שמכסה את הנושאים הכי מרכזיים ומאפשרת להתחיל פרויקט ריילס עם ClojureScript יחסית בקלות, ותעזור גם לכם לכתוב את אפליקציית ה Rails/ClojureScript הראשונה שלכם.

המשך קריאה

טכנולוגיות של סוטים

07/04/2020

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

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

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

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

אפשרות שניה היא ללכת על טכנולוגיות עם קהילה קטנה שאין לה ברירה אחרת. זה טריקי כי כשהקהילה קטנה מדי אתה מחוסל, והקהילה יכולה פתאום לגדול ואז עברת למיינסטרים אבל יכול גם לפעמים לעבוד. ריילס היא דוגמא טובה שעברה מזמן את ההייפ שלה אבל עדיין מספקת חווית פיתוח מעולה. אורליה בעולם ה Front End היתה איתנו המון זמן ועדיין מתוחזקת ועובדת טוב למרות היעדר ההייפ. אליקסיר ואיתה פיניקס נותנת פיתרון מלהיב לפיתוח ווב שעדיין לא הגיע למיינסטרים (ואולי לעולם לא יגיע) ו Qt בפיתוח Desktop Applications שכנראה לעולם תגיע.

ריאקט ו SVG הם שילוב מעולה

06/04/2020

אחת הטכנולוגיות הנשכחות של פיתוח Web היא SVG. איכשהו כש Canvas יצאה היא הצליחה לעשות המון רעש, וכמובן ש WebGL היה מלהיב, אבל SVG? זה לא הדבר ההוא שדומה ל XML?. אז כן ולא. תקן SVG יצא לראשונה ב 2001 והשילוב בינו לבין דפדפנים ידע עליות ומורדות לאורך השנים, אבל בשנים האחרונות התמיכה ב SVG בדפדפנים ובספריות פיתוח היא מאוד יציבה ו SVG יכול לתת לכם פיתרון אמין ומהיר להצגה של נתונים בצורה ויזואלית.

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

function App(props) {
  return (
    <div>
      <svg>
        <circle cx="100" cy="100" r="40" />
      </svg>
    </div>
  )
}

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

svg {
  background: white;
  border: 1px solid black;;
}

circle {
  fill: red;
}

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

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

שילוב קומפוננטות SVG ביישום לא דורש שום ספריה חיצונית, נתמך בכל הדפדפנים ומאפשר להוסיף בקלות צורות מתוחכמות יותר מדברים שהיינו מוצאים בדרך כלל ב CSS.

כן, לשכתב. אבל חכם.

05/04/2020

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

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

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

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

  1. מידע - איזה מידע המנגנון שומר ב DB? איך יהיה אפשר להעביר את המידע כך שישמר במקום אחר? אני מאוד אוהב את הארכיטקטורה של Rails Active Storage בהיבט הזה, שמאפשרת לעבור בקלות בין מקומות אחסון.

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

items[1].name.first

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

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

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

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

האם תכנות פונקציונאלי הוא בכלל פשוט יותר?

04/04/2020

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

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

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

result = 0
for i in range(1000):
    if i % 5 == 0 or i % 3 == 0:
        result += i

print(result)

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

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

def divides_by_5_or_3(n):
    return n % 5 == 0 or n % 3 == 0

res = sum(filter(divides_by_5_or_3, range(1_000)))
print(res)

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

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