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

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

מה האורך של דגל ישראל ב 2022

30/01/2022

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

המשך קריאה

קריאה מודרכת בקוד של Axios

29/01/2022

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

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

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

המשך קריאה

כל הבדיקות שבעולם

28/01/2022

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

  1. לא כתבת בדיקות מספיק טובות?

  2. לא כתבת מספיק בדיקות?

  3. יש באגים שבדיקות לא יכולות לאתר?

  4. כתיבת בדיקות לא שווה את הזמן שלך?

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

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

היום למדתי: משתנים גלובאליים ב node.js

27/01/2022

פיצ'ר שאף פעם לא חשבתי שאצטרך ב Node.JS הוא המשתנה המיוחד global. כמו window בדפדפן, global הוא האוביקט ש node הולך אליו כשפניתם למשתנה אבל node לא מצליח למצוא את המשתנה הזה בשום מקום. על global אנחנו נוכל למצוא את הדברים הגלובאליים של נוד כמו setTimeout, clearTimeout וכמובן גם את global עצמו.

בעזרת global אנחנו יכולים לשתול משתנה גלובאלי בקובץ אחר. לדוגמה נניח שיש לי קובץ בשם b.js עם התוכן הבא:

console.log(foo);

אז ברור שאם ננסה להריץ ישירות את b.js נקבל שגיאה כי foo אינו משתנה מוגדר. אבל במקום להריץ את b.js אני יכול לכתוב קובץ חדש בשם a.js לדוגמה עם התוכן הבא:

global.foo = 10;
const b = require('./b.js');

ועכשיו כשאני מריץ את a.js הוא יטען את b.js ו b כבר ימצא את המשתנה foo כי הוא הוגדר על global בקובץ a.

נ.ב. מתי נרצה להשתמש ב global אתם שואלים? בגדול אף פעם. בקטן דמיינו שאתם צריכים להריץ בדיקות עם react-testing-library בתוך סביבת node.js, למשל ב jest או mocha. דמיינו גם שהיישום שלכם טוען איזה קובץ שמותאם לריצה בדפדפן כי הוא משתמש באיזשהו אוביקט גלובאלי כמו window, fetch או IntersectionObserver (כן יש דבר כזה). עכשיו בשביל להריץ את הבדיקה על היישום שלכם אתם צריכים שאותו קובץ יצליח למצוא את ה window או ה fetch הגלובאליים.

הספריה node-window-polyfill מספקת דוגמה לשימוש כזה ב global כדי לייצר משתנה window שכולם יכירו. הנה סניפט ממנה שממחיש את הנקודה:

var globalObject = global;

var registerWindow = function () {
    globalObject.window = globalObject.window || {};
    exports.registerWindowProperties();
};

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

שני שימושים הגיוניים ל git stash

26/01/2022

הרבה זמן לא הבנתי את git stash. הרי למה לזרוק את כל השינויים שלי ל stash כשאני יכול לעשות להם קומיט ל branch זמני חדש? מה אני מרוויח מלשים אותם במקום שבו רק יהיה לי יותר קשה למצוא אותם?

אז אם גם אתם לא מהמשתמשים הכבדים של גיט סטאש הנה שני מצבים שבהם כן כדאי להכיר אותו ולהשתמש בו-

המשך קריאה

ארבעה סוגים של בדיקות שכדאי לכתוב

25/01/2022

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

המשך קריאה

קריאה מודרכת בקוד של left-pad

24/01/2022

במרץ 2016 מתכנת בשם Azer Koçulu (לא בטוח שאני יודע לתרגם את השם הזה לעברית) שבר את האינטרנט. הוא מחק מ npm כמה מודולים שפירסם בפרשה שהביאה בפעם הראשונה את מנהלי npm להחזיר מודול שמשתמש מחק. המודול במרכז הפרשה נקרא left-pad ומה שמיוחד בו הוא שאינספור חבילות npm השתמשו בו בתור דרישת קדם. ברגע שמודול זה ירד, אי אפשר היה יותר להתקין אף חבילה שתלויה בו וכך מאות אלפי מתכנתים ברחבי העולם לא הצליחו להפעיל npm install.

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

המשך קריאה

היום למדתי: בחירת טיפוס ממערך ב TypeScript

23/01/2022

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

const animals = [
    { id: 1, name: 'cat' },
    { id: 2, name: 'dog' },
    { id: 3, name: 'mouse' },
];

type AnimalName = 'cat' | 'dog' | 'mouse'

function getAnimal(name: AnimalName) {
  return animals.find(a => a.name === name)
}

עכשיו אנחנו יכולים להפעיל:

console.log(getAnimal('dog'));

ולקבל את התוצאה בלי בעיה, אבל אם ננסה להפעיל:

console.log(getAnimal('bird'));

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

עכשיו זה מעולה אבל השורה הזאת:

type AnimalName = 'cat' | 'dog' | 'mouse'

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

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

const animals = [
    { id: 1, name: 'cat' },
    { id: 2, name: 'dog' },
    { id: 3, name: 'mouse' },
] as const;

type AnimalName = typeof animals[number]['name'];

function getAnimal(name: AnimalName) {
  return animals.find(a => a.name === name)
}

console.log(getAnimal('dog'));

רק אל תשכחו להוסיף אחרי הגדרת המערך את המילים as const אחרת TypeScript יגדיר את AnimalName להיות פשוט string ולא יזרוק שום שגיאה.

למה צריך להוסיף `@latest` בהפעלת npx?

22/01/2022

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

$ npx create-react-app yoyo
Need to install the following packages:
  create-react-app
Ok to proceed? (y)

You are running `create-react-app` 4.0.3, which is behind the latest release (5.0.0).

We no longer support global installation of Create React App.

Please remove any global installs with one of the following commands:
- npm uninstall -g create-react-app
- yarn global remove create-react-app

The latest instructions for creating a new app can be found here:
https://create-react-app.dev/docs/getting-started/

מיותר לציין שאין לי שום התקנה גלובאלית של create-react-app ולכן שתי ההצעות שלו להסרת create-react-app לא היו רלוונטיות.

מה קרה כאן? זה פשוט - גם ל npx יש cache. הוא שומר אותו בתיקיית ~/.npm/_npx. כשהוא שואל אותי אם להתקין את create-react-app ואני מאשר הוא שם לב שלא ביקשתי גירסה מסוימת, אז הולך ל cache, מוצא שם את גירסה 4 ומתקין אותה.

דרך קלה לצאת מזה היא לציין את הגירסה, וזו המשמעות של כרוכית latest - כלומר הפעלה כזו:

$ npx create-react-app@latest yoyo

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

$ rm -rf ~/.npm/_npx
$ npx create-react-app yoyo

קל לשנות

21/01/2022

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

  1. מימוש של פונקציה

  2. חתימה של פונקציה

  3. רשימת פונקציות או מחלקות שמיוצאות ממודול

  4. רשימת טבלאות ב DB ועמודות של כל טבלה

  5. רשימת API Routes והחלטה על הפרמטרים של כל נתיב

  6. פרוטוקולים לתקשורת בין מערכות (API ציבורי)

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

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