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

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

הדפסת הודעות לוג לקובץ יומן ב Express

25/12/2018

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

app.use(morgan('dev'));

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

המשך קריאה

קומיטים קטנים ממש

24/12/2018
git

אני מקווה שאתם מכירים את ההמלצה לחלק את השינויים שלכם לקומיטים לפי נושאים, כך שכל קומיט יתאים ל Issue במערכת ניהול ה Issues שלכם. אבל מה עושים אם שכחתם את עצמכם בהתלהבות של הקידוד והתעוררתם שעתיים אחרי עם 5 שינויים מ-5 נושאים שונים באותו קובץ?

אל תדאגו - אני יודע גיט.

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

# My Cool Project

This is a demo project

ועכשיו נוסיף לו שני בלוקים של טקסט שאמורים להיות מפוצלים ל-2 קומיטים שונים:

# My Cool Project

This is a demo project

# Installation
you need to download this app and install it if you want to use it

fixing first issue
fixing second issue
fixing third issue

במקום לעשות cut-and-paste עם קובץ נוסף אפשר פשוט להפעיל את git add במצב אינטרקטיבי:

$ git add --interactive -p

diff --git a/readme.txt b/readme.txt
index d3ef36a..a53fb88 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,3 +1,12 @@
 # My Cool Project

 This is a demo project
+
+# Installation
+you need to download this app and install it if you want to use it
+
+fixing first issue
+fixing second issue
+fixing third issue
+
+

Stage this hunk [y,n,q,a,d,e,?]? 

גיט מזהה את השינויים ושואל אולי מה לעשות. כרגע כל השינויים צמודים אחד לשני ומבחינת גיט זה נראה כמו שינוי יחיד. אני רוצה לקחת את הבלוק שמתחיל ב Installation ולשמור אותו בתור קומיט משלו ולכן אני לוחץ e כלומר edit (במצבים בהם הבלוקים לא היו רציפים גיט היה מבצע את הפיצול בצורה אוטומטית). בתגובה git יפתח את ה EDITOR המועדף עליי ויציג לי מסך עריכה שנראה כך:

# Manual hunk edit mode -- see bottom for a quick guide.
@@ -1,3 +1,12 @@
 # My Cool Project

 This is a demo project
+
+# Installation
+you need to download this app and install it if you want to use it
+
+fixing first issue
+fixing second issue
+fixing third issue
+
+
# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.

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

# Manual hunk edit mode -- see bottom for a quick guide.
@@ -1,3 +1,12 @@
 # My Cool Project

 This is a demo project
+
+# Installation
+you need to download this app and install it if you want to use it
+
# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
# 
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging.
# If it does not apply cleanly, you will be given an opportunity to
# edit again.  If all lines of the hunk are removed, then the edit is
# aborted and the hunk is left unchanged.

שמירה ויציאה ותראו את הסטטוס:

$ git status
On branch main
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   readme.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   readme.txt

הקובץ readme.txt מופיע גם בתור משהו שייכנס לקומיט הבא וגם בתור שינויים שלא ייכנסו לקומיט הבא. הפעלת diff תראה לנו את ההסבר:

$ git diff

diff --git a/readme.txt b/readme.txt
index 6076e63..a53fb88 100644
--- a/readme.txt
+++ b/readme.txt
@@ -5,3 +5,8 @@ This is a demo project
 # Installation
 you need to download this app and install it if you want to use it

+fixing first issue
+fixing second issue
+fixing third issue
+
+

בלוק הטקסט השני, שמסומן ב +, נמצא אצלי בתיקיית העבודה אבל לא ב Staging. לעומתו הבלוק שמעליו כן נמצא ב Staging area ולכן לא מופיע ב diff.

נפעיל קומיט כדי לשמור את השינוי:

$ git commit -m 'add installation instructions' 

ובסטטוס הבא נראה שהקובץ עדיין ב Modified אבל הפעם רק החלק השני שלו. עכשיו אפשר להמשיך ל add ו commit נוספים כדי להכניס את בלוק הטקסט השני:

$ git add .
$ git commit -m 'fixed more issues'

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

commit 3612ce51ab22876a6337b56050a1f16bff9ea9e9 (HEAD -> main)
Author: ynonp <ynonperek@gmail.com>
Date:   Sun Dec 23 14:49:12 2018 +0200

    fixed more issues

commit b4c25f7ac3cb7fdd3d8101750ff03cb2b3d7b5e1
Author: ynonp <ynonperek@gmail.com>
Date:   Sun Dec 23 14:47:38 2018 +0200

    add installation instructions

אוהבים גיט ורוצים ללמוד להשתמש בו טוב יותר? אני חושב שתהנו מקורס Git Hero שיש לנו כאן באתר שכולל מעל שש שעות של הסברים, דוגמאות וטיפים לשימוש חכם יותר ב Git. פרטים והרשמה בקישור https://www.tocode.co.il/bundles/git

תהנה מהדרך

23/12/2018

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

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

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

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

ניצחונות קטנים

22/12/2018

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

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

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

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

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

ביטויים רגולאריים וקסמים של וים

21/12/2018
vim

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

<img src="cat.png" />

והופך אותה לשורה שנראית כך:

<img src="cat-1.png" />

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

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

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

/\V\[0-9]\[0-9]

עדיין אפשר להשתמש בקיצור \d כך שגם החיפוש הזה יעבוד:

/\V\d\d

למצב קצת קסום אנחנו נכנסים עם \M בתחילת הביטוי ומצב זה ממש דומה ל"לא קסום בכלל" מלבד התווים ^ ו $ שלא צריכים שתכתבו \\ לפניהם.

למצב קסום אנחנו נכנסים עם \m בתחילת הביטוי. מצב זה מזכיר מאוד את grep ובו רוב הסימנים המיוחדים יעבדו בלי \\ אבל עדיין יהיו מספר סימנים מיוחדים שכן יצטרכו \\ לפניהם לדוגמא +, ? ו {}.

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

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

:s/\vsrc="(\w+)\.(\w+)"/src="\1-1.\2"/

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

התיקון הכי פשוט יהיה להוסיף \\ לפני סימן השווה ואז נקבל את הביטוי הבא שעובד:

:s/\vsrc\="(\w+)\.(\w+)"/src="\1-1.\2"/

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

:s/\Vsrc="\(\w\+\).\(\w\+\)"/src="\1-1.\2"/
:s/\msrc="\(\w\+\).\(\w\+\)"/src="\1-1.\2"/
:s/\Msrc="\(\w\+\).\(\w\+\)"/src="\1-1.\2"/

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

http://vimdoc.sourceforge.net/htmldoc/pattern.html#pattern

החיים שלי עם ביטויים רגולאריים

20/12/2018

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

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

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

    https://www.tocode.co.il/blog/2015-05-vim-html-image-gallery

  3. עוד כלי שתומך בביטויים רגולאריים הוא גיט ובפרט הפקודה git log שמקבלת פרמטר בשם grep. החיפוש הזה ייתן את כל הקומיטים שההודעה שלהם מתקנת Issue בן שלוש ספרות או יותר.
    $ git log -i -E --grep='(fix|close).*[0-9]{3}'
    
  4. ביטויים רגולאריים יכולים לעשות קסמים כשאתם צריכים החלפה מהירה של מילים בסקריפט. נכון של Bash ולכל סביבה יש את הכלים המיוחדים שלה להחלפות, אבל הייתרון בביטויים רגולאריים שתחביר אחד עובד תמיד: אנחנו נמצא אותם ב awk, sed וכמובן ב grep.

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

    text = 'hello.txt'
    puts text.chomp('.txt') # prints hello
    

    אבל אז אתם עוברים לפייתון ופתאום צריכים לכתוב קוד כזה:

    text = 'hello.txt'
    if url.endswith('.txt'):
        print(text[:len('.txt') + 1])
    

    בעוד שבאמצעות ביטוי רגולארי הייתם פותרים את הבעיה בשתי השפות עם אותו קוד בדיוק.

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

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

https://www.tocode.co.il/workshops/59

השוואת גבהים בריאקט - חלק 2

19/12/2018

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

המשך קריאה

אבל... זה עבד לי בפיתוח

18/12/2018

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

קרה לכם? ברור. בואו נרשום לקחים:

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

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

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

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

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

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

    apt list --installed
    

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

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

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

השוואת גבהים בריאקט

17/12/2018

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

המשך קריאה

דברים שאני מנסה כשכבר נגמרו הרעיונות

16/12/2018

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

  1. מתחיל למחוק קוד באקראי ולראות אם משהו מתחיל להתנהג אחרת.

  2. מוסיף מלא הדפסות Debug ומקווה שחלק מהמידע ייתן לי השראה.

  3. עושה הפסקה.

  4. חוזר ומגלה שהבעיה עדיין שם, ולי עדיין אין רעיונות.

  5. כותב בדיקות אוטומטיות.

  6. מוסיף עוד הדפסות ומנסה לחפש חוקיות.

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

  8. מתייעץ עם חבר.

  9. מתרגל לחיים עם הבאג.

רעיונות נוספים? מוזמנים לשתף בתגובות.