ToCode
Ir al canal en Telegram
1 419
Suscriptores
Sin datos24 horas
-17 días
+230 días
Archivo de publicaciones
1 419
בנוסף ה API של testing-library נועד לעזור לנו המתכנתים לבנות קוד טוב יותר - לדוגמה מתכנת יצטרך מאוד להתאמץ כדי לתפוס אלמנט לפי CSS Selector, והרבה יותר קל ומובנה להסתכל שם על אלמנטים לפי Aria Role. המטרה היא כמובן לעודד מתכנתים להטמיע Aria Roles במקומות הנכונים ובאופן כללי לעבוד בצורה נגישה.
## מה רע ב Cypress
סייפרס מפעיל דפדפן חיצוני ולכן זמן העליה שלו ארוך יותר. במשחקים שלי איתו הוא גם נתקע לעתים יותר קרובות והייתי צריך לסגור את ה GUI ולפתוח מחדש.
ה API של סייפרס מבוסס על jQuery וגם זה מרגיש קצת מיושן היום.
## מה רע ב Testing Library
ספריות testing-library נועדו לבדוק קומפוננטה ספציפית ולעזור למתכנתים לכתוב קוד טוב יותר לאותה קומפוננטה. אם אתם בודקים קוד שלכם זה יכול להיות מאוד נוח, אבל אם בודקים קוד שאין לכם שליטה עליו או שצריכים לכתוב בדיקת אינטגרציה שמשלבת מספר קומפוננטות אז testing-library מתחיל להיראות מסורבל.
הממשק של testing-library מאוד נוח כשצריך לבדוק קומפוננטה שכתובה טוב ומתנהגת כמו שצריך, אבל אין לו הרבה סבלנות לקוד גרוע.
גם יכולת ה Debugging של testing-library הוא בעייתית. יש טענות שאפשר לחבר אותו ל VS Code ולהשתמש בדיבגר המובנה שלהם, אבל אני לא הצלחתי לגרום לזה לעבוד.
## אז במה לבחור?
האמ;לק שלנו להיום הוא פשוט:
1. אם אתם צריכים לבדוק קומפוננטה ספציפית שאתם כותבים ורוצים ספריית בדיקות שתעודד אתכם לכתוב את הקוד שלה כמה שיותר נקי - לכו על testing-library ו Jest.
2. אם אתם צריכים לבדוק אינטגרציה בין כמה קומפוננטות או קומפוננטה מסובכת שאין לכם דרך קלה לשנות את ה Markup שלה - לכו על Cypress.
בכל מקרה שווה לשחק עם שני הכלים. אף פעם אי אפשר לדעת מראש איזה כלי יזרום יותר טוב עבורכם, עבור הצוות שלכם ועבור הפרויקט שלכם.
1 419
# השוואה זריזה בין Cypress ל testing-library
סייפרס הוא ספריית בדיקות ה End-to-end האהובה ביותר על מתכנתי Front End היום ו testing-library היא ספריית ה Unit Test המובילה. הנה סיכום קצר של ההבדלים בין שני הדברים ובסוף המלצה במה כדאי להשתמש.
## מה זה Cypress
סייפרס היא ספריית בדיקות שמטרתה להחליף את Selenium בתור ספריית בדיקות ה End To End המובילה והנוחה בעולם. זו בעצם תוכנה שרצה אצלכם על המחשב ומפעילה דפדפן בצורה מסוימת כך שהיא תוכל לשלוט בדפדפן דרך סקריפטים.
תוכנית בדיקה ב Cypress היא תוכנית JavaScript שרצה בתוך סייפרס ונותנת הוראות לדפדפן באמצעות API שסייפרס פיתחו. תוכנית לדוגמה נראית כך:
describe('My First Test', () => {
it('clicking "type" navigates to a new url', () => {
cy.visit('https://example.cypress.io')
cy.contains('type').click()
// Should be on a new URL which includes '/commands/actions'
cy.url().should('include', '/commands/actions')
})
})
כתיב ה describe/it צריך להיות מוכר גם מפריימוורקים אחרים. תוכן ה it הוא הבדיקה עצמה. המשתנה המיוחד cy מגיע מסייפרס והוא אוביקט החיבור שלנו ל API של הסביבה: בעזרתו נגרום לדפדפן לבקר באתר מסוים (עם הפקודה visit), למשוך DOM Element מסוים עם הפקודה get, ללחוץ על אותו אלמנט עם הפקודה click ולהסתכל על ה URL של העמוד.
הבדיקה בדוגמה אגב מחפשת אלמנט עם הטקסט type, לוחצת עליו ואז מוודאת שה URL החדש של העמוד מכיל את הטקסט /commands/actions.
מה שחשוב לראות כאן הוא שהבדיקה בסייפרס רצה בתוך דפדפן חיצוני שיכול להתחבר לכל אתר שנרצה - ובזה הוא מאוד דומה לסלניום.
## מה זה Testing Library
טסטינג לייבררי הוא אוסף של ספריות בדיקה ל Components Based Frameworks. יש לנו react-testing-library לריאקט, vue-testing-library ל Vue, וגם angular-testing-library, reason-testing-library, svelte-testing-library ורבות נוספות.
ספריות אלה עובדות בשיתוף פעולה עם כלי הרצת בדיקות כמו jest או mocha, ומאפשרות לקוד הבדיקה לתקשר עם קוד הפריימוורק. הן כוללות פונקציות כדי לרנדר קומפוננטה מסוימת לסביבת בדיקה, לגשת ל DOM Elements שאותה קומפוננטה יצרה, לשלוח אירועים לאותה קומפוננטה וכך הלאה.
במילים אחרות testing-library היא ספריה שאחראית רק על הקוד של הבדיקה עצמה, ולא על המנגנון שמריץ את הבדיקה. היא תמיד צריכה לעבוד בשילוב עם כלי הרצת בדיקות. ואגב שני ואריאנטים מעניינים של testing-library הם cypress-testing-library ו webdriverio-testing-library שמאפשרים להריץ את הבדיקות בסגנון testing-library בתוך כלי הרצת בדיקות cypress או selenium.
קוד בדיקה של react-testing-library לדוגמה נראה כך:
test('loads and displays greeting', async () => {
render(<Fetch url="/greeting" />)
fireEvent.click(screen.getByText('Load Greeting'))
await waitFor(() => screen.getByRole('heading'))
expect(screen.getByRole('heading')).toHaveTextContent('hello there')
expect(screen.getByRole('button')).toBeDisabled()
})
## מה טוב ב Cypress
מתכנתים אוהבים את סייפרס כי מאוד קל להתקין אותו, הוא עובד על כל מערכת הפעלה, לא צריך להוריד קובץ דרייבר מיוחד כמו בסלניום (ואז להוריד חדש כשיוצאת גירסה חדשה של הדפדפן), וקוד הבדיקה יחסית אינטואיטיבי.
יותר מזה, ה GUI של סייפרס מעולה ומראה לנו את כל השלבים של הבדיקה עם אפשרות לחזור אחורה בזמן לכל שלב - וכל זה ליד הדפדפן שמריץ בפועל את הבדיקה. אפשר לשים נקודת עצירה איפה שרוצים לאורך הבדיקה ולהמשיך בדיקה דרך ה console של הדפדפן, וככה זה מאוד נוח למצוא בעיות.
לסייפרס יש גם מנגנון של שיתוף הבדיקות עם אנשים אחרים ואז אתם יכולים לכתוב בדיקות ואנשי צוות אחרים, אנשי פרודקט או אפילו הלקוח יכולים להריץ את הבדיקות ולראות את ההתנהגות האוטומטית.
לסייפרס יש גם אינטגרציה עם Front End Frameworks וככה אתם יכולים להריץ בדיקה רק על קומפוננטת ריאקט ספציפית לדוגמה במקום לרוץ על כל העמוד.
## מה טוב ב Testing Library
הווריאנטים הפופולרים של testing-library משתמשים ב jest כדי להריץ את הבדיקות. ג'סט הוא כלי הרצה שמדלג לגמרי על הדפדפן ומריץ את הבדיקה בתוך Node.JS. היתרון של ג'סט בתור סביבת הרצת בדיקות הוא המהירות: בגלל שלא צריך דפדפן הבדיקה רצה הרבה יותר מהר.1 419
# ואם היית חושב שזה אפשרי?
ואם היית חושב שזה אפשרי, האם היית מוותר על שעה בפייסבוק כל יום בשביל להתקדם בפרויקט הזה?
ואם היית חושב שזה חשוב, היית מסכים לקום שעה קודם כל יום בשביל לעבוד על זה?
ואם היית מבין שזאת ההזדמנות האחרונה, האם היית מוצא דרך לפנות שעה ביום בשביל לבנות את זה?
כולנו עברנו שטיפת מוח קולקטיבית. לימדו אותנו שזה לא אפשרי, שזה לא חשוב ושתמיד יהיה זמן יותר טוב. שקודם כל צריך להתמקד במה שאפשר למדוד ושחלומות יכולים לחכות לזמן שבו הכל יהיה מסודר (כלומר לעולם לא). הדבר הזה שרצית לבנות או ללמוד? אתה יכול להצליח בו; ההצלחה שלו יותר חשובה מרוב הדברים שאתה עושה עכשיו וההזדמנות שיש לך עכשיו לא תחזור. עכשיו הזמן להתחיל.
1 419
אחרי ששיכנענו את המחשב לוותר על Modern Standby ולחזור להשתמש במצב שינה קלאסי נשארה רק בעיה אחת - זה לא עבד. לפחות אצלי על המכונה. מה שקרה שעכשיו בחלק מהפעמים שהמחשב נכנס למצב שינה הוא התרסק מיד בכניסה למצב שינה וכשניסיתי להעיר אותו גיליתי מחשב תקוע. בחיפוש באינטרנט הדבר היחיד שהצלחתי למצוא היה אנשים שמקטרים על משהו שנקרא BSOD, ואחרי עוד חיפושים למדתי שזה ראשי תיבות של Blue Screen Of Death שזאת הדרך של אנשים לדבר על התרסקויות של Windows (למרות שבהתרסקות הספציפית אצלי לא היה שום מסך כחול כי זה היה בכניסה למצב שינה).
הפיתרון בכל מקרה היה להיכנס ל Event Viewer ושם למצוא את ההודעה על אותה התרסקות. ההודעה היתה מסוג Bugcheck ולוותה בטקסט הסבר קצר שאומר שמצב הזיכרון שגרם להתרסקות נשמר בקובץ
C:\Windows\memory.dmp. את הקובץ הזה אפשר לפתוח באמצעות תוכנה בשם windbg שאותה אפשר להוריד מכאן:
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools
פתיחה של הקובץ העבירה אותי להודעת השגיאה האמיתית שהובילה להתרסקות. ההודעה הגיעה מדרייבר של דל שאחראי למרבה האירוניה על ניטור תקלות במחשב. ביטול של הדרייבר גרם למחשב להפסיק להתרסק ולמצב שינה להתחיל לעבוד.1 419
# מצב שינה בחלונות: קצת יותר ממה שרציתם לדעת
מצב שינה הוא מהפיצ'רים הכי משעממים שיש במחשב. כל מה שאתה רוצה זה שהוא יעבוד כמו שצריך, כלומר שכשהמחשב לא מחובר לחשמל ואני לא עובד איתו שגם לא יבזבז סוללה. מפה מתכנתים מתחילים לגזור כל מיני תנאים כמו:
1. אם הלפטופ עובד על סוללה וסוגרים את הכיסוי יש להקפיא יישומים שלוקחים הרבה סוללה.
2. אם משתמש לא נגע בלפטופ כמה דקות והוא לא מחובר לחשמל כדאי לסגור את חיבורי הרשת.
3. אם המחשב לא בשימוש אפשר לסגור את התצוגה.
ועוד אינסוף דברים קטנים שיחד מרכיבים את הפיצ'ר שנקרא מצב שינה. ב Windows הפיצ'ר הזה עבד לי מספיק גרוע כדי שאצטרך לחקור אותו ולנסות לתקן, אלה הדברים שגיליתי:
## מצבי שינה קלאסיים: S1, S2, S3
מהר מאוד מתכנני מערכות הפעלה הבינו שכדאי שיהיה "מצב עבודה" מיוחד שיצרוך פחות סוללה. אנחנו קוראים לזה מצב שינה, ולמעשה יש מספר מצבים שמסמנים מספר דרגות של חיסכון בחשמל. מצבי השינה מסומנים ב S ואחריו מספר, וככל שהמספר יותר גבוה כך המצב יותר חוסך בסוללה. כך מצב שינה S3 הוא יותר חסכוני ממצב S2, והוא יותר חסכוני ממצב S1.
בשביל לגלות איזה מצבי שינה נתמכים במערכת שלכם אתם יכולים לכתוב מ cmd:
powercfg /a
בדרך כלל לוקח למחשב מספר שניות לצאת ממצב שינה, והטרייד אוף כאן הוא שככל שאנחנו מכבים יותר רכיבים בכניסה למצב שינה וכך חוסכים יותר בחשמל, כך ייקח יותר זמן לכל המחשב להתעורר.
## מצב שנת חורף (Hibernation)
מצב השינה הרביעי מסומן ב S4 וקיבל את הכינוי המיוחד Hibernation. בשלושת מצבי השינה הרגילים המחשב ממשיך לספק חשמל לזיכרון ולכן כל מצב המערכת נשמר שם. במצב S4 המחשב סוגר את החשמל גם לרכיבי הזיכרון. כדי להתעורר ממצב S4 המחשב כותב קובץ מיוחד לדיסק לפני הכניסה למצב זה והיציאה ממצב Hibernation היא כמעט כמו הדלקה מחדש של המחשב - רק שבמקום לחזור למצב זיכרון "נקי" מערכת ההפעלה קוראת את הקובץ ומאתחלת את ה State ממנו.
במצב שנת חורף החיסכון בחיי סוללה הוא הגדול ביותר, אבל גם זמן ההתעוררות ממצב זה הוא הארוך ביותר.
## מצב Fast Startup
אחרי שאנחנו מבינים מה זה Hibernation קל להבין עוד הגדרה שמופיעה בהרבה מסכי ניהול צריכת חשמל ונקראת Fast Startup. הרעיון פה הוא שאפשר להשתמש ב Hibernation כדי לקצר את זמן ההדלקה של המחשב אחרי כיבוי: במקום לכבות לגמרי את המחשב ה Windows בסך הכל סוגר את כל היישומים ומנתק את המשתמש הנוכחי, ואז נכנס ל Hibernation. ההדלקה הבאה כבר לא תהיה הדלקה מאפס אלא רק יציאה מ Hibernation ולכן תהיה מהירה יותר.
החיסרון היחיד של הפיצ'ר הזה הוא שיש דברים ש Windows עושה רק בהדלקה מחדש - למשל התקנת עידכונים. אם אתם עובדים קבוע עם Fast Startup ותמיד מכבים את המחשב אז לא תהיה לו הזדמנות להתקין את העדכונים. אני לא חושב שזה מצב ריאלי כי Windows ממילא דורש ממני לעשות Restart משהו כמו 3 פעמים בשעה ו Restart אינו מושפע ממצב זה.
## מצב שינה מודרני S0
במחשבים חדשים (למשל אצלי ב Dell XPS13) מייקרוסופט הוסיפה מצב שינה חדש שנקרא Modern Standby. החלום שלהם היה ליצור חוויה כמו של טלפון, כך שההדלקה של המחשב אחרי שינה תהיה מיידית ובנוסף בתוך השינה המחשב עדיין יהיה מחובר לרשת ואפשר יהיה להתקין עדכונים בזמן שהמחשב ישן.
התוצאה היא ש Modern Standby לא חוסך בחשמל הרבה יותר מאשר כיבוי התצוגה. צריכת הסוללה במצב שינה זה (שהוא ברירת המחדל בהתקנת מערכת הפעלה) היא גבוהה ואחרי כמה שעות ללא טעינה הסוללה כבר תתרוקן לגמרי.
## איך להחזיר את מצב השינה הקלאסי במערכת Windows 10
אחרי שלמדתי הרבה יותר ממה שרציתי לדעת על מצבי שינה של מערכת ההפעלה הבנתי שאני מעדיף לוותר על Modern Standby, לחסוך את ההדלקה המיידית ולחזור למצבי השינה הקלאסיים כדי לחסוך בסוללה בזמן שהמחשב לא בשימוש.
ברמה הטכנית השינוי לא מופיע במסכי ההגדרות של חלונות. הצלחתי למצוא את הטריק ברדיט כאן:
https://www.reddit.com/r/Dell/comments/h0r56s/getting_back_s3_sleep_and_disabling_modern/
בקצרה מה שעושים זה להוסיף מפתח ל Registry באמצעות הרצת הפקודה:
reg add HKLM\System\CurrentControlSet\Control\Power /v PlatformAoAcOverride /t REG_DWORD /d 0
## מה עושים כשזה לא עובד1 419
# עבודה מיותרת / עבודה גרועה
עבודה מיותרת זה מה שקורה כשאת כותבת משהו שלא באמת היית צריכה. לדוגמה בכתיבת חנות דיגיטלית ללקוח, הלקוח יודע שהוא הולך לבצע עיסקאות רק דרך פייפאל אבל את מגדילה ראש וכותבת מנגנון גנרי כדי שיוכל מתי שהוא רוצה להחליף חברת סליקה.
עבודה גרועה קורית כשאת מתעקשת להשתמש בעבודה המיותרת שכתבת גם כשזה לא באינטרס של הלקוח. באותה חנות דיגיטלית, אם ללקוח יש מסך של רשימת עיסקאות שבוצעו הוא היה רוצה לראות ליד כל עיסקה את מזהה העיסקה כמו שמופיע בפייפאל כדי שאפשר יהיה לוודא פרטים של עיסקה מסוימת. לא להציג את המידע הזה רק בגלל שיש חברת סליקה אחרת (שלא משתמשים בה) שבעיסקאות דרכה המידע לא מתקבל זה להפוך עבודה מיותרת לעבודה גרועה.
רק בגלל שכתבת את המנגנון זה לא אומר שחייבים להשתמש בו.
1 419
# ה Power Shell הראשון שלי
החדשות הגדולות הן שהחלטתי לתת צ'אנס ל Windows אחרי שהתייאשתי מלמצוא פיתרון גיבוי טוב ללינוקס על הלפטופ. החדשות היותר קטנות הן שניצלתי את ההזדמנות ללמוד Power Shell - ואת המעט שהבנתי רציתי לשתף כאן בפוסט.
## מה הסקריפט עושה
אז הדבר הראשון שאתה עושה אחרי שאתה מתקין Windows זה להפעיל את WSL שזה הלינוקס שרץ בתוך ה Windows. יש מנגנון די מסובך שבסך הכל עובד לא רע, אבל הוא לא כולל עדיין תמיכה ביישומים גרפיים. הפיתרון המקובל הוא להרים שרת X ואז לעדכן את משתנה הסביבה DISPLAY כדי שהתוכנית תכתוב ל X שרץ בחלונות.
ופה אנחנו נכנסים ל Power Shell.
המשימה שלנו היא להריץ אימקס כדי שאפשר יהיה לכתוב פוסטים. בשביל זה צריך לגלות את כתובת ה IP של המחשב ואז להריץ את הפקודה:
> wsl.exe DISPLAY=<Windows IP Address>:0 emacs
## הקוד עצמו וקצת על Power Shell
נתחיל עם הסקריפט עצמו ששמור אצלי בקובץ בשם emacs.ps1:
$ip=Get-NetIPAddress -InterfaceAlias "vEthernet (WSL)" -AddressFamily IPv4|select -expand IPAddress
Invoke-Expression -Command "wsl DISPLAY=${ip}:0 emacs"
בסך הכל שתי שורות אבל מאוד עמוסות, הנה ההסבר (הלא בטוח מדויק) שלי מה זה עושה:
1. משתנים ב Power Shell מוגדרים באמצעות סימן $ ולכן השורה הראשונה מגדירה משתנה חדש בשם $ip
2. אפשר להשתמש בסימן = בשורה בשביל השמה. מתוך הרגל הצמדתי את הכל בלי רווח אבל זה יעבוד גם אם נשים רווחים מסביב לסימן השווה (טירוף).
3. הפקודות ב Power Shell מורכבות בדרך כלל משתי מילים עם מקף ביניהן, כשהמילה הראשונה מתארת מה רוצים לעשות והשניה מתוך איזה מודול או אוביקט. אז Get-NetIPAddress אומרת שאנחנו רוצים לקחת את הפרטים של התקן הרשת.
4. לפקודה יש אופציות שאנחנו מעבירים עם סימן - כמו שאנחנו מצפים, אבל אופציה הפעם הוא מילה שלמה ולא אות בודדת. האופציה InterfaceAlias אומרת איזה ממשק רשת אנחנו רוצים לקבל, והאופציה AddressFamily עוזרת לסנן איזה מהכתובות אנחנו רוצים.
5. סימן | עושה בדיוק מה שהייתם מצפים, ומעביר את התוצאה של הפקודה לפקודה הבאה בשורה. אבל - ופה הקסם - ב Power Shell כל התוצאות הן אוביקטים ולא סתם טקסטים, ולכן אנחנו צריכים פקודות מיוחדות שלהם כדי לקחת שדות מסוימים מתוך האוביקטים (או להדפיס אותם בצורה מסוימת או כל דבר בסגנון).
6. הפקודה select לוקחת שדה אחד מתוך האוביקט שקיבלה. האופציה expand מחזירה את התוכן של השדה עצמו בלי שם השדה.
7. השורה הבאה היא גם הפקודה הבאה - Invoke-Expression והיא פשוט מפעילה תוכנית שאנחנו מעבירים לה בתור מחרוזת. את הקריאה מהמשתנה אני מפריד משאר המחרוזת עם סוגריים מסולסלים כדי ש Power Shell לא יחשוב שהנקודותיים אפס הם חלק משם המשתנה או קשורים למשתנה באיזשהו אופן.
## איך מריצים סקריפט Power Shell
בניגוד ליוניקס, קובץ ps1 של Power Shell לא ניתן להפעלה רגילה מכל מיני סיבות אבטחה. במקום זה אנחנו צריכים ליצור Shortcut חדש שיכיל את ה Target הבא:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden -ExecutionPolicy Bypass -File C:\Users\ynonp\ps1\emacs.ps1
את הקיצור הזה כבר אפשר להפעיל באמצעות לחיצה כפולה על ה Shortcut, או אפילו יותר טוב אם תשימו אותו בתוך התיקיה:
C:\Users\<Your Username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\
אז הקיצור יתווסף לתפריט "התחל" ותוכלו למצוא ולהפעיל אותו דרך התפריט או דרך כל Launcher שיש לכם.1 419
# אזהרת טריגר
לכל תעשיה יש את הסודות המקצועיים שלה ואחד הסודות שהכי חשוב להכיר הוא הטריגרים. טריגר הוא דבר שאם תעשו אותו בחברה באופן אוטומטי אנשים יסתכלו עליכם מוזר או ירגישו שעשיתם משהו לא בסדר. פוליטיקאים יכולים להיות ממש גרועים בזה ואז מתחילה סערה ציבורית והפוליטיקאי לא מבין מה כולם רוצים ממנו. אבל הנקודה שטריגרים קיימים בכל חברה ובכל תרבות.
בתרבויות של מתכנתים יש המון טריגרים שיגרמו לאנשים להפסיק להקשיב לכם: לחלק מהאנשים זה שימוש בשפת תכנות מסוימת, עבור אחרים זה סגנון כתיבה או שימוש בספריה מסוימת, או הכי בולט הוא חוסר תשומת לב לפרט שכל האחרים מבינים שהוא חשוב.
אז לדוגמה אם אתם ניגשים למשרת תכנות PHP ואתם כותבים במשימת בית קוד עם בעיית אבטחה מסוג SQL Injection, יש הרבה מאוד אנשים שרק על השורה הזאת יפסלו אתכם מהמשרה - אפילו אם זו שורה בודדת בתרגיל של מאות שורות.
הטריגר הוא טעות שתמיד קל לתקן אותה ברגע שאנחנו מבינים שעשינו אותה, וזה בדיוק מה שהופך אותו לכל כך מרגיז.
בתהליך של ראיונות עבודה ובמיוחד בתקופה של ראיונות שלא מצליחים, חשוב לחפש את הדברים הקטנים שאתם אומרים או עושים שגורמים לאנשים להפסיק להקשיב לכם. את הטריגרים שאתם דורכים עליהם בלי לשים לב. כל אחד כזה שתצליחו לאסוף מראיון עבודה, גם אם נכשלתם בראיון, זה משהו ששווה לזכור ולשמור לכל החיים.
1 419
const [snakeData, setSnakeData] = useState(getSnakeData(snake));
const [appleData, setAppleData] = useState(getAppleData(apple));
useEffect(function() {
const clock = setInterval(function() {
tick();
setSnakeData(getSnakeData(snake));
setAppleData(getAppleData(apple));
}, 200);
return function() {
clearInterval(clock);
}
}, [])
return (
_.range(50).map(row => (
<div className="row" key={`row-${row}`}>
{
_.range(50).map(col => (
<div
className="col"
style={{ background: colorOf(row, col, snakeData, appleData)}}
key={`col-${row}-${col}`}
/>
))
}
</div>
))
)
}
הסטייט מאותחל דרך פונקציות ההעתקה שכתבנו קודם - ועובר ממידע חיצוני בקובץ הנחש למידע פנימי בפורמט שהקומפוננטה מכירה.
האפקט מפעיל את tick כל 200 מילי שניות ואחרי זה מחשב מחדש את הסטייט כדי שממשק המשתמש יראה את תוצאת החישוב.
ותוכן הקומפוננטה עצמו פשוט מצייר 50 שורות של 50 משבצות בשורה כדי שאפשר יהיה לצבוע אותן בכחול עבור הנחש או באדום עבור התפוח.
## שינוי כיוון עם החצים
אם תכתבו את הקוד עד עכשיו תקבלו נחש שהולך תמיד רק למטה. הסיבה היא שהכיוון של הנחש אף פעם לא משתנה. הוסיפו איפשהו בתוכנית את הקוד הבא שמטפל בשינוי כיוון הנחש לפי לחיצה על כפתורי החצים:
window.addEventListener('keydown', function(ev) {
if (ev.key === "ArrowDown") {
snake.direction = [1, 0];
}
if (ev.key === "ArrowUp") {
snake.direction = [-1, 0];
}
if (ev.key === "ArrowLeft") {
snake.direction = [0, -1];
}
if (ev.key === "ArrowRight") {
snake.direction = [0, 1];
}
});
ואנחנו מוכנים למשחק.
## עכשיו אתם
כמו ששמתם לב הפוסט מורכב מקטעי קוד והסברים עליהם בלי תוכנית מלאה ובלי קישור לאיזה קודסנדבוקס. הפעם אני רוצה להעביר את הכדור (או התפוח) אליכם ולהציע לכם לקחת את קטעי הקוד ולנסות לחבר אותם בעצמכם למשחק סנייק שעובד אצלכם על המכונה. שימו לב שתצטרכו לכתוב את ה CSS המתאים כדי שלוח המשחק גם יראה כמו לוח.
אחרי שתסיימו תוכלו להשתולל - להוסיף עוד תפוחים או פירות אחרים, להוסיף עוד נחש כדי לאפשר משחק בשני שחקנים (או עוד 5 נחשים ל-5 שחקנים) ואפילו לאפשר לאנשים לשחק עם חברים ברשת.
נ.ב. ביום חמישי הקרוב אני מעביר כאן וובינר על בדיקות יישומי ריאקט ושם אראה לכם איך לבדוק את משחק הסנייק הזה, ותוכניות ריאקט באופן כללי. מוזמנים לקפוץ להגיד שלום. הרשמה בקישור: https://www.tocode.co.il/workshops/108.1 419
# סקיצה לפיתוח משחק Snake ב React
ריאקט הוא קודם כל פריימוורק לפיתוח ממשקים גרפיים, וידוע שאין ממשק גרפי יותר מעניין ממשחק סנייק. אם יש לכם חצי שעה פנויה מוזמנים לבנות איתי משחק סנייק בריאקט כדי ללמוד יותר לעומק על החיבור בין ריאקט לקוד חיצוני.
## הקוד החיצוני
מה שיפה במשחק סנייק זה שמאוד קל לראות ולבנות את הלוגיקה שלו: בגירסה הבסיסית של המשחק יש בסך הכל נחש אחד שצריך לתפוס תפוח אחד. בלי ריאקט אני יכול לכתוב את הלוגיקה של המשחק בפחות מ 50 שורות:
1. הנחש שומר את המיקום והכיוון שלו
2. התפוח שומר את המיקום שלו
3. כל X זמן הנחש מתקדם צעד אחד: אם הוא פגע בתפוח הוא גדל, ואם הוא פגע בעצמו מתחילים מהתחלה.
מוזמנים לנסות לכתוב את הקוד בעצמכם. זה מה שיצא לי ושמרתי בקובץ בשם
game/snake.js:
import _ from 'lodash';
function restart() {
snake.size = 4;
snake.pos = [[0, 0]];
snake.direction = [1, 0];
apple.pos = [_.random(-25, 25), _.random(-25, 25)];
}
export const snake = {
pos: [[0, 0]],
size: 4,
direction: [1, 0],
}
export const apple = {
pos: [_.random(-25, 25), _.random(-25, 25)]
}
function collides(pos1, pos2) {
return pos1[0] === pos2[0] && pos1[1] === pos2[1];
}
export function tick() {
if (collides(snake.pos[0], apple.pos)) {
snake.size += 1;
apple.pos = [_.random(-25, 25), _.random(-25, 25)];
}
const snakeHead = snake.pos[0];
const nextHead = [snakeHead[0] + snake.direction[0], snakeHead[1] + snake.direction[1]];
if (nextHead[0] > 25) { nextHead[0] = -25; }
if (nextHead[0] < -25) { nextHead[0] = 25; }
if (nextHead[1] > 25) { nextHead[1] = -25; }
if (nextHead[1] < -25) { nextHead[1] = 25; }
if (snake.pos.filter(p => collides(p, nextHead)).length > 0) {
// snake collides with itself
return restart();
}
snake.pos.unshift(nextHead);
if (snake.pos.length > snake.size) {
snake.pos.pop();
}
}
עיקר הלוגיקה קורה בפונקציה tick - שמקדמת את הנחש בצעד אחד ובודקת התנגשויות.
## חיבור הקוד החיצוני לריאקט
אבל אנחנו לא פה בשביל לדבר על לוגיקה - אנחנו רוצים לשחק ובשביל לשחק צריך גם לראות צבעים זזים על מסך. החיבור של הלוגיקה לריאקט הוא בדיוק הקסם של ריאקט: זאת הבחירה במידע שאנחנו רוצים לשמור בתוך הסטייט.
במשחק סנייק מה שחשוב לנו זה לדעת איפה נמצא הנחש ואיפה נמצא התפוח. אפשר להגיד שרשימת הקורדינטות היא בדיוק הסטייט של הקומפוננטה. כל שינוי במיקומים של הנחש או התפוח דורש ציור מחדש של חלק מהלוח. הדרך המקובלת לקחת מידע חיצוני ולהשתמש בו בתור סטייט של קומפוננטת ריאקט היא לשכפל את המידע ולתרגם אותו לצורה שרלוונטית לקומפוננטה. במילים אחרות אם הקומפוננטה שלי צריכה לדעת איפה נמצא הנחש אז אני יוצר בסטייט משתנה מסוג Set שיכיל את כל המיקומים של הנחש. ואם הקומפוננטה צריכה לדעת איפה התפוח אני יוצר בסטייט Set (או משתנה בודד זה לא ממש משנה) שיכיל את כל המיקומים של התפוח - שכרגע זה כמובן רק מקום אחד.
ב JavaScript שלושת הפונקציות האלה יכולות להיות מימוש טוב למנגנון יצירת הסטייט מתוך המידע החיצוני:
function translate(coord) {
return `${coord[0] + 25},${coord[1] + 25}`;
}
function getAppleData(apple) {
return new Set([translate(apple.pos)]);
}
function getSnakeData(snake) {
return new Set(snake.pos.map(translate));
}
ופה צריך לשים לב שהרבה יותר קל לנו לבנות Set-ים חדשים ולהשתמש בהם בסטייט, מאשר לשמור Reference למידע החיצוני מהסטייט. מבחינת ריאקט כשהוא יקבל Set חדש הוא יפעיל מחדש Render ויבדוק איך השינוי בסטייט משפיע על הקומפוננטה, ובמקרה של משחק הנחש זה בדיוק מה שאנחנו רוצים.
עוד פונקציית עזר קטנה לפני הקומפוננטה תקבל מיקום וסטייט ותגיד מה הצבע של המשבצת במיקום שבחרנו:
function colorOf(row, col, snakeData, appleData) {
if (snakeData.has(`${row},${col}`)) {
return "blue";
}
if (appleData.has(`${row},${col}`)) {
return "red";
}
return "transparent";
}
ועכשיו יש לנו את כל המידע וקטעי הקוד הדרושים כדי לכתוב את קומפוננטת הנחש עצמה. הקומפוננטה יחסית ארוכה וכוללת גם קוד לתצוגה, גם הגדרת State וגם הגדרת אפקט. זה הקוד המלא שאני כתבתי:
export default function Snake(props) {1 419
# הוראות מדויקות
הצורך המאוד טבעי שלנו למצוא הוראות מדויקות מתחבר יפה לרצון של אתרים רבים להיות ידידותיים, וכך אנחנו מגיעים למשפט הבא בהוראות ההתקנה של rvm:
$ \curl -sSL https://get.rvm.io | bash
שכולל מצד אחד את ה \ בהתחלה כדי להגיע לגירסה האמיתית של curl בלי alias-ים, אבל מצד שני מתעלם מזה שבמחשבים ישנים או כאלה שמאחורי proxy, עלולה להיות בעיה עם התעודות שתכשיל את כל המהלך.
כמובן שהיינו כועסים עליהם באותה מידה אם הם היו מכניסים גם -k להוראות ההתקנה - מה פתאום שמישהו ימליץ לי להתעלם משגיאות אבטחה? ובמיוחד כשאני הולך להתקין כלי רגיש כמו rvm.
לא, מקור הבעיה אינו חוסר דיוק בהוראות. אין הוראות מדויקות מספיק שיתאימו לכולם. מקור הבעיה הוא הניסיון לעזור לאנשים שלא יודעים איך להוריד סקריפט bash ולהריץ אותו, להצליח לעשות את זה בלי להבין את מה שהם עושים.
ההוראות הכי טובות הן אלה שמתארות במילים "מה צריך לעשות" ונותנות לי לשבור את הראש על ה"איך". זה אולי ייקח יותר זמן אבל לפחות יחסוך טעויות ופאדיחות.1 419
# חמישה טיפים לניקיון בין המשימות
כמו שפעם בכמה זמן אתם עוצרים כדי לנקות את הבית, כך גם הקוד שלכם צריך מדי פעם שתיקחו עצירה ותעבירו עליו סמרטוט. וכמו בבית, גם קוד שלא מנקים אותו הרבה זמן מתחיל להראות סימנים של לכלוך וגורם לאנשים חדשים לרצות לברוח.
אז מה עושים? הנה 5 טיפים קצרים שיעזרו לשמור את הקוד שלכם נקי:
## משדרגים תלויות
קחו פעם בשבוע או שבועיים כמה שעות לשדרג את כל התלויות. כמו בניקיון בבית, אנשים שמקפידים לנקות את הארונות פעם בשבועיים מגלים שהניקיון זורם די מהר, אבל אלה שמנקים את הארון פעם בשנה או שנתיים יגלו שכל יום ניקיון כזה לוקח כמעט שבוע.
האתגר- מדי פעם אנחנו נגלה ששידרוג תלות מסוים שובר משהו בקוד שלנו. זאת בדיוק ההזדמנות לתקן את הקוד יחד עם השידרוג כדי לוודא שנוכל תמיד להישאר בגירסאות הכי מעודכנות.
## מעיפים קוד מיותר
בתהליך כתיבת קוד נוצר גם הרבה זבל: לפעמים זה קובץ CSS שכבר לא צריך אותו, לפעמים זו קומפוננטה שבסוף התגלתה כרעיון גרוע ולפעמים קוד צד שרת או שינויים בבסיס הנתונים.
תהליך נוסף שיוצר זבל הוא האבולוציה הטבעית של המוצר. פיצ'רים שיורדים מהמוצר לוקחים איתם גם עמודות בבסיס הנתונים, קבצי עיצוב, קבצי תיעוד ישנים, פונקציות Utility שמפוזרות בכל מיני מקומות במערכת ועוד ועוד.
ותהליך שלישי הוא המחשבה על עתיד מסוים שבסופו של דבר לא מתממש. אלה המנגנונים הגנריים שכתבנו לפני שנתיים ובעצם עדיין משמשים רק ל Use Case אחד. מחיקה של מנגנונים גנריים והפיכתם לספציפיים יותר יכולה להקל על מי שיבוא לתחזק ולתקן בעיות בקוד בהמשך.
הבעיה שבמהלך הרגיל של כתיבת קוד אנחנו כמעט תמיד באיחור בפיצ'ר וכך יוצר שכשמשהו כבר עובד אנחנו ממשיכים מיד לפיצ'ר הבא ומשאירים את כל הקבצים המיותרים בפרויקט. אם יש לכם זמן בין המשימות, מחיקת כל הקוד הישן הזה תעזור לתחזוקה קלה יותר בעתיד ותקל על אנשים חדשים להיכנס לפרויקט.
## מתקנים קוד גרוע
תהליך חבר של המחיקה הוא הריפקטורינג - תהליך שבו אנחנו לוקחים אלגוריתם לא הכי יעיל ומשכתבים אותו לגירסה יעילה. או, לוקחים קוד כפול שמופיע במספר מקומות ובונים מנגנון גנרי שיחסוך לנו את הקוד הכפול.
יעד נוסף לריפקטורינג הוא קוד שכתבתם כשלא הכי הכרתם את הפריימוורק, והיום כבר נראה לכם חובבני או טרחני. אם יש מנגנון מובנה בפריימוורק שמטפל במקרה מסוים, עדיף להשתמש במנגנון המובנה במקום לבנות בעצמכם, ואם כבר בניתם בעצמכם אז הריפקטורינג זה השלב בו אתם מוחקים את המנגנון שלכם ועוברים להשתמש במנגנון המובנה.
## מוסיפים, מוחקים או מתקנים בדיקות
סט בדיקות ה End To End שלכם צריך קצת אהבה? הבדיקות לפעמים מצליחות ולפעמים נכשלות ואף אחד לא מבין למה? תהליכים מרכזיים במערכת לא נבדקים? לא צריך להרגיש רע בגלל זה - זה המצב אצל כולם. בדיקות End To End זה החלק במערכת שמתיישן הכי מהר ושצריך לנקות אותו בתדירות הגבוהה ביותר (כן בדיוק כמו השירותים אצלכם בבית).
בניקיון השבועי אנחנו מוחקים בדיקות שנכשלות (תמיד או לפעמים), מוסיפים בדיקות לתהליכים מרכזיים ששכחנו ומתקנים את כל הבדיקות שכבר לא עוברות כי מישהו שינה איזה שטות ב HTML.
## משפרים תהליכי עבודה
נשאר לכם עוד זמן פנוי בסוף הניקיון? זה הזמן לזהות איזה תהליכי עבודה לוקחים לכם זמן ולשפר אותם. וממש לא צריך ללכת על כל הקופה - מספיק לבנות Template טוב יותר לקומפוננטה שתתאים למערכת הפנימית שלכם, או סקריפט קטן שחוסך לכם הקלדה ב Deployment הבא, או לחבר את הג'נקינס לסלאק כדי שיהיה לכם קל יותר לראות את הבדיקות שנכשלו. כל דבר שקצת יעשה את החיים שלכם קלים יותר יתקבל בברכה, והכי נחמד אלה השיפורים שעושים אוטומציה לדברים הקטנים שאנחנו עושים כל יום.
יש לכם רעיונות נוספים לדברים שחייבים לנקות בפרויקט כל שבוע-שבועיים? מוזמנים להוסיף אותם פה בתגובות.
¡Ya disponible! Investigación de Telegram 2025 — los principales insights del año 
