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

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

מי צריך לכתוב את ה Dockerfile?

12/02/2022

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

נקודות המפגש בין שתי הקבוצות היא ה Dockerfile.

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

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

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

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

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

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

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

איך לבדוק פונקציות שאינן מיוצאות?

11/02/2022

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

המדריך כאן אתם יכולים לנסות לקרוא אותו: https://www.samanthaming.com/journal/2-testing-non-exported-functions/#proficiency-leads-to-result

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

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

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

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

שלוש דרכים להתמודד עם סיבוכים

10/02/2022

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

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

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

Due to the complexity and dependencies of our List components, we are not able to take new feature requests at this time.

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

עדיף לא לבדוק

09/02/2022

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

המשך קריאה

שלוש דוגמאות חמודות ליצירת JSON-ים עם jo

08/02/2022

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

המשך קריאה

מה אפשר להגיד במקום ״אי אפשר״

07/02/2022

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

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

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

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

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

  1. יכול להיות שהגבלת ה Redirects באקסיוס מאוד חשובה, מספיק חשובה בשביל לתרום לאקסיוס קוד שתומך בזה.

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

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

או במקרה של ג'סט, יכול להיות שאפשר להשתמש בספריית בדיקה אחרת; יכול להיות שאפשר להפעיל eject או לוותר על create-react-app לחלוטין.

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

לא מכיר את הכללים

06/02/2022

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

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

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

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

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

על שליחת פרמטרים בלי Content Type (ולמה התקלקל לי הדמו בוובינר אתמול)

04/02/2022

במהלך וובינר על Next.JS שהעברתי אתמול ניסיתי לשלוח הודעה לשרת מתוך curl עם הפקודה הבאה:

$ curl -X POST -d hello 'localhost:3000/api/todos'

קוד צד השרת שקיבל את ההודעה נראה כך:

export default function handler(req, res) {
  console.log(`add ${JSON.stringify(req.body)}`);
  addTodo(req.query.text);
  console.log(`todos = ${JSON.stringify(getTodos())}`);
  res.status(200).json({});
}

וכמו שקורה לעתים קרובות כשמנסים לאלתר במהלך Live Coding הקוד לא עבד. במקום ש req.body יכיל את המילה hello כמו שהתכוונתי שיקרה, הוא הכיל אוביקט. תוצאת ההדפסה היתה:

add {"hello":""}

כלומר req.body הכיל אוביקט עם מפתח יחיד בשם hello וערך ריק.

מה?

בחזרה ל curl, המתג -d אומר שמה שיבוא אחריו הוא גוף ההודעה, והמתג -X POST אומר שאני שולח בקשה מסוג POST. בסך הכל יש לנו בקשת POST שגוף ההודעה שלה מורכב מהמילה הבודדת hello. אז איך req.body הגיע להיות אוביקט, ואיך hello הגיע להיות המפתח?

המשך קריאה