הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

הדרך הכי טובה לאבד מוטיבציה

16/04/2021

הדרך הכי טובה לאבד מוטיבציה היא להסתכל על התוצאות: האם הצלחתי לפתור את התרגיל? האם התקבלתי לעבודה? כמה אנשים עשו לי "לייק" בסטאק אוברפלו או האם ענו לי על ה Pull Request ששלחתי?

וזה גרוע גם אם התוצאה חיובית וגם אם שלילית.

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

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

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

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

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

לי זה לקח חודשיים

15/04/2021

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

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

בעקבות פירסום שראיתי לקורס Qt התחלתי לחשוב - החודשיים שהשקעתי באמת היו אפקטיביים, אבל האם היה אפשר לקצר אותם? האם קורס מרוכז היה עוזר לי להגיע לאותה רמה בהשקעה של 5 ימי עבודה בלבד?

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

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

לי זה לקח חודשיים, ואם אני צריך לבנות מסלול לימוד לחבר שיעזור לו ללמוד Qt זה בדיוק יהיה אורך המסלול (ואגב, בניתי מסלול כזה, קוראים לו קורס Qt פה באתר). אז מה בכל זאת אפשר לעשות עם קורס של 5 ימים? שני רעיונות:

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

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

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

אף אחד אף פעם לא ביקש ללמוד על Higher Order Components

14/04/2021

לא נעים להגיד אבל יש בטכנולוגיה פיצ'רים שאנשים רוצים ללמוד עליהם ואחרים שלא ממש. אף אחד לא נכנס לקורס ריאקט ומבקש ללמוד איך עובד Higher Order Component או לקורס JavaScript ומבקש ללמוד איך לממש לבד Class System עם פרוטוטייפים.

מצד שני כשאנשים נכנסים לקורס על בדיקות הם קודם כל רוצים לשמוע איך להשתמש ב Mock Objects, ב Spies ובכל היכולות הכי מתקדמות של ספריית הבדיקות. בקורס ריאקט אנשים ישאלו אותי לעתים קרובות איך עובדים עם Concurrent Mode וכמובן על useContext ו useMemo.

ויש סיבה למשחק הזה.

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

האמת הפוכה לגמרי: כמעט כל קוד בדיקה שראיתי שהשתמש ב Mock Objects כדי "לדרוס" חלקים במערכת היה אפשר לשכתב בקלות לגירסה יותר אמינה בלי אותם Mock Objects. כמעט אף אחד לא צריך את PureComponent או useMemo כי ריאקט עובד טוב מספיק בלעדיו.

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

זה נראה לך בסדר?

13/04/2021

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

זה נראה לך בסדר?

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

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

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

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

לשבור, בטח לשבור

12/04/2021

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

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

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

אז מה בכלל יש לכם נגד לולאות?

10/04/2021

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

def double(arr):
    result = []
    for item in arr:
        result.append(item * 2)

    return result
def 

ולעומתה:

def mymap(f, arr):
    result = []
    for item in arr:
        result.append(f(item))

    return result

def double(arr):
    return mymap(lambda x: x * 2, arr)

וזו:

def double(arr):
    return map(lambda x: x * 2, arr)

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

המשך קריאה

איך אומרים "תקליט" ברוסית?

09/04/2021

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

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

ואז התחלתי לחשוב-

אולי אני יכול לקצר זמנים? מה אם אקשיב ל-3 פרקים ביום? או אכוון את המהירות לכפול 2 ואקשיב ל-6 פרקים ביום? אם אצליח לסיים להקשיב לכל 100 הפרקים של הפודקסט בשלושה ימים, האם אוכל לקבל את אותה דחיפה קדימה, כמו בתוכנית הפרק ביום המקורית שלי?

כמובן שלא.

שני דברים חשובים הולכים לאיבוד בגירסת הלמידה בהילוך מהיר:

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

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

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

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

השעה הראשונה

08/04/2021

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

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

יש משהו בלהיות בתוך הפרוסס הזה של כתיבה שנותן את ה Context לכל המסביב. וברגע שיש Context ומוטיבציה כל השאר רץ מעצמו.

היום גיליתי: brew ב linux עלול לשבור הכל

07/04/2021

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

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

ומה הבעיה עם זה שהומברו יתקין את pkg-config אתם שואלים? נו זה ברור, ה pkg-config שהומברו מתקין יכול להחזיר מידע רק על חבילות שהומברו התקין. אז עכשיו אנחנו יכולים לנסות לבנות תוכנה שצריכה איזו חבילה (נגיד libdbus-1-dev), ואפילו שהחבילה מותקנת דרך apt-get אי אפשר יהיה לבנות את התוכנה שלנו כי הבניה מפעילה את pkg-config שמחפש רק בספריות שהותקנו דרך הומברו.

אחרי שמבינים מה לחפש גם הפיתרון די פשוט ומופיע ב Issue הזה. כל מה שצריך זה להסיר את pkg-config מהומברו וכך חוזרים לגירסה של המערכת:

brew unlink pkg-config

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