2020-05-16

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

ראשית כל, בואו ונשאל: למה שתעניין אותנו הפילוסופיה של יוניקס? - פילוסופיה של חבורת אנשים מזוקנים משנות ה 60 וה 70 של המאה הקודמת?!

כלומר: אלוהים ישמור! למה שנתעניין במשהו בן 50 שנה? הרי אנחנו בתרבות שמקדשת את החדש-ביותר. כל מה שקרה לפני הקורונה - נראה היום כבר רחוק וכמעט לא-רלוונטי.

אפשר לטעון שיוניקס היא מערכת ההפעלה הטובה ביותר (הנדסית) שנכתבה אי-פעם. אפשר לטעון שהפילוסופיה של יוניקס הכילה את עקרונות ה SOLID, מיקרו-שירותים, Lean, ו Devops culture כבר בשנות ה-70, רעיונות שעדיין פופולריים גם היום - מה שעשוי בהחלט להקל עלינו את ההתעניינות בפילוסופיה הזו.

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

אז מה היא בדיוק הפילוסופיה של יוניקס?

- בפילוסופיה, כמו בפילוסופיה - אין דבר כזה שאפשר לתמצת במשפט אחד.



קיצור (אגרסיבי) של הפילוסופיה של יוניקס


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

בכל מקרה, ממגוון הגרסאות, יש שני כללים שבולטים וזכורים יותר מכולם. נבחן אותם אחד אחרי השני:
Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new “features.”

מילות המפתח שצצות כאן הן: מודולריות, פשטות, Single Responsibility, העקרון הפתוח-סגור, ו Lean.

ארכיטקטורת הבסיס של לינוקס היא ארכיטקטורה של קרנל:
  • ליבה (kernel) קטנה, אמינה, יעילה מוגנת ובדוקה היטב.
  • סט גדול של אפליקציות קטנטנות המאפשרות את הפיצ׳רים השונים. הן יכולות להגיע ממקורות שונים, פחות אמינים - כי הליבה מגינה על מערכת ההפעלה.
כלומר: ה״ליבה״ (להלן core) וה״הרחבות״ (להלן extensions) מייצגות איכויות שונות בתכלית - המשלימות זו את זו: ה core הוא קבוע, קטן, מנוהל היטב וה extensions מאפשרים בחירה ומגוון גדול.

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

אבל....

מכיוון שכל אפליקציה היא קטנה פשוטה ועושה בדיוק דבר אחד - לא ניתן לבנות פונקציוליות עשירה ומורכבת, ללא הכלל השני:
Expect the output of every program to become the input to another, as yet unknown, program.
פונקציונליות עשירה יותר, מורכבת ע״י ״הרכבה״ של אפליקציות פשוטות בזו על זו.

cat foo.txt | wc -l

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

אנו משתמשים מכאן ב Pipe (אם אתם לא יודעים מה זה pipe - לכו מיד וקראו!), על מנת להעביר את הפלט לאפליקציה אחרת, wc (קיצור של word count [א]) ורק היא תשלח את התוצאה שלה ל standard output.

תכנון ה pipe ע״י Doug McIlroy בשנת 1964. קצר, פשוט, ענייני.


wc מקבלת פרמטרים (במקרה שלנו l-) המאפשרים לה לפעול טיפה אחרת, ובעצם לספור שורות.

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

ה Pipe מאפשר הרכבה גמישה בין מרחב גדול כל-כך של אפליציות, ומאפשר ל Shell של יוניקס לבצע מגוון אדיר של פעולות פשוטות ומורכבות. ההצלחה של ה Pipe נובעת מתוך הגדרה של ממשק כללי ופשוט להחריד:
  • שטף של בתים (לא ביטים), בד״כ ב ASCII. כלומר: טקסט.
  • אפשר שיהיה לו סוף - בדמות EOF.
  • n\ סימן להפרדה בין רשומות (או ״שורות״)
  • +[t\ ] (כמות כלשהי של טאבים או רווחים) - הפרדה אפשרית בין שדות.

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

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

בגלל הסימנים הנוספים שהיא מוסיפה לטקסט בכדי להשיג את התסדיר של ה Syntax highlighting - היא כבר לא תעבוד טוב עם wc (או הרבה אפליקציות אחרות). היא חטאה לממשק הפשוט של ה Pipe.

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

פשטות אמיתית דורשת המון משמעת, כמו שנאמר: ״Simplicity is the ultimate sophistication״.



סיכום 


אז מה היא הפילוסופיה של יוניקס, ולמה היא חשובה?

הפילוסופיה מקדמת, מיישמת, ומדגימה סדרה ארוכה של עקרונות חשובים בהנדסת תוכנה. זה כבר ערך בפני עצמו. קראו את הפסקה הבאה:
״Build a prototype as soon as possible. Most users looking for a new piece of software won't know what they really want until they see it, so requirements documents are often misleading about the users' real needs. The Unix design philosophy makes prototyping a central part of the methodology: give the user something, anything, up-front to criticise, and work from there.״
אתם מאמינים שהיא נכתבה במיליניום הקודם? אז מי המציא את ה Lean-Startup? אריק ריס או מפתחי היוניקס?!

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

למשל: כל מודל הרכיבים (components) של RactJS או +Angular2 - מרגיש כמו שידור חוזר של הפילוסופיה של יוניקס: רכיבים פשוטים, לשימוש חוזר, שניתן לזרוק בקלות אם הם כבר לא רלוונטיים, וממשק פשוט ככל האפשר.

לפני כעשור ועוד עבדתי עם מודלים אחרים של רכיבי UI, בעיקר Java Portlets או כל מיני תקנים של widgets ו gadgets אחרים. הממשק היה כמעט תמיד מורכב בהרבה - והקשה מאוד על קהילה רחבה לתרום למודלים הללו. זה לא היה פשוט.

כאשר אני מתכנן רכיבים ב React/Angular אני עדיין יכול לעשות אותם גדולים ומורכבים (״רכיב Alpha 16 יספק את כל צורכי המערכת בטבלאות חיפוש, לכל האובייקטים, בשנים הקרובות״) או קטנים ופשוטים.

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


שיהיה בהצלחה!


----

[א] הערת אגב: עם הכבוד הרב שאני רוחש לפילוסופיה של יוניקס - אני עדיין מאמין ששמות מאוד קצרים הם טעות גדולה של יוניקס שמחירה מודגם שוב ושוב. שמות מאוד קצרים קשה יותר לזכור, וקל מאוד לבלבל בינהם / לפספס את המשמעות.
יוניקס הייתה טיפה מוצלחת יותר אם ל cat היו קוראים concat, ול wc היו קוראים wordcount (או פשוט count - מכיוון שיש לה הרבה אופציות ספירה שונות), ול man היו קוראים manual. הקנאות לקיצור הרגה את הקריאות ביוניקס.


----

לינקים רלוונטיים

סיכום החוקים של הפילוסופיה של יוניקס. אפשר לקרוא ולהנות.

כמה מילים על הפילוסופיה של יוניקס מספר מ 1995. מופיע בוויקי המקורי - תמציתי ומעניין.


7 תגובות:

  1. פוסט חשוב

    השבמחק
  2. חי ונושם לינוקס ומעולם לא הקדשתי דקה לחשוב על הצד ״הפילוסופי״ שלה.

    תודה על הפוסט :)

    השבמחק
  3. אנונימי18/5/20 06:44

    פוסט מעניין ומפתיע!

    הערה קטנה, במשפט הבא אמור להיות ׳קל׳ במקום ׳כל׳, לא?
    ״ע״פ הפילוסופיה של יוניקס ... תוכנה פשוטה כל לכתוב, וסביר יותר ...״

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

    השבמחק
    תשובות
    1. לא הכרתי, חיפשתי קצת ומצאתי משהו דומה למה שאתה מספר:
      https://www.quora.com/Why-did-Unix-use-shorthands-for-common-command-names-instead-of-their-full-name-for-example-cp-instead-of-copy

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

      מחק