למה מערך ריק שווה 0?
לא תמיד אנחנו מסכימים עם השגעונות של ג'אווהסקריפט אבל הרבה פעמים כן יש איזה היגיון פנימי שיכול לעזור להסביר את הטירוף. ועם ההקדמה הזאת בואו נדבר על מערכים.
טיפים קצרים וחדשות למתכנתים
לא תמיד אנחנו מסכימים עם השגעונות של ג'אווהסקריפט אבל הרבה פעמים כן יש איזה היגיון פנימי שיכול לעזור להסביר את הטירוף. ועם ההקדמה הזאת בואו נדבר על מערכים.
אני זוכר שישבתי עם חבר שעבד בתחום של Penetration Testing ואמרתי לו - "וואו יש לך את העבודה הכי כיפית בעולם, כל היום אתה מחפש חולשות במערכות ויכול לשבור דברים". "תמשיך לחלום" הוא ענה לי, "נכון, יש את החלק הזה שצריך לשבור דברים ולמצוא חולשות, אבל רוב היום אני רק כותב דוחות ומארגן יפה ומסודר את כל מה שמצאתי". ההבדל בין לעשות משהו בשביל הכיף ולעשות משהו בשביל עבודה מעולם לא נראה ברור יותר.
ואותו הבדל תוקף אותנו גם כשאנחנו באים לשדרג את הקריירה או הקוד שלנו:
בכתיבת פרויקט צד, ההתחלה נראית מלהיבה (איזה כיף אני הולך להתעסק עם מלא טכנולוגיות חדשות), עד שאתה מגלה שבשביל שדברים יעבדו טוב יחד מעבר ל Tutorial הבסיסי, צריך להתאמץ, לא להבין ולפעמים פשוט לזרוק עוד שורות קוד על הבעיה, בדיוק כמו בעבודה האמיתית.
לימוד תחום חדש עשוי להיראות כמו הדבר הכי מלהיב בעולם, עד שאתה מגלה שבשנה הראשונה הדברים היחידים שתצליח לבנות הם הרבה פחות מלהיבים מאלה שחלמת עליהם. שלפני שתצליח לבנות את המשחק שתמיד חלמת עליו תצטרך לבנות אינסוף משחקים פשוטים ומשעממים רק כדי ללמוד את היסודות.
הכנסת טכנולוגיה חדשה לפרויקט עשויה להיראות כמו רעיון ממש מלהיב, עד שמתחילים תכל'ס לכתוב את הקוד ורואים שדברים לוקחים יותר זמן ממה שקיווית, ואפילו התקנות והגדרות שנראו ממש פשוטות ב Tutorial הופכות לאתגר כשצריך לשלב אותן עם פרויקט אמיתי.
הרבה מתכנתים חולמים על פרויקט Green Field, שבו יוכלו להתחיל הכל מאפס, או על איזה Rewrite גדול שאחריו כל הבעיות יעלמו. ברוב המקרים הסיבה שפרויקט Green Field הוא פשוט יותר היא בדיוק בגלל שהתחלנו מאפס. ככל שמוסיפים פיצ'רים הקוד מסתבך והכיף שוב נעלם.
אז נכון תהליך הלימוד, תהליך הפיתוח, תהליך הקידוד, הם אולי לא מלהיבים כמו שהייתם רוצים שיהיו. אבל אל תתנו לבלבול הזה לייאש אתכם - לאורך זמן, שילוב טכנולוגיות חדשות ולימוד תחומים חדשים זו הדרך היחידה קדימה.
גיירמו ראוך מ vercel הגדיר את ורסל עצמה והרבה מהמתחרות שלה בתור "ענן שכבה 2", אם בחברות הענן המסורתיות אנחנו צריכים לשבור את השיניים בשביל לבנות אפליקציה - בחברות הענן החדשות אנחנו נקבל Deployments בלחיצת כפתור, חיבור לגיטהאב וגם אפשרות להרצה ובדיקה מקומית.
ריילווי היא אחת מחברות הענן החדשות האלה והנה כמה דברים שנראה לי שתאהבו בה:
רוצים להכניס טייפסקריפט לפרויקט אבל חברי הצוות עושים פרצוף? הנה ארבע תגובות שלפעמים אנחנו שומעים על טייפסקריפט, ומה לענות בכל מצב.
בכל נקודה בפיתוח, יותר זול לי לתקן באג או להוסיף פיצ'ר תוך כדי בדיקה ידנית שהצלחתי, מאשר לבנות תשתית בדיקות.
ובכל נקודה אם היתה לי תשתית בדיקות טובה הייתי יכול לבנות את הפיצ'ר או לתקן את הבאג יותר מהר מאשר בלעדיה.
הבעיה שבדרך כלל אנחנו בונים תשתית בדיקות לא מספיק טובה, ואז משלמים פעמיים - גם השקענו עבודה בבניית ההתשתית, וגם בשוטף אנחנו משקיעים יותר זמן בפיתוח פיצ'רים ותיקון באגים (כי צריך גם להוסיף בדיקה שרק גוזלת זמן).
המפתח קדימה הוא לחזור למשפט השני בפוסט הזה, ולזכור ש"תשתית בדיקות טובה משפרת קצב". כל עוד תשתית הבדיקות שלכם מאטה אתכם, צריך להמשיך לשפר אותה (או לוותר ולזרוק).
גיטהאב אקשן מספק מנגנון ממש נוח ל Deployment אוטומטי למערכת שלכם, אבל יש טוויסט: אנחנו לא רוצים לעשות deploy על כל PR חדש שממוזג ל main, אבל אנחנו גם לא רוצים לעשות את הקומיט ידנית בלחיצת כפתור כי כן מאוד נוח לעבוד רק דרך גיט. פיתרון אחד קל הוא להחליט על תבנית שם של tag שיגרום ל deploy, למשל נחליט שכל תג שמתחיל במילה deploy ואחריה מקף יגרום לגיטהאב להפעיל אקשן שיעשה deployment חדש.
הטריגר ב Github Action יראה כך:
on:
push:
tags:
- 'deploy-*'
ואז אפשר ליצור את התג עם תוספת של timestamp ולדחוף אותו לשרת עם הפקודות:
$ git tag deploy-$(date +%s)
$ git push --tags
נתון אוסף של תיקיות בכל אחת יש פרויקט אחר. המשימה שלנו היום היא ליצור בתוך כל תיקיה תת-תיקיה בשם app אם אין כזאת, ואם הצלחנו ליצור אז גם להעביר את כל הקבצים והתיקיות שהיו בתוך אותה תיקיה לתוך app. אם היתה app קודם אפשר לדלג על התיקיה.
כל עוד מדובר ב 2-3 פרויקטים אין בעיה לעבור אחד אחד, אבל כשיש עשרות הרבה יותר כיף להשתמש ב find.
המשימה הראשונה היא למצוא את כל תיקיות הפרויקטים, כלומר התיקיות ברמה "הראשית". בשביל זה find מציע לנו את maxdepth, type ו mindepth. עבור דוגמה פשוטה שמכילה שלוש תיקיות פרויקטים בשמות a, b ו c אני מריץ:
$ find . -mindepth 1 -maxdepth 1 -type d
./a
./c
./b
בזכות מסנן ה type הפקודה מדפיסה רק את התיקיות גם אם היו קבצים בתיקיה הראשית. אפשר לסנן עוד יותר גם לפי שמות קבצים של אותן תיקיות פרויקטים עם תוספת מתג -name
.
אחרי שיש לנו את תיקיות הפרויקטים צריך בכל תיקיה להריץ את הפקודות:
mkdir app && mv * app
שימו לב לסימן ה &&
בין שתי הפקודות: אני רוצה להריץ את ה mv רק אם הצלחתי ליצור את התיקיה. אם mkdir נכשל זה כנראה אומר ש app היתה שם קודם (למרות שיכול להיות שמדובר בבעיית הרשאות, אבל גם במקרה כזה אין טעם לנסות להעביר לשם קבצים).
בשביל זה ל find יש כפתור exec. אבל אני לא יכול להריץ ישירות את ה &&
בתוך ה exec ולכן אני מריץ עותק חדש של bash שיפעיל את שתי הפקודות:
find . -mindepth 1 -maxdepth 1 -type d -exec bash -c "mkdir {}/app && mv {}/* {}/app" \;
ופה בדיוק הכח והיופי של הכלים הקטנים של יוניקס - היכרות טובה איתם עוזרת לתקשר עם המחשב טוב יותר ולחסוך זמן במשימות שבאמת לא הגיוני לעשות אותן ידנית.
אחד השינויים המעניינים שתמצאו ברשימת החידושים של פייתון 11 נקרא Regular Expressions Atomic Grouping. מסתבר שמאחורי השם המפוצץ מסתתר תחביר פשוט וחמוד, שאפילו יכול להציל את המערכת שלכם מהתרסקות אטומית.
אחת הבעיות עם ביטויים רגולאריים נקראת Catastrophic Backtracking. קחו לדוגמה את הביטוי הרגולארי:
re = /W(X|Y+)+Z/
ואת הטקסט:
text = "WYYYYYYYYYYYYYYYYYYYYYYYYYYYYA"
כשתבקשו מרובי (או כל מפענח אחר) לבדוק אם הטקסט מתאים לביטוי הרגולארי תופתעו לראות שלמרות ששום דבר פה לא ארוך במיוחד, זה לוקח כמה שניות טובות עד שמקבלים תשובה. הסיבה היא שמנוע הביטויים הרגולאריים כל הזמן חוזר ומנסה עוד ועוד אפשרויות מתוך הקבוצה X|Y+
, ועל כל אפשרות מנסה עוד ועוד אפשרויות לכמה פעמים הקבוצה תופיע.
סימון קבוצה בתור קבוצה אטומית אומר למנוע הביטויים הרגולאריים לא לחזור לחפש התאמות מאותה קבוצה אחרי שכבר בחרנו ממנה איזושהי אפשרות. כלומר פעם אחת נכנסת ולקחת את כל ה Y-ים שיתאימו ל Y שבתוך הקבוצה, וזהו זה מה שיש. מפה אתה לא נכנס שוב לקבוצה הזאת ומנסה מספר אחר של Y-ים שיתאימו. הצליח? יופי, לא הצליח? מנתקים.
בשביל להגדיר קבוצה אטומטית אנחנו כותבים בתוך הסוגריים סימן שאלה ואחריו סימן גדול-מ ואז את התוכן, במקרה שלנו הביטוי הרגולארי יהיה:
re = /W(?>X|Y+)+Z/
ניסיון להתאים ביטוי כזה על הטקסט ייכשל מיד, מה שעשוי להציל את השרת אם הקלט גדול ומכוון להזיק.
שימו לב ששינוי קבוצה לקבוצה אטומית משנה את המשמעות של הביטוי. לדוגמה הביטוי הזה:
re = /a(bc|b)c/
יתאים לטקסטים abc
ו abcc
, אבל אם אני הופך את הקבוצה לאטומית והאופציה של bc תיכשל, המנוע לא יחזור לנסות את b ולכן הטקסט abc
לא יתאים לביטוי a(?>bc|b)c
. בסך הכל קבוצות אטומיות הן כלי מתקדם שחשוב להכיר אם אתם משתמשים בביטויים רגולאריים על קלט לא מפולטר ורוצים לוודא שקלט זדוני לא שובר לכם את השרת. והחל מפייתון 3.11 תוכלו להשתמש בהן גם בפייתון.
לקח לי קצת זמן לשים לב לזה אז משתף כדי שאתם לא תתבלבלו. מנגנון ה Type Inference של טייפסקריפט, זה שאחראי על בחירת הטיפוסים בצורה אוטומטית בקוד שלכם, משתמש בתחילית let או const כדי להחליט אם "להרחיב" את הטיפוס או להשתמש בטיפוס ליטרלי.
במילים אחרות ויותר ספציפי, הקוד הזה מגדיר את x להיות מהטיפוס הליטרלי 10:
const x = 10;
אבל הקוד הזה מגדיר את x להיות number:
let x = 10;
בדרך כלל לא נשים לב להבדל עד שזה יתחיל להפריע. למשל הקוד הזה לא מתקמפל:
const movie = { name: 'Return Of The Jedi', rating: 5 };
let key = Math.random() > 0.5 ? "name" : "rating";
console.log(movie[key]);
ולא בגלל שטייפסקריפט כועס על הדירוג הגבוה של "שובו של הג'דיי". הוא פשוט רואה את ה let לפני ה key, מחליט ש key הוא string ולא מבין איך אפשר להשתמש ב string כללי בתור מפתח בגישה לאוביקט movie.
התיקון הכי קל הוא להפוך את הגדרת המשתנה ל const:
const movie = { name: 'Return Of The Jedi', rating: 5 };
const key = Math.random() > 0.5 ? "name" : "rating";
console.log(movie[key]);
וככה טייפסקריפט מבין שהטיפוס של key הוא האיחוד בין שני הטיפוסים הליטרליים name ו rating, ובגלל ששניהם מפתחות ב movie הוא מרשה לי להשתמש ב key בתור מפתח באוביקט.
נ.ב. לאלה מכן שפחות אוהבים להתחכם, אפשר לכתוב את אותה הדוגמה בלי ה random בכלל:
const movie = { name: 'Return Of The Jedi', rating: 5 };
let key = "name";
console.log(movie[key]);
אבל זה עלול להרוס את הכיף.
אתר טוקוד החדש עלה לאוויר אתמול ואם אתם קוראים את זה מהאתר אתם כבר יכולים לראות את השינוי (אם אתם במייל או בטלגרם - תקפצו לבקר דרך הלינק). חוץ משינוי העיצוב יש גם כמה פיצ'רים חדשים:
נוספה אפשרות למנוי שנתי, בו אתם משלמים על 10 חודשים מראש ומקבלים את החודשיים האחרונים מתנה.
נוספה אפשרות למנוי בתשלום מראש שאינו מתחדש לתקופה לבחירתכם. אתם פשוט מסמנים כמה חודשים אתם רוצים, משלמים ושוכחים מזה.
נוספה אפשרות לצפיה בטקסט ובוידאו באותו זמן: בתוך נגן הוידאו אתם לוחצים על האייקון שמראה חץ קטן לתוך ריבוע בצד (זה בתוך הוידאו אני לא בטוח שתיארתי אותו נכון, פשוט תנסו את זה), ואז הסרט "יוצא" מהנגן ומתחיל לרחף באתר. כשזה קורה אתם עוברים לטאב "טקסט" ותוכלו לראות שהוידאו ממשיך להתנגן. בעתיד אולי אמצא דרך להשאיר את הוידאו מנגן גם בניווט לדפים אחרים.
נוסף "מצב חשוך" למי שאוהבים לקרוא מהטלפון בלילה.
מאחורי הקלעים השינוי הכי גדול זה המעבר החוצה מריאקט לכלי ה JavaScript של ריילס שזה טורבו וסטימולוס. המטרה שלי כאן היתה להוריד עלויות ולאפשר שינויי עיצוב מהירים רק דרך שינוי HTML בלי לחשוב על המערכת בתור "אפליקציה", ובעצם להפוך את הקוד להרבה יותר פשוט.
אם אתם מנויים של האתר ורוצים לעבור לאחד המסלולים של "מנוי שנתי" או "מנוי בתשלום מראש" כרגע תצטרכו לבצע "ביטול מנוי" וכשתקופת המנוי תסתיים תוכלו להירשם מחדש לאחד המסלולים. בקרוב אוסיף אפשרות של מעבר בין מסלולים למסך "החשבון שלי" וכשזה יקרה גם אעדכן פה בבלוג.
למרות הרבה בדיקות שלי על הגירסה החדשה אני בטוח שיש לא מעט דברים שעדיין שבורים. אם אתם נתקלים בבעיות בבקשה אל תהססו להשאיר הודעה או לשלוח לי מייל.
מקווה שתהנו מהאתר החדש ותמשיכו להצליח בקורסים. ינון.