עיצוב קוד באמצעות פונקציות

פוסט זה כולל טיפ קצר בנושא פיתוח Front End. אם אתם רוצים ללמוד יותר לעומק על פיתוח Front End מהבסיס ועד הנושאים המתקדמים תשמחו לשמוע שבניתי קורס וידאו מקיף בנושא זה הכולל מעל 50 שיעורי וידאו והמון תרגול מעשי.
למידע נוסף והצטרפות לקורס בקרו בדף קורס Front End באתר.
 

כשאנחנו חושבים על עיצוב קוד (Code Design) מיד עולה לראש עולם המונחים מונחה העצמים: ירושה, כימוס, פולימורפיזם וכמובן מחלקות ותבניות עיצוב, אבל האמת היא שאפשר לכתוב קוד מודולרי ונקי גם ללא שימוש במחלקות. במיוחד נכון הדבר בשפות תכנות המתיחסות ברצינות לפונקציות ולהרכבה שלהן כפי שנראה בדוגמא הבאה.

1. התוכנית

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

See the Pen functional filters demo by Ynon Perek (@ynonp) on CodePen.

2. סינון מבוסס פונקציות

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

בקוד הדוגמא בחרתי באפשרות הראשונה.

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

function hlLong(text) {
  return text.length > 60;
}

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

var filters = {
  'long lines': hlLong,
  'short lines': hlShort,
  'ends with a .': endSentence
};

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

3. מה עוד הרווחנו

מאחר ומדובר בפונקציות אפשר להציע פונקציות מסדר גבוה כדי לארגן את הקוד טוב יותר. קחו לדוגמא את הפונקציה Fand:

function Fand(...filters) {
  return function(text) {
    if ( filters.length === 0 ) { return false; }
    return filters.every((f) => f(text));
  }
}

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

var filters = {
  'long lines': hlLong,
  'short lines': hlShort,
  'short lines that end with a .': Fand(hlShort, endSentence),
  'ends with a .': endSentence
};

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