ניהול מורכבות

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

פשטות ומורכבות

בהרצאה Simple Made Easy, ריץ' היקי מדבר על האיכות של דברים פשוטים לעומת דברים מורכבים. הוא מתאר דברים פשוטים כמו התמקדות בדברים הבאים:

"תפקיד אחד, משימה אחת, קונספט אחד או מאפיין אחד".

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

"קבלת מופע אחד או ביצוע פעולה אחת."

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

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

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

ניהול המורכבות של PWA

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

ה-thread הראשי הוא:

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

כפי שסורמה הוסיף בהרצאה שקיימה בנושא Chrome Dev ב-2019, השרשור הראשי עמוס מדי ואין בו מימון מועט.

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

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

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

החדשות הרעות? הוספת מורכבות לשרשור הראשי היא דרך כמעט ודאית להקשות על העמידה ביעדים האלה. אבל יש גם חדשות טובות! כי מה שה-thread הראשי צריך לעשות הוא ברור: הוא יכול לשמש כמדריך כדי לצמצם את ההסתמכות עליו בהמשך האפליקציה.

הפרדת חששות

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

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

עבודה שלא מבוססת על ממשק משתמש יכולה לכלול, למשל:

  • חישובים בלבד.
  • גישה לנתונים (אחזור, IndexedDB וכו').
  • הצפנה.
  • העברת הודעות.
  • יצירה או מניפולציה של blob או שידור.

בדרך כלל, עבודות שלא מתבצעות דרך ממשק המשתמש מתוזמנות על ידי עבודה דרך ממשק המשתמש: משתמש לוחץ על לחצן שמפעיל בקשת רשת עבור ממשק API, שמחזיר תוצאות מנותחות שמשמשות לאחר מכן לעדכון ה-DOM. כשכותבים קוד, לרוב יש התייחסות לחוויה מקצה לקצה, אבל לרוב זו לא חוויה של כל חלק בזרימה. חשוב להביא בחשבון את הגבולות בין עבודה בממשק המשתמש לבין עבודה שלא מבוססת על ממשק משתמש, לא פחות מאשר בחוויות מקצה לקצה, כי זהו המקום הראשון שבו אפשר להפחית את המורכבות של ה-thread הראשי.

התמקדות במשימה אחת

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

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

הגבולות הברורים הראשונים הם בין עבודה בממשק המשתמש לבין עבודה שלא מבוססת על ממשק משתמש. לאחר מכן יש קריאות להפעיל שיקול דעת: האם ביצוע וניתוח של בקשת API משימה אחת או שתיים? אם השינויים ב-DOM לא מתבצעים בממשק המשתמש, האם הם נכללים בחבילה עם ה-API? באותו שרשור? נמצא בשרשור אחר? רמת ההפרדה הנכונה כאן היא המפתח גם לפשט את ה-codebase וגם להעביר בהצלחה חלקים מה-thread הראשי.

קומפוזביליות

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

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

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

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

על סמך המידע הזה, תוכלו ליצור ספרייה של פונקציונליות קומפוזבילית על ידי סיווג הקוד ויצירת ממשקי קלט/פלט (I/O) נפוצים לקטגוריות האלה. קוד קומפוזבילי הוא סימן ההיכר של בסיסי קוד פשוטים: חלקים שניתנים להחלפה באופן רופף שיכולים לשבת "ליד", ולהיבנות זה על גבי זה, בניגוד לקוד מורכב שמחובר ביניהם באופן הדוק ולכן לא ניתן להפריד ביניהם בקלות. באינטרנט, קוד קומפוזבילי יכול לעשות את ההבדל בין עיבוד יתר של ה-thread הראשי או לא.

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

שימוש בעובדי אינטרנט כדי להפחית את המורכבות

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

עובדי אינטרנט מאפשרים ל-PWA להריץ JavaScript (חלק) מחוץ ל-thread הראשי.

יש שלושה סוגי עובדים.

אפשר להשתמש בעובדים יעודיים (Dworked work) כשמתארים עובדי אינטרנט, סקריפט יחיד במופע יחיד של PWA. כשאפשר, יש להעביר עבודה שאין לה אינטראקציה ישירה עם ה-DOM ל-Web worker כדי לשפר את הביצועים.

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

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

עובד האינטרנט האחרון הוא אחד מהנושאים הנלמדים בקורס בהרחבה: service worker, שמשמשים כשרת proxy לבקשות רשת ומשותפים בין כל המופעים של PWA.

התנסות עצמית

הגיע הזמן לקוד! פיתוח PWA מאפס על סמך כל מה שלמדתם במודול הזה.

משאבים