ארבע דרכים לקרוא קובץ טקסט ב Node.JS
נוד נועד לרוץ על השרת ולכן יש לו גישה למחשב המקומי, מה שאנחנו לא מוצאים ב JavaScript שרץ על הדפדפן. אחד הדברים הראשונים שאנשים רוצים לעשות עם גישה זו הוא לכתוב ולקרוא מקבצים כפי שנראה בשיעור זה.
טיפים קצרים וחדשות למתכנתים
נוד נועד לרוץ על השרת ולכן יש לו גישה למחשב המקומי, מה שאנחנו לא מוצאים ב JavaScript שרץ על הדפדפן. אחד הדברים הראשונים שאנשים רוצים לעשות עם גישה זו הוא לכתוב ולקרוא מקבצים כפי שנראה בשיעור זה.
הרבה מהפיתרונות שאנו מוצאים כמתכנתים מתחילים ניתנים לאימות. לדוגמא יש לך באג בקוד והפונקציה לא מחזירה את מה שצריך. אתה יכול לשנות את הקוד, להריץ שוב את הפונקציה ולראות אם השינוי תיקן את הבעיה.
כשהבעיות הופכות יותר מורכבות האימות נהיה קשה יותר אבל הרבה פעמים עדיין אפשרי. אם יש לך בעיה בקוד מקבילי שנובעת מ Race Condition בין התהליכונים השונים אז צריך יותר להתאמץ כדי לראות את הבעיה בסביבת בדיקות ואולי להוסיף המתנות יזומות כדי שמקרה הקצה באמת יקרה יותר פעמים. או אם יש לכם בעיית ביצועים בשרת רק במצב של עומס מסוים אז צריך להתאמץ ולסמלץ את אותו העומס בסביבת הבדיקות כדי שנוכל לבדוק אם השינוי שלנו פותר את הבעיה.
והטעות שאנחנו עושים בנושא אימות היא לחשוב שיש פה רצף ושכל פיתרון אפשר לאמת אם רק נתאמץ מספיק. אבל האמת שלא משנה כמה תתאמצו אתם לא יכולים לדעת בוודאות אם Angular או React יתאימו יותר לצוות או לפרויקט שלכם עד אחרי שאתם עמוק בתוך הפרויקט. ואתם לא יכולים לדעת אם React Native תגיע לביצועים שאתם צריכים בהשקעה שאתם מוכנים להשקיע ביישום או שעדיף לכם לפתח Native מההתחלה. ואתם לא יכולים לוודא אם פיתרון אבטחת המידע שבניתם יהיה מספיק מאובטח או שפורצים יצליחו לעבור אותו.
איפה שאפשר לאמת את הפיתרון חשוב לעשות זאת, וגם להוסיף בדיקה אוטומטית כדי שהזיכרון יישאר לפעם הבאה. אבל איפה שאי אפשר - תחסכו לעצמכם את זמן הבדיקה ופשוט תתחילו לעבוד. יהיו בעיות בדרך זה ברור, אבל כנראה זה נכון גם לגבי הדרך השניה.
לא מזמן תלמיד בקורס React שאל אותי למה קוד מסוים לא עובד. גירסא פשוטה של הקוד שלו נראתה בערך כך:
import React from 'react';
class App extends React.Component {
render() {
return
<div>
Hello World
</div>
}
}
אחרי כמה דקות של מחשבה קל לראות שמשהו לא בסדר אחרי המילה return: בדרך כלל היינו מוצאים שם פתיחת סוגריים עגולים או מיד באותה השורה את האלמנט, והנה כאן יש לנו ירידת שורה לפני ה div. ירידת השורה גרמה ל JavaScript להתיחס ל return הזה כאילו הסתיים באותה השורה ולכן מה ש JavaScript ראה היה משהו כזה:
import React from 'react';
class App extends React.Component {
render() {
return undefined;
<div>
Hello World
</div>
}
}
הפונקציה הסתיימה בשורת ה return ואף אחד לא הגיע לקוד שמופיע אחרי.
ורק כמה ימים אחרי שהתאוששנו מההלם הזה תלמידה אחרת בקורס Linux שאלה אותי על תוכנית Awk שלא עובדת. הקוד שלה נראה בערך כך:
/^#/
{
gsub(".", "-");
}
{
print;
}
במטרה להפוך את כל התווים לסימן מינוס רק בשורות שמתחילות בסולמית. אבל זה לא בדיוק עבד. כשהפעלנו את התוכנית על הקלט הבא:
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/usr/local/bin/zsh
התוצאה היתה:
# List of acceptable shells for chpass(1).
------------------------------------------
# Ftpd will not allow users to connect who are not using
--------------------------------------------------------
# one of these shells.
----------------------
---------
--------
--------
-------
---------
--------
------------------
כל התווים בכל השורות הפכו למינוסים, ושורות שמתחילות בסולמית הודפסו בנוסף כמו שהן לפני ההחלפה. אחרי עוד כמה דקות של מחשבה נזכרתי בסיפור על React וכך הבנתי איך awk ראה את הקוד שלנו:
/^#/ { print; }
{
gsub(".", "-");
}
{
print;
}
ירידת השורה מיד אחרי התנאי גרמה ל awk לחשוב שהפקודה מסתיימת שם. תנאי בלי בלוק פעולות ב awk גורם להדפסה אוטומטית של שורות שמתאימות לתנאי. הבלוק הבא מבחינת awk היה פקודה בלי תנאי, ולכן התאים לכל השורות. בקצרה awk הדפיס כל שורה שמתחילה בסולמית, אחרי זה החליף בכל שורה את כל התווים למינוסים ובסוף הדפיס את השורה. גם כאן בדומה ל React התיקון היה פשוט לוותר על ירידת השורה ולכתוב את התוכנית:
/^#/ {
gsub(".", "-");
}
{
print;
}
ומה אפשר ללמוד משתי הטעויות? שהרבה פעמים הקשר בין עולמות שונים בתכנות הוא הרבה יותר חזק ממה שנראה בהתחלה. שככל שתלמדו ותבינו יותר טכנולוגיות מעולמות מגוונים יש סיכוי טוב יותר שתצליחו להיכנס לראש של האנשים שכתבו אותן.
מה עושים כשיש לכם קובץ עם מספרים שאתם רוצים לרפד באפסים? ביטוי רגולארי כמובן. נראה כמה דוגמאות.
יש לכם bash גירסא 4? גם אתם יכולים להשתמש ב globstar שיגרום לתבניות הגלוב שלכם לתפוס יותר קבצים. בואו נראה מה זה ואיך מפעילים.
אנחנו אוהבים להשתמש באנאלוגיות כדי להבין איך דברים עובדים, והרבה פעמים אנאלוגיות כאלה עוזרות לנו לדמיין את המידע הדיגיטלי במחשב בצורה ויזואלית ולהסיק מסקנות מועילות לגביו. אבל גם לפעמים לא.
קחו לדוגמא את מערכת הקבצים: רבים אוהבים לחשוב על זה כמו מסמכים ששמורים בתיקיות. כך גם סייר הקבצים מציג לנו את המידע. וזה עוזר, עד שנזכרים ב Hard Links ושקובץ יכול להיות בשני מקומות בו-זמנית. כשהמודל המנטאלי שלכם הוא של מסמכים בתוך תיקיות הרעיון של מספר Hard Links לאותו קובץ הוא בלתי נתפס. הדרך היחידה להבין אותו היא להבין שקבצים הם שמות באינדקס שנקרא מערכת קבצים, ושהמידע עצמו נמצא בכלל על הדיסק וממש לא לפי סדר התיקיות שאנחנו רגילים להסתכל עליו.
או ניזכר ב git: אם המודל המנטאלי שלכם אומר שקומיט מייצג את השינויים בין שתי גירסאות יהיה לכם קשה מאוד להבין איך filter-branch או rebase עובדים. רק כשמחליפים מודל מנטאלי ומתיחסים לקומיט בתור "מצב הפרויקט ברגע מסוים בהיסטוריה" כל השאר מתחבר ונהיה הגיוני.
כשאתם מנסים ללמוד משהו חדש ודברים נראים לא הגיוניים, נסו לחשוב על המודל המנטאלי באמצעותו אתם מנסים להבין את הנושא החדש. אולי תיקון המודל יעזור לכם להבין טוב יותר את המציאות.
יש טכנולוגיות שהן כל כך גדולות שהליכה לאיבוד היא ברירת המחדל בהן. הדוגמאות מהחיים שלי הן: Rails, Angular וכמובן Unix. וככל שטכנולוגיה גדולה כזו חיה יותר שנים כך נוצרות יותר ויותר דרכים "פשוטות" לעשות דברים, דרכים שכמובן רק מגדילות את נפח הפנים של הבעיה שלפנינו.
גישה אחת בעבודה עם מערכות כאלה היא להיצמד למוכר. בגלל זה כשמסתובבים בחברות אתם מוצאים בקלות מערכות שכתובות ב Angular אבל מנצלות רק 20% מהיכולות של הכלי. המתכנתים שם מצאו את ה 20% שעובדים להם וזה מספיק. הרבה פעמים גם מבחינה ארגונית זה הפיתרון הטוב ביותר.
אבל למתכנת שעובד על כזו מערכת זו גישה הרסנית. לאורך זמן אתם לא מנצלים את השנים בעבודה על המערכת כדי לצבור ניסיון רלוונטי ובעוד 4 שנים תמצאו את עצמכם יודעים רק את אותם 20% שעבדו עבורכם באותו מקום. כשתגיעו לראיון עבודה במקום חדש שעובד באנגולר זה יהיה מביך לשני הצדדים.
אני רוצה להציע רעיון אחר- עשו לעצמכם הרגל ופעם בשבוע בחרו בעיה עליה עבדתם השבוע ופיתרו אותה שוב בדרך שונה, תוך שימוש בחלקים בתשתית שאתם לא מכירים. אם יצא לכם פיתרון יותר טוב החליפו את הקוד המקורי שכתבתם, ואם פחות טוב זירקו את זה כניסוי שלא הצליח.
ארבע שנים קדימה והרווחתם מיומנות אמיתית בפריימוורק ואני מקווה שגם נהניתם מהדרך.
נ.ב. אם קראתם את זה וחשבתם "רעיונות יפים יש לבחור אבל מה זה קשור אליי? אצלנו אין זמן למשחקים ולפתור דברים פעמיים" אתם יכולים להירגע. כולם מרגישים ככה. ובכל זאת כולם מבלים שעות בפייסבוק, ב ynet, באינסטוש, בפינת קפה, בארוחת צהריים בחוץ, בישיבות, בימי גיבוש ובעוד עשרות פעילויות שאינן תכנות. שעה בשבוע ללמידה אתם יכולים למצוא.
התחלתם עבודה חדשה? מזל טוב! אומרים שאין הזדמנות שניה ליצור רושם ראשוני ולכן החודשים הקרובים בטח יהיו מאוד מרגשים וגם גורליים. איך תיצרו את הרושם הראשוני הכי טוב שאתם יכולים על המנהלים ועל חבריכם החדשים לצוות? הנה שלוש עצות שאני בטוח שיעזרו.
גירסת ES6 של JavaScript הוסיפה יכולת שחיכינו לה המון זמן והיא שיערוך משתנה בתוך מחרוזת. הקוד הבא לדוגמא מדפיס Hello ynon:
name = 'ynon';
console.log(`Hello ${name}`);
מהר מאוד מתכנתים הבינו שאפשר להשתמש בזה כדי לבנות טמפלייטס ל HTML לדוגמא הקוד הבא שפונה ל swapi.co כדי להביא את השם של הדמות הראשית ולהציג אותה על המסך:
$.get('https://swapi.co/api/people/1', luke => {
$('body').append(`<p>Character 1's name is: ${luke.name}`);
});
וכמו שזה פשוט ככה זה שבור: הרי אם המידע שמגיע מהרשת כולל תגיות HTML או חלילה את התגית script אז הדפדפן של כל אחד מהגולשים יריץ את הסקריפט הזה ויצרנו פירצת XSS בלי להתכוון.
אם אתם משתמשים בטכניקה הזו בקוד שלכם ספריה קטנה בשם common-tags עשויה לעזור. היא כוללת אוסף של Tagged Template Literals שזה פונקציות חלופיות לשיערוך משתנים בתוך מחרוזות. הנה גירסא נוספת להשוואה הכוללת קודם הכנסה לא מאובטחת של משתנה ואחר כך גירסא מאובטחת:
import { safeHtml } from 'common-tags';
const name = 'demo <b>haha</b>';
$('body').append(`<p>Character 1's name is: ${name}`);
$('body').append(safeHtml`<p>Character 1's name is: ${name}`);
והתוצאה בקודפן:
וכן איך שלא נסובב את זה תשתיות לא מאובטחות מסוג זה הן מתכון לאסון וכבר מצאתי לא מעט דוגמאות כאלה מפוזרות ברשת. בואו ננסה להיות זהירים לפחות עם המערכות שלנו.
דרך אחת לשפר ביצועים של קוד היא לזרוק אותו למספר תהליכים שירוצו על הקוד במקביל. זה עובד אבל מתכנתים חכמים יודעים שכמעט תמיד אפשר למצוא טריק יותר אפקטיבי. הנה דוגמא קטנה להמחשה ותזכורת.