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

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

הערכות זמנים (טייק 712)

12/09/2021

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

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

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

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

אינדאסטרי סטנדרט

10/09/2021

הכלי שנחשב Industry Standard הוא לא בהכרח יותר טוב, לא בהכרח יותר פשוט ולא בהכרח יותר יעיל מהמתחרים. היתרונות הם אחרים:

  1. מישהו שמשתמש בו כנראה כבר נתקל ברוב הבעיות שאתם צפויים להיתקל בהן.

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

  3. יש תיעוד לא רע בכלל, ודי הרבה תשובות ב Stack Overflow וב Github Issues של האנשים שלא הצליחו למצוא את מה שמחפשים בתיעוד.

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

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

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

כשמישהו מספר לי על Bundler יותר טוב מ Webpack, על Web Framework יותר טוב מ Express, על GraphQL Federation יותר טוב מ Apollo או על Orchestrator יותר טוב מקוברנטס אני לא מתווכח. כל עוד אני שומר לעצמי את האפשרות להחליף בעתיד, אני אפילו שמח לתת לכלי החדש צ'אנס.

טיפ JavaScript: טיפול באוביקט או Promise מאותה פונקציה

09/09/2021

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

function capitalize(item) {
  return item.replace(/\b(\w)/g, c => c.toUpperCase());
}

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

function capitalize(itemOrPromise) {
  if (itemOrPromise.then) {
    return itemOrPromise.then(capitalize);
  }

  // Now we know it's an item
  return itemOrPromise.replace(/\b(\w)/g, c => c.toUpperCase());
}

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

ומי שבכלל רוצה להתחשב יכול להוסיף גם טיפול במערכים ועל הדרך במערכים של Promises:

function capitalize(itemOrPromise) {
  if (Array.isArray(itemOrPromise)) {
    return itemOrPromise.map(capitalize);
  }

  if (itemOrPromise.then) {
    return itemOrPromise.then(capitalize);
  }

  // Now we know it's an item
  return itemOrPromise.replace(/\b(\w)/g, c => c.toUpperCase());
}

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

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

function handleAllThenThings(func) {
  return function handler(itemOrPromise) {
    if (Array.isArray(itemOrPromise)) {
      return itemOrPromise.map(handler);
    }

    if (itemOrPromise.then) {
      return itemOrPromise.then(handler);
    }

    // Now we know it's an item
    return func(itemOrPromise);
  };
}

מתי לכתוב קוד גרוע

08/09/2021

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

זה לעתים נדירות המקרה.

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

זה לא סתם שכל Front End Framwork שהיתה בשכונה מספיק זמן עברה אינסוף סבבי Refactoring ובשלב מסוים גם כתיבה מחדש מאפס. באנגולר זה קרה במעבר מגירסה 1 ל-2, בריאקט במעבר מגירסה 15 ל 16 ובויו זה היה המעבר ל Vue3. אנחנו יכולים לקשקש עד מחר על Design Patterns וכתיבה נכונה, אבל בסוף כשמערכת פוגשת את העולם דברים משתנים.

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

העלאת סרביס מ docker-compose ל Kubernetes

07/09/2021

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

המשך קריאה

פרופורציה

06/09/2021

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

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

כל חודש יש אינסוף משימות דחופות שלא השאירו לי זמן ללמוד מיומנות חדשה.

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

ועדיין-

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

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

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

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

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

טיפ דוקר: איך להוסיף קוד איתחול לאימג'

05/09/2021

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

המשך קריאה

לא רקוב מספיק

04/09/2021

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

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

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

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

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

מדריך קצר לאגרגציות ב MongoDB

03/09/2021

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

המשך קריאה