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

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

יותר מדרך אחת

30/06/2021

מה הדרך הכי טובה לבנות מערכת? מה הדרך הכי טובה להתקבל לעבודה בהייטק? מה הדרך הכי טובה ללמוד טכנולוגיה חדשה?

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

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

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

צרות של כולם

29/06/2021

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

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

והרגלים (Habbits) נותנים לנו המתכנתים את היכולת להשתמש בתשתיות בצורה מיטבית. ההרגל להתחיל את היום בחצי שעה למידה; ההרגל להריץ את הבדיקות ולהסתכל בתוצאות שלהן כל פעם שמסיימים לעבוד על משהו; הרגלי עבודה בתוך IDEs חכמים ויכולת לקרוא מהר את הנתונים של אינסוף הכלים שעומדים לרשותנו. ההרגל לכתוב הודעות קומיט מועילות ולהסתכל בהודעות קומיט ישנות כדי להבין את ההיגיון מאחורי הקוד.

קשה לבנות תשתיות טובות וקשה עוד יותר לבנות הרגלים טובים, ובדיוק בגלל זה אנחנו חייבים.

היום למדתי: איך להתעלם מקומיטים ב git blame

28/06/2021

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

אבל-

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

דוגמה קצרה תעזור להמחיש את העניין. נניח שיש לי קובץ Python עם התוכן הבא:

def twice(x):
    return x * 2


if __name__ == "__main__":
    x = int(input("Pick a number: "))
    print(f"{x} x 2 = {twice(x)}")

ואני רוצה לדעת למה הודעת ההדפסה מציגה דווקא את הסימן x כדי לסמן מכפלה. פקודת git blame היתה יכולה לעזור לי:

$ git blame a.py
7391c20d (ynonp 2021-06-27 14:39:12 +0300 1) def twice(x):
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 2)     return x * 2
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 3) 
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 4) 
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 5) if __name__ == "__main__":
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 6)     x = int(input("Pick a number: "))
7391c20d (ynonp 2021-06-27 14:39:12 +0300 7)     print(f"{x} x 2 = {twice(x)}")
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 8) 

והנה אני רואה שהקומיט האחרון שהשפיע על השורה שמעניינת אותי הוא קומיט מספר 7391c20d. בואו נראה מה קרה בקומיט הזה:

$ git show 7391c20d

commit 7391c20df9f8eec472494602ffa727542151c553 (HEAD -> main)
Author: ynonp <ynonperek@gmail.com>
Date:   Sun Jun 27 14:39:12 2021 +0300

    Renamed function

diff --git a/a.py b/a.py
index 6e899d5..a883ec7 100644
--- a/a.py
+++ b/a.py
@@ -1,8 +1,8 @@
-def double(x):
+def twice(x):
     return x * 2


 if __name__ == "__main__":
     x = int(input("Pick a number: "))
-    print(f"{x} x 2 = {double(x)}")
+    print(f"{x} x 2 = {twice(x)}")

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

$ git blame --ignore-rev 7391c20d a.py
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 1) def twice(x):
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 2)     return x * 2
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 3) 
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 4) 
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 5) if __name__ == "__main__":
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 6)     x = int(input("Pick a number: "))
373b123e (ynonp 2021-06-27 14:38:12 +0300 7)     print(f"{x} x 2 = {twice(x)}")
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 8) 

ועכשיו אני מקבל את הקומיט הקודם שהשפיע על השורה, ודרכו אפשר לראות את הודעת הקומיט ולהיזכר:

$ git show 373b123e

commit 373b123e76b02fe6972de79daf52839f5b08664a
Author: ynonp <ynonperek@gmail.com>
Date:   Sun Jun 27 14:38:12 2021 +0300

    Changed multiplication symbol

    Turns out we've received multiple complaints about clients
    not understanding that a * is actually a multiplication sign,
    so product asked to replace the * with an "x"

diff --git a/a.py b/a.py
index 9cc6552..6e899d5 100644
--- a/a.py
+++ b/a.py
@@ -4,5 +4,5 @@ def double(x):

 if __name__ == "__main__":
     x = int(input("Pick a number: "))
-    print(f"{x} * 2 = {double(x)}")
+    print(f"{x} x 2 = {double(x)}")

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

בשביל זה אנחנו יוצרים קובץ בתיקיית הפרויקט (אפשר לבחור לו כל שם, אני קראתי לו .git-blame-ignore-revs), ורושמים לתוכו את המזהה ממנו רוצים להתעלם:

$ echo 7391c20df9f8eec472494602ffa727542151c553 >> .git-blame-ignore-revs 

(שימו לב לרשום לקובץ את מזהה הקומיט המלא ללא קיצורים)

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

$ git config blame.ignoreRevsFile .git-blame-ignore-revs

ו-הפתעה. עכשיו כשנפעיל git blame הקומיט הבעייתי לא יופיע ונגיע ישר לקומיט שמעניין אותנו:

$ git blame a.py

cae63ff (ynonp 2021-06-27 14:36:40 +0300 1) def twice(x):
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 2)     return x * 2
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 3) 
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 4) 
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 5) if __name__ == "__main__":
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 6)     x = int(input("Pick a number: "))
373b123e (ynonp 2021-06-27 14:38:12 +0300 7)     print(f"{x} x 2 = {twice(x)}")
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 8) 

ואגב אחרון, אם עשיתם את כל ההוראות לפי הפוסט ועכשיו דווקא מתחשק לכם לוותר על הדילוג ולראות את git blame האמיתי תוכלו תמיד להפעיל:

$ git blame --ignore-revs-file "" a.py

7391c20d (ynonp 2021-06-27 14:39:12 +0300 1) def twice(x):
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 2)     return x * 2
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 3) 
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 4) 
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 5) if __name__ == "__main__":
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 6)     x = int(input("Pick a number: "))
7391c20d (ynonp 2021-06-27 14:39:12 +0300 7)     print(f"{x} x 2 = {twice(x)}")
^cae63ff (ynonp 2021-06-27 14:36:40 +0300 8) 

ללמוד מניסיון של אחרים

27/06/2021

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

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

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

פיתרון חידת ריאקט מאתמול

26/06/2021

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

import "./styles.css";

import React, { useRef, useState } from "react";

export default function Targil1(props) {
  const inputCount = 4;

  const [inputsText, setInputsText] = useState(new Array(inputCount).fill(""));

  const inputsRef = [];

  for (let i = 0; i < inputCount; i++) {
    inputsRef.push(useRef(null));
  }

  const containerDiv = {
    display: "flex"
  };

  function ChangeValueAndFocus(index, e) {
    inputsText[index] += e.key;

    inputsRef[(index + 1) % inputCount].current.focus();

    setInputsText([...inputsText]);
  }

  return (
    <div style={containerDiv}>
      {inputsText.map((item, index) => (
        <input
          value={item}
          key={index}
          autoFocus={index === 0 ? true : false}
          ref={inputsRef[index]}
          onKeyPress={(e) => ChangeValueAndFocus(index, e)}
        />
      ))}
    </div>
  );
}

וזה בקודסנדבוקס: https://codesandbox.io/s/tender-curie-ux3g5?file=/src/App.js

המשך קריאה

חידת ריאקט: פוקוס

25/06/2021

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

import "./styles.css";

import React, { useRef, useState } from "react";

export default function Targil1(props) {
  const inputCount = 4;

  const [inputsText, setInputsText] = useState(new Array(inputCount).fill(""));

  const inputsRef = [];

  for (let i = 0; i < inputCount; i++) {
    inputsRef.push(useRef(null));
  }

  const containerDiv = {
    display: "flex"
  };

  function ChangeValueAndFocus(index, e) {
    inputsText[index] += e.key;

    inputsRef[(index + 1) % inputCount].current.focus();

    setInputsText([...inputsText]);
  }

  return (
    <div style={containerDiv}>
      {inputsText.map((item, index) => (
        <input
          value={item}
          key={index}
          autoFocus={index === 0 ? true : false}
          ref={inputsRef[index]}
          onKeyPress={(e) => ChangeValueAndFocus(index, e)}
        />
      ))}
    </div>
  );
}

וזה בקודסנדבוקס: https://codesandbox.io/s/tender-curie-ux3g5?file=/src/App.js

לדעת מה לחפש

24/06/2021

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

בקיצור מפה לשם אני מצלצל לגוגל לשאול איך יוצרים קובץ ב Github Action ויש מגיע לתוסף הזה: https://github.com/marketplace/actions/create-file.

נראה סופר מקצועי, מופיע תוצאה ראשונה בגוגל בחיפוש אבל תכל'ס בזבוז זמן טוטאלי. גיטהאב אקשנס יודע להריץ כל Shell Command שאתם צריכים. בשביל ליצור קובץ מספיק להוסיף ל Workflow קטע קוד בסגנון הזה:

    - name: Create file
      run: |
        echo First        > other.txt
        echo Second Line >> other.txt
        echo Third       >> other.txt

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

ניסיון מר

23/06/2021

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

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

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

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

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

בדיקת רכיב חיפוש פגישות ב Meetup

22/06/2021

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

  1. טופס החיפוש מורכב משני שדות Input, אחד עבור נושא האירוע והשני עבור המיקום

  2. בשדה הנושא אפשר לרשום כל מה שרוצים - הכל טוב.

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

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

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

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

קוד הבדיקה המלא עם השרשרת נראה כך:

def test_search_form(browser):
    browser.get(meetup_homepage_url)

    form = browser.find_element_by_tag_name("form")
    subject_input = form.find_element_by_id("search-keyword-input")
    subject_input.send_keys("hiking")

    location_input = form.find_element_by_id('location-typeahead-searchLocation')

    action = ActionChains(browser)
    action.move_to_element(location_input)
    action.click()
    action.send_keys("London, GB")
    action.pause(2)
    action.send_keys(Keys.DOWN)
    # Select location
    action.send_keys(Keys.ENTER)

    # Submit the form
    action.send_keys(Keys.ENTER)
    action.perform()

    assert browser.current_url == "https://www.meetup.com/find/?keywords=hiking&location=gb--greater-london--london&source=EVENTS"

שימו לב להגדרת המשתנה action ולבניה האיטית שלו: קודם הולכים לשדה ה Location, אחר כך לוחצים עם העכבר כדי להעביר את הפוקוס, אחר כך כותבים טקסט, מחכים שתי שניות (בשביל ה Ajax), ואז לוחצים חץ למטה, Enter ורק אז Enter נוסף כדי להגיש את הטופס. הפקודה action.perform היא זאת שמפעילה את השרשרת.

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

הפילוסופיה של יוניקס

21/06/2021

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

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

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

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