כשמחפשים עבודה, אחד הדברים החשובים ביותר הוא להתכונן לראיון העבודה בצורה נכונה. מעבר ללמידת שפות תכנות חדשות ובניית פרויקטים לשמירה על כושר, חשוב גם להבין ללמוד איך לצלוח את הראיון עצמו.
במאמר הזה אשתף 5 אסטרטגיות לפתרון בעיות בתכנות, במטרה שזה יעזור לכם להתכונן לשאלות אלגוריתמים בראיונות. את האסטרטגיות שאפרט עליהם לאורך מאמר למדתי במסגרת קורס אונליין של קולט סטיל.
המסמך שלפניכן הוא סיכום של פרק 4 - "Problem Solving Approach" מתוך הקורס "JavaScript Algorithms and Data Structures Masterclass" מאת Colt Steele ביודמי. המאמר נכתב בלשון נקבה אך פונה לכלל המינים.
תוכן עניינים
בראיונות עבודה המראיין עלול לבקש מאיתנו לפתור בעיה ולכתוב אלגוריתם שיפתור אותה. אותו אלגוריתם, הוא תהליך, או שורה של צעדים למימוש פתרון לבעיה, או ביצוע משימה מסוימת.
למשל: סדרה של שלבים מתמטיים שצריך לבצע כדי לפתור בעיה, אלגוריתם כמו של פייסבוק שנועד להמליץ על פרסומות מתאימות או אפילו האלגוריתם של גוגל. על האחרון כנראה עבדו מעל 100 מפתחים במשך שנים ארוכות, אך גם הפונקציה הכי פשוטה שנועדה לחשב סכום של שני מספרים היא אלגוריתם.
כאשר אנו נמצאות במצב בו מוצגת לפנינו בעיה שמעולם לא נתקלנו בה בעבר, רצוי להכיר את האסטרטגיות לפתרון בעיות. קחו בחשבון שזה בהחלט יכול לקרות בראיון עבודה, ובוודאי שזה יקרה במהלך העבודה השוטפת כמפתחות.
השיטות שהובאו בקורס מבוססות על הספר How to Solve It (מאת George Pólya). להלן נסקור לעומק את חמשת הצעדים לפתרון בעיות, מתוך אוריינטציה של ראיון לתפקיד מפתחת JavaScript.
חמשת הצעדים בדרך לפתרון בעיות בתכנות
- הבנת הבעיה
- סקירת דוגמאות קונקרטיות
- פירוק הפתרון למרכיבים
- פתרון או פישוט הבעיה
- הערכה מחדש ושיפור הקוד (Refactoring)
1. הבנת הבעיה
- ניסוח הבעיה במילים שלך.
- לוודא מהם הפרמטרים* שהפונקציה צריכה לקבל.
- לוודא מה הפונקציה אמורה להחזיר.
- האם מה שמוחזר יכול להקבע על ידי מה שהפונקציה מקבלת?
- בדיקה מהם הנתונים החשובים ביותר בדרך לפתרון הבעיה.
- האם קיבלתי מספיק מידע לפתרון הבעיה?
דוגמה:
"כתבי פונקציה שמקבלת 2 מספרים ומחזירה את הסכום שלהם"
- ניסוח הבעיה במילים שלי:
יישמי פונקציה שמבצעת פעולת חיבור בין 2 מספרים.
- מהם הפרמטרים שהפונקציה צריכה לקבל?
האם מדובר על מספרים שלמים? עם נקודה עשרונית? האם הפונקציה יכולה לקבל סטרינגים? האם יש גבול עליון לגודל המספרים (בחיבור מספרים ממש גדולים JavaScript תחזיר Infinity)? מה אמור לקרות אם לא מקבלים 2 ארגומנטים*?
*פרמטרים - שמות המשתנים שהפונקציה אמורה לקבל במעמד הגדרת הפונקציה. *ארגומנטים - הערכים האמיתיים שהפונקציה מקבלת כאשר היא מופעלת/נקראת.
- מה הפונקציה אמורה להחזיר?
האם זה צריך להיות Int, Float, String?
- האם מה שמוחזר יכול להקבע על ידי מה שהפונקציה מקבלת?
אם מעבירים לפונקציה סטרינגים, האם היא צריכה להחזיר סטרינג או מספר? אם מועברים floats מה היא צריכה להחזיר? מה קורה אם מעבירים רק ארגומנט אחד? או לא מעבירים ארגומנטים בכלל?
- מהם הנתונים החשובים ביותר בדרך לפתרון הבעיה?
- הארגומנטים שהפונקציה תקבל.
- הערך המוחזר.
2. סקירת דוגמאות קונקרטיות
- לחשוב על דוגמאות שיכולות לעזור לי להבין את הבעיה טוב יותר.
- דוגמאות מאפשרות לי לוודא שהפתרון יעבוד כמצופה ממני.
- התחילי בדוגמאות קטנות. כדאי לרשום אותן כדי שניתן יהיה להסתכל עליהן לאחר מכן.
- התקדמי לדוגמאות מורכבות יותר.
- סקרי דוגמאות קצה עם קלט לא חוקי, חלקי, ריק וכו'.
דוגמה:
"כתבי פונקציה שמקבלת סטרינג ומחזירה ספירה של כל תו בסטרינג".
נשאלת השאלה האם צריך להחזיר רשימה רק של האותיות הקיימות או גם של האותיות החסרות כשהכמות שלהן היא 0? כיצד יש להתייחס לאותיות קטנות וגדולות? כיצד יש להתייחס למספרים? לסימני פיסוק? לרווחים? כיצד יש להתייחס לאינפוט של סטרינג ריק או ללא אינפוט בכלל? כיצד להתייחס לאינפוט של מספר? האם זה חוקי?
3. פירוק הפתרון למרכיבים
בטרם ניגש לכתוב את הפתרון עצמו כדאי לכתוב פסודו קוד או הערות, שמתארים שלב שלב את דרך פתרון הבעיה. זה מכריח חשיבה על כיצד יש לכתוב את הקוד בפועל, לפני שנכתוב אותו באמת. כמו כן זה עוזר לתפוס אי אילו אי הבנות לפני שכותבים את הקוד ממש ולהעלות עוד שאלות שאולי אינן ברורות.
דוגמה:
"כתבי פונקציה שמקבלת סטרינג ומחזירה ספירה של כל תו בסטרינג".
4. פתרון או פישוט הבעיה
אם ניתן, אפשר לגשת לפתרון הבעיה בשלב זה. אם לא הכל מחוור, ניתן לפשט את הבעיה על ידי פתרון החלקים היותר קלים בבעיה. לעתים קרובות על ידי פישוט הבעיה, מתקבלות תובנות אודות הבעיה עצמה, הקשה יותר.
כיצד לפשט?
- מציאת הקושי העיקרי.
- התעלמות זמנית מהקושי.
- כתיבת הפתרון היידוע או הפשוט.
- התמודדות עם הקושי.
נמשיך עם הדוגמה שלנו. נניח ואיננו זוכרות איך נקראת הפונקציה של JavaScript שהופכת סטרינגים לאותיות קטנות או איננו יודעות כיצד לבדוק האם תו הוא אלפנומרי, נתחיל לכתוב בקוד את חלקי הפתרון שאנו יודעות כיצד לפתור ואת הבעיות הללו נשאיר לסוף, ונשאיר בהערה את החלקים הללו. ניתן לברר עם המראיין האם ניתן לחפש בגוגל או האם הוא אפילו יכול לעזור וזה לגיטימי לגמרי.
5. הערכה מחדש ושיפור הקוד (Refactoring)
כאשר סוף סוף פותרים את הבעיה זה מאוד מפתה להסתפק בזה, אבל זה מאוד חשוב לשאוף לשפר את הקוד. חשוב להקדיש זמן ולהביט לאחור על הקוד ולחשוב כיצד ניתן לשפר אותו, לייעל אותו, לנקות אותו, להפוך אותו לקריא יותר לאחרים ועוד. זה חשוב בראיון עבודה וזה חשוב על אחת כמה וכמה בסביבת עבודה מקצועית.
שאלות לשיפור הקוד:
- האם ניתן להבין את הקוד במבט חטוף? עד כמה הוא אינטואיטיבי?
- האם ניתן לשפר את הביצועים של הפונקציה?
- האם הקוד יעבוד בכל מקרי הקצה?
- האם בכל זאת ישנה דרך לפתור את הבעיה בדרך שונה ממה שעשיתי?
- האם הפונקציה הזו יכולה לפתור לי בעיות דומות שנתקלתי בהן בעבר?
- האם הקוד תואם את הקונבנציה המקובלת?
- כיצד אנשים אחרים פתרו בעיה דומה?
בהתייחס לסעיף האחרון, בחיים המקצועיים זה לגיטימי לבדוק כיצד אחרים פתרו בעיות דומות, אולי אפילו בשפות תכנות אחרות או במקרי קצה שונים, כדי לקבל פרספקטיבה על כיצד ניתן לגשת לפתרון הבעיה ולהרחיב את האופקים המקצועיים. בראיון עבודה זה בהחלט רצוי לשאול את המראיין כיצד אחרים פתרו את הבעיה והאם הציעו פתרונות אחרים ומהם. זה עושה רושם טוב ומראה שאת בעלת סקרנות בריאה, רצון להרחיב אופקים ותשוקה לתכנות.
להלן כמה דוגמאות כיצד ניתן לפתור את הבעיה לדוגמה שלנו, החל מהפתרונות הפחות טובים, עד לפתרון האופטימלי:
לקריאה נוספת:
- 11 קורסי אונליין שלימדו אותי פיתוח פרונט אנד
- 25 שאלות על ריאקט | “שליף” אולטימטיבי לראיון ב- React
- 10 טיפים לראיון קוד מוצלח