ru
Feedback
ToCode

ToCode

Открыть в Telegram

טיפים קצרים למתכנתים מאת ינון פרק

Больше
1 420
Подписчики
Нет данных24 часа
+27 дней
-230 день
Архив постов
ToCode
1 420
# גיט add הכל הוא הרגל רע פותח בראנץ, כותב קוד, בודק שהכל עובד, עושה קומיט, מגלה טעות, מתקן, שוב מוסיף הכל וקומיט, כותב בדיקה אוטומטית, מגלה עוד שתי טעויות, מתקן וקומיט. אם התיאור הזה נשמע לכם מוכר זה זמן טוב לעצור, או לפחות להתעכב על השלב "עושה קומיט". במהלך הפיתוח ובמיוחד בתוך רצף עבודה מאוד מפתה להשתמש בפקודות:
$ git add .
$ git commit
או בגירסה המתונה יותר git commit -a. הבעיה בשתי הגירסאות נובעת משילוב שני גורמים: 1. קומיטים ספונטניים נוטים לכלול שינויים שקשורים למספר נושאים. כשאותו קומיט מכיל שינויים במספר נושאים אנחנו רואים הודעות קומיט מורכבות (במקרה הטוב) או התעלמות משינויים קטנים במקרה הנפוץ. דוגמה קלה היא כשבמהלך העבודה על פיצ'ר מגלים שגיאת כתיב בקובץ לא-קשור-בכלל. 2. הרבה פעולות של גיט עובדות ברמת קומיט וכשהקומיטים לא מדויקים אנחנו מפסידים. בדוגמת תיקון שגיאת הכתיב, אם בעתיד ארצה לעשות revert לקומיט הזה אני מוותר גם על תיקון שגיאת הכתיב. אם אני צריך את תיקון האיות גם בענף אחר אני עכשיו צריך לקחת ב cherry pick גם את השינוי הגדול יותר. מה עושים במקום? האפשרות המועדפת עליי היא להפעיל git status ו git diff לפני שמתחילים להכניס דברים לקומיט, ואז להכניס את השינויים לקומיט בצורה מבוקרת - או באמצעות הוספת קבצים מלאים או אפילו באמצעות git add -i שמאפשר לבחור איזה שורות בקובץ צריכות להיכנס לקומיט. הכנסה מבוקרת של שינויים לקומיטים מייצרת קומיטים נקיים יותר ותחסוך לחברים שלכם התמודדות עם חצאי שינויים שבמקרה נכנסו לקומיט ששיתפתם.

ToCode
1 420
MATCH (neo4j:Category {name: "neo4j"})

MERGE (foo)-[:SUBSCRIBED_TO]-(spam)
MERGE (bar)-[:SUBSCRIBED_TO]-(neo4j)
MERGE (buz)-[:SUBSCRIBED_TO]-(spam)
MERGE (buz)-[:SUBSCRIBED_TO]-(neo4j)
## כתיבת שאילתות על יחסים אז עכשיו שהפוסטים שייכים לקטגוריות והקוראים מנויים לקטגוריות אפשר לשפר את השאילתות שלנו, למשל אפשר לבדוק מהם כל הפוסטים שקורא מסוים צריך לקבל. בשלב ראשון ובגלל שעוד אין לי מידע על דיוורים שנשלחו במערכת, אלה יהיו פשוט כל הפוסטים בקטגוריות שמתאימות למנוי. עבור הקורא foo שמנוי לקטגוריית spam זאת השאילתה:
MATCH (foo:Reader {email: "foo@demomail.com"})
MATCH (foo)-[:SUBSCRIBED_TO]-(c:Category)
MATCH (p:Post)-[:BELONGS_TO]-(c)
RETURN p
## עדכון המודל כדי לאפשר קטגוריות-על אחד הדברים היפים במודל של neo4j הוא הגמישות של הסכימה. בדוגמה שלנו אפשר לדמיין שנרצה לאפשר למנוי להירשם לכל הקטגוריות, כולל קטגוריות שעדיין לא נוצרו, או לקבוצה דינמית של קטגוריות. למשל אפשר לדמיין שקטגוריות כמו "פיתוח צד-לקוח", "פיתוח node.js" ו"SQL" יהיו שייכות כולן לקטגוריה גדולה יותר בשם "פיתוח Full Stack", ואגב גם זו יכולה להיות שייכת לקטגוריה גדולה יותר כמו "פיתוח", שתהיה שייכת לקטגוריית "כל הפוסטים". אנחנו יודעים שפוסט יכול להיות שייך לקטגוריה בזכות יחס BELONGS_TO שיצרנו, ועכשיו אנחנו צריכים שגם קטגוריה תוכל להיות שייכת לקטגוריה. ל neo4j זה לא משנה בכלל. ניצור קטגוריה חדשה בשם all:
MERGE (:Category {name: "all"})
ועכשיו נוסיף את שתי הקטגוריות שיש לנו כך שיהיו שייכות ל all:
MATCH (a:Category {name: "all"})
MATCH (c:Category)
WHERE c <> a
MERGE (c)-[:BELONGS_TO]-(a)
וניצור קורא חדש שמנוי לקטגוריית all:
MATCH (a:Category {name: "all"})
MERGE (r:Reader {email: "me@demomail.com"})-[:SUBSCRIBED_TO]-(a)
וכן אפשר ליצור קורא ולחבר אותו לקטגוריה בפקודת MERGE אחת. זה מדליק. בשביל להציג את כל הפוסטים שהקורא החדש צריך לקבל אני צריך רק עדכון קטן לשאילתה שכבר כתבתי:
MATCH (r:Reader {email: "me@demomail.com"})
MATCH (r)-[:SUBSCRIBED_TO]-(c:Category)
MATCH (p:Post)-[:BELONGS_TO*]-(c)
RETURN p
שימו לב לסימן הכוכבית אחרי המילה BELONGS_TO. הכוכבית הופכת את החיפוש לרקורסיבי ומבקשת מ neo4j להחזיר את כל הפוסטים שיש מהם מסלול שמורכב מכמה חיבורי BELONGS_TO לקטגוריה אליה הוא מנוי. ## לאן ממשיכים השאילתה האחרונה צריכה להצית את הדמיון, כי חיפושים רקורסיביים ב SQL היו נראים הרבה יותר ארוכים וקשים לכתיבה, ובדרך כלל יעלו לנו בביצועים איומים. בסיסי נתונים גרפיים חיים בשביל שאילתות כאלה, וכאן הכח שלהם. ננסה לעצום עיניים ולעשות תרגיל דומה בבסיס נתונים רלציוני - זה יתחיל בטבלה של פוסטים, טבלה של קטגוריות וטבלת חיבור שמכילה מזהה פוסט בעמודה אחת ומזהה קטגוריה בעמודה שניה. ואז מגיעה הדרישה לחבר כמה קטגוריות לקטגוריה גדולה יותר. אז עכשיו צריך לעדכן את טבלת החיבור ולהפוך אותה לטבלה פולימורפית, כלומר להוסיף עוד עמודה שתגיד אם עמודת ה"פוסט" מכילה בעצם פוסט או קטגוריה, וכמובן לעדכן את השאילתה כדי לשלב את החיפוש הרקורסיבי. ואם הדוגמאות כאן עשו לכם חשק ללמוד יותר על neo4j אני ממליץ על אתר הלימוד הרשמי שלהם בכתובת: https://graphacademy.neo4j.com/

ToCode
1 420
MERGE (:Reader {email: "foo@demomail.com"})
MERGE (:Reader {email: "bar@demomail.com"})
MERGE (:Reader {email: "buz@demomail.com"})
## כתיבת שאילתות על צמתים הפקודה MATCH מספקת דרך בסיסית לקרוא מידע ב neo4j. המידע שלנו בינתיים מאוחסן רק בצמתים והפקודה MATCH יכולה לקבל קריטריון חיפוש ולהחזיר את כל הצמתים שמתאימים לקריטריון. שימו לב שביצירת כל צומת העברנו ל MERGE מילה שמתארת את הצומת - המילה שמתחילה באות גדולה מיד אחרי הנקודותיים. מילה זו נקראת Label והיא נקודת ההתחלה לכל חיפוש. לכן בשביל למצוא את כל קוראי הבלוג אני אכתוב:
MATCH (r:Reader) return r
בתוך ממשק הניהול של בסיס הנתונים אני מקבל את התוצאה בתור גרף ויזואלי, ויכול גם לבחור להציג את התוצאה בתור Table או Raw. התשובה בתור טבלה נראית כך:
{
  identity: 5,
  labels: ["Reader"],
  properties: {
    email: "foo@demomail.com"
  },
  elementId: "4:afd409dc-b534-4d20-bc87-dbccb412845c:5"
}
{
  identity: 6,
  labels: ["Reader"],
  properties: {
    email: "bar@demomail.com"
  },
  elementId: "4:afd409dc-b534-4d20-bc87-dbccb412845c:6"
}
{
  identity: 7,
  labels: ["Reader"],
  properties: {
    email: "buz@demomail.com"
  },
  elementId: "4:afd409dc-b534-4d20-bc87-dbccb412845c:7"
}
אנחנו יכולים לראות שכל צומת במערכת מכיל את ה label שבחרתי (במקרה של "קורא" זו המילה Reader), וכן שמתם לב נכון ש labels הוא מערך ואפשר להגדיר מספר תוויות לצומת. הצומת מכיל גם שדה בשם identity שזה מספר קצר שמזהה אותו וגם elementId שזה כבר מספר יותר מורכב. בגדול מומלץ לא לשמור ערכים אלה כי neo4j ממחזר אותם כשצמתים נמחקים. וכמובן כל המאפיינים שהגדרנו נשמרים בתוך הטבלה properties. הנה שאילתה דומה עבור פוסטים:
MATCH (p:Post) return p

{
  identity: 2,
  labels: ["Post"],
  properties: {
    publishedAt: 2023-01-24T06:00:00Z,
    title: "first post",
    slug: "first"
  },
  elementId: "4:afd409dc-b534-4d20-bc87-dbccb412845c:2"
}
{
  identity: 3,
  labels: ["Post"],
  properties: {
    publishedAt: 2023-01-25T06:00:00Z,
    title: "second post",
    slug: "second"
  },
  elementId: "4:afd409dc-b534-4d20-bc87-dbccb412845c:3"
}
{
  identity: 4,
  labels: ["Post"],
  properties: {
    publishedAt: 2023-04-02T06:00:00Z,
    title: "Hello World in Neo4j",
    slug: "hello-neo4j"
  },
  elementId: "4:afd409dc-b534-4d20-bc87-dbccb412845c:4"
}
פקודת MATCH יודעת גם לסנן את התוצאות לפי ערכי ה properties. לדוגמה אני יכול לשלוף רק את הקטגוריה שנקראת neo4j:
MATCH (c:Category) WHERE c.name = "neo4j" return c
או את כל הפוסטים שפורסמו באפריל 2023:
MATCH (p:Post) 
WHERE datetime({year: 2023, month: 4, day: 1}) <= p.publishedAt <= datetime({ year: 2023, month: 5, day: 1})
RETURN p
## הוספת קשרים בין הצמתים עד לפה neo4j לא נראה שונה מכל בסיס נתונים מבוסס מסמכים. מה שהופך אותו לבסיס נתונים גרפי הוא החיבור בין הצמתים באמצעות קשתות. אנחנו יוצרים חיבור בין שני צמתים בעזרת פקודת MATCH ... MERGE. החלק של ה MATCH ישמש כדי למצוא צמתים ואז ה MERGE ייצור את החיבור ביניהם. הפקודה הבאה משייכת את שני הפוסטים הראשונים לקטגוריית spam:
MATCH (p: Post)
WHERE p.slug IN ["first", "second"]
MATCH (c: Category {name: "spam"})
MERGE (p)-[:BELONGS_TO]->(c)
פקודת MERGE בשורה האחרונה היא החשובה: בצד שמאל יש לנו את הפוסט, בצד ימין את הקטגוריה ובאמצע שם היחס בין שניהם, במקרה שלנו BELONGS_TO, כלומר פוסט שייך לקטגוריה. בגלל שיש שני פוסטים שמתאימים ל WHERE אז שניהם יחוברו לאותה קטגוריה. נריץ גם את הפקודה הבאה כדי לשייך את הפוסט האחרון לקטגוריית neo4j:
MATCH (p: Post)
WHERE p.slug = "hello-neo4j"
MATCH (c: Category {name: "neo4j"})
MERGE (p)-[:BELONGS_TO]->(c)
כמו כן קוראים יכולים להירשם לקטגוריות מסוימות בבלוג, אז בואו נשייך קורא אחד לקטגוריית spam, קורא שני לקטגוריית neo4j וקורא שלישי לשתי הקטגוריות גם יחד:
MATCH (foo:Reader {email: "foo@demomail.com"})
MATCH (bar:Reader {email: "bar@demomail.com"})
MATCH (buz:Reader {email: "buz@demomail.com"})
MATCH (spam:Category {name: "spam"})

ToCode
1 420
# צעדים ראשונים עם neo4j בסיסי נתונים גרפיים נכנסו לחיינו כבר לפני מספר שנים במחשבה שאם המידע שלנו לא "מתאים" לטבלה אז במקום לאלץ את המידע לתוך התבנית שאנחנו מכירים אפשר לשנות את מודל האחסון. neo4j הוא אחד מבסיסי הנתונים הגרפיים הפופולריים ביותר גם היום ב 2023. יש לו קהילה חזקה, כלי פיתוח נוחים והתממשקות לכל שפת תכנות שאנחנו מכירים. ## מהו Neo4j לפני שנשאל מהו neo4j נרצה לדבר על מהו בסיס נתונים גרפי (ולא, אין שום קשר לתמונות). גרף הוא מבנה נתונים שבנוי מצמתים (Nodes) ומקשתות המחברות אותם (Edges). בסיס נתונים גרפי הוא בסיס נתונים שנותן לנו שפה כדי להגדיר ולתשאל מידע בצורה של גרף. הצרכים שלנו מבסיס נתונים גרפי יהיו: 1. יכולת ליצור צמתים בגרף. 2. יכולת לחבר צמתים בקשתות. 3. יכולת להוסיף מידע בצמתים. 4. יכולת להוסיף מידע על הקשתות. 5. יכולת לחפש מידע, כולל חיפוש המבוסס על קשר בין צמתים. וכמו שיש עולמות תוכן שמאוד קל לייצג בטבלאות, כך יש עולמות תוכן שלמים שייצוג באמצעות גרף פשוט מתאים להם כמו כפפה ליד. חישבו לדוגמה על רשת חברתית, בה כל צומת מייצג חבר ברשת והקשתות מייצגות את ה"חברות" בין החברים ברשת. שאילתות ברשת חברתית יתחילו מצומת מסוים וינסו לברר מי החברים שלו, מי החברים של החברים שלו, איזה אנשים הוא כנראה יכיר (כי אם הרבה חברים שלי הם גם חברים של מישהו מסוים אז בטח גם אני מכיר אותו). בסיס הנתונים neo4j יאפשר לנו לייצג בקלות תרחישים כמו רשת חברתית ותרחישים רבים נוספים בהם הדגש הוא על הקשרים בין פריטי מידע מסוימים, ואנחנו לא יודעים מראש את כל פריטי המידע והמאפיינים שלהם. ## איך מקבלים בסיס נתונים בשביל להתחיל לעבוד עם neo4j אפשר להריץ אותו אצלנו על המחשב בהתקנה מקומית או דוקר (הכל קוד פתוח), אבל הדרך הכי קלה היא לפתוח בסיס נתונים בענן שלהם שנקרא auro db. הכניסה בקישור: https://neo4j.com/cloud/platform/aura-graph-database/ אחרי רישום קצר תוכלו ליצור בסיס נתונים חדש וריק, שימו לב רק שבמסך יצירת בסיס הנתונים הם מציגים סיסמת חיבור ואחרי זה לא תוכלו לראות שוב את הסיסמה הזו ובלעדיה לא תוכלו להתחבר לבסיס הנתונים אז צריך להעתיק אותה הצידה לפני שממשיכים. אחרי שתיצרו את בסיס הנתונים ב Aura תוכלו להיכנס לממשק גרפי לעבודה איתו באמצעות לחיצה על כפתור Open במסך רשימת בסיסי הנתונים. מדביקים את הסיסמה, לוחצים Connect ואתם יכולים להתחיל להריץ שאילתות. ## יצירת מודל נתונים עבור מנויים לבלוג בשביל לשחק עם בסיס הנתונים אני אצור מודל נתונים לייצוג משתמשים שנרשמים לקבלת פוסטים במייל מהבלוג. זה אותו מודל שהשתמשתי בו בפוסט שכתבתי על Datomic אז אפשר גם לחזור לקרוא שם כדי להיזכר ולהשוות. בשביל לאפשר לאנשים להירשם לקבלת פוסטים מהבלוג למייל אני צריך לשמור את פרטי המייל של מי שנרשם, אני צריך לשמור פוסטים ובגלל שאולי לא כל הפוסטים מעניינים את כולם אני רוצה לסדר את הפוסטים לקטגוריות ולאפשר לאנשים להירשם רק לקטגוריות מסוימות. במודל גרפי נוכל להגיד שהצמתים בגרף יהיו: 1. מנוי - שיחזיק מזהה משתמש, כתובת מייל עדכנית ואולי מידע נוסף שמעניין אותי לגבי המנוי. 2. קטגוריה - שתחזיק את שם הקטגוריה. 3. פוסט - שיחזיק את הפרטים לגבי הפוסט כמו הכותרת, התוכן ומתי פורסם. 4. דיוור - כדי לשלוח מייל למנויים אני ארצה לזכור מה שלחתי למי ואם היו בעיות בשליחה. מבחינת הקשרים (הקשתות) בין הצמתים נוכל לדבר על: 1. מנוי יכול להיות "רשום ל" קטגוריה, כדי לקבל למייל פוסטים מקטגוריה מסוימת. 2. פוסט יכול להיות "שייך ל" קטגוריה. 3. דיוור "נשלח" למנוי באימייל. 4. דיוור "כולל" פוסט או אוסף של פוסטים. הפקודה MERGE ב neo4j יוצרת פריטים חדשים. בואו ניצור כמה פריטים לסכימה שתיארתי. תחילה אני יוצר פוסט עם מאפיין slug (זה השם שמופיע ב url), title עבור שורת הכותרת ו publishedAt עם תאריך ושעת הפירסום:
MERGE (:Post {slug: "first", title: "first post", publishedAt: datetime('2023-01-24T06:00:00')})
ועוד כמה פוסטים בשביל שיהיה מעניין:
MERGE (:Post {slug: "second", title: "second post", publishedAt: datetime('2023-01-25T06:00:00')})

MERGE (:Post {slug: "hello-neo4j", title: "Hello World in Neo4j", publishedAt: datetime('2023-04-02T06:00:00')})
עכשיו אפשר ליצור קטגוריות:
MERGE (:Category {name: "spam"})
MERGE (:Category {name: "neo4j"})
וכמה מנויים:

ToCode
1 420
# הזמן הכי טוב לקחת קורס מתי הזמן הכי טוב לקחת קורס על נושא שאתם צריכים לפרויקט? האם זה יהיה לפני תחילת העבודה, כדי להבין על מה מדובר ולהחליט את ההחלטות הנכונות כבר מהצעד הראשון? האם תוך כדי הפרויקט, כדי לא לבזבז זמן? או שאולי בכלל אחרי, כשיש לכם כבר הבנה מעשית של עולם התוכן ועכשיו צריך את התיאוריה כדי לשים את החלקים במקום? בפיתוח תוכנה - כל התשובות נכונות. לפני תחילת העבודה אנחנו צריכים מושג כללי של עולם התוכן, והוראות בסיסיות איך להתחיל. אבל אחרי שקיבלנו את הכלים הבסיסיים נרצה להתקדם ולחקור את הבעיה שלנו, לנסות לכתוב קוד, להיכשל ולראות מה עובד ומה לא. נכון שהרבה פעמים אפשר להסתדר לבד בשלב הזה עם Tutorials ו Stack Overflow, כשלא מבינים כלום עלולים לעשות טעויות שאחרי זה יהיה קשה לראות ולתקן. אחרי שנצליח להפעיל כמה דברים ונישאר אבודים לגבי כמה דברים אחרים, נוכל להמשיך ללמוד בצורה מסודרת תוך כדי המשך עבודה. ההבנה הבסיסית שקיבלנו תקבל חיזוק מעבודה על פרויקט שמעניין אותנו, ובמהלך הצפיה בשיעורים נוכל לחשוב איך דברים מתחברים - גם בתרגילים וגם בפרויקט האישי שאנחנו בונים. וכשהפרויקט באוויר? זה הזמן הכי מהנה לקחת קורס, כי כבר לא צריך לדאוג אם נצליח ליישם את השיעור על הפרויקט שלנו, כי אנחנו כבר יודעים את הסוף וכי זה יהיה הזמן להתעמק בכל פרק, לקרוא את תכני ההעשרה ולהבין יותר טוב מה עשינו, מה עבד ומה עוד אפשר לשפר. ממילא פרויקט תוכנה אף פעם לא "גמור", וידע טוב יותר יעזור לבנות גירסה 2 יעילה יותר. אי אפשר (ואנחנו גם לא רוצים) לברוח מבניית פרויקטים בטכנולוגיות שאנחנו לא מכירים ומשילוב לימוד תוך כדי עבודה. וכשהקורס מלווה אותנו בכל שלבי העבודה הוא מפסיק להיות "מטלה" והופך למשהו שכיף לחזור אליו.

ToCode
1 420
# תחליטי עכשיו! פותח פרויקט ריילס חדש, ומיד מיליון שאלות: רוצה import maps או webpack (או אולי בכלל parcel)? איך לנהל משתמשים? באיזה ספריית בדיקות להשתמש? מה ה Database? האם זו מערכת מלאה שכוללת HTML או שמספיק רק API? איזה כללי Style לשים ב Rubocop? רוצה להשתמש ב tailwind או לכתוב CSS רגיל? ואני לא מאשים את ריילס פה. המצב דומה בכל סטאק טכנולוגי שתבחרו, ואפילו במקום שיש ברירות מחדל סבירות ככל שמתקדמים בפרויקט תמיד יהיה יותר קשה לשנות החלטות שקיבלת בהתחלה. ואין דבר יותר ממכר מלהתלבט על בחירות טכנולוגיות בתחילת הדרך. וכמובן כל השאלות חשובות וכל תשובה לא נכונה תחזור לנקום בנו בעתיד. בדוגמה של CSS עבודה ללא תכנון ובלי לבחור סטנדרט מההתחלה עלולה להביא אתכם למצב שה CSS יצא משליטה ותצטרכו לשכתב את כל קבצי ה CSS למבנה חדש ומסודר. ואותו דבר לגבי כל החלטה טכנולוגית אחרת במוצר. ברור שעדיף בהרבה להחליט את ההחלטות הטובות ביותר בתחילת הדרך. טוב יותר אבל לא ממש ריאלי, כי אנחנו עוד לא יודעים מספיק על המוצר. לכן הפיתרון הוא בדיוק הפוך. במקום "תחליטי עכשיו" נגיד "תתחילי עכשיו". כן זה יהיה מבאס לשנות את כל ה CSS בעוד שנה כשיהיה לך מוצר בפרודקשן עם משתמשים אמיתיים, אבל לפחות יהיה לך מוצר בפרודקשן עם משתמשים אמיתיים. (ולא, אני לא חושב שצריך להתחיל לעבוד בלי לדעת מה אנחנו עושים. חשוב לבדוק דברים ולהתאים בחירות טכניות למוצר, אבל זה תהליך שחייבים לתחום אותו בזמן, ולא משנה כמה זמן יש לכם בסוף תצטרכו לחיות עם זה שחלק מהבחירות הטכנולוגיות יהיו שגויות).

ToCode
1 420
# שבעה אתרים יותר טובים מ ynet בשביל הבריאות הנפשית שלכם אין דבר שמשפיע על המח יותר מהסביבה שלנו, והיום הסביבה הזאת היא ברובה וירטואלית. בכל זאת וכנראה בגלל שכל כך קל לקפוץ לאתר רק לבדוק מה חדש, אנחנו שוכחים את המחיר של כל "קפיצה" כזו ואת ההשפעה המצטברת של אותם ביקורים. הנה כמה אתרים שאני אוהב לבקר ברגעים מתים, עם השפעה מצטברת חיובית: 1. Product Hunt{https://www.producthunt.com) - מרכז השקות של מוצרים ותמיד מעניין לראות מה אנשים אחרים בונים 2. r/programming - חדשות מעניינות על פיתוח תוכנה 3. Hacker News - עוד אתר חדשות מעולה עם עיצוב בסיסי ודיונים ששווים זהב 4. Indie Hackers - פורום ולוח מודעות לסטארטאפים קטנים 5. פלאנט תוכנה חופשית בישראל - אגרגטור שמרכז פוסטים מהמון בלוגים ישראלים על תוכנה חופשית וקוד פתוח 6. Cybersecurity Dive - חדשות ומאמרים קצרים על אבטחת מידע, לא טכני מדי ולא שיווקי מדי 7. Geektime - ואי אפשר בלי גיקטיים שמלווה כבר שנים את התעשיה בארץ ואם יום אחד יהיה לי זמן ללמוד לכתוב תוספים לדפדפן, כנראה שהתוסף הראשון שאכתוב פשוט יזהה כניסה לדפים "בעייתיים" (אתרי חדשות, פייסבוק וכו) וינתב באקראי לאתר מעניין יותר מתוך רשימה.

ToCode
1 420
# הקפיצה הבאה של ריאקט "אם אתם רוצים לבנות אפליקציה או אתר חדש בריאקט, אנחנו ממליצים להשתמש בפריימוורק". כך מתחיל דף המידע איך להתחיל פרויקט ריאקט חדש בתיעוד החדש של ריאקט. התחלה זו מסכמת דיון ארוך על create-react-app שתקופה ארוכה לא תוחזק ואינו מומלץ יותר לשימוש. לקח לי הרבה זמן לתת ל create-react-app הזדמנות. תקופה ארוכה שהכלי הזה נראה לי כמו "קיצור דרך" שלא באמת מתאים לפרויקטים אמיתיים, בגלל שהוא משלב אינסוף ספריות מובנות והגדרות. כשאתה משתמש ב create-react-app אתה בעצם מקבל ערימה של יכולות שאתה לא צריך, ואותן יכולות יוצרות ערימה של אילוצים שאולי לא היית בוחר בהם. ולקח רק 7 שנים לבועה הזאת להתפוצץ. רשימת ההמלצות שהיום מופיעה באותו דף תיעוד מספרת לנו על הכיוון העתידי של ריאקט. היא כוללת את Next.JS, Remix ו Gatsby לפרויקטי ווב, Expo לפרויקטי ריאקט נייטיב ובאותיות קטנות בתוך אקורדיון סגור בפינה מתחבאת האופציה של vite כדי להשתמש בריאקט בלי פריימוורק. הפיצ'ר הגדול שעובדים עליו בריאקט היום נקרא React Server Components, והוא אמור לאפשר לקוד ריאקט להסתנכרן בין חלקים שרצים בצד השרת לחלקים שרצים בצד הקלאיינט. בצד של האיחסון יישומי ה Full Stack האלה יכולים לרוץ על התשתית של AWS, Netlify, Vercel ועוד באמצעות התקנה מהירה בלחיצת כפתור ובחינם - מה שמזכיר לי לפחות ימים מאושרים ב PHP. האם המטוטלת משנה כיוון? האם בקרוב נראה את הסוף של יישומי עמוד-יחיד בצד הלקוח שמתממשקים ל API שנבנה עצמאית? עדיין מוקדם להגיד. העתיד נראה מעניין.

ToCode
1 420
# הקפיצה הבאה של ריאקט "אם אתם רוצים לבנות אפליקציה או אתר חדש בריאקט, אנחנו ממליצים להשתמש בפריימוורק". כך מתחיל דף המידע איך להתחיל פרויקט ריאקט חדש בתיעוד החדש של ריאקט. התחלה זו מסכמת דיון ארוך על create-react-app שתקופה ארוכה לא תוחזק ואינו מומלץ יותר לשימוש. לקח לי הרבה זמן לתת ל create-react-app הזדמנות. תקופה ארוכה שהכלי הזה נראה לי כמו "קיצור דרך" שלא באמת מתאים לפרויקטים אמיתיים, בגלל שהוא משלב אינסוף ספריות מובנות והגדרות. כשאתה משתמש ב create-react-app אתה בעצם מקבל ערימה של יכולות שאתה לא צריך, ואותן יכולות יוצרות ערימה של אילוצים שאולי לא היית בוחר בהם. ולקח רק 7 שנים לבועה הזאת להתפוצץ. רשימת ההמלצות שהיום מופיעה באותו דף תיעוד מספרת לנו על הכיוון העתידי של ריאקט. היא כוללת את Next.JS, Remix ו Gatsby לפרויקטי ווב, Expo לפרויקטי ריאקט נייטיב ובאותיות קטנות בתוך אקורדיון סגור בפינה מתחבאת האופציה של vite כדי להשתמש בריאקט בלי פריימוורק. הפיצ'ר הגדול שעובדים עליו בריאקט היום נקרא React Server Components, והוא אמור לאפשר לקוד ריאקט להסתנכרן בין חלקים שרצים בצד השרת לחלקים שרצים בצד הקלאיינט. בצד של האיחסון יישומי ה Full Stack האלה יכולים לרוץ על התשתית של AWS, Netlify, Vercel ועוד באמצעות התקנה מהירה בלחיצת כפתור ובחינם - מה שמזכיר לי לפחות ימים מאושרים ב PHP. האם המטוטלת משנה כיוון? האם בקרוב נראה את הסוף של יישומי עמוד-יחיד בצד הלקוח שמתממשקים ל API שנבנה עצמאית? עדיין מוקדם להגיד. העתיד נראה מעניין.

ToCode
1 420
# להילחם ב Complexity או להכיל אותה כל פרויקט מתחיל בעולם שנקרא "שדה ירוק" - אין עדיין קוד ולכן אין עדיין אילוצים. אין מידע ב DB ולכן אין בעיה להחליט על מבנה הטבלאות. אפשר לבחור את הגירסאות החדשות ביותר של כל הספריות וכלי הפיתוח ולא צריך להתחשב בקוד קיים שמסתמך על גירסה מסוימת ישנה יותר. החיים הטובים. אבל כמובן שעם הזמן והקוד הנוסף שנכתב מתחילים האילוצים והם מכניסים מורכבות למערכת. לקוחות קיימים רוצים לשמר פונקציונאליות ישנה ולא מאפשרים לך לשדרג, נתונים שכבר שמורים בבסיס הנתונים דורשים תהליך המרה מסובך, ולאט לאט עם כל מקרה קצה נוסף שאנחנו צריכים לטפל בו הפונקציות מתארכות והיופי של הקוד מתחיל לדהות. יש שתי גישות להתמודד עם התהליך הבלתי נמנע הזה- 1. אפשר להילחם ב Complexity - לשמור על מודולים קטנים, לשכתב בקיצוניות קוד ברגע שמתחיל להיות מסורבל, הביטוי Move fast and break things מתאר סוג כזה של פיתוח. 2. אפשר להכיל את ה Complexity - לבנות ארכיטקטורות Object Oriented מורכבות, להשתמש ב Type System, לכתוב בדיקות, ללמוד לחיות עם זה שלעולם לא תצליח להבין כל פרט בקוד, ללמוד להשתמש ב Debugger, לכתוב המון תיעוד ו wikis ואפילו להיעזר ב AI כדי לקבל תשובות על הקוד. אני לא פה בשביל להכריע בויכוח הזה. אם אתם כותבים קוד יותר משנה כנראה שיש לכם דעה נחרצת איך פיתוח צריך להיראות ומה עושים עם ה Complexity שנוצר. זה בסדר, כל עוד אתם מסונכרנים על הגישה עם האנשים שעובדים אתכם, כי לנסות לעשות את שני הדברים ביחד יכול להיות מאוד מתסכל.

ToCode
1 420
# עדכון מפתח ה RSA של גיטהאב אם ניסיתם למשוך או לדחוף קוד לגיטהאב בימים האחרונים יש סיכוי שנתקלתם בהודעה בסגנון הזה:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s.
Please contact your system administrator.
Add correct host key in /Users/ynonp/.ssh/known_hosts to get rid of this message.
Offending RSA key in /Users/ynonp/.ssh/known_hosts:13
Host key for github.com has changed and you have requested strict checking.
Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
בואו נראה מה קרה ואיך מתקנים ## מה זה מפתח RSA בשביל שנוכל לדבר בביטחה עם גיטהאב אנחנו משתמשים בטכנולוגיית הצפנה אסימטרית. בשיטה כזאת השרת של גיטהאב מייצר שני ערכים שיש קשר ביניהם. אפשר לחשוב על זה כמו "סינדרלה" ו"נעל הזכוכית" שלה באגדה. אם הנסיך מגיע עם נעל הזכוכית לרגל של סינדרלה הוא ידע שזו אהבת חייו, אבל כל רגל אחרת לא תיכנס לנעל. בפעם הראשונה שאנחנו מתחברים לגיטהאב בפרוטוקול גיט המחשב שלנו שומר את החלק "הציבורי" של המפתח, או את נעל הזכוכית בקובץ (ביוניקס זה קובץ שנקרא ~/.ssh/known_hosts). בפעם הבאה שננסה להתחבר המחשב מתחיל את החיבור באימות זהות של גיטהאב - האם הרגל עדיין מתאימה לנעל הזכוכית ששמורה אצלי בקובץ. אם כן הכל טוב, אם לא עוצרים הכל ומציגים שגיאה. יש מספר שיטות להצפנה אסימטרית ו RSA היא אחת מהן. ההבדל בין השיטות הוא המתמטיקה שמאחוריהן ושווה לקרוא על זה בהרחבה בויקיפדיה בערך מפתח ציבורי ## מה קרה בגיטהאב גיטהאב גילו שבטעות אחד המפתחים שלהם העלה את החלק הפרטי של המפתח - הרגל של סינדרלה באנלוגיה - למאגר קוד ציבורי. התוצאה היתה שלכל אחד בעולם היתה גישה לפרק זמן קצר למפתח זה, ואנחנו לא יכולים לדעת אם מישהו לא לקח את המפתח. לקיחת המפתח הפרטי היא בעייתית כיוון שהיא מאפשרת לייצר "התאמות" מזויפות. יום אחד מישהו יוכל להקים שרת שמתחזה לשרת גיטהאב, והמחשב שלנו ישלח אליו את הקוד אפילו שזה לא גיטהאב האמיתי. לכן החליטו בגיטהאב לא לקחת סיכונים והחליפו מיד את המפתח הפרטי, מה שגרם להחלפה אוטומטית גם של המפתח הציבורי. בעצם החלפנו לסינדרלה את הרגל וכמובן גם את הנעל. ## למה ואיך העדכון משפיע עליי? אם השתמשתם במפתחות RSA כדי לדחוף ולמשוך קוד מגיטהאב, וכבר יצרתם בעבר קשר עם גיטהאב כך שהמפתח הציבורי שלו שמור אצלכם על המחשב, אז ניסיון לדחוף או למשוך קוד יוביל לשגיאה צפויה: ברור שהנעל לא מתאימה לרגל החדשה של סינדרלה, הרי הרגל הוחלפה וגם הנעל. אנחנו צריכים לעדכן את המפתח הציבורי ששמור אצלנו במחשב כדי שיתאים למפתחות החדשים של גיטהאב. בשביל זה עלינו למחוק את המפתח הקיים של גיטהאב עם הפקודה:
$ ssh-keygen -R github.com
או למחוק את השורה מהקובץ known_hosts. לאחר מכן אפשר להשתמש בפקודה הבאה כדי להוסיף את המפתח החדש לסוף קובץ ה known_hosts:
curl -L https://api.github.com/meta | jq -r '.ssh_keys | .[]' | sed -e 's/^/github.com /' >> ~/.ssh/known_hosts
פרטים מלאים על השינוי תוכלו למצוא בהודעה של גיטהאב בקישור: https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/