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

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

התחלתי לכתוב קוד רקורסיבי ב JavaScript ולא תאמינו מה קרה אחר כך (או: מה זה TCO)

23/09/2018

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

המשך קריאה

איך למחוק קובץ לחלוטין מכל ההיסטוריה של גיט באמצעות git filter branch

22/09/2018

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

המשך קריאה

קוד פרוצדורלי וקוד פונקציונאלי נפגשו לצהריים

21/09/2018

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

המשך קריאה

פעולות אוטומטיות על קבצים עם Git Filters

20/09/2018

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

המשך קריאה

האופרטור % וקריאה אחרי סוף המערך

19/09/2018

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

https://forum.tocode.co.il/t/advent-of-code/778

במהלך הדיון על החידה הראשונה עלה הנושא של קריאה ממערך בצורה מעגלית - לדוגמא בהינתן המערך:

arr = [10, 20, 30, 40]

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

מסתבר שהאופרטור % עוזר לפתור מהר שאלות מסוג זה. האופרטור % מחזיר את שארית החלוקה לדוגמא:

5 % 2 == 1

בגלל שהכפולה של 2 שהכי קרובה ל-5 היא המספר 4 (זה הכי קרוב שנגיע ל-5), ונשאר עוד 1 שנקרא שארית. שיטה די מקובלת לרוץ בצורה מעגלית על מערך היא להסתכל על שארית החלוקה באורך המערך. לדוגמא המערך שלנו הוא באורך 4. לכן קל לשאול מה האיבר באינדקס 0 (זה 10) או באינדקס 2 (זה 30). אבל, מה האיבר באינדקס 4? באינדקס 10? באינדקס 12? כלומר מה יקרה כשתקדם במערך אחרי האורך שלו?

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

real_index = i % len(arr)

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

arr[4 % len(arr)] == arr[0] == 10

arr[5 % len(arr)] == arr[1] == 20

arr[10 % len(arr)] == arr[2] == 30

arr[12 % len(arr)] == arr[0] == 10

שימוש באופרטור % הוא הרבה יותר מהיר מחישוב האינדקס בלולאה למשל ולכן נרצה להשתמש בו גם בתרגילים ב Advent Of Code אבל כמובן גם בחיים בכלל.

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

const colors = ['red', 'blue', 'green', 'white', 'yellow', 'brown', 'magenta', 'cyan', 'pink', 'orange'];
let idx = 0;

function changeColor() {
  idx = (idx + 1) % colors.length;
  document.body.style.backgroundColor = colors[idx];
}

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

מהו קוד אידמפוטנטי (ולמה שיהיה לכם אכפת)

18/09/2018

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

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

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

def sum_digits(x):
    return sum([int(n) for n in str(x)])

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

x = 12
print(sum_digits(x))
print(sum_digits(x))
print(sum_digits(x))

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

event = Notification("Don't think twice it's alright")
notify_user('ynon@hotmail.com', event)
notify_user('ynon@hotmail.com', event)
notify_user('ynon@hotmail.com', event)

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

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

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

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

ריאקט למתחילים ממש

17/09/2018

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

המשך קריאה

אתגר תכנות: בואו נפתור את Advent Of Code יחד

15/09/2018

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

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

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

מוכנים? הנה הסיפור:

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

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

https://forum.tocode.co.il/t/advent-of-code/763/2

צעד שני בהייטק

14/09/2018

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

המשך קריאה