דעה: 5 תחומי-המומחיות ש"עושים" ארכיטקט

מקצוע ארכיטקט התוכנה הוא מקצוע שאינו מוגדר בצורה טובה. רק חשבו על הווריאציות הרבות (או השמות השונים) של התפקיד:
  • Development architect
  • System architect
  • Enterprise Architect
  • Solution architect
  • Application Architect
  • Integration architect
  • Data architect
האם מישהו יכול לומר מה ההבדל בין התפקידים הנ״ל בצורה ברורה?
האם מישהו יכול לתת לאחד התפקידים הנ״ל הגדרה מעשית ויציבה?
חוסר בהירות – הוא כנראה חלק מהתפקיד.


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

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

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




 

מומחיות מספר 1: מומחיות טכנולוגית

"ארכיטקט" הוא קודם כל תפקיד טכני. ללא הבנה טכנית סבירה במערכת / שיטות וכלי העבודה – אני לא רואה כיצד ארכיטקט יכול לבצע את העבודה.

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

לארכיטקט חשובה יותר הבנה כיצד הדברים עובדים – מאשר היכולת "לקחת מקלדת ולבצע". יש הרבה ידע ו skill שנדרש כדי לבצע (quirks של סביבת העבודה וה build, להכיר היטב את תהליכי העבודה המעשיים – ולא התאורטיים, ידע מעשי של השימוש בכלים קצה לקצה) – skill שיש להשקיע בכדי לשמר.

חשוב שארכיטקט יוכל, מדי פעם, "לקחת מקלדת" ולכתוב קוד: לראות ולהבין את המערכת כפי שהיא. בסופו של דבר המערכת היא קוד שרץ – ולא רעיונות או תרשימים.
חשוב לעשות זאת "just enough", ופחות חשוב – לעשות זאת מעבר ל "just enough".

איך יודעים מה זה "just enough"? אי אפשר לדעת. זה תלוי באדם הספציפי, בארגון ובתקופה.
זה כמו לדעת בים כמה אפשר להתרחק מהחוף מבלי להסתכן: הכי בטוח זה לשבת על החוף (עם חגורת הצלה) – אבל זה לא כ"כ יעיל. ארכיטקט יכול להשקיע ולשלוט בקוד כמו כל מתכנת אחר – אבל אז הוא לא משקיע ברמת הבנה שאין למתכנתים בד"כ, הבנה שרק מישהו שלא שקוע בלחץ שוטף כל הזמן – יכול לפתח.

מדד מעניין לידע "Architect-like" הוא היחס בין "מה שאני יודע שאיני יודע" (בקיצור: "לא.יודע") לבין "מה שאני לא-יודע שאיני יודע" (בקיצור: "אין.מושג").

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

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

גם בידע הטכני שאותו יודע הארכיקט, יותר חשוב להבין איך הדברים עובדים מאשר להיות fully hands-on.
היכולת להבין נושאים לעומק – היא "היכולת המיוחדת" של הארכיטקט (או לפחות: אני מרגיש ששלי). עדיף לי להתמקד במה שחסר לקבוצה, במקום להיות "עוד שחקן אחד".

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

  • SQL ו noSQL
  • Open Source ו Commercial Software
  • שפות typed (כמו ג'אווה או ++C) ושפות דינאמיות (Python או javaScript)
  • ארכיטקטורת מונחית Data / שירותים וארכיטקטורה של components או Object-Oriented.
  • UI צד-לקוח, UI צד-שרת או Desktop UI [א]
קיים יתרון אמיתי לארכיטקט ש"מאמין" ביכולת לפתור בעיות ב-2 האלטרנטיבות, ארכיטקט שאינו "משוחד" לפתרון מסוג מסוים.
אמנם לא קל להגיע למצב שמכירים, ומאמינים (להכיר בכדי לנגח – זה לא מספיק) שני צדדים ויותר – ובמספר תחומים.
זוהי שאיפה ארוכת-טווח.

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

"הכל זה trade-offs" — משפט של ארכיטקטים.

מומחיות מספר 2: תקשורתיות טכנית

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

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

במידה מסוימת, ארכיטקטים הם ה "חומר מגשר" בין צוותים, קבוצות, פרויקטים או גופים שונים. לצוות או שניים – אין בד"כ בעיה לעבוד היטב ביחד. כשהמערכת גדלה ויש עוד ועוד אנשים מעורבים – נושאים חשובים נופלים בין הכיסאות ולא מטופלים. יש יותר ויותר "Local Optimizations" – צוותים שעושים מה שטוב לרכיב שלהם, או לתחום האחריות הצר שלהם, אבל לא מה טוב לכלל המערכת – קרי "Global Optimization".

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

סוגי ארכיטקטים שונים, כחומרים מגשרים בין גופים שונים.

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

מומחיות מספר 3: תקשורתיות אנושית והנעת אנשים

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

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

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

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

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

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

אפשר לומר שיכולת הארכיטקט להשפיע מורכבת מ:  יכולות טכניות x יכולות אנושיות.

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

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

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

מומחיות מספר 4: Domain knowledge

יש סיפור [ג] על פיתוח מטוס ה F-16:
בפיתוח גרסה מוקדמת של מטוס ה F-16 הייתה דרישה למהירות טיסה של עד שניים וחצי מאך (מהר!). צוות התכנון החל לעבוד על מנוע בעל עוצמה יוצאת דופן שיוכל לספק כוח לכזו מהירות, אולם אחד המתכננים הראשיים הבין שהחומרים מהם בנוי המטוס לא יחזיקו מעמד במהירות גבוהה כ"כ.
הוא היה יכול להחליף את החומרים לחומרים עמידים יותר – ולעלות בצורה משמעותית את עלות הייצור של כל יחידה, כי "אין ברירה הנדסית אחרת". הוא כנראה היה צודק.

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

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

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

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

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

על כן, הבנת ה domain – היא שאיפה חשובה לארכיטקט. כלי עבודה ממשי.
ה domain לא קל להבנה: בדר"כ אין לא מומחה יחיד / "גורו" נגיש, אין לו ספרות מסודרת (לפחות בראיית high level) או הדרכות. הדרך ללמוד את ה domain היא ארוכה – וקשה. אבל גם משתלמת.

מומחיות מספר 5: כלים של "ארכיטקטורת תוכנה"

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

  • מערכות של עקרונות הנדסת תוכנה כגון SOLID או GRASP. [כתבתי עליהן קצת בפוסט הזה, ובאופן עקיף גם בפוסט ההוא]
  • UML/sysML – שפות לתיאור פשוט של מערכות (מורכבות).
  • Quality Attributes – כלי להבנת ה non-function requirements של המערכת [כתבתי עליו בפוסט הזה]
  • ATAM – כלי להבחנה בין Trade-offs בהם נעשה שימוש במערכת.
  • "Architecture Styles" ו "Architectural Patterns" (שלעתים עושים יותר נזק מתועלת). הם שימושיים לתקשורת יעילה יותר בין אלו שמכירים אותם.
  • עוד כמה כלים… שאני פשוט לא מאמין בהם: למשל CBAM או Architectural Views אדוקים – שמעולם לא סייעו לי.
  • מתודולוגיה: סקראם, Lean Startup או Continuous Delivery. לא רק עניינם של ארכיטקטים, אבל גם.
  • הרבה Buzz words ותחכומים – להתחבא מאחוריהם.

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

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

קטרוג: "לא צריכים ארכיטקט"

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

"מדוע עדיף שלא יהיה ארכיטקט"

ביקורת לא כ"כ מבוססת או עניינית:

  1. ארכיטקט, כהגדרה, הוא לא מעודכן בטכנולוגיה. כשהוא היה היה מתכנת, COBOL (או ג'אווה – אולי "הקובול הבא") הייתה השפה – ועכשיו הכל אחרת והוא לא מבין שומדבר.
  2. ארכיטקט רק אוהב לצייר ריבועים ולסבך מערכות. הוא מזיק ולא תורם. דיי כבר עם SOA, MDA, EJB או Software Factories!
  3. ארכיטקטים עסוקים בליצר Job Security ולדאוג שכולם יהיו תלויים בהם – ובדרך רק עושים נזק.
לא שאין ארכיטקטים כאלו: פשוט תעמידו אותם במקום או אל תעסיקו אותם. זה לא טיעון רציני כנגד רעיון הארכיטקט ככלל.

ביקורת יותר עניינית:

  1. עצם קיומו של ארכיטקט, פוגע בעצמאות של המתכנתים: אם זה מישהו להישען עליו בפתרונות טכנולוגיים או קבלת החלטות, ואם בהבנת התמונה המלאה של כלל-המערכת.
  2. ארכיטקט שלא ממש חי את הקוד, אפילו אם הוא מבין פחות או יותר את הטכנולוגיה, עלול להוביל את המתכנתים למקומות לא נכונים. רק הבנה מלאה בפרטים – מספיקה כדי לקחת החלטות שמשפיעות על הקוד.
  3. ארכיטקט הוא לא גוף ביצועי (לפחות לא כמו מתכנתים) – ולכן הוא יכול להרשות לעצמו להטיל ביקורת על המבצעים ללא היכר. התוצאה: ניכור ומורל נמוך בקרב המתכנתים – שיוצר יותר נזק מסה"כ התועלת של הארכיטקט.
  4. ארכיטקט, מעצם קיומו או תפקידו, יכול לייצר מתח נוסף בקרב המפתחים ו / או אנשי המוצר (גם QA, Performance וכו'). חבל.
  5. כשהארכיטקט הופך להיות middleman – הוא יוצר שכבה מיותרת ומסרבלת של תהליכי הפיתוח.

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

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

סיכום

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

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

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

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

—-

[א] המקבילה המודרנית של Desktop UI היא native mobile app.

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

סדרה: לינוקס / אובונטו

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

  • היא "נחשבת"
  • היא שונה וקצת יותר נחמדה/מגניבה ממה שאתקל בעבודה (בעיקר הפצת SLES – Suse Linux Enterprise Server ואולי טיפה Red Hat Enterprise Linux).
  • ראיתי שכ"כ הרבה תוכנות זמינות או מתעדות שימוש ב apt-get (של אובונטו/debian) אבל לא ב zypper (של SUSE) או אפילו yum (של Red Hat/Centos/Fedora) – ורציתי לראות למה…
הערה: אם אין לכם מושג מה אמרתי, אבל אתם מרגישים שזה יכול להיות חשוב עבורכם – סדרת הפוסטים הזו היא בשבילכם.
אובונטו (ומשפחתו) נחשבים קצת יותר חזקים בצד ה Desktop – אבל אותי מעניין דווקא צד השרת ושימוש ב shell / command line בלבד. סדרה זו לא תקדם את מי שרוצה להשתמש בממשק גרפי בלינוקס, אלא אם מעניין אתכם מהם ה internals שמאחורי הממשק הגרפי.
למרות שההפצה "הכי מומלצת" ללמידת צד-השרת של לינוקס היא כנראה CentOS (סוג של red hat חינמי) – רוב מה שאכתוב בסדרת פוסטים זו תהיה רלוונטית כנראה גם למשתמשי CentOS/RHEL/SLES/Fedora וגם למשתמשים שולחניים (בעיקר Mint/Ubuntu) שרוצים להכנס לעומק ולהבין מה יש מאחורי ה"פנים היפות" של הממשק הגרפי.
—-
הפוסטים בסדרה:
פוסט בו נעשה הכרות מהירה עם אובונטו ונקבל כמה כלי הישרדות בסיסיים-ביותר לסביבה זו.
אם אתם רוצים להיות מסוגלים להתקין כל אפליקציה על (כמעט) על הפצה – זהו הפוסט בשבילכם.
בפוסט קצר זה נראה כמה כלים שימושים לעבודה עם קבצים בלינוקס: ה PATH, וכלים כמו tr ו sed (בקטנה)
אנו ממשיכים עוד קצת עם הטיול שלנו במערכת הקבצים, וקובעים מטרה: לוגים. אבל גם נהנים מהדרך עם: tail, redirects, find, קבצים מיוחדים ועוד כמה טריקים קטנים…
—-
קישורים:
אובונטו Server הופך לשחקן משמעותי: ?Is Ubuntu becoming a big name in enterprise Linux servers

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

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

בעבר ניווט בים נעשה ע"י סכימת מרחקי שיט שהספינה עברה. הספינה יצאה מנמל (עכו, למשל) והקפטן ספר: "6 שעות לכיוון מערב במהירות 10".
המהירות חושבה בצורה מדעית למדי: מלח השליך בול עץ (log) למים מחרטום האוניה. מכיוון שהאוניה מהירה יותר (יש לה הנעה מהמפרשים), היא עקפה את בול העץ בהדרגה. המלח ליווה את בול העץ מחרטום האוניה על לירכתיים – ושר לעצמו שיר. ברגע שבול העץ הגיע לקו יכרכתי האוניה, השירה נפסקה ובול העץ נשלף מהמים. ע"פ המקום בו הפסיק השיר נקבעה – מהירות השיט: "אבל את לא מבינה…" – מהירות 7. "…אל תהיי תמימה" – מהירות 6.

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

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

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

פוסט זה הוא חלק מהסדרה: לינוקס / אובונטו

חיפוש אחר …

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

find ~ -name index.html

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

התחביר שלה בפועל הוא משהו כזה:

find
  • symbolic links options – נתעלם מחלק זה. כברירת מחדל find לא "נכנסת" ל symbolic links.
  • root path- מתחתיו יתבצע החיפוש. אם לא צוין, יהיה . (התיקיה הנוכחית).
  • search options – נוגעים לאופן החיפוש: איזה עומק לחפש (depth), האם לחפש ב mounted drives (פרמטר mount-) וכו'.
  • search arguments – נוגעים לתכונות הקבצים עצמם: שם, גודל, תאריכים, הרשאות וכו'.
  • action- מה לעשות עם הקבצים שהתאימו לחיפוש. ברירת המחדל היא print- (הצגה ל standard output). אפשרויות אחרות כוללות הפעלה פקודה כלשהי בלינוקס (rm, mv וכו').
קצת קשה לזכור את הסדר של סוגי הפרמטרים השונים. אם מתבלבלים בסדר הפרמטרים אזי יופיע warning נוסח "non-option argument", או במקרה הפחות טוב – יקרה משהו שונה ממה שהתכוונתם.

הנה דוגמה לכמה חיפושים אפשריים:

find ~/js_project -iname "*.js" -size -10k

תחפש קבצים בסיומת js. הארגומנט iname מחפש ע"פ שם בהתעלמות מ case. כלומר גם סיומת "Js" תמצא. הארגומנט size- מגביל את גודל הקובץ, במקרה שלנו עד 10kB. שימוש ב 10k+ היה מחפש קבצים בגודל 10kB ומעלה.

דוגמה קצת יותר מורכבת:

find /home ! -user baronlior -exec touch {} \\;

תחפש את הקבצים של משתמש שאינו (סימן !) המשתמש "baronlior" בתיקיה home/, ובמקום להדפיס את הקבצים למסך – תפעיל עליהם את פקודת הלינוקס touch. הפעולה exec- מקבלת expression כלשהו שנגמר ב ;. באובונטו צריך escaping (כל הפצה מתנהגת מעט שונה) – ולכן  ;\\ מציין את סוף ה expression. הסוגריים המסולסלים יוחלפו כל פעם בשם הקובץ. לכן המשמעות בפועל היא הפעלת הביטוי הבא על כל קובץ שנמצא:

touch

פקודת touch מעדכנת את ה modification date של הקובץ לזמן הנוכחי. "נוגעת בקובץ, מבלי לשנות את תוכנו באמת".
אם הקובץ לא קיים – היא תיצור אותו. פקודה שאני מוצא כשימושית למדי.

אחד העקרונות של ה shell של לינוקס הוא: "נגעת – נשאת". אין שאלות "Are you sure" גם על פעולות משמעותיות. כדי להמנע מ"תקלה מצערת", ניתן להפעיל את פקודת ה find הנ"ל בצורה הבאה:

find /home ! -user baronlior –ok touch {} \\;

ok- הוא כמו exec-, רק שהוא שואל אותנו, קובץ אחר קובץ, אם אנחנו בטוחים.

הנה כמה לינקים עם דוגמאות נוספות לשימוש ב find:
60 דוגמאות מעשיות ל find – חלק א'
60 דוגמאות מעשיות ל find – חלק ב'
15 דוגמאות מעשיות לשימוש ב find (קצר יותר)

חיפוש אחר לוגים

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

find /var -name "*log*" | grep log
כאשר משתמשים ב regex / wildcards – כדאי לעטוף את הערכים במרכאות כדי למנוע בלבול.
אני משתמש גם ב grep, כטריק קטן, בכדי להדגיש את התוצאות.
grep, אם אתם לא זוכרים מהפוסט השני בסדרה, הוא כלי ש"מפלטר" זרם (stream) של טקסט רק לשורות המכילות מילת מפתח – וגם מדגיש את המלים הללו.
grep יכול לעשות יותר מזה. הוספה של פרמטר 2 A- ,למשל, תאמר ל grep להציג 2 שורות נוספות מהטקסט לאחר השורה שבה היה match. הפרמטר הוא A עבור after ויש לו אח מקביל, B, עבור before.
ב grep ניתן להשתמש גם באופן עצמאי בכדי לחפש טקסט בתוך מספר קבצים (ע"פ pattern).
בכל מקרה, הנה התוצאה של החיפוש שלי:
קצת ארוך. בואו נקצר ע"י בקשה של חיפוש אחר תיקיות (type = d) בלבד:
2 תוצאות שמצאנו – נראות בהחלט רלוונטיות.
כפי שניתן לראות יש עוד 4 תיקיות בהן לא הצלחנו לבצע חיפוש – מכיוון שאין לנו הרשאות קריאה בהן. אולי אנחנו מפספסים משהו?
ניתן להשתמש ב sudo.
קצת מעצבן להקליד את השורה הארוכה (נניח) שכבר הרכבנו פעם נוספת, לא?
בעזרת SSH client מתקדם ל ניתן להריץ מחדש עם sudo בקלות יחסית עם העכבר / קופי-פייסט.
יש דרך קלה אפילו יותר, שתעבוד עם ה SSH client הפרימיטיבי ביותר / terminal:
sudo !!
!! הוא משתנה שערכו הוא הפקודה האחרונה שהוקלדה ב shell. לאחר שימוש בפקודה. כאשר אנו משתמשים ב !!, ה history שיזכר הוא כאילו הקלדנו הכל מחדש. מאוד נוח – רק שימו לב לא להקל ראש בשימוש ב sudo עם הטריק הזה.
בעזרת הרשאות sudo, מצאנו עוד תיקיה בשם logrotate. לא תיקיה שמעניינת אותנו כרגע.
בואו נתבונן על תסריט מעט אחר:
נניח שלא ניתן להשתמש ב sudo ויש הרבה תיקיות שאין לנו אליהן הרשאות (מצב הגיוני בשימוש ב find, במיוחד על שרת production). מה עושים? כיצד מפלטרים את כל הודעות השגיאה מהתוכן המשמעותי?
תזכורת של ה"בעיה"
אפשר בוודאי לעשות משהו עם grep, אבל אני רוצה לתקוף את הבעיה מכיוון אחר. ננסה:
זהו. אני מרגיש שהתחלנו להיכנס ל hardcore של השימוש ב shell. אני מניח שרוב מפתחי java ו / או C מכירים את 3 הערוצים של מערכת ההפעלה: stdout, stdin ו stderr (הממוספרים 0, 1 ו 2 – בהתאמה).
אלו הם ערוצי ה shell של לינוקס שב C עושים בהם שימוש, וג'אווה אמצה אותם כממשק (תחת המחלקה System):
ישנו ערוץ אחד של קלט (stdin) ושני ערוצי פלט. למרות שאנו רואים על המסך תוצאה של הרצת התוכנה / פקודה כשטף אחד של שורות טקסט, בעצם מערכת ההפעלה מסווגת ומנהלת אותם כ 2 ערוצים שונים:
  • stdout הוא קיצור של standard output – תוצאת ההרצה
  • stderr הוא קיצור של standard error – שגיאות שהתגלו בהרצה.
בעזרת פעולת I/O redirect (קרי <, <<, אך גם > הנדירה יותר) אנו יכולים לשלוח את התוצאות של פלט התכנית ל stream (קובץ, רשת) שהגדרנו. בעזרת " <n ", כאשר n הוא מספר ערוץ הפלט 1 או 2, אנו יכולים לפצל את הערוצים ולשלוח רק אחד מהם ל stream נבחר.בפקודה למעלה שלחתי את ערוץ השגיאות לקובץ בשם err.txt, שכפי שניתן לראות בתצוגה שלו מיד לאחר כך – הוא קיבל את כל הודעות השגיאה.

אני מקווה שההסבר מובן.

קבצים מיוחדים

נשמור את קובץ השגיאות שלנו עכשיו במקום אחר:

find /var -name "*log*" -type d 2> /dev/null | grep log

מה זה הקובץ הזה? בואו נבדוק:

  1. ניסינו להציג את הקובץ – אך שום תוכן לא נראה. היכן השגיאות שלנו?!
  2. האם קובץ כזה בכלל קיים? בדקנו – וכן, הוא קיים.
  3. נשתמש ב file לבדוק מאיזה טיפוס הוא. הממ… "סוג מיוחד" (character special)

מה קורה פה?
dev/null/ הוא קובץ מערכת מיוחד, אחד מכמה בודדים במערכת Linux (עד כמה שידוע לי).
dev/null/ הוא סוג של "recycled bin": מה שנשלח אליו – נמחק לעד לפני שתספיקו לומר… "… sudo".

מתי הוא שימושי? כתחליף לקובץ זמני שאנו מתכננים למחוק – אך אנו יכולים לשכוח למחוק (ואז נשאר "זבל"). אני מניח שהוא גם מהיר יותר – כי שום דבר לא נכתב באמת לדיסק.
אם יש לנו פעולה שמייצרת הרבה error, אבל אנו יודעים שזה בסדר ולא רוצים לראות את השגיאות (כמו בדוגמה לעיל) – כתיבה ל dev/null/ במקום err.txt – היא שימושית.
קובץ מיוחד נוסף הוא dev/zero שהוא בעצם stream אינסופי של אפסים.
כיצד ניתן להשתמש בכזו חיה מוזרה?
למשל:
cat /dev/zero >> large.txt
ייצר לנו קובץ (מלא אפסים) בגודל כמה MB תוך שניות בודדות. שימושי לצורך בדיקות מקרי-קצה.
הפקודה "cat large.txt" לא תציג שום דבר, כי ערך 0 של ASCII הוא בלתי מוצג (זה לא התו "0", שערך ה ASCII שלו הוא 48). הפקודה:

xxd large.txt | less
דווקא תציג את תוכן הקובץ. xxd – קיצור (משונה) של hex dump. תוכנה זו הופכת מידע בינארי (כלומר: בייצוג הטבעי שלו) לתצוגה בינארית [א]. הצגתי את תוצאת ההמרה בתוך ה viewer הפשוט של לינוקס שנקרא less.

כשאפסים לא מתאימים למשימה, ניתן להשתמש באופן דומה dev/urandom/, שהוא פחות מהיר אך מייצר stream של מספרים פסודו-אקראיים.

קובץ מיוחד אחרון שאזכיר הוא dev/full/, שבכל פעם שננסה לכתוב אליו נקבל שגיאה שהדיסק מלא (שימושי עבור בדיקות).

אבל מה עם הלוגים?!

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

אפשר לראות שלוגים ישנים יותר נדחסים (צבע אדום) בכדי לחסוך מקום. התהליך שעושה זאת נקרא logrotate.
אפשר לראות תיקיות עם עוד logs ע"פ נושאים (apt – התקנות או upstart – תהליך האתחול של אובונטו). כשמותקן שרת Apache, לדוגמה, הוא יאכסן את הלוגים שלו בתיקיית בת בשם /httpd.

כדי לצפות בקובץ שדחוס ב gzip (סיומת gz), יש פשוט להשתמש ב zcat, גרסה של cat שפותחת את הדחיסה on the fly:

zcat syslog.2.gz

אפשר לציין כמה לוגים עקריים:

  • syslog – לוג ברירת המחדל להודעות מערכת. syslog הוא לא רק קובץ לוג, אלא גם שם של פרוטוקול להעברת לוגים בין מערכות. למשל: הקצאת שרת אחד עליו יכתבו כל הלוגים של כל שרתי ה production.
  • daemon.log – לוג של שירותים שרצים ברקע.
  • kernel.log – הודעות קרנל של מערכת ההפעלה.
  • auth.log – רשימה של פעולות התחברות למערכת ושימוש בפקודת sudo.

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

[Timestamp in syslog format] [Host] [Process]: [Message text]

host, אפרופו, הוא חשוב מכיוון שפעמים רבות מרכזים בעזרת syslog את הלוגים לא על השרת בו התרחשו האירועים.

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

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

קובץ ההגדרות הראשי הוא rsyslog.conf (הנמצא במקביל תיקיה rsyslog.d) – המגדיר את המודולים האחראים על הלוגים, הרשאות של קבצי log שיכתבו וכו'.

את ההגדרות היותר שימושיות ניתן למצוא בקובץ ברירת המחדל של הגדרות הלוג etc/rsyslog.d/50-default.conf:

ניתן למשל לראות, שקובץ הלוג של תהליכי הרקע (daemon.log) הוא disabled כברירת מחדל.

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

tail -50 syslog | less

תציג לנו בתוכנת less רק את 50 השורות האחרונות של קובץ ה syslog. הטריק הוא לקרוא את כל הקובץ ולהציג רק את 50 השורות האחרונות: tail בעצם מבצע seek על הקובץ וקורא רק את הבלוקים האחרונים שלו עד שיש לו את מספר השורות שביקשנו – מה שמיעל דרמטית את זמן הטעינה של הלוג.

עוד דבר נחמד שקיים ב tail הוא הפרמטר f- (קיצור של follow) שיאזין לשינויים בקובץ לוג ויציג אותם ברגע שיתווספו לקובץ. למשל:

tail -f syslog

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

סיכום

עברנו עוד כברת דרך בטיפול בקבצים בלינוקס/אובונטו: פקודת find, קבצים מיוחדים, לוגים, ועוד. לפעמים ה"עוד" הזה הוא החלק החשוב ביותר 🙂
בתחום הקבצים בלינוקס/אובונטו נותר לנו לדבר בעיקר על הרשאות ו symbolic links…

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

[א] בדומה למצב debug ב DOS – למי שזוכר, אבל אז כל מילה הייתה 16 ביט / 2 בתים.

לינוקס/אובונטו – התנהלות עם קבצים, ההתחלה…

בלינוקס, יש לנו path המתאר תיקיות בהן מחפשים קבצים, אם הם לא נמצאו בתיקיה הנוכחית – ממש כמו בחלונות.הערה: קצת מוזר לומר שמשהו ב Linux דומה לחלונות. המקור ממנו שתיהן הושפעו הוא כמובן UNIX, כאשר Linux הושפעה מאוד מ UNIX, וחלונות – רק במעט. בגרסאות האחרונות (Windows server 2003 ומעלה) ניתן לראות יותר מנגנונים בחלונות שדומים ל UNIX (ביצוע פעולות עם super user, יציאה מה registry לתיקיות קונפיגורציה, כל ההתפתחות של power shell, ועוד) – אולי בכדי לסגור פערים מול פ'יצרים מוערכים בלינוקס.

פוסט זה הוא חלק מהסדרה: לינוקס / אובונטו

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

echo $PATH | tr ':' '\\n'
מדוע השתמשתי בפקודה tr*?
א. כדי להוסיף קצת אקשן, וללמוד כמה דברים נוספים על הדרך, ו
ב. כדי לא לקרוא את ה path בשורה אחת צפופה, כמו כלב.

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

הנה תוצאת הפקודה על המחשב שלי:

כמה הסברים על התוצאה – מדוע כך נראה PATH ברירת-המחדל:

  • לינוקס מפרידה בין executables לשימוש כללי (תיקיות bin; קבצים לדוגמה: ls או cat) ו executables המשמשים את מערכת ההפעלה עצמה (תיקיות  sbin; קבצים לדוגמה: reboot, init או mkfs [א]).
  • תיקיות bin/ ו sbin/ (ישירות תחת ה root) – הן עבור executables שצריכים להיות זמינים בשלב מוקדם של ה boot sequence של מערכת ההפעלה, לפני שהתבצע mount לתיקיית ה usr/
  • תיקיית usr/, בניגוד ליוניקס או חלונות, היא איננה תיקיית "user data" אלא "user applications".
  • תיקיות */usr/local/ נועדו לאפליקציות (או סקריפטים) שאנו מוסיפים למערכת. הם לא חלק מהמערכת  ו / או מנוהלים ע"י ה package manager. אפליקציות שמגיעות דרך ה package manager לא יכולות להיות מותקנות בתיקיית ה local.
  • משחקים? על ubuntu server? אולי לשעות המתות של ההתקנות… (התיקיות עצמן ריקות).

נחזור לפקודה עצמה:

echo – אנחנו מכירים (אמורים להכיר מפוסט קודם). שלא כמו בחלונות, יש להקפיד על upper-case ב PATH (או כל משתנה אחר).

tr (קיצור של transliterate, אפשר לזכור את זה כקיצור של translate) הוא בעצם סוג של כלי search-replace. אנו מחליפים את ":" (ה separator בין paths במשתנה PATH) לשורה חדשה. מתכנתים אמורים להרגיש נוח עם n\\.

tr עובדת על תווים בודים (characters) ומבצעת החלפה, בהתאמה, בין ערכי הפרמטר הראשון לערכי הפרמטר השני. לצורך התרגיל:
echo $PATH | tr ':' '\\n' | tr 'a-z' 'A-Z'
תחליף גם אותיות לטיניות ל upper case.

אם אנו באים מרקע של חלונות, אולי כדאי להציג את ה PATH בצורה יותר מוכרת, ב "Windows format"?     😉

echo $PATH | tr ':' '\\n' | tr 'a-z' 'A-Z' | tr '/' '\\\\' | sed -e 's/^/C:/'
הנה התוצאה:
לא להיבהל אם הפקודה עמוסה בסימנים. חתכו בראש את ה pipes ועברו שלב-שלב: אלו שלבים פשוטים.
את ההתחלה אתם כבר מכירים. עבור התו \\ היינו זקוקים ל escaping (\\\\). את ההוספה של :C בתחילת כל שורה לא יכולתי לעשות בעזרת tr: מכיוון ש tr מחליפה כל סימן בסימן אחר (או כלום) – אך היא לא יכולה לטפל במחרוזות ארוכות יותר ":C". הקלידו man tr בשורת הפקודה כדי ללמוד על כמה אופציות נוספות שיש לה (בעיקר זיהוי סימנים טוב יותר או העלמה יעילה של תוים – החלפה בכלום).
כש tr הפשוטה לא מספיקה – עוברים ל sed (קיצור של stream editor).sed היא פקודה רבת-עוצמה המאפשרת חופש פעולה רב מאוד. במקרה הזה השתמשתי בה בכדי לבצע החלפת טקסט דומה ל tr. הפרמטר e- אומר שאני רוצה לעבוד עם sed script (מה שבמרכאות) והפתיחה באות s היא פקודה ב sed script בפורמט "/s/regex/replacement". כלומר: ה regex הוא ^ (תחילת שורה) וההחלפה היא המחרוזת ":C". / הם רק separators בין הפרמטרים.

צחקנו קצת – יופי.

הוספה ל path
נניח ואנו רואים את ה path ולא מרוצים ממנו. אנו רוצים להוסיף לו את התיקיה: usr/local/games/2048/ כדי שהמשחק (בגרסה ה shell-ית שלו) יהיה זמין לנו להפעלה מכל מקום ובכל רגע.

2048. גם אנשי bash – מתמכרים.

כדי להוסיף למשתנה path יש לכתוב:

PATH=$PATH:/usr/local/games/2048

תחביר דומה ל x = x + n. שימו לב שאנו זקוקים prefix של $ בכדי לקרוא את הפרמטר PATH – אך לא כדי לכתוב לתוכו.

יש לנו בעיה: לאחר login מחדש עם ה shell – ה PATH יחזור למצבו הקודם.
הסיבה: בכל התחברות מחדש עם SSH – רץ סקריפט שדורס את משתנה ה PATH.

מה נעשה? נדרוס אותו עוד פעם בעצמנו.

אתנחתא קלה

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

ובכן, הכל בסדר בלינוקס. לינוקס פשוט – גלויה יותר.
גם בחלונות רצים scripts להגדרת הסביבה בכל פתיחה שלה (יהיה זה PowerShell, cmd, או Connect-WSMan) – פשוט מערכת ההפעלה מחביאה פרט זה מהמשתמש. כל script כזה הולך למקום בו שמורים ה environment variables ויוצר אותם בסביבה. אפשר בקלות רבה לממש לוגיקה דומה בלינוקס: קובץ משתנים וסקריפט שנטען לכל משתמש ויוצר את המשתנים הללו בסביבה.

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

  1. etc/profile/ – סקריפט אתחול לכלל המשתמשים
  2. profile./~ – סקריפט אתחול למשתמש, שבעקרון קיים בשביל תאימות-לאחור (אך בהחלט אפשר להשתמש בו)
  3. bash_profile./~ סקריפט שרץ בזמן login של המשתמש
  4. etc/bash.bashrc/ סקירפט אתחול לכלל המשתמשים בעת הפעלה של bash ב interactive mode (קרי טרמינל או SSH).
  5. bashrc./~ סקריפט אתחול למשתמש בעת הפעלה של bash ב interactive mode.
רשימת הסקריפטים שנטענים תהיה שונה אם עובדים עם shell אחר, למשל ksh (קיצור של kornShell).
בד"כ עורכים את bashrc/~ (כלומר: בתיקיית הבית של המשתמש), אם רוצים להשפיע על המשתמש הבודד ב bash.
אם מדובר על משתני סביבה שיהיו בשימוש עבור איזה תהליך שרץ עבור המשתמש, בלי שהוא מחובר אינטרקטיבית – יש לערוך את profile./~ בכדי לקבל את התוצאה הרצויה.
איך עושים זאת בצורה פשוטה מקוצרת [ב]?
echo 'PATH=$PATH:/usr/local/games/2048' >> ~/.bashrc

"<<" עובד בדיוק כמו שעובד בחלונות (הוספה לסוף קובץ),  כך שלא משנה מה יש בקובץ – הוספה לסופו היא בטוחה למדי (כלומר: יחסית. כל מה שיכול להשתבש – אכן ישתבש).

"Unix is user-friendly. It just isn't promiscuous about which users it's friendly with." – "Steven King, Software Archaeologist"

עוד טיפ קטן: לפעמים אתם רוצים לדעת איפה executable יושב: אולי חסרות לו הרשאות, ואולי לכם הוא זמין ב PATH ולחברכם לא – אבל אתם לא רוצים לזרוק עליו עשרה paths שאתם משתמשים בהם. פקודת which מחפשת ב PATH (ללא כניסה ל symbolic links) אחר executables ומדווחת על מיקומם:

סיכום

בחיי שרציתי לדבר על ניהול קבצים! ניהול הרשאות עם chmod, חיפוש עם find, אולי symbolic links, אולי משהו נוסף.
אבל – קצת נגררתי. אני רוצה לכסות את הנושאים בהם אני נוגע בצורה מעמיקה, כך שמי שקורא יבין ולא רק "ידע" – אבל בלינוקס זה אומר כנראה שיש הרבה מאוד מה ללמוד.

נראה לי שמשיך עוד קצת, עד שימאס לי או שאראה (ע"פ השימוש) – שלכם הקוראים זה נמאס.

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

—[א]  קיצור של make file system

[ב] הדרך הפשוטה להוסיף שורה בסוף הקובץ הוא לפתוח אותו ב editor כלשהו ולראות בעיניים מה עושים (אלא אם עושים זאת בסקריפט).

ה UNIX WAY אומרת: Clarity is better than cleverness. בטוח שהרבה כותבי סקריפטים בלינוקס לא הולכים לפי כלל זה. הנה דוגמה לסקריפט למעלה כשהוא "מתוחכם", אך לא קריא (לטעמי):

echo $PATH | tr ':/a-z' '\\n\\\\A-Z' | sed -e 's/^/C:/'

ניסוי בטכנולוגיות צד-לקוח (React.js)

פוסט זה נכתב בשיתוף פעולה של ניר בנימין, איתמר שגב ושלי.
הוא מסכם ניסיון של 3 ימים בכתיבה בראקט, שהתרחשה במסגרת "האקתון" במעבדות SAP.
הפוסט פורסם לראשונה ב geektime, אך ללא הפיסקה "כמה נושאים מעט יותר מתקדמים" (בעצתו של ניר – בכדי להקל מעט על הקוראים). אני רוצה להאמין שקוראי בלוג זה הם בעלי קיבולת גבוהה יותר מ 1600 מלים / 7 דקות קריאה – המומלצות לבלוגים.אמרו לי אם לא. אני לא מזלזל בטענה "זה קצת ארוך מדי בשבילי". אנחנו בני-אדם.

—-

Angular.js, ספריית ה MVC מבית גוגל לצד-הלקוח, הופכת לבחירה יותר ויותר מקובלת בקרב מפתחים. כיום, היא אחד הנושאים המדוברים ביותר בטכנולוגיות צד-לקוח.

בצד ההגמוניה ההולכת ונבנית ע"י אנגולר בצד-הלקוח, נשמעים בד בדד, גם קולות הטוענים שאנגולר מורכבת מדי – שאפשר לעשות את הדברים בצורה פשוטה יותר. פשטות היא ערך משמעותי בעולם הקוד הפתוח ובצד הלקוח בפרט. אחד הקולות הללו מגיע מצד Facebook ו Instagram. הפתרון שלהם: ספרייה ששוחררה לפני כשנה בשם react.js.

React.js (להלן "ראקט"), לא תתחרה באנגולר ראש-בראש בעתיד הנראה לעין: אנגולר היא מקיפה הרבה יותר (הן פונקציונלית והן תהליכית), ומתאימה הרבה יותר ל mainstream.
ראקט פותרת רק חלק קטן ממה שאנגולר פותרת – ועושה זו בצורה לא שגרתית, מה שעלול להרחיק ממנה מפתחים רבים מה mainstream. היא אנדרדוג. כמה מהרעיונות שלה מקוממים במבט ראשון. אולי גם במבט שני :).

יש כבר כמה דוגמאות לשימושים ב React.js במוצרים מרכזיים[א]: פייסבוק (חלקים), אינסטגרם (עם ה router של backbone) ו Khan Academy (עם Backbone). ניתן למצוא עליה דיונים ב StackOverflow ואפילו יש 4 גרסאות שונות שלה לשימוש ב jsFiddle.

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

יצאנו לבדוק במה מדובר…

מה ראקט מציעה?

הדבר הראשון הניכר משימוש בראקט הוא מ Client Side Rendering מהיר ביותר! ראקט יכולה לשמש לכתיבת אפליקציות שמרגישות מאוד "חלקות" ולא נתקעות. היא מתאימה לאפליקציות בעלות רינדור אינטנסיבי.

עד כמה שזה מרשים – זה עדיין לא פיצ'ר שמצדיק שימוש בספרייה עבור רוב המשתמשים. היכולות הללו בעיקר קוסמות למי שנמצא ב extreme optimization של אפליקציות ווב (כמו חברי "מועדון ה sub-second") ומחפש דרך לאופטימיזציה גבוהה מאוד, מבלי לחרב את הקוד.

האלמנט השני שמאפיין את ראקט הוא פישוט צד-הלקוח בכל הנוגע לעדכונים של ה DOM.
בד"כ באפליקציה נראה 2 סוגי עבודה עם ה DOM: בנייה ראשונית של האפליקציה (על בסיס state מסוים) ועדכון ה DOM הקיים בנתונים חדשים. באפליקציות SPA, עדכון ה DOM הוא חלק משמעותי מהאפליקציה.

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

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

רעיון שלישי ואחרון של ראקט הוא חלוקה מחדש של ה concerns בצד הלקוח: במקום הפרדה בין UI, לוגיקה, נתונים ואולי שליטה (וריאציות שונות של MVC) – ראקט מציעה הפרדה לרכיבים המחולקים ע"פ "יכולות עסקיות", כאשר כל רכיב אחראי על הנתונים, הלוגיקה וה UI שלו בעצמו.

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

רבים ממשתמשי ראקט לא מאמצים / מאמצים חלקית בלבד את הרעיון השלישי, ומשתמשים בראקט בתור שכבת UI (קרי View) לארכיטקטורת MVC סטנדרטית. MVC היא אולי לא מושלמת – אך היא מוכרת ומובנת (כלומר: כל קבוצה מכירה אותה בדרך משלה).
שימוש בראקט עם Angular או Ember אפשרי, אך הוא לא נפוץ. השימוש בראקט מייתר חלק מיכולות Angular/Ember ומחליש את הסדר המובנה שהן מציעות. שימוש בראקט עם Backbone.js, הוא דווקא טבעי בהרבה – כאשר ראקט מחליפה את ספריית ה Template ליצירת Views.

יש כאלו הממליצים להתחיל לעבוד עם ראקט כ View של Backbone, ורק לאחר שמשיגים בצורה זו שליטה – להמשיך הלאה.

סיכום ביניים:

  • ראקט לא מציעה MVC, או תחליף ישיר ל MVC.
  • ראקט מהווה סוג של תחליף ל Templates (וקצת יותר מכך). במקום שפת template "מנוונת" – ראקט מאפשרת להשתמש (פחות או יותר) בג'אווהסקריפט לבניית ה markup.
  • ראקט מערבבת בין ג'אווהסקריפט לבין "HTML) Markup)", אך מפרידה בין רכיבים על הדף – כל אחד אחראי על הפונקציונליות שלו.
  • ראקט יעילה מאוד ברינדור, ומתאימה לאפליקציות אינטנסיביות ברינדור (בעיקר כאלו שעובדות על ה DOM).
    אציין שגם Ember יעילה למדי בתחום זה (בעזרת Handlebars) – אולם נראה שהקוד יהיה פחות קריא.

כיצד ראקט עובדת

React.js היא ספרייה פשוטה, יחסית, בעלת אלמנטים ספורים.

הגדרת רכיבים (Components) נעשית ע"י המבנה הבא:

var = React.createClass({
  method1: function(…){..};
  method2: function(…){..};
});
לא שונה בהרבה מ Backbone, Angular, או ספריות נפוצות אחרות.

בראקט ישנה הבחנה בין 2 סוגי רכיבים:
  • רכיבים שהם Immutable
  • רכיבים בעלי state
שני הרכיבים נוצרים ע"י createClass, אך הם שונים בשימוש שלהם ב State: האם כותבים משהו על ה state של הרכיב או לא. ראקט מעודדת לנסות ולכתוב כמה שיותר רכיבים Immutable – עבור יתרון בביצועים. כדי לחסוך ב Garbage Collections ראקט מבצעת pooling של אובייקטים (כגון Events) ועושה בהם שימוש-חוזר.הרכיבים מושפעים בעת הרינדור שלהם מ2 מקורות: ה properties – שנקבעים בעת יצירת המופע של הרכיב (ולא ניתן לשנותם מרגע זה) וה state – שנשמר על הרכיב, וניתן לשנותו בכל רגע. בד"כ ה properties ישמשו גורם חיצוני לקבוע את התנהגות הרכיב, בעוד ה state הוא פנימי לשימושו של הרכיב.

אפליקציית ראקט טיפוסית מתחילה בקריאת:

 React.RenderComponent();
היוצרת את רכיב האב וקוראת ל ()render שלו. הוא מצידו יקרא ייצור מופעים של רכיבים בנים (משולבים ב HTML markup) – ויקרא ל render שלהם וכך חוזר חלילה לעומק עץ של רכיבים ו markup.

כאשר יש שינוי ב state של אחד הרכיבים – פונקציית ה ()render של אותו רכיב תקרא ותגרום לעדכון של תת העץ שלו.
הרכיבים בראקט מגדירים את המראה שלהם בעזרת Markup ורכיבים בנים, כאשר הם לא כותבים ישירות ל DOM של הדפדפן לא רק ל React.DOM – ה DOM הוירטואלי שראקט מנהלת.

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

ראקט מחלקת את הטקסט לרכיבים אטומיים קטנים, כך שיהיה אפשר לעדכן רק את ה nodes של הערכים (בירוק), מבלי לעדכן את הערכים של ה Labels (בצהוב). שימו לב למספור שראקט מייצרת על ה DOM (תכונת data-reactid) – בעזרתו היא מבצעת השאוות יעילות של ה DOM.
הרעיון של Virtual DOM אינו חדש, אגב: Backbase הציגה מין Virtual DOM משלה לפני שנים (היא כנראה לא היחידה), וטכניקה דומה נמצאת בשימוש במנועים גרפיים של משחקי מחשב.
הניתוק מה DOM מאפשר לראקט גם לרוץ בצד השרת (עבור מכשירים חלשים / sub-second load time) – ממש כמו rendr עבור Backbone.js.
השוואה לא מדוייקת בין האתר Hacker News (שורה עליונה) ו clone שלו שכתבנו בראקט (שורה תחתונה). אדום – טעינה ראשונית. בכחול – פעולת דפדפוף בין הכתבות (האתר שלנו היה הרבה-הרבה יותר מהיר). פרופיל ה timeline שקבלנו מקוד הראקט מאוד לא אופייני לאתר / אפליקציה שלא עברה עדיין שום אופטימיזציית ביצועים.

דוגמת קוד

אין כמו לראות קצת קוד.
הנה אפליקציה פשוטה למדי עם 2 כפתורים (++X ו ++Y) המעלים את הערכים של ה counters המתאימים במרכז המסך.

התוצאה הסופית של האפליקציה

קוד ב react ניתן לכתוב באחד מ2 סגננונות: JSX ו"ג'אווהסקריפט נקי".
JSX הוא הרחבה לג'אווהסקריפט עם XML (מבוסס E4X?), המאפשרת לכתוב snippets של XML בתוך הג'אווהסקריפט ע"פ חוקים מסויימים.

JSX אמור להיות פשוט יותר ונקי יותר לכתיבה – ועל כן מועדף ע"י החלק הגדול של מפתחי ראקט. ה JSX מקומפל לג'אווהסקריפט רגיל לפני שהוא מורץ על הדפדפן. ניתן לקמפל אותו בתוך הדפדפן ע"י הוספת קובץ ג'אווהסקריפט בשם JSXTransformer (לפיתוח מהיר יותר) או בצד השרת ע"י רכיב מתאים של Node (לביצועים טובים יותר).

אנו עבדנו ב IDE בשם WebStorm (מומלץ) שקיבל יפה מאוד את הרחבות ה XML בתוך קובצי ה javaScript, והמשיך לתפקד היטב עם קוד הג'אווהסקריפט (hinting, ניווט, וכו').

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

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

  1. כאשר משתמשים ב JSX Transformer בכדי לקמפל JSX "תוך כדי שימוש" ("on the fly") – חייבים לכלות הערה זו בתחילת הקובץ.
  2. אנו מגדירים רכיב (component) פשוט של ראקט, בשם Simple.
  3. את הרצת התוכנה בראקט מבצעים בעזרת פקודת renderCompoent על הרכיב הראשי. שימו לב לתגים ה Simple – שאיננה סטנדרטית ב HTML, אלא מבטאת את הרכיב שלנו. אנו שולחים לרכיב ה Simple שלנו Property (בלתי ניתן לשינוי immutable) – בשם message ואומרים לראקט להוסיף את הרכיב בתוך document.body (קרי InnerHTML).
  4. אחד השלבים הראשונים במחזור החיים של רכיב react הוא קריאה למתודה ()getInitialState המאתחלת את ה state של הרכיב. בשלב זה, ניתן להבין שזהו stateful component.
  5. שלב מעט מאוחר יותר במחזור החיים של הרכיב, הוא הקריאה למתודה ()render המייצרת את ה markup של הרכיב – ומחזירה אותו לרכיב האב (במקרה זה – זהו רכיב האב).
  6. יצירת ה markup נעשית על ידי כתיבה inline של markup ב JSX. עטפנו הכל בסוגריים כדי שנוכל למקם את ה div הראשון בשורה חדשה (אחרת JavaScript יחשוב שרצינו לכתוב ;return, ואח"כ אולי עוד משהו לא רלוונטי).
  7. סוגריים מסולסלות הוא ה escaping לשילוב ביטויי ג'אווהסקריפט בתוך ה XML (חייב לחזור ערך). במקרה זה אנו קוראים לאובייקט ה properties של הרכיב (שהוא immutable  – בלתי ניתן לשינוי). את הערך של התכונה message קבענו בשלב 3.
  8. באופן דומה אנו רושמים מטפלים לאירועים (incX, incY).
  9. כאשר האירועים נקראים (בעקבות לחיצה של העכבר על אחד הכפתורים), מספיק שנשנה את ה state של הרכיב – כדי ש react ידאג לקרוא ל render, ובצורה יעילה (למשל: לא יותר מפעם אחת ב Animation Frame של הדפדפן).
  10. לתחביר ה XML יש כמה תכונות מיוחדות – למשל הטיפול ב inline style attribute.
ניתן למצוא online JSX compiler בקישור הבא
כפי שאפשר להבחין, ה markup שאנו כותבים ב JSX הוא איננו HTML. זהו XML שרק דומה ל HTML. הסיבה לשימוש ב XML הוא הצורך ב markup קל לפענוח – HTML הוא מאוד סלחן ובעייתי לפענוח.
הדרך הכי בולטת לשים לב להבדל בין ה JSX XML ו HTML היא לקחת דוגמת HTML מהאינטרנט (שעובדת!) ולהדביק אותה לתוך האפליקציה. כמה הבדלים מרכזיים הם:
  1. אלמנטים חייבים להסגר. לא עוד
    אלא רק
    .
  2. מכיוון שה markup מקומפל לג'אווהסקריפט, לא ניתן להשתמש במלים שמורות של שפת ג'אווהסקריפט. למשל, במקום תכונת class משתמשים ב className.
  3. inline style attribute לא נכתב כמו ב HTML, אלא כאובייקט – כמו בדוגמת הקוד למעלה. אפשר גם לכתוב אותה inline בעזרת סוגריים מסולסלים כפולים {{…}}=style.

בסה"כ, בניגוד לציפיותנו, התרגלנו לכתיבת ה XML דיי מהר – והיא לא היוותה מטרד מיוחד.
מעניין לציין ש react עושה escaping ל markup בכדי להגן בפני חולשות XSS.

הנה הקוד לאחר שקומפל ל JavaScript בעזרת ה JSX Transformer:

הודאה קטנה: זה לא בדיוק הקוד. הקוד שנוצר הוא מעט "עמוס" בגלל השימוש ב "React.DOM" בכל מקום – ולכן עשינו לביטוי זה extract למשתנה שפחות תופס את העין: קו תחתון (בירוק).
הכנסנו את הביטוי במקום שורת רווח כדי לא "לקלקל" את מספרי השורות. ה JSX Transformer דואג לשמר את מספרי השורות בין ה source JSX לתוצר ה javaScript שנוצר.

כמה נושאים מעט יותר מתקדמים

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

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

אפשר לנהל את מודל כזה בצורה הקלאסי (חיבור למודל backbone, למשל) או לתת לרכיב להביא את המידע לו הוא זקוק ישירות מהשרת בעזרת קריאת Ajax (גישה של micro-services – כל רכיב דואג לעצמו מא' ועד ת').

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

  1. List רכיב שמיצג את הרשימה כולה – רכיב זה ייצור ListItem עבור כל אחת מהרשומות במודל שלנו, וגם ינהל את הרשימה במידה ויש צורך.
  2. ListItem רכיב שמייצג כל רשומה – רכיב זה יצטרך להכיר את המאפיינים של כל רשומה וידע להציג אותם כראוי.

כזכור, בראקט כל אחד מהרכיבים מחזיר בפונקציות ה () renderאת מבנה ה DOM שעליו הוא אחראי.
בדוגמה שלפנינו, כל רשומה היא בעצם DIV שמכיל את מבנה ה DOM של הרשומה. רכיב ה ListItem יחזיר אך ורק את ה DOM שנדרש בשביל להציג את הרשומה הבודדת.
רכיב ה List שאמור להציג את כלל הרשומות, יחזיר רק את העטיפה הנדרשת לכלל הרשומות, במקרה שלנו רק DIV עוטף אחד.

  1. זוהי הגדרת רכיב האב, ה List. בעת יצירתו הרכיב מקבל startIndex – מאיזה מספר רשומה להציג את ה listItems ו data – הנתונים עצמם המגיעים מהשרת מבנה json.
  2. דרך יעילה לרנדר רשימה של אברים היא היא לעבור על נתוני המקור (this.props.data) בעזרת פונקציית map (של מערך בג'אווהסקריפט) וליצור מכל פריט נתונים – מופע של הרכיב (ListItem).
    לא הייתה מניעה, אגב ש ListItem יהיה מורכב גם הוא מתתי-רכיבים. במקרה שלנו הפרדנו רק אלמנט אחד לרכיב-בן: Comment (האלמנט האחרון).
  3. הרכיב ListItem הוא עצמאי ואינו מודע ל List. אחד הרעיונות בראקט הוא לייצר רכיבים הניתנים לשימוש חוזר.
  4. ניתן לראות כיצד ListItem משתמש בטבעיות כ properties שהושמו לו ביצירה (שלב 2) – אלו בעצם הנתונים כפי שקיבלנו אותם מהשרת.
  5. שראקט יודע לטפל ב markup (למשל: אלמנט div), רכיבים (למשל ) או במערך של רכיבים / אלמנטי markup – כמו במקרה זה.
בעקבות שלב 5 בקוד, ראקט יוציא לנו הערה ב console של הדפדפן בזמן ריצה:
לא כדאי להתעלם מהערות אלו (ואחרות שהוא מוציא): כאשר יש רשימה, ראקט מבקש מאתנו מפתח ייחודי שבעזרתו יזהה שינוי state באובייקטי הרשימה. אחרת, האופטימיזציות של ראקט עלולות לגרום לו לדלג על שינויים שנעשו באובייקט – מבלי לעדכן אותם על המסך.
הנה דוגמה ל key כזה שהוספנו לאובייקט הרשימה בפרויקט שלנו:



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

יש עוד כמה נושאים ששווים ציון, אך היריעה קצרה להכיל. הנה מספר נקודות התייחסות אליהם:
מחזור החיים של הרכיב
כדאי להכיר: Component Lifecycle Event
כשתכתבו רכיבים מורכבים יותר – כנראה שתוכלו להיעזר בשלבים שונים ב lifecycle.
ממשק חיצוני של רכיב
כפי שאמרנו, רכיבים נבנו לשימוש חוזר / תחוף. ראקט מספקת מספר כלים כדי לכתוב רכיבים עמידים (robust):
  • default props – ערכי default במידה והמשתמש לא הגדיר את Property נדרש.
  • propTypes – מנגנון אימות על properties: האם יש property שחייבים להגדיר (isRequired), האם יש Property שסט הערכים התקניים שלו הוא סגור ( ([…])isRequired, ) וכו'.
שימוש חוזר בקוד בין רכיבים
במקום להסתבך עם prototype chains, ראקט מציעה מנגנון נוח יותר של mixins, לשיתוף התנהגות בין כמה components שונים.
שינויים נקודתיים
על רכיב ניתן לשמור קישורים (תכונת refs) לאובייקטים מסוימים ב DOM בכדי לבדוק / לעדכן אותם בצורה נקודתית.

סיכום ורשמים אישיים

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

התיעוד שלה – לא טוב. את רוב התשובות מצאנו ב stackoverflow וכמעט לא בתיעוד הרשמי. נציין שכל נושא שלא עניין אותנו, דווקא היה מתועד בצורה מופתית! ("חוק מרפי של התיעוד").נתקענו כמה פעמים על בעיות, לזמן לא קצר – אך בסוף הצלחנו לפתור את הבעיות ולהבין את מקורן. למשל גילינו, בדרך הקשה, שקביעת ערך לאובייקט ה state (כלומר (…)setState) לא מתרחשת מיידית, אלא היא מנוהלת בתור ומבוצעת רק לפני ציור ה Activation Frame (כלומר האירוע בו הדפדפן מעדכן את תצוגת המסך, שאמור להתרחש 60 פעמים בשנייה). קביעת ערך בפונציה א' לא מבטיח שזה הערך שיקרא מאובייקט ה state בפונקציה ב' שמתרחשת מיד לאחר מכן. עדיף להעביר את הערך כפרטמר לפונקציה ולא להסתמך על ה state שיהיה מעודכן.

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

היינו מנסים את react.js בעתיד באפליקציות לא-גדולות ועתירות רינדור (הייתה לנו אחת כזו לפני מספר חודשים).
מכיוון שרקאט היא לא כ"כ דומה ל frameworks אחרים, כדאי כנראה להשתמש בה רק בצוות שירגיש נוח איתה – לרוב מפתחי client-side hardcore הרגילים לכתוב קרוב ל DOM.
שאר המפתחים – יוכלו להמתין שראקט תתבגר עוד קצת ותגיע לגרסה…נאמר, 0.5.

כותבים שותפים:




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



איתמר שגב הוא מפתח Client-Side ב SAP מאוד אוהב טכנולוגיות חדשות ובעיקר את כל מה שגוגל עושה.

קישורים

[א] בהשוואה לאנגולר. ניתן להזכיר שגוגל לא משתמשת באנגולר במוצרים המרכזיים שלה.