Domain Knowledge: מוניות

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

"שנייה אחת!" אתם עלולים לתהות, "מה קורה פה?".
האם האקרים מ השתלטו על בלוג ארכיטקטורת תוכנה ושתלו בו סיפורים על … מוניות?! מה הקשר?

צודקים! אני אסביר:

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

החלטתי, לקראת השנה החדשה, לעשות שינוי קריירה ולעבור מ SAP (חברת ענק לתוכנה עסקית), לחברה קטנה ומקומית – "תביא-מונית" (כלומר: GetTaxi). אני עוד ארצה לספר על המעבר בעתיד.

באופן משעשע, אגב, אני נתקל ביותר אנשים שמכירים את השם GetTaxi מאשר אלו שמכירים את השם SAP. "מאיפה אתה עובר?" – כבר שאלו אותי. SAP היא חברה גדולה פי 300 בערך, ובעלת-ברית צמודה של רוב ארגוני-הענק בעולם. קצת מוזר שהיא מוכרת פחות.

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

עבורכם הקוראים, אני חושב זה עשוי להיות תרגיל מעניין לראות איך נראה Domain Knowledge של תחום אחר. האם יש דברים שמסקרנים אותכם, בתחום שלכם, לאחר שקראתם את מה שכתבתי שאתם עוד לא יודעים?
אם יש לכם מה להוסיף ולהעיר – רק אשמח על כך!

המונית כ"עסק"

איך אדם נהייה "נהג מונית"?

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

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

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

בכדי להתפרנס, הנהג זקוק לנוסעים, אותם הוא יכול להשיג ב-2 דרכים עיקריות:

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

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

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

בתוך מספר שנים הוכפל מספר המוניות בארץ מ 9,000 עד לכ 20,000 מוניות. כ 90% מהמוניות הן מוניות "ספיישל" – והשאר מוניות גדולות יותר (מוניות שירות, בעיקר. מקור).

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

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

קטע מתוך האתר של משרד התחבורה, נובמבר 2013:

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

חברת גט-טקסי (וחברות דומות) גם הם משנות את כללי המשחק: מערכת הקישור הממוחשבת בין נוסע-לנהג היא יעילה ומדויקת הרבה יותר מסדרן בתחנת מוניות. גודל החברה (גט-טקסי היא "תחנת המוניות" הגדולה בארץ, בהפרש ניכר) גם הוא מהווה יתרון משמעותי ביכולת לקשר בין נהג ונוסע שהם קרובים יותר. התייעלות מובנה זו שוב מצמצמת את מספר נהגי המונית הנדרשים בכדי לספק את הביקוש – ומגבירה את הלחץ על הנהגים שאינם חלק מהמערכת. תחנות המוניות הקיימות מתקשות להתחרות מול החברות החדשות ב 2 חזיתות מרכזיות: בטכנולוגיה (איגוד המוניות הוציא אפליקציה בשם Taxi To Go – לא נראית תחרותית במיוחד) ובשירות הלקוחות. במשך שנים, תודעת השירות בתחום הייתה דיי נמוכה.

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

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

חברת אובר (Uber) איננה דומיננטית כ"א בארץ, אך היא משמעותית מאוד בעולם – הולכת צעד אחד קדימה ומאפשרת ממש לכל אדם עם רכב להירשם בזמן קצר שעומד בתנאים בסיסיים [א], ולצאת לדרך כנהג מונית – במשרה חלקית או במשרה מלאה. חברות נוספות (Lyft, SideCar) מציעות מודלים של "נהגים מזדמנים", המאפשרים הפחתה משמעותית של מחירי הנסיעה ב-2 דרכים עיקריות:

  • אם אני נוסע, בכל מקרה, ממקום A למקום B, אני יכול לאסוף "נוסעים בתשלום" בדרך ולקבל החזר על חלק מההוצאות שהיו לי. כדאי לציין שרוב הפעילות של "נהגים מזדמנים" היא כשהנהג נמצא "באזור מסוים ויש לו זמן פנוי", ולא כחלק ממסלול מובנה.
  • חלק מהנהגים המזדמנים לא עושים אומדן עלויות נכון (למשל אבדן ערך של הרכב, בלאי, זמנם שלהם) – ועובדים בעצם בתנאים גרועים למדי.
אפשר "לבטל" את מודל "הנהגים המזדמנים" כ"תת-מונית" (רכב שאולי אינו מהודר, נהג לא מקצועי), אך ההיסטוריה מלאה במודלים שנחשבו כ"נחותים", זכו להתעלמות, ואז השתפרו עם הזמן ו"לקחו את הבכורה".
רק להזכיר מקרה אחר: חברות הרכבות היו אולטרה-עשירות ובעלות אמצעים לפני כמאה שנה. הן שמו לב להתפתחות הרכב הפרטי ושלחו צוותי מחקר-שוק לבדוק. אלו, חזרו עם תוצאות מעודדות "זה פתרון נישתי שלעולם לא יגיע לפלח משמעותי באוכלוסיה" – הם דיווחו. הרכבים היו לא-אמינים, יקרים, לא כ"כ נוחים, ואפילו לא היו להם בלמים (היה צריך לדומם מנוע כ 100-200 מ' לפני נקודת העצירה בכדי לעצור) – לא היו, ולא נראה שום כיוון טכנולוגי לפתרון. חברות הרכבת התעלמו מחברות הרכב – ולאחר עשור הומצאו בלמים, המחירים ירדו בהתמדה, והמוצר השתפר. מיותר לומר מה הייתה התוצאה לאחר כמה עשורים.

כמה נתונים מספריים על שוק המוניות בארץ (נתוני 2006):

  • כ 40,000 נהגים (עובדים במשמרות על כ 20,000 מוניות).
  • מחזור שנתי של 3.5 מיליארד ש"ח (כנראה 5 מיליארד בשנת 2014)
  • כ 600,000 נסיעות ביום.
  • כ 400 תחנות מוניות.

מודל כלכלי

כיצד נראה המודל הכלכלי של נהג מונית? מהן ההוצאות ומהן ההכנסות העיקריות?
מצאתי בגוגל כמה אומדנים כלכליים מפונפנים (דוגמה 1, דוגמה 2) – אבל הם לא היו עקביים אחד עם השני. חלק מהם העלו כמה הנחות לא סבירות (למשל: הוצאת דלק חודשית כ 1500 ש"ח, טוקבקיסטים אמרו שלפחות 4000 ש"ח).

משעשע לראות מודלים כלכליים המציגים דיוק לכאורה (סעיפים עם מספר לא עגול, למשל 1532 ש"ח ו16 אגורות) – תוך כדי שהם מפספסים את הדברים הגדולים (הוצאת הדלק היא בערך פי 3). "Precise, but not accurate" – למי שקרא את פוסט חנוכה השנה.

אנסה בכל זאת לתת תמונה כללית של המודל (לא Precise ואולי חצי Accurate), למיטב הבנתי:
הוצאות מרכזיות:

  • עלות הרכב כ 100-200 אלף ש"ח לרכב חדש. כשרוכשים רכב שיהיה מונית לא צריך לשלם מכס ומע"מ (זו הוצאה מוכרת) – יש להוסיף אותם ביום בו מוכרים את הרכב לידיים פרטיות (וזה נהיה משתלם בערך אחרי 5 שנים – לאחר שהרכב איבד הרבה מערכו). שני הדגמים הנפוצים ביותר הם ב-2 קצוות המחירים המקובילים: סקודה אוטביה עולה כ 100,000 ש"ח, מרצדס כ 200,000 ש"ח (ללא מע"מ ומכס). נהגי המוניות היקרות משרתים בעיקר לקוחות עסקיים – היכן שאיכות הרכב יכולה להחזיר את ההוצאה.
    בתחשיב חודשי של איבוד ערך הרכב + הוצאות מימון, מדובר בכ 2000-3000 ש"ח בחודש.
  • דלק תלוי כמובן בשימוש. יש תחנות שמגבילות את הנהגים שלהן ל 8-9 שעות עבודה ביממה, ויש נהגים שעובדים 12 שעות ביממה ויותר. נאמר 3000-5000 ש"ח בחודש (ללא מע"מ).
  • ביטוח רכב (המחירים למוניות גבוהים יותר, כי הן נוסעות הרבה יותר) – כ 1000 ש"ח לחודש.
  • שכירת מספר ירוק (מי שקונה חוסך קצת לאורך זמן) – כ 1000 ש"ח בחודר
  • הוצאות שונות (תיקונים, טיפולים, ניהול חשבונות, קנסות, וכו') – כ 1000 ש"ח בחודש.
  • חברות בתחנת מוניות – כ 1000-1500 ש"ח בחודש.
סה"כ יוצא טווח של 9000-12,500 ש"ח בחודש.
על הנהג להכניס כ 20,000 ש"ח בחודש – בכדי להשיג את השכר הממוצע במשק. כל זאת בניקוי חופשות, ימי מחלה, או ימים בהם הרכב במוסך, וכו'. המספר שיצא דיי דומה לתחשיבים האחרים שאמרו שנדרש כ 850 ש"ח פדיון ביום בכדי להגיע לשכר ממוצע.
הכנסה נוספת אפשרית היא בעקבות הצבת פרסומות על המוניות (מן משולש שיושב על הגג, בד"כ). אפשרות זו מנוהלת בד"כ מול תחנות – כי הרי משרד הפרסום לא ייצור התקשרות עם נהגים בודדים . התחום הזה פחות מפותח בארץ מאשר בערים הגדולות בעולם.

איפה הכסף?

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

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

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

הדרישה למוניות גוברת בצורה משמעותית בימים גשומים.

מתוך הסרט האלמותי "נהג מונית", עם רוברט דה-נירו. לא נהג המונית הטיפוסי.

רמאויות

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

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

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

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

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

מוניות בעולם

מה ההבדל בין מוניות בארץ למוניות בשאר העולם?

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

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

  • מוניות צהובות (medallion taxis [ב]) – הן מוניות להן מותר רק לאסוף אנשים מהרחוב (ללא תיאום מראש), או מתחנות המוניות שיועדו לכך. מספרן מוגבל ע"י רגולציה. דגמי הרכב המשמשים את המוניות הצהובות, נמצאים כרגע בתהליך החלפה שיסתיים ב 2018 – והן יוחלפו לדגם של ניסן הדומה יותר למיניואן (בכדי לאפשר הסעה של נכים הנעזרים בכיסאות גלגלים).
  • מוניות שחורות (livery או FHVs) – הן מוניות להזמנה מראש בלבד – ואסור להן לאסוף נוסעים אקראיים.
  • מוניות ירוקות (ירוק-וואסבי) (SHL, נקראות גם boro) – הן כמו מוניות שחורות, אך שמותר להן גם לאסוף נוסעים – מהרחוב ה 110 (או 96 מזרח) וצפונה בלבד [ג]. זהו אזור דליל יחסית ב"נוסעים מזדמנים" – ושבעלי המוניות הצהובות לא ששים להסתובב בו. כרגע יש תהליך בו מאפשרים ליותר ויותר מהמוניות השחורות "להפוך" לירוקות.

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

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

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

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

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

תחרות

עניין התחרות הוא עמוק, מקיף – ולא נראה שאוכל לכסות אותו ברצינות רבה מתוך שיטוט בגוגל. מסיבות אלו – אקצר.הרעיון של שיפור ואוטומציה של שימוש במוניות איננו חדש. כבר שנים שחברות טלפוניה מספקות שירות (פרימיום) להזמנת מונית תחת המספר 8294 (הספרות עליהן מופיע בטלפון האותיות T-A-X-I). חברת הטלפוניה (ע"פ התשתית שלה) ידעה לקשר אתכם לתחנת מוניות קרובה – שכנראה גם שילמה בכדי להיות חלק מהשירות. עם חדירת האינטרנט, השירות התקדם ל http://8294.tel – אבל עדיין נותר "ספר טלפונים לתחנות מוניות".

ב 2007 יצאה אפליקציה לניהול נסיעות במונית (מן organizer אישי) בשם RideCharge, שאח"כ הפכה ב 2009 ל TaxiMagic שגם עוזרת להזמין מוניות (אפליקציה שמוכרת היום כ Curb).

השינוי הגדול היה בהופעת ה iPhone ומעט אחריו – בפתיחת ה AppStore, באמצע שנת 2008. כמה מהאפליקציות המוכרות הופיעו בסביבות שנת 2010 – זמן סביר להבין שיש ב iPhone פוטנציאל אמיתי + זמן פיתוח אפליקציה ראשונה.

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

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

  • GetTaxi – כמובן. גאווה ישראלית! (נקראת Gett בארה"ב, איני יודע למה). השירות מתמקד בנהגי מוניות מקצועיים.
  • Uber – שצמחה מסן פרנסיסקו, "הגורילה" של התחום. החברה הגדולה ביותר, בפריסה הרחבה ביותר. מרכז הכובד שלה הוא "נהגים מזדמנים", אך היא גם מספקת שירותי מוניות "קלאסיים". החברה פעילה גם בישראל.
  • Lyft – הוא גם שירות שמתמקד בנהגים מזדמנים ופעיל בערים רבות בארה"ב. ייחודיות של Lyft הוא ה "Lyft Line" – היכולת למצוא נוסעים מזדמנים אחרים בדרך, אותם ניתן להוסיף לנסיעה ולהוזיל עוד יותר את המחיר. יש פה מנגנון שמוזיל באופן מובנה את הנסיעה מבלי לרושש אף-אחד, אבל נראה שהוא עדיין לא הוכיח את עצמו כ "Game changer". חברת אובר הציגה לאחרונה שירות דומה בשם Uber Pool.
  • Sidecar הוא שירות דומה לשניים האחרונים, אבל נותן יותר שליטה לנוסע לבחון ולבחור ממש את הנהג (ע"פ סטטיסטיקות, וכו'). גם הוא זמין בכמה ערים גדולות בארה"ב.
  • Curb, לשעבר TaxiMagic, שהחלה מחברות הסליקה של תשלום המוניות (שהצליחו לעשות זאת בעמלה נמוכה יותר) היא ותיקה ועם פריסה רחבה של כ 60 ערים במדינות שונות (ארה"ב, UK, קנדה או מקסיקו). היא מתמקדת בנהגי מוניות מקצועיים. נחשב שירות זול ולא כ"כ איכותי.
  • Easy Taxi – אפליקציה החלה לפעול בברזיל, והיום היא זמינה ב 26 מדינות (כולל ישראל). השירות מתמקד בנהגים מקצועיים.
  • Hailo – צמחה בבריטניה, וזמינה בכמה ערים בעולם. השירות מתמקד בנהגים מקצועיים.
הזכרתי קודם, את TaxiToGo אותה הוציא איגוד נהגי המוניות בארץ אותה. יש גם עוד אפליקציה ישראלית בשם "קליק למונית" מבית סלקום, גם היא מקומית. אפליקציות אלו אינן בסדר הגודל של האפליקציות הנ"ל: לא באיכות האפליקציה, ולא ביכולת של מי שעומד מאחוריה לפרוץ ולנהל אופרציה גלובלית של תפעול מוניות.

כמות האפליקציות, והקצב המהיר בו החברות הללו צומחות מעיד שיש פה שוק צומח ומשמעותי: גט-טקסי גייסה 150M$ לאחרונה, אובר גייסה 1.2B$ לפי שווי של 40B$ (חברה שהוקמה ב 2009 !!!) – כנראה הגיוס הגדול ביותר שהיה אי פעם, שלא דרך הבורסה.

מלבד ההבחנה בין עבודה עם נהגים מקצועיים, נהגים מזדמנים, או "גם וגם", יש שוני מהותי בין האפליקציות, בנקודת המבט "מיהו הלקוח?".
Uber ו Lyft, למשל, מתמקדות כמעט לגמרי בצד של הנוסע: הן לוחצות תדיר על הנהגים להוריד מחירים (יש להן תחרות לא-קלה בתחום הזה) ולשפר את השירות. נהג שקיבל תלונות של לקוחות ימצא את עצמו מהר "בחוץ", ורוב הפיצ'רים שלהן ממוקדות בנוסע. אובר למשל כותבת לנוסעים שלה "No need to Tip". סרטון ההדרכה לנהג – מבהיר מהר מאוד "מי הבוס".

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

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

איזה מודל הוא נכון יותר? הזמן יגיד.

Uber

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

אובר הוקמה ב 2009 ע"י Travis Kalanick, ה"פנים" של אובר, לו זו החברה השלישית שהקים, ביחד עם שותף בשם Garrett Camp, שמאז עבר להתמקד בחברה אחר בשם Expa.

אובר החלה כחברת Premium עם מוניות בקצה-הגבוה של הסקאלה, אבל בהדרגה החלה לנסות מודלים שונים. ב 2012 היא הקימה "סדנת חדשנות" בשיקגו (ה "Garage") – שם ניסתה רעיונות שונים: משאית גלידה אותה ניתן להזמין דרך האפליקציה, מונית שנראית כמו ה DeLorean מ"בחזרה לעתיד" – עבור מעריציה הסדרה, הזמנת מסוק (במחיר מתאים), וכו' וכו'.
העיר שיקגו נבחרה בגלל התחרות הרבה שיש בה בין המוניות, והמחירים הנמוכים המקובלים. "אם משהו עובד בשיקאגו – כנראה שבאמת יש לו פוטנציאל".

בעקבות תחרות קשה על המחירים, אובר "יצאה" מנישת מוניות-היוקרה, והציגה את ה UberTaxi (שיתוף פעולה עם נהגי מוניות מקומיים) וה UberX (מוניות זולות, רכבים שבישראל נחשבים "רגילים", אבל בארה"ב הם רכבים "זולים").

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

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

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

בעיתונות אובר מוזכרת לפעמים כ"חברת Data Science", כנראה בעיקר מתוך אי-היכולת של העיתונאים להתמודד עם המושג הנשגב.

מודל כלכלי

ההכנסות העיקריות (כנראה?) של אובר הן מ 20% עמלה שהיא לוקחת מהנהגים על כל נסיעה. בנוסף יש תשלום שבועי של 10$ מכל נהג "לכיסוי הוצאות התפעול של אובר".

לאובר יש אלגוריתם (surge pricing) שמגביה בזמן אמת את תעריפי הנסיעות כאשר הדרישה למוניות היא גבוהה במיוחד (בוקר, גשם, או סילבסטר) וכך מאזן במידה גם את העומס: היכולת "לעשות מכה" מעודדת נהגים מזדמנים להיות זמינים בשעות העומס – וכך לספק את הביקוש. הפי'צר הזה אינו זוכה לאהדה רבה מצד המשתמשים, במיוחד כאשר מחיר הנסיעה יכול להעלות עד פי 7 יותר (מה שקרה בסילבסטר של 2011) מהמחיר הרגיל. אובר הגיבה לתלונות בכך שהיא "משנה את כללי המשחק בתחבורה – והיא מבינה שייקח זמן לאנשים להתרגל". האמת: זה לא דמיוני (חשבו על הנתיב המהיר של כביש י-ם – ת"א).

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

ביקורת

אם יש משהו שלא חסר לאובר (חוץ ממימון, אולי) – הוא ביקורת.

  • צעדים שאובר עשתה מול הנהגים שלה (הכנסת מוניות זולות, העלאת העמלה מ 5% ל 20%, הוספת עלות שבועית לנהגים) – גרמה למרמור רב בקרב הנהגים.
  • אובר זכתה להפגנות שונות ברחבי העולם (פריס, לונדון, וכו'), מידי נהגי-מונית שהיא ניסתה לחדור לערים שלהם. הטיעון העיקרי הוא שאובר מציבה תחרות לא הוגנת, כי השירות שלה שקול למוניות, אך היא לא משלמת מסים והתרים כמו נהגי המוניות הרגילים, ואינה נדרשת להכשרות / ביטוח שקול.
  • בישראל, אובר הפעילה נסיעות בחינם במשך 48 שעות (בכדי לעורר תיאבון לשירות בקרב התושבים + כי אסור ל"נהגים מזדמנים" להסיע בתשלום) – צעד שלא בנה אמון בקרב הנהגים ("אם יאושר מודל אובר, תהיה אינתיפדה").
  • אובר נמצאת בתסבוכות עם הרגולציה ברחבי העולם, מטעמים שונים (תרשים):
  • אנשי מכירות של אובר הזמינו מוניות של גט-טקסי בניו-יורק, ואז ביטלו את הנסיעות. כך הם השיגו טלפונים של נהגי גט-טקסי, אותם הם ניסו לשדל לעבור לאובר, אבל תוך כדי כך הם גם הפריעו לשירות התקין של גט-טקסי, בצורת התקפת Denial Of Service (פשוטה, אך שעבדה). פעולה זו עוררה גלים באינטרנט וזכתה לפרסום גם באתרים כגון TheVerge או TechCrunch.
    את אותו התרגיל הם עשו גם ל Lyft, כבר כמה פעמים. המהלכים נגד Lyft היו מכוונים ומצאו תיעוד שלהם במה שנקרא באובר "Operation SLOG".
  • אובר הואשמה גם באיום על עיתונאים, שימוש בכוחה למעקב אחר עיתונאיםאי שמירה על פרטיות משתמשיה, ושימוש באפליקציית האנדרואיד שלה באיסוף נתונים מוגזם על המשתמשים ("Uber's App is a malware").
את כל אלו מלבה הסגנון האישי של המנכ"ל, טראוויס קלניק, שמצליח בעיקר להרגיז ולא לפייס את המרוגזים. קו שחוזר על עצמו בתקשורת של אובר הוא בטחון עצמי של המנכל / החברה שהמודל של אובר הוא טוב ונכון יותר ממה שקיים – ושעל הקיים להתרגל לאובר. זהו סגנון דיי שחצני – שגורם למבקרים של אובר לטעון ש"טרוואיס הוא רשע, שלא יעצור עד שלא יכבוש את העולם".
אובר נתפסה גם בכמה מקרים של חוסר אמינות:
  • אובר אוהבת לטעון שהשירות שלה יפחית את מספר המכוניות שנמצאות על הכבישים – מצב שיכול לחסוך למדינות מיליארדים בתשתיות. טרוואיס קלאניק הכריז "making car ownership a thing of the past" והחברה אף הגדילה והציבה מספרים: "מיליון מכוניות פחות על כבישי לונדון עד סוף שנת 2014". קשה למדוד מה קרה בפועל, ספק אם מישהו באמת יודע, אך ע"פ סקר של פורבס, 90% מהמשתמשים הקבועים של אובר לא שוקלים בכלל לוותר על הרכב הפרטי שלהם, מה שמצביע על כך שהשינוי לא כאן. לפחות לא עדיין.
  • אובר פרסמה נתונים שהמשכורת החציונית של נהג שלה הוא $90,766 בשנה. בתור חברה של "Data Science" ניתן להעריך שזה נתון מחושב ומדויק, אך עיתונאי שמסקר את אובר לא הצליח למצוא נהג יחיד שהגיע לסכום הזה. אובר עדכנה את הפרסומים שלה ל"אתה יכול להרוויח 70K$", אבל גם זה כנראה מספר לא מציאותי (ההערכות שאני מצאתי מדברות על 50K$).
מקור
  • אובר, למשל, מחשבת את זמן העבודה של הנהגים בצורה קצת מוזרה: להסיע לקוח או לנסוע לקראתו הוא זמן עבודה, אך זמינות והמתנה ללקוח הבא – אינו נחשב כזמן עבודה. האפליקציה לנהגים מציגה את שעות העבודה לפי החישוב של אובר – מה שמרגיז נהגים: היות וזמן העבודה ע"פ אובר יכול להיות נמוך ב 20% או יותר מזמן העבודה – כפי שהנהגים מבינים אותו (ובינינו: מאוד מקובל להבין. הדבר דומה לקופאית בסופר שלא סופרים לה זמן עבודה בזמן שאין מישהו בקופה…). התחשיבים של אובר גם הם מתייחסים ל"זמן העבודה נטו-נטו" – מה שמסביר חלקית את התחשיבים האופטימיסטיים שלהם.
  • אובר איננה אהודה על הנהגים, ונהגים רבים נוטשים אותה לאחר שעבדו איתה זמן-מה. "תשעה מתוך 10 נהגים שדיברנו איתם מעדיפים לעבוד ב Lyft מאשר באובר".
  • בכדי קצת לאזן: כנראה שאובר כן מציעה לחלק מהנהגים הכנסה גבוהה יותר מהאלטרנטיבות הקיימות.
גרף שנשלח ללקוחות UBER בברלין (בעיקר: נהגים), שעוזר להם לצפות את התנועה בליל הסלבטר.

סיכום

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

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

—–

Being an Uber Driver סרטון ביוטיב של בחור שעבד דרך אובר. יש לו כמה סרטונים. והנה עוד מישהי שמשתפת בחוויות.

—-

[א] ע"פ תשובה ב Quora התנאים הם:

  • רכב 4 דלתות, שנת 2005 או חדש יותר
  • מסמכים וביטוחים בתוקף
  • נהג ללא הרשעות נהיגה ו/או פליליות

[ב] medallion הוא "המספר הירוק" בארה"ב.

[ג] הם שמו GPS במונה, והמונה פשוט לא יעבוד אם לא מדובר באזור "המותר".

ריילס, רובי on ריילס

ריילס, או בשמה המלא Ruby On Rails (קיצור מקובל: ROR) היא מסגרת פיתוח (Framework) פופולרית לבניית אפליקציות ווב.

ספציפית: אפליקציות עם ממשק וובי מצד אחד, ובסיס נתונים (בד\"כ רלציוני, אבל לא רק) – בצד השני. 
מדוע ריילס?
ריילס הגיעה כתגובה ל JEE (בימיו הפחות יפים – תחילת דרכו) וכאלטרנטיבה פשוטה ומהירה לכתיבת אפליקציות ווב. באותם הימים, מרכז הכובד של JEE היה ה Enterprise JavaBeans (בקיצור EJB) שהיו כבדים ומסובכים. למשל, ה Guideline היה לכתוב לכל רכיב שמייצג נתונים 4 Interfaces נפרדים (רגיל, Home, Remote, ו LocalHome – אם אני זוכר נכון). ל EJB היו ה-מ-ו-ן קובצי קונפיגורציה XML לא-ידידותיים, ולמרות הכל – זה היה טרנד חם ורבים עברו לעבוד בו.
JEE הביא יתרונות רבים (סביבת multi-platform סטנדרטית, המתאימה ל Enterprise), אך במחיר גבוה. הוא כנראה היה טוב יותר מ Microsoft DNA או CORBA (כנראה…), אבל היו אנשים שחשבו שאפשר להשיג את הערך בעלות נמוכה יותר.
אחד מהם הוא Rod Johnson שיצר את Spring Framework, ה Framework שהפך הכל להרבה יותר פשוט (בעיקר הציג אלטרנטיבה פשוטה ל EJBs) – ומה שאח\"כ הפך להיות הסטנדרט של JEE, בצורת EJB גרסה 3.0 (שהעתיקה הכל, כמעט, מ Spring + Hibernate).
חלוץ אחר הוא David Heinemeier Hansson (ידוע גם בקיצור DHH), בחור דני צעיר יחסית (יליד 79) שעבד בחברה בשם 37singals (היום נקראת basecamp) שפיתחה לעצמה Framework יעיל מאוד לפיתוח מערכות ווב בשפת רובי. ה Framework הזה יצא כ Open Source ונקרא Ruby on Rails. נראה שריילס, אגב, השפיעה באזורים מסוימים גם על Spring בגרסאותיה המאוחרות (אני לא מדבר רק על Spring Boot) – ומשם היא השפיעה גם על JEE. בכלל, ריילס הוא Framework רק השפעה, שניתן למצוא השפעות שלו במקומות רבים בעולם התוכנה.

מקור השם Rails הוא כזה: \"במקום להתקדם באיטיות, כל אחד במסלול שלו, הצטרפו אלי: אני קובע את הדרך – אבל תוכלו לנוע במהירות\". ריילס הוא יישום של אוסף של best practices (ש DHH האמין שהן מוצלחות, לא אוסף גנרי) – שמתאימים זה לזה, ומסביבם נכתב Framework שהופך את השימוש בהם למאוד קל ומאוד מהיר. ריילס הוא לא סיפור על פלורליזם – זהו סיפור על דעה מוצקה כיצד נכון לפתח אפליקציות ווב. אם אתם רוצים להיות יעילים בריילס, עליכם לקבל עליכם את \"The Rails Way\", או לפחות את רובה. אם תקבלו – תגלו את אחד ה Framework הפרודקטייבים הקיימים לפיתוח אפליקציות ווב. ריילס פרחה ביוחד בסביבות של סאטראט-אפים, שהדבר שהכי חשוב להם הוא לספק Value מהיר לשוק שאותו הם עוד לומדים.

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

התכונות העיקריות של ריילס

ההחלטה התכנונית המרכזית של ריילס, אם כן, היא \"פריון (productivity) על פני גמישות\".

שני עקרונות מרכזיים שנוהגים להזכיר שוב ושוב, בהקשר של ריילס, הם:
  • Convention over Configuration – במקום לומר היכן נמצא משהו (קובץ, משתנה, וכו\') ומה שמו – בואו נגדיר כלל מוסכם (convention) היכן הוא אמור להימצא / איך הוא ייקרא – ונחסוך לנו את כל התקשורת הזו. הרעיון של CoC הוא לא חדש, ניתן למצוא אותו במייבן, למשל, שקצת קדמה לריילס. בכל זאת, ריילס היא זו שעשתה PR משמעותי מאוד לעקרון התכנוני הזה (ובמיוחד כ contra ל JEE) – והשפיעה בכך רבות על התעשייה.
  • Don\'t Repeat Yourself (בקיצור DRY) – גם זה רעיון שכבר מקובל עשרות שנים, אבל ריילס חרטה אותו על דגלה. לא לכתוב בקוד שום דבר פעמיים.
בעזרת עקרונות אלו (ועוד כמה אחרים) הצליחה ריילס ליצור סביבה סופר-פרודקטיבית לכתיבת אפליקציות ווב. כלל אצבע אחד אומר שבריילס יהיה עליכם לכתוב חמישית משורות הקוד בג\'אווה בכדי להשיג את אותה התוצאה.
ריילס צמחה על גבי שפת רובי, קצת רחוק מהקהילה הטבעית של ג\'אווה (ה Enterprises), ולכן ההשפעה שלה הייתה קצת יותר רחוקה. אל דאגה! JEE ננגחה שוב ושוב על היתירות של הקוד שהיא יצרה (בתרגיל הנדסי כ\"כ מרשים): גם ע\"י NET. (מי שזוכר את קרבות ה PetShop) וגם ע\"י Spring – בניצוחו של רוד ג\'ונסון (Rod Johnson), שגילה מעט מאוד עדינות כלפי החבר\'ה של JEE. היום מצבה של JEE טוב בהרבה מאשר היה באותם הימים, אבל עדיין – פיתוח בריילס נחשב מהיר בהרבה.
עוד אלמנטים מרכזיים בריילס שכדאי לציין הם:
הרחבה לשפת רובי:
רובי, כתכונה של השפה מאפשרת (ומעודדת) שימוש ב metaprogramming בכדי להרחיב את השפה עצמה וליצור DSLs חדשים. יכולות אלו, הן אולי הסיבה המרכזית שריילס הצליחה להיות יותר אפקטיבית [א] מספריות ווב אחריות (ASP.NET MVC, Lavarel או !Play) – שהיו משוחררות גם הן מ\"כבלי ארכיטקטורת ה Enterprise של JEE\". פקודות שימושיות בכתיבה של אפליקציות ריילס (למשל הגדרות שונות על המודל) הן בעצם הרחבות של ריילס לשפת רובי. מתכנת ריילס ללא רקע משמעותי ברובי עשוי לא להיות מסוגל להבחין אלו תכונות בהן הוא משתמש שייכות לשפת רובי – ואלו שייכות לריילס (ואולי גם לא ממש אכפת לו).

אינטגרציה:

ריילס כוללת stack של טכנולוגיות שמחוברות טוב מאוד זו לזו, ומספקות חווית פיתוח אחידה end-to-end. החל מבסיס הנתונים (Active Records – כלי ה ORM של ריילס), ועד צד הלקוח (SASS, Haml, ו CoffeeScript [ה]) – הכל מרגיש מתאים, ודומה למדי. החוויה דומה, אולי, לזו של פיתוח בפלטפורמת NET. של מייקרוסופט – לה שליטה רחבה על כל ה Stack הטכנולוגי.

עד גרסה 2, ריילס הייתה gem [ב] אחד, שלא גמיש להחלפות. החל מגרסה 2 חלק מהרכיבים (Active Records, למשל) הופיעו כרכיבים הניתנים להחלפה, אם כי ההחלפה בפועל הייתה מאתגרת למדי. ובמשך הזמן ממש התפתחו plug-in APIs המאפשרים לעשות החלפות אלו בצורה פשוטה יותר ויותר.
שלא תבינו לא נכון: אם אתם הולכים לכתוב אפליקציה ראשונה בריילס, ורוצים כבר בשלב זה להחליף רכיבים כראות עיניכם – זה לא ממש כדאי. החלפת רכיבים היא עדיין פרקטיקה מתקדמת שמומלצת רק למי שמבין היטב את דרכי העבודה של ריילס. באפליקציות הראשונות – כדאי להיצמד לסטדרטי ולמקובל.

הגישה שרואה בריילס \"אוסף של רכיבים\" (מה שטכנית באמת נכון) – מהם ניתן להרכיב תצורה מותאמת-אישית, נקראת (גם) Hexagonal Rails (ע\"ש Hexagonal Architecture, שדוגלת בהפרדת ה domain model משאר הרכיבים, ורואה בהם סוג של plugins שמתחברים מסביב אליו) – והיא פחות נפוצה, ואולי אף שנויה במחלוקת: האם ההשקעה, הלא פשוטה, \"לאלף את ריילס\" מתירה בסופו של דבר תוצר שמצדיק את ההשקעה הזו?

בדיקתיות:

תכונה אחרונה של ריילס שארצה לציין היא \"בדיקתיות\". יוצרי ריילס (ממש כמו יוצרי AngularJS, למשל) היו מודעים היטב לצורך בבדיקות – והם בנו תשתית שמאפשרת לבדוק את הקוד שרץ עליה בקלות יחסית. בדיקות יחידה ואינטגרציה הן חלק מובנה מריילס, ו flows הבדיקה מאופשרים היטב בכל הרמות , אם כי קצת יותר לכיוון ה integration tests וקצת פחות לכיוון ה isolated unit tests. כמות ספריות הבדיקה הזמינה לשפת רובי היא מרשימה (RSpec, MiniTest, Test::Unit, Cucumber, Factory_girl), ולכמה מהספריות הללו יש הרחבות מיוחדות לריילס (למשל Rspec_rails או Factory_girl_rails). בדיקות הוא לא רעיון זר בקהילת הרובי או ה RoR…

מעניין לציין שדווקא DHH הוא זה בשנה האחרונה העלה כמה דברי ביקורת על כתיבת בדיקות. בגלל ש DHH קידם מאוד את תרבות כתיבת הבדיקות (וגם בגלל שהוא הגורו הבלתי-מערוער בעולם של ריילס?) – דבריו זכו לתהודה רבה. הוא כתיב פוסט בשם Test-induced design damage, ואח\"כ העביר סשן בשם \"?Is TDD Dead\". בסוף הפוסט תוכלו למצוא לינק לסדרת הסשנים המעניינת בה הפגישו אותו עם יוצר ה TDD (קנט בק) ומרטין פאוולר (ששימש כמגשר?). סדרה של 3 שעות – אך בהחלט מעניינת.

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

ריילס בחזית הטכנולוגיה

בעולם של Single Page Applications, בעולם בו חווית משתמש שהפכה מקובלת, שדורשת שקוד משמעותי ירוץ בדפדפן, ובעולם של noSQL – ריילס כבר זוהרת פחות. אפשר לעשות את כל הדברים האלו עם ריילס, אבל היא כבר לא יעילה כמו שהייתה בעבר, ומפתחי ריילס צריכים לפעמים להיות יבשושים ולכתוב קוד משעמם / קצת פחות יעיל.
אם אתם מחפשים את החלופה \"העכשווית\" לריילס שתוכננה במקור לקוד צד-לקוח משמעותי, ו MongoDB – אתם כנראה מחפשים את MeteorJS (עם כל היתרונות, וגם החסרונות שלה).

אכן נראה שחלק ממפתחי הריילס (כלומר: רובי + ריילס) עוזבים את ריילס ומחפשים Frameworks חדשים לעבוד איתם. הטיעון ששמעתי כבר כמה פעמים הוא \"אני לא רואה הגיון לעשות MVC גם בשרת וגם בצד הלקוח\" (ברור שלא! מוזר לשמוע בכלל ניסו כזה דבר). באופן טבעי, חלקם מחפשים את המוכר, ולא מפתיע למוצא frameworks שמנסים לספק את הצורך הזה. קשה לי שלא לציין את Sails – של node.js ו grails של שפת גרובי (groovy). האחרון הוא לא חדש – אבל קשה להתעלם מהצליל המוכר שהוא בחר לעצמו 🙂

הרכיבים העיקריים בריילס

ריילס בבסיסה היא ספריית MVC שמושפעת ישירות מה MVC (המקורי) של שפת smalltalk:

המודל – שומר את ה state של המערכת (בעזרת בסיס הנתונים, אם כי לפעמים רק בזכרון), אוכף \"חוקים עסקיים\" על נכונות ה data (למשל: סטודנט חייב להיות רשום לתוכנית לימודים כלשהי). הוא לא בהכרח המאמת היחידי של הנתונים, אלא ה gatekeeper לפני שהמידע נשמר / משותף עם חלקים אחרים במערכת. בניגוד ל MVC של Smalltalk הוא גם כולל חלק מהלוגיקה – ראו בהמשך את ההסבר על Active Records.
המודל, בגדול – הוא זמין לכלל האפליקציה, אין בו partitioning (או bounded context).

ה View – הוא הקוד שמייצר דפי HTML למשתמש, על בסיס מידע במודל. ריילס היא תשתית לכתיבת MVC בצד-השרת (כלומר: השרת מייצר HTML, ומוסיף JavaScript לאינטרקטיביות). בדומה למודל ה MVC הקלאסי ה View לא מקבל input מהמשתמש, ולא מנהל איתו שום סוג של אינטרקציה (לפחות לא בצד-השרת).

ה controller – אחראי לקבלת קלט מהמשתמש, טיפול בו, ותפעול (ניתן לומר: orchestration) של המערכת עד שהמשתמש מקבל בחזרה את התשובה שלו. דרך העבודה שלו היא לעדכן את המודל, ואז להזניק את ה View המתאים (הוא לא מעביר מידע ל view ישירות).

בריילס יש גם routers – שהם ממפים URLs, ומצבים – ל Views. לדוגמה: אם משתמש שהוא admin ניגש לדף מסוים – הוא יקבל View אחר ממשתמש רגיל. ה router עושה מה שבמערכות אחרות עושה סוג של \"super controller\". הוא דקלרטיבי, בעזרת סט של ״פקודות״ מיוחדות לעניין (מה שהופך אותו לפשוט יותר לכתיבה ותחזוקה) – וסה\"כ הוא מהווה הרחבה מבורכת על מודל ה MVC ה\"קלאסי\".

רכיבים עיקריים של ריילס הם:

Active Records (בקיצור: AR)

כלי ה lightweight ORM של רובי, המנהל בפועל את הגישה לבסיס הנתונים של המודל. רובי מספקת גם כלים להגדרת טבלאות ברובי דקלרטיבי (ולא SQL, על הווריאנטים תלויי בסיס הנתונים הספציפי שלו) וכלים מובנים לביצוע migrations בין גרסאות שונות לסכמת בסיס הנתונים (מה שמקובל בג׳אווה לעשות עם flyway).

השם \"Active Records\" הוא בעצם של שם של דפוס-עיצוב (מופיע בספר PoEAA) אותו המודול מממש.

דפוס העיצוב \"Active Record\" מגדיר מחלקה בשפה (במקרה שלנו: רובי) שמתארת נתונים של שורה (להלן Record) בבסיס הנתונים, אבל מוסיפה עליהם גם את התנהגות ה domain הרלוונטית לאותם נתונים (להלן Active). למשל: validation, חישובים, derived fields, וכו\'. הבהרה: יש מחלקה אחת לכל טבלה, ומייצרים מופעים שלה ע\"פ הרשומות להם נזקקים באותו הרגע.

דפוס עיצוב זה מרשה לערבב בין מיפוי הנתונים בין בסיס הנתונים לזיכרון, עם לוגיקה עסקית – כל עוד הלוגיקה העסקית היא רק ברמה של הרשומה הבודדת (ולא \"שייכת\" ל scope רחב יותר). ערבוב זה, נמצא בוויכוח תמידי על הלגיטימיות שלו, מכיוון שהוא סותר כלל מקובל בארכיטקטורה הנפוצה ביותר למערכות מבוססות-נתונים (הרי היא Layered Architecture) – הפרדה בין Persistence ל Business Logic, או בצורת דפוס העיצוב \"Data Mapper\" אותה מממשים רוב כלי ה ORM המוכרים – הפרדה מוחלטת בין לוגיקה עסקית למיפוי הנתונים בין בסיס הנתונים לזיכרון [ו].

בריילס, יידרש מאמץ מיוחד בכדי לא-לעבוד עם Active Records, אז כדאי שתתנו לדפוס זה הזדמנות – גם אם כל חייכם \"גדלתם\" על Data Mappers ;-).

Active Records מאפשר לנו לכתוב אובייקט \"פשוט\" ברובי, לרשת מ ActiveRecord::Base ולקבל את פעולות ה CRUD הבסיסיות ע\"י סיפוק הגדרות בסיסיות של מה שאנו רוצים (declarative programming).
לא! זה לא \"בחינם\", אין ארוחות-חינם בהנדסת תוכנה. אנו מוותרים על גמישות וקצת על ביצועים – בכדי לקבל את הנוחות הזו.

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

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

  • Action Pack – זהו הרכיב שמתפעל את ה MVC בריילס. כל פעולת משתמש בריילס נקראת \"Action\". הוא מורכב מ -3 תתי-מודולים:
    • Action Dispatch – אחראי ל routing.
    • Action Controller – מספק את מחלקת ה ActionController::Base ממנה יורשים כל ה controllers במערכת. 
    • Action View – אחראי לרינדור ה Views, בעזרת מנגנון ה ERB (קיצור של Embedded Ruby) – מנגנון שדומה מאוד ל JSP בג\'אווה או ל PHP: סוג של template (בד\"כ HTML, יכול להיות אחר) שבו מושתל קוד רובי המתאר את ההתנהגות הדינאמית.
  • Active Model – המשמש כ Facade של AR מול ה Action Pack.
  • Active Resource – המספק יכולות צריכה של שירותי REST חיצוניים. סוג של שירות אינטגרציה בין מערכות.
  • Active support – סט של utilities כלליים (שימושיים) שמגיע עם ריילס. המקבילה של Apache Commons – של מג\'אווה.
  • Action Mailer – אשר תופס בתיעוד, משום מה, נתח מכובד. הוא בסה״כ שולח מיילים.
  • Active Job – לניהול Queues של jobs. הוא בעצם שכבת הפשטה למימושים קיימים (כגון Resque) ולא מימוש בפני עצמו. הוא חדש בריילס 4.2 .
  • Railties (\"קשרי מסילה\") – זהו ה gluing logic של כל רכיבי ה Active / Action למיניהם. ה Strategy של תפעול אפליקציות הריילס.
  • Rails – רכיב קטן למדי, שאחראי על אתחול המערכת – והכנסת המודולים האחרים לפעולה.

כל עבודת ה low-level ברמת ה HTTP הוא לא חלק מריילס. חלק זה יטופל ברמת ה Application Server – עליו נדבר בהמשך.

מבנה אפליקציית ריילס

כחלק מה Convention over Configuration, לאפליקציית ריילס יש מבנה תיקיות מוסכם-מראש. בכדי ליצור מבנה זה יש להקליד בשורת הפקודה:

$ rails new [optional: -d ]

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

מבנה אפליקציית ריילס חדשה

התיקיות המעניינות ביותר באפליקציית הריילס הן תיקיות ה app, config, ו lib. אם יש בדיקות טובות – הוסיפו לכך (במקום גבוה) את תיקיית ה tests (לפעמים תראו אותה בשם spec).

תיקיית ה bin כוללת את הסקריפטים לפעולות הבסיסיות של האפליקציה. אלו בעצם wrapper scripts (נקראים ברובי גם binstubs) שרק מכינים את סביבת הריצה ואז קוראים ל executable הנכון. לפני ריילס גרסה 4 קראו לתיקיה זו בשם \"scripts\".

קובץ ה Gemfile (מתחיל באות גדולה) הוא קובץ של כלי רובי בשם bundler, כלי שעוזר להגדיר, ואז להתקין – תלויות (gems [ב]) על סביבות חדשות בהן תרוץ האפליקציה.
ברגע שמריצים את הפקודה \"bundle install\", אז bundler יקרא את קובץ ה Gemfile, יבדוק מהן הספריות הנדרשות וגרסאותיהן, ויתקין את מה שלא נמצא – בגרסאות המתאימות. אם אתם מכירים את קובץ ה package.json של node.js – זה ממש אותו הדבר.

קובץ ה Gemfile שנוצר בעקבות הפקודה \"rails new\" כולל כבר רשימה של ספריות שימושיות: דרייבר לבסיס הנתונים שהגדרתם, כמה ספריות צד-לקוח, ספרייה ל generation של תיעוד, ספריה לעבודה עם JSON, וכו\'.

Gemfile.lock הוא קובץ בו bundler מנהל לעצמו את הגרסאות שמותקנות בפועל. זהו קובץ שתרצו להכניס ל git repository שלכם – אך לא לשנות ידנית (אין קשר לקבצי lock של MS Office, שמטפלים ב concurrency).


קובץ ה rakefile הוא של כלי ה build של רובי שנקרא rake. ה build ברובי כולל בעיקר בדיקות, פענוח הסכמה, Linting, וטיפול בקצבי HTML ו CSS (למשל: minification).

קובץ ה rakefile של ריילס יהיה לרוב מינימלי, והדבר המרכזי שהוא יעשה הוא לטעון ולהריץ רשימה של rake tasks (שאתם תכתבו). קבצי ה task יושבים בתיקיה lib/tasks.

בריילס, עובדים לא מעט עם command line עבור scaffolding [ג]: ניהול בסיס הנתונים, ביצוע buid, הרצת האפליקציה, ועוד.

לפעמים הפקודות הללו לא עובדות כראוי, ו\"טריק\" מקובל הוא לקרוא ל  <bundle exec rake <rake params – מה שהופך את כל ה gems שמצוינים ב Gemfile לזמינים, אפילו אם הם לא ב path של מערכת ההפעלה.

התיקייה lib, ע\"פ הגדרה אחת, כוללת קוד שהוא לא מודל, controller, router, או View.
התיקייה lib, ע\"פ הגדרה נוספת, כוללת קוד שניתן לעשות שימוש חוזר בו בין הרכיבים השונים (view, model, controller).
מלבד כמה תתי ספריות נדרשות (למשל tasks) – יש לכם חופש כיצד לארגן אותה.

בגרסאות ישנות של ריילס, כל הקבצים שישבו ב lib נטענו כזמינים לכל הרכיבים במערכת. כלל זה שונה והיום עליכם להדיר במפורש באיזה lib רכיב ה app שלכם רצה להשתמש – בכדי להשתמש בו. ( או פשוט להוסיף ל config/application.rb את הפקודה config.autoload_paths += %W(#{Rails.root}/lib שתעשה מה שריילס עשתה בגרסאות ישנות).

נוהגים לומר שהקהילה של ריילס \"התבגרה\" בשנים האחרונות. ריילס \"ניסתה לדלג\" על כל מיני כללים מקובלים של הנדסת תוכנה בכדי להאיץ את קצב הפיתוח. חלק מהדילוגים הללו הוכחו כבעייתיים – ואז ריילס חזרה בה (נראה לי שהמקרה הנ״ל הוא אחד כזה). דילוגים אחרים – אולי הוכחו כלא בעייתיים, בהקשרים בהם ריילס עובדת. אני זוכר ששמעתי דיונים על כך בקהילת הג\'אווה לפני מספר שנים: \"הנה ריילס מתבגרת, והחברה שם עושים היום יותר ויותר הנדסת תוכנה כמו ג\'אווה\". המסקנה שהוסקה (שגם לי נראתה הגיונית, בזמנו) הייתה ש\"ג\'אווה צדקה\" (שהחילה על עצמה כל כלל אפשרי של הנדסת תוכנה) – וריילס \"בדרך להיות סוג של ג\'אווה\".
נו טוב, סתם רכילות cross-קהילתית.

שני קבצים חשובים שנטענים בעליה של ריילס הם config/environement.rb ו config/application.rb.
בנוסף תמצאו בתיקיה config/environemnts קובץ קונפיגורציה לכל סוג סביבה: development, production ו test – זה הבסיס למערכת ה staging של ריילס.
כשמפעילים את אפליקציית הריילס, ניתן לציין את הסביבה כפרמטר, למשל:

$ rails server – e development

בכדי לטעון קונפיגורציה לסביבת ה staging המתאימה.

זהו.

ייתכן ותתקלו בקבצים ריקים בשם ״keep.״. מטרתם היא למנוע מכלים מסוימים להתעלם מהתיקיות שנוצרו ע\"י \"rails new\" – וניתן (ומומלץ) למחוק אותם כאשר התיקיה מתמלאה בתוכן. חבל לראות פרויקט ריילס בן כמה שנים – שעדיין שמר את הקבצים הללו.

החידושים שהגיעו עם ריילס 4, ששוחררה באמצע 2013. גרסה מג\'ורית של ריילס משוחררת אחת לשלוש שנים, בערך. מקור.

ה Application Server

הפעלת האפליקציה נעשית ע\"י פקודת \"rails server\", או בקיצור \"rails s\".
כל אפליקציית ריילס רצה על \"שרת ווב משלה\", בתוך תהליך של מערכת ההפעלה. ניהול של כמה אפליקציות על אותו שרת פיסי, מתרחשת ע\"י הפעלה של כמה \"תהליכי שרת\", אולי מסוגים שונים ו/או גרסאות שונות.

ריילס מגיע כברירת מחדל עם שרת \"רזה\" בשם WEBrick. זהו שרת פשוט למדי – שמשמש בעיקר לצורכי פיתוח (ולא ל production). ב Production מקובל להשתמש ב Puma, Raptor או ב Unicorn.

Rack הוא שמה של הספציפיקציה של שרת ווב ברובי, וגם השם של ה Reference Implementation שלה.
Rack דומה בתפקידו ל Servlet API של ג\'אווה, שבמקרה יש לו גם מימוש באותו השם (דמיינו ש Tomcat נקרא \"Servlet\"). החלק החשוב יותר של Rack הוא הספסיפיקציה. כנראה שהחבר\'ה של רובי ראו מה קרה בעולם של פייטון, שבו לא היה תקן שכזה, וכל שרת ווב עושה את אותו הדבר – אבל מגדיר זאת אחרת.

סה\"כ ה API ש Rack מציע הוא מאוד בסיסי: הוא עובד ברמת הפשטה מאוד נמוכה – ה HTTP Request-Response Lifecycle (בדומה ל CGI – אם אתם ותיקים מספיק בכדי לדעת מה זה).
מצד מימושי השרת, המימושים הנפוצים ביותר הם Rack (כמובן), Unicorn, או Mongrel.
ספסיפקציית ה Rack משתמש לא רק את RoR, אלא גם Frameworks אחרים כגון Sinatra, Ramaze ו Merb (שמוזג לתוך RoR בגרסה 3.0).

כמה מלים על Rack כ reference implementation:
מקור השם Rack הוא הכוננית בחדר השרתים שעליה מתקינים את השרתים / ציוד הרשת. יוצריו בחרו בשם זה בגלל מנגנון ה plugins שלו, שמאפשר למודולים צד שלישי (הנקראים middleware, דומים ל Servlet Filters בג\'אווה) להרחיב אותו בקלות. הנה רשימה של מודולים זמינים.
מעניין להזכיר את Rack::MockRequest שמייצר mocks לאובייקטי request ו response (נחמד שזה מגיע מ\"הספק\"), ו Rack::Lint שעושה Linting על קוד המשתמש ב API של Rack ומוצא כמה common pitfalls.

קובץ הקונפיגורציה של Rack, הנקרא config.ru מכיל את ההגדרה של ה middlewares שאנו משתמשים בהם, ו metals.
Rails Metal Apps (בקיצור: metal, מלשון \"bare-metal\" – אני מניח) הן חתיכות קוד באפליקציית הריילס שלנו, שירוצו ישירות מעל ה API של Rack, ללא תוספות.

מדוע לעשות זאת? בגלל ביצועים, למשל: כדי לספק REST API שקוראים לו בקצב מהיר.

ה stack של ריילס שמריץ את ה controllers (ה Action Controller Stack) מציב תקורה משמעותית לכל request שמטופל. אם אנו רוצים לספק תשובה פשוטה, ולעשות זאת מהר – כדאי לעקוף אותו.

הערה: ברור שאם אנו זקוקים לביצועים ממש גבוהים – גם metal עדיין מציב מגבלה על מה שאפשר להשיג מהחומרה. שפת רובי היא לא concurrent (השתפרה, אבל עדיין לא ממש) ואין לה parallelism. כדי להגיע ל throughput או tps גבוה במיוחד – כדאי לשקול עבודה נקודתית עם node.js (עבור קוד \"רעב\" ל I/O) או עבודה ב Go (עבור קוד \"רעב\" ל CPU) [ד].

אחרונה חביבה, היא ספרייה בשם spring שעובדת עם rake (שהיא כבר חלק מובנה מריילס 4.1 ומעלה) שעושה preloading לשינויים באפליקציית הריילס מבלי לעשות restart לשרת (אלא על בסיס של fork של ה process – לא עובד ב Windows או ב JRuby). יכולת דומה קיימת באופן מובנה בשרת ה Unicorn.

ה Conventions של ריילס

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

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

שמות של טבלאות בבסיס הנתונים יהיו ב snake_case – כמו משתנים. טבלאות תמיד יקראו ע\"פ צורת הרבים של האובייקט (plural): למשל People או Invoices ולא Person או Invoice.
למה? כדי שהקוד יהיה קרוב יותר לשפה הטבעית: \"Select a Product from products\". אני מניח שהבדל זה יכול גם להקל להבחין מהר בין מחלקה לטבלה בבסיס הנתונים.

שמות של קבצים (model, view, controller, וכו\') יהיו גם הם ב snake_case – כפי שמקובל ברובי גם מחוץ לריילס.

נניח שאנו רוצים ליצור מודל בשם LineItem (שם מחלקה ברובי הוא CamelCase). כדי שהכל יעבוד, ללא קונפיגורציה נוספת, על שם הקובץ המכיל את המחלקה להיות line_item.rb (והיא תהיה בתיקייה app/models), ועל שם הטבלה בבסיס הנתונים להיות line_items.

\"אני מבין איך עושים זאת עבור line_items, אבל איך *לעזאזל* ריילס תקשר עבורי בין people ל person?\". שאלה טובה. הציצו ב utility של ActiveSupport שעושה זאת: inflections.rb. הוא מכיר יוצאי-דופן מוכרים כמו person-people או octopus-octupi, ואתם גם יכולים ללמד אותו כללים חדשים, למשל: selfie-selfieez.

ל controllers יש כללים נוספים:

אם יש לנו Controller ששם המחלקה שלו הוא InvoiceController, אז עליו להיות בקובץ בשם invoice_controller.rb שנמצא בתיקייה app/controllers. עד כאן – זה כמו המודלים.

בנוסף, ריילס תצפה שיהיה קובץ נוסף בשם invoice_helper.rb בתיקייה app/helpers שיכיל מחלקה בשם InvoiceHelper.

ריילס גם תצפה שה view templates של ה controller הזה יהיו בתיקיה בשם apps/views/invoice. כהתנהגות ברירת מחדל, ריילס תשתמש ב output של ה templates הללו ותכיל אותם בתוך layout template (לא דיברנו עדיין ממש על הפרטים של ה view…) בשם invoice.html.erb (או invoice.xml.erb – אם מישהו משתמש עדיין ב XML/XHTML) שנמצא בתיקייה app/views/layout.

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

אם יש לנו כמה controllers הקשורים זה לזה (למשל Admin screens), אנו יכולים להגדיר אותם בהיררכיה בתוך התיקיה app/controllers. אם הדפדפן ביקש URL בשל admin/user אז ריילס תחפש את ה controller בקובץ בשם user_controller.rb בתיקיה app/controllers/admin (כלומר: תת-התיקיה admin מקבצת את כל ה controllers בקבוצה).

בכדי למנוע התנגשות בין שני controllers בעלי אותו השם (נאמר user_conroller.rb בתיקיה app/controller/report), שם המחלקה יהיה namespaced ע\"י מודול בשם של תת-התיקיה. במקרה שלנו: Admin::UserController.

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



קישורים נוספים:

The Rails Doctrine – הרעיונות התכנוניים / פילוסופיים מאחורי ריילס.

מה ההבדל בין RDoc ל Markdown

?Is TDD Dead

A Conversation with Badri Janakiraman about Hexagonal Rails

פוסט על הארכיטקטורה של ריילס



[א] זו לא אמת חד-משמעית, אך כך מקובל להאמין.

[ב] Gems, הן ספריות קוד של רובי אותן ניתן להתקין בקלות (<gem install <gem name $) מ repository משותף-לכל. דומה ל npm packages של node.s, ל eggs של פייטון, או Pears (אגסים) של PHP.

[ג] פירוש המילה: פיגומים. הוספת templates קטנים (controller חדש, מודל חדש) תוך כדי עבודה ע\"י הפעלה ב command line של \"… rails generate\", או בקיצור: \"… rails g\". זו המקבילה הרזה ל Create New Wizard ב Eclipse, למשל. פקודת rails generate דומה מאוד ל Yo – למי שמכיר, ובעצם הייתה עבורה מקור ההשראה.
[ד] יש כמובן את Scala, Elixier, Rust, ועוד. הצגתי את הבחירות הנפוצות של אנשי רובי.

[ה] טכנולוגיות אלו הן לא \"של ריילס\", אבל ריילס עושה בהן שימוש מקיף, ואלי גם השפיעה עליהן במידה:

  • SASS – שפת מטא ל CSS
  • Haml – תחביר מקוצר ל HTML 
  • CoffeeScript – שפת מטא לכתיבת ג\'אווהסקריפט, בתחביר שדומה לשפת רובי.

כתבתי על שפות המטא של ג\'אווהסקיפט ו CCS בעבר.

[ו] Data Mapper, כמו Hibernate – מבודד את ה Domain מבסיס הנתונים, בכדי להפוך את ה Domain Logic לבלתי תלוי, קל לבדיקה (Unit Testing), ולאפשר שינויים בבסיס הנתונים במנותק מה Domain וליהפך. אמנם במקרים רבים הצוות משתמש ב Data Mapper כי זה \"Best Practice\" למרות שהכוונה הברורה היא שבסיס הנתונים יהיו מיפוי מדויק של המודל – או ליהפך (הכוונה: תמיד אובייקט = טבלה, בלי שום רמת הפשטה). כמובן שרמת ההפשטה האפשרית בפועל מעל בסיס הנתונים היא מסוימת – ולא \"אינסופית\". כדאי להזכיר ש Data Mappers נולדו בסביבת ה Enterprise, בה לעתים רבות לאפליקציה לא הייתה בלעדיות על ה Database schema.

פוסט חנוכה: הגיגי-שפה

מה יותר "חד": Bleeding Edge או Cutting Edge?
מה ההבדל בין Accurate ו Precise (יש הבדל משמעותי) או בין Edge case ו Corner case?

סופגנייה מול Donuts – מה בעצם ההבדל?

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

ראשית, נתחמם עם כמה מוכרים יותר (סביר שחלקם יהיו כבר מוכרים לכם):

ניסוי ותהייה או ניסוי וטעייה?

אני שנים חשבתי שמדובר בתהייה… מלשון לתהות, עד שהסבירו לי שמדובר ב"ניסוי וטעייה" – מלשון טעות: "נסה, וקבל פידבק שלילי על כישלונות".
האמת היא ש"טעייה" היא בחירה קונקרטית של מישהו באקדמיה ללשון עברית, אבל יש כאלו שעדיין מעדיפים תרגום הביטוי "Trial and Error" ל"ניסוי ותהייה" או אפילו ל"ניסוי ותעייה" (לתעות – ללכת לאיבוד). הכל עניין של טעם.

עיקר ותפל או עיקר וטפל?

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

ובכן טפל הוא "משני" והבחנה בין "עיקר וטפל" היא המקבילה לביטוי האנגלי "Primary and Secondary", כלומר: הבחנה בין הכי חשוב, לשני הכי חשוב (הבחנה שהיא לא-פשוטה), ולא כפי שניתן לחשוב בטעות שזו הבחנה בין "נהדר למטופש" – משהו שנשמע בסיסי או קל.

(שימו לב שעל כמה מההבדלים להלן – כתבתי בפוסטים לאורך השנים)

Parameter או Argument

האם אלו מילים נרדפות – או שיש הבדל?
ובכן… parameter הוא המשתנה שנמצא בחתימת הפונקציה (כיצד הפונקציה מכירה את המשתנה), ו Argument הוא הערך שנשלח לפונקציה בעת ההפעלה – כפי שהקוד שמפעיל את הפונקציה מכיר אותו. בקיצור: יש הבדל ברור.

Accurate vs. Precise

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

בגדול: Accuracy הוא הכיוון הנכון, Precision הוא הדיוק בפרטים.

מקור הביטוי Pros and Cons

מה זה "Pro" ומה זה "Con"? האם אלו מלים? האם ניתן להשתמש בהן בצורת יחיד? מה משמעותן?
ובכן, המקור הוא ביטוי בלטינית בשם "pro and contra" שמשמעו: "בעד ונגד", ובפועל משמש בימנו כ"יתרונות וחסרונות". contra קוצר ל con, ומכיוון שיש יותר מייתרון / חסרון יחיד – משתמשים בהם בצורת רבים: pros and cons.

Transparent vs. Opaque

לפעמים רואים מלים אלו כנרדפות ומתארות שקיפות ("זה שקוף לך!"), אבל בפועל אלו הפכים:
Transparent – משמע שקוף.
Opaque – משמע אטום.כשאנו משתמשים בהכמסה בקוד בכדי להסתיר פרטי מימוש אנו נוהגים לומר: "זה transparent – זה שקוף לך!", למרות שבפועל היה נכון לומר: "זה opaque – זה אטום לך! אתה יכול לא-לדעת".

General vs. Generic

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

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

Corner Case vs. Edge Case

האם יש באמת הבדל? האם אני צריך להסיק מסקנות אישית – כשאני מריץ בגוגל כאלו שאילתות?!

ובכן – יש הבדל מוגדר היטב:

Edge Case ("מקרה קצה") – הוא מקרה קיצוני, שלרוב מתרחש בנקודות מקסימום או מינימום של ערכים. הוא יכול להיות צפוי ומובן לנו, או לא צפוי ומפתיע.

Corner Case (איני יודע אם יש מינוח עברי מקובל) – הוא תופעה פתולוגית, שמתרחשת רק כאשר רצף של מקרים, לא נפוצים מתרחש. באופן ויזאולי ניתן לחשוב עליו כהרכבה של כמה edge cases שמתרחשים בו-זמנית (ואכן פינה היא נקודת חיבור של כמה קצוות). זה בעצם מה שנתקלים בו כאשר משחררים תוכנה מורכבת ללקוחות מורכבים.

מה יותר חד: "bleeding edge" או "cutting edge"?

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

באופן מעט מפתיע – דווקא יש הגדרה ברורה:

Cutting Edge (ביטוי נרדף: "Leading Edge") מציין את הפיתוח הכי מתוחכם ומתקדם בתחום. אין לו הקשר לסיכון או לחוסר בשלות.

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

ההבדל הוא בעצם בין "הטוב ביותר" ל"חדש ביותר" (מקור).

מהיכן מגיע המונח "באג"?

(לצעירים שביננו שעדיין לא שמעו זאת כבר חמש פעמים)

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

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

הנה צילום המחברת של גרייס (שנלקח מתוך הביוגרפיה שלה):

UK מול "בריטניה הגדולה"

נכון, זה לא ממש לא קשור לתחום התוכנה, אבל נתקלתי בהבחנה הזו כחלק מהעבודה – תוך כדי קריאה של איזה תקן.
מה שמשך את תשומת לבי היא הערה בתקן שאמרה בערך כך: "אמנם אנו משתמשים בקיצור GB – אבל הכוונה היא ל United Kingdom ולא ל Great Britian, זו טעות היסטורית שלא ניתן לשנות".

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

מקור

כמה הגיות שאנו נוהגים להגות לא נכון (תזכורת):

מה שעלול לבלבל את השומעים הלא-ישראלים שלנו במידה…

Digital נשמע כמו דיג'יטל, ולא דיגיטל.

Medium נשמע כמו מידיום (midi) ולא מדיום (med). מדיום הוא מדיום-תקשורת.

Char הוא קיצור של Character, ולכן הגיוני יותר להגות אותו כ"קר" ולא כ"צ'ר" (למרות ששמעתי גם אמריקאים אומרים "צ'ר").

בשני האחרונים כדאי לנסות לחקות את ההגייה של הנשיא פרס (פולני):

Data הוא דייטה (deyTa) ולא דטה (dahTa).

Micro (כמו במיקרו-שירותים) הוא מייקרו (mai) ולא מיקרו (mi)

סיכום

אני מקווה שניהנתם.
אתם יותר ממוזמנים להגיב ולהוסיף את ההגיגים שלכם.

וחג שמח!

דפוסי ארכיטקטורה: מיקרו-שירותים (Micro-Services Architecture)

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

מיקרו-שירותים הוא "הטרנד החם" בנושא הארכיטקטורה בשנים האחרונות, ונראה שהוא כבר עכשיו הדיח את ארכיטקטורת השכבות ממקומה והפך ל "ארכיטקטורת ברירת המחדל למערכות ווב" (או מה שאוהבים לקרוא לו היום Twelve-Factor App)

יש בזה הגיון רב: בסאפ יצא לי לראות מערכות בהן Layered Architecture התאימה בצורה נהדרת לאתגרים והדרישות. מדובר במערכות עסקיות, גדולות ומורכבות בהן ה UI הוא שיקוף של הסכמה בבסיס הנתונים.
במערכות מודרניות יותר, בהן ה UI הוא עשיר יותר ובעצם בסיס הנתונים הוא שיקוף של חווית השימוש שתוכננה, חלק מההנחות של ארכיטקטורת השכבות (למשל: "ה UI משתנה ללא שינויים ב Business Logic ו/או ה Persistence") – פשוט לא משקפות את המציאות.

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

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

הסבירו לי נא, בדקה, מה "הקטע" של מיקרו-שירותים?

אנחנו עוד נחזור ונעמיק בדברים, אבל אנסה קודם להסביר בקצרה את עיקרי-הדברים.

הגורם הדוחף העיקרי לארכיטקטורה של מיקרו-שירותים הוא כנראה הנושא של Continuous Deployment: כיצד אנו מרכיבים את המערכת שלנו כך שנוכל לעשות deploy לגרסה חדשה 10 פעמים ביום – ומשם מאיצים את הקצב עוד ועוד?
ארכיטקטורה של שכבות בכלל לא מסייעת לעניין זה, אלא אם אתם הולכים לעשות deploy כל פעם ל Layer בודד אחר.

בפועל, רוב היכולות של מערכות הווב המודרניות מרכיבות גם UI, גם לוגיקה, וגם Persistence – כך שכל deploy דורש את כל שכבות המערכת.

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

  • ניתן לעשות לכל שירות deploy באופן בלתי-תלוי באחרים.
    לאמזון יש עשרות אלפי מיקרו-שירותים, והיא עושה deploy כל 10 שניות (בממוצע). איך ייתכן? היא פשוט עושה deploy כל פעם לחתיכה קטנה אחרת של קוד.
    בדרך כלל מיקרו-שירותים מורצים כתהליכים נפרדים של מערכת ההפעלה, המתקשרים זה עם זה על גבי HTTP / REST.
  • ניתן לפתח כל שירות באופן בלתי תלוי: CI, בדיקות, וסביבת העבודה היא בלתי-תלויה. אולי גם שפת התכנות.
    תכונה זו היא מרכזית מאוד, ומטרתה לשפר את ה scalability של הפיתוח: כמה מפתחים בצורה יעילה במקביל על הקוד. ההנחה כאן שהיא שיותר קל לפתח הרבה רכיבים קטנים – מאשר רכיב אחד גדול.
  • לכל שירות יש Persistence בלתי-תלוי.
    תנאי זה בא לשרת את שני העקרונות הקודמים – והוא לא מטרה בפני עצמה. Persistence היא תלות בין רכיבים במערכת, אם כי פחות מורגשת. אם שני שירותים ישתמשו באותן טבלאות בבסיס הנתונים – יהיה לכם הרבה יותר קשה להגיע ל deployment בלתי תלוי. גם אי-התלות בסביבת הפיתוח תשתפר מתנאי זה.
  • מיקרו-שירותים הם קטנים.
    "כמה קטנים?" – זהו דיון חם עליו אפשר לכתוב פוסט בפני עצמו. הנה כמה מדדים מקובלים (ולא-מתואמים) לגודל המומלץ למיקרו-שירותים. למרות שהם שונים – כולם מרמזים על "קטן למדי":

    • מספיק קטן כך שאדם אחד יכול להכיר היטב את כל הקוד של השירות ("כזה שיכנס כולו לראש שלי" – הגדיר ג'יימס לואיס, חלוץ בתחום ה MSA)
    • מספיק קטן שצוות אחד (שניתן להאכיל בעזרת 2 פיצות אמריקאיות גדולות) – יכול לפתח ולתחזק אותו.
    • כמה מאות שורות של קוד.
    • מספיק קטן שלא יהיה קשה לארגון "לזרוק" אותו – ולכתוב אותו מחדש.
      מספרים שדף הבית של אמזון מפעיל כ 100-150 שירותים שונים (תלוי במקרה המדויק) בכדי לשרת כניסה של משתמש.
  • שירות עושה "דבר אחד בלבד" – Single Responsibility Principle.
    כמובן שגם "מתפעל את הלוגיסטיקה של וולמארט" הוא דבר אחד בלבד – ולא דבר קטן בכלל!
    זהו כמובן כלל קונספטואלי, שלא ניתן לאמוד אותו "מתמטית" – ושיהיה עליכם ליצור קונצנזוס ארגוני לגביו. כלל זה בא לשרת ולסייע לכם לקיים את כל התנאים הנ"ל.
היתרונות העיקריים של ארכיטקטורת המיקרו-שירותים הם:
  • ארכיטקטורה שתומכת ב Continuous Deployment. שניה! האם CD הוא מטרה או אמצעי? ובכן… גם וגם. CD משרת מטרות עסקיות (feedback מהיר ולמידה מהירה) והוא מנבא מוצלח של ההצלחה העסקית של הארגון (מקור).
  • Scalability של הפיתוח, הרבה מפתחים יכולים לעשות הרבה שינויים במקביל – ולפחד פחות.
    הנחה סמויה – יש לכם לא רק את הארכיטקטורה של מיקרו-שירותים, אלא גם מערך מקיף של בדיקות אוטומטיות שהכרחיות לקיום של CD סביר.
  • High Availability – קריסה של שירות אחד (או חמישה) – לא משביתים את המערכת שלכם, אם הם לא קריטיים ל flows המרכזיים של המערכת. שירות קרס בצורה בלתי צפויה? יש memory leak? מכיוון שכל שירות רץ כתהליך נפרד של מערכת ההפעלה – הוא עשוי לא להשפיע על השירותים האחרים. קריסה של קוד ב Layered Architecture / Monolith – סביר יותר שתגרום להשבתה.
  • אפשור / קידום שכתוב הדרגתי של המערכת.
    אם למשל, החלטתם לעבור מרובי לסקאלה (עוד מופע של "Ruby doesn't scale") או מ Framework אחד ל Framework שני – המשמעות בארכיטקטורה Layered היא דרמטית: עצירה ארוכה בכדי לאפשר שינוי שכזה.
    מצד שני, זה הרבה יותר פשוט בארכיטקטורת מיקרו-שירותים: ניתן להתחיל להעביר שירותים ל Stack החדש בזה אחר זה – וחלק מהם לא להעביר לעולם. רק שימו לב שאתם לא נגררים לתפעול של stacks רבים רק כי "אפשר", או מחוסר תשומת לב – זו טעות קלאסית.
    תכונה זו של הארכיטקטורה היא שימושית במיוחד כאשר אתם חיים בעולם שבו המערכת שלכם נמצאת ב Refactoring תמידי (כי העסק דינאמי ומבנה השירות הישן כבר לא עושה את העבודה אחרי שנה-שנתיים…).
  • Scalability של ה production – מכיוון שאתם יכולים "לשכפל" ו/או לבצע אופטימיזציות על שירות X מבלי להתמודד עם שכפול או השפעות הביצועים של שירות Y שמתקשה להשתכפל. בעיות Scalability מטופלות בשיטה "פרה, פרה".
    נושא זה הוא גם, בד בבד, חולשה של מיקרו-שירותים, נסביר מיד.
באופן טבעי, יש לארכיטקטורת מיקרו-השירותים גם כמה חולשות:
  • קושי ב monitoring ושחזור בעיות ב production. כאשר יש לכם עשרות (שלא לדבר על מאות) שירותים שונים – קשה יותר לשחזר בעיות ולנתח. למשל: לאסוף ולסנכרן לוגים של שירותים שונים, במיוחד אם כמה שירותים התעדכנו לגרסאות שונות מאז. צפו השקעה בניהול והפצה של ה session id בין כל הקריאות. מיקרו שירותים "מפרקים את התמונה" להרבה תמונות קטנות, וכדי להבין מה קורה במערכת – יש להשקיע ב "להרכיב את התמונה בחזרה".
  • Scalability של ה production, ויעילות בכלל – מכיוון ששירותים שיכלו עד עכשיו לתקשר בזיכרון, מתקשרים כעת על גבי HTTP  – לכל קריאה נוסף overhead מסוים. מכיוון שיש הרבה מיקרו-שירותים, שיגרמו להרבה קריאות וה overhead הזה ילך ויגבר.
    פעמים רבות, ה overhead הזה מחייב מעבר ל I/O אסינכרוני – מה שמסבך את הקוד.
  • Refracting יכול להיות מורכב – אם הוא חוצה-שירותים.
  • Operational Complexity – בעוד monitoring הוא האתגר הראשון, הוא לא האחרון. תפעול של שירות בודד אולי הוא קל יותר, אך לתפעל מערכת של מאות שירותים (גרסאות, היכן רצים, כיצד לשדרג) – היא משימה לא קלה לכל הדעות. אומרים שאימוץ של מיקרו-שירותים מעביר מורכבות מהפיתוח ל Operations. סביר להניח שאימוץ ארכיטקטורה של מיקרו-שירותים תאלץ את גוף ה Operations שלכם "לעלות מדרגה" מבחינת היכולות שלו. אם הוא לא יצליח – זה הולך להיות כואב מאוד…

באופן מעט מפתיע, המונח Microservice Envy נוסף כמשהו שכדאי להיזהר ממנו, בדו"ח של Technology Radar Jan2015 של חברת Thoghtworks. למה מפתיע? כי Micro-Services הוא משהו שמדברים עליו קצת יותר משנה, אז הגענו מהר למדי למצב בו מתריעים משימוש יתר / שימוש ללא הבנה מספיקה. הנה הציטוט המדוייק:

We remain convinced that microservices can offer significant advantages to organizations, in terms of improving team autonomy and faster frequency of change. The additional complexity that comes from distributed systems requires an additional level of maturity and investment. We are concerned that some teams are rushing in to adopting microservices without understanding the changes to development, test, and operations that are required to do them well. Our general advice remains simple. Avoid microservice envy and start with one or two services before rushing headlong into developing more, to allow your teams time to adjust and understand the right level of granularity.

אז מה ההבדל בין מיקרו-שרותים ל SOA?

זו כנראה השאלה השנייה הכי נפוצה ששמעתי בכל דיון על מיקרו-שירותים (הראשונה היא: "אז מה הם בעצם מיקרו-שירותים?").

הקושי הבולט שאני נתקל בו בניסיון לענות על השאלה הזו, היא שבעוד שאנו מסכימים (כנראה) מהם מיקרו-שירותים – מי בכלל מסכים בעולם על ההגדרה של SOA?!

הדרך היחידה בה אני יכול לענות על השאלה הזו, היא להניח כל פעם על פרשנות שונה של "SOA" – ואז לנסות ולענות.

אם SOA עבורכם הם SOAP ותקני ה *-WS
אז התשובה היא פשוטה: אתם יכולים להשתמש ב *-WS גם במיקרו שירותים, אבל סביר שתקורת הפיתוח ותקורת הביצועים – יהרגו אתכם.
אחת מהנחות היסוד של *-WS היא "coarse grained services" – וזה היהפך המוחלט בהנחת היסוד של מיקרו-שירותים שהם קטנים. חוץ מזה – אין ספק שיש גם הרבה עקרונות משותפים.

אם SOA עבורכם היא ניהול ("mix and match") של שירותים בדמות ESB או CMDB
ESB (קיצור של Enterprise Service Bus) הוא הרעיון בו ניתן יהיה לעשות שינויים במערכת לא בקוד, אלא בקונפיגורציה – וכנראה ע"י power business users. יהיו הרבה שירותים שעושים פעולות טכניות (חישוב עלות טיסה, רישום הזמנה, וכו') – אך כל flow בעל משמעות יורכב בעצם ב ESB ע"י חיווט של השירותים הנתונים בקונפיגורציות שונות.

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

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

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

אם SOA עבורכם הוא מידול של המערכת לשירותים stateless ופונקציונליים
כלומר: אתם מאמינים שניתן לחלק את המערכת לפונקציות ("רכיב לכל משימה") – ולא דווקא ע"פ חלוקה OO. את השירותים עצמם – ניתן כמובן לפתח ב OO. כמו כן – אי-תלות מובנה בין השירותים.

במקרה כזה, ההבדל בין SOA למיקרו-שירותים הוא סמנטי, כלומר: יש להתאמץ מעט בכדי למצוא אותו. לא בכדי קוראים אנשי המיקרו-שירותים לפרשנות כזו של SOA בשם "SOA done right" (דוגמה, במסגרת הכתומה).

ההבדלים שניתן למצוא (כי חיפשנו) הם:

  • CD כסביבת הפעולה
  • אי-תלות ב Persistence כתנאי מרכזי (ולא רק כ"אפשר עם, אפשר בלי")
  • הקפדה על גודל קטן, והשיח על "זריקת שירותים – וכתיבתם מחדש, כתהליך מכוון".
לא הבדלים שקשה לגשר עליהם – אם אתם כבר מאמינים בפרשנות הזו של SOA.

האנטומיה של מיקרו-שירות

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

עד עכשיו סיפקתי סקירה high level של הנושא – אך יש עוד פרטים רבים שהייתי רוצה לגעת בהם.
למשל: כיצד מתחילים? כיצד "מפרקים" מערכת למיקרו-שירותים (להזכיר: MSA = Micro-Services Architecture)?

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

על השירות להיות self-contained: להכיל את ה deployment script העצמאי משלו, את הפרוייקט ב IDE משלו, את הבדיקות שלו, את התלויות שלו (ספריות צד-שלישי, בגרסאותיהן השונות) – וכו'.
מבחן טוב לעצמאות הזו היא מפתח חדש שמקנפג סביבה רק עבור השירות הזה, פותח רק אותו ב IDE – ומצליח לעשות שינויים ולהעביר אותם ל production מבלי להסתבך. השאיפה היא ליצור מערכת גדולה – מתוך הרבה רכיבים קטנים ופשוטים, ושפיתוח של כל רכיב קטן שכזה – יהיה פשוט כמו כתיבה של רכיב פשוט עצמאי (נאמר: תרגיל בקורס באוניברסיטה).

השלכה משמעותית של רעיון זה, הוא שאת השירות צריכה לכתוב קבוצת אנשים שיכולה לבצע את כל המטלות הנדרשות מהם (UI, Operations, DB, ולוגיקה עסקית). ע"פ Conway's law, אם בארגון שלכם יש "צוותי UI", "צוותי DB", ו"צוותי server" (ולא "צוותים פונקציונליים") – אזי סביר שהיישום של השירותים אצלכם יהיה: שירותי UI, שירותי DB, ושירותי Server – שזה נחשב מידול לא טוב של מיקרו-שירותים. ייתכן ויהיה עליכם לשנות את המבנה הארגוני בכדי להגיע ל MSA מוצלח.

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

הנה כמה תשובות לדילמות נפוצות. שימו לב שהן רק guideline – מכיוון שהן נענות "למקרה הממוצע", ולא לכל מקרה באשר הוא.

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

   האם על כל שירות להיות מנוהל ב Git Repository עצמאי?
זה עניין של טעם. למשל: גוגל מנהלים 90% מהשירותים שלהם ב repository יחיד. Git repository לכל שירות – גם הוא סביר בעיני.

   מה עושים עם ספריות שכל השירותים צריכים? למשל Logging או אבטחה?

מה שאתם עושים עם כל ספריית Open Source שאתם משתמשים בה הרבה – הוסיפו אותה כ dependency לכל השירותים שזקוקים לה. זה אמנם לא שירות – אבל לא כל הקוד חייב להתמפות לשירותים, יכולים להיות גם "סתם רכיבים לשימוש חוזר". הרגישו נוח לייצר וריאציה שלכם על דפוס הארכיטקטורה.
אפשר לדמיין מיקרו-שירות שעובר ל production כתא חי: יש את פנים התא שהוא ייחודי, ועוד קצת infrastructure שיש לשלוח עם כל תא ל production בכדי לקיים אותו. וכן – יהיו הרבה instances של השירותים הללו חיים (מה שמקשה על ניטור ו root cause analysis).

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

   מה??? יהיו לי במערכת גרסאות שונות של 3rd Parties? יהיה עלי להתמודד גם עם באגים של SpringFW 3.0.1 וגם עם אלו של SpringFW 4.1.2?
ובכן – היכולת להשתמש בגרסאות שונות של ספריות הוא דווקא יתרון גדול של MSA. כשיש מערכת גדולה ועותק יחיד של הספריה – אנחנו נאלצים לרוב "להיתקע" עם גרסה ישנה לאורך זמן, או לצאת ל"מסע צלב" בכדי לשדרג אותה. הפחד מ"ריבוי באגים" הוא לא תמיד כ"כ ריאלי. בכל מקרה – ברור שיש תקורה בשימוש במספר רב של גרסאות של אותה הספרייה – הייתי ממליץ לנהל "רשימת גרסאות מאושרת" שניתן יהיה לבחור רק ממנה במוצר. לאזן בין גמישות לשליטה.

יש מצבים בהם יש בעיה טכנית להשתמש בגרסאות שונות של אותה הספרייה (למשל: כאשר השירותים הם לא תהליכים שונים של מערכת ההפעלה אלא למשל wars ב JEE application server, או שימוש ב jQuery כאשר UI של שירותים שונים מוצג זה לצד זה על אותו דף של דפדפן. מה עושים? מתפשרים, או מחליפים טכנולוגיה – כמו תמיד.

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

הייתי מסכם זאת כך: RDBMS (בסיסי נתונים רלציוניים) הם בעלי התאמה גבוהה לארכיטקטורת Layers, אך בעלי התאמה פחות טובה – ל MSA. אם אתם עובדים עם MSA (או רק CD) – הבעיות יהיו קטנות יותר אם תעבדו עם בסיסי נתונים שהם schema-less כמו K/V DB או Document DB.
האמת שהיכולות המתקדמות של RDBMS עודדו הפרות משמעותיות של עקרונות ארכיטקטוניים חשובים (הכמסה, שבירת ה Layering שהוגדר, וכו'). איך קיבלנו זאת כל השנים? – זה פשוט עבד.

   איך מנהלים Transactions אם הנתונים שלנו מבוזרים לטבלאות שונות?
פשוט לא עושים. לא מגיעים ל Internet Scale כשעובדים עם ACID. נוקטים מדיניות של Eventually Consistent.

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

   כיצד שירותים מתקשרים זה עם זה? כיצד הם יודעים על קיומו אחד של השני?
בדרך כלל לכל שירות יש URL וניתן להשתמש ב DNS ו Load Balancer בכדי לנהל כמה עותקים – ולמצוא עותק זמין. הכי נפוץ הוא להשתמש בתקשורת REST, הרי – למה להמציא את הגלגל מחדש. אפשר גם על גבי TCP/UDP, אולי RPC או Thrift – הכל ע"פ הצרכים שלכם. בד"כ יהיו לכם גרסאות שונות של ה APIs של השירות, וכמה גרסאות של API שיחיו במקביל – עד שתוכלו באמת להשבית אותם.

דפוס נפוץ בארגון APIs של מיקרו-שירותים הוא ה API Gateway (מסמך: כיצד נטפליקס עושים זאת): שירות נוסף שכל תפקידו לקבל בקשה מה Client (ב URL אחד וב HTTP request אחד) – ולקרוא לכמה שירותים, להרכיב את התוצאות, ולהחזיר הכל באותה הקריאה. שירות זה הוא סוג של Facade שיסתיר מ clients חלק מהשינויים במבנה השירותים (פיצול, שינויי API, וכו')

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

עקרון ההפרדה (isolation) הוא מספיק חשוב בכדי להצדיק תקשורת דרך הרשת. מצד אחד – זה מוסיף ל resilience של המערכת, מצד שני זו תקורה ברורה בפיתוח ובזמן הריצה.

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

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

   האם אין תשתית כזאת, שתפתור לי את כל הבעיות שנובעות מ MSA – ותשאיר אותי עם כל התהילה, והיכולת להתמקד בכתיבת הקוד העסקי?
יש כל-מיני ניסיונות. יש את סנסה ל node.js, את rodent לרובי, או DropWizard של Yammer לעולם ה JVM. משום מה כולם עוסקים בפיתוח של המיקרו-שירותים (החלק הקל) ולא בתפעול שלהם (החלק היותר מורכב).
בכל מקרה… אם אתם קוראים את הבלוג – אתם אמורים לדעת מה דעתי האישית בנושא.

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

Bounded Contexts

רעיון שחוזר על עצמו שוב ושוב בהקשר ל MSA הוא רעיון ה Bounded Context, רעיון של מתודולוגיית ה Domain-Driven Design (בקיצור: DDD) של אריק אוונס. הרעיון מזהה שה Domain Model שלנו (תיאור האובייקטים בעולם והקשרים ביניהם. לא בתוכנה – ב"ביזנס") הוא לא אבסולוטי – אלא תלוי הקשר.

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

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

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

בכל מודל תחום (BC) יש רק את אוסף האובייקטים והתכונות שרלוונטיים לעולם הזה. המתכנתים ואנשי הביזנס מתקשרים על עולם מושגים שהם יכולים להכיל ולשלוט בו. הגבלנו בכוונה את "טווח הראיה" שלהם לטווח ניתן לשליטה.

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

יש לכך כמה פתרונות: אפשר לנהל Shared Context שמכיל את ההזמנה ומשותף לשני העולמות, ניתן לעשות "המרה" של אובייקט מ BC אחד ל BC שני, אפשר שה BC יראה רק view – אבל בבסיס הנתונים (שכבה נמוכה יותר) יהיה מודל שהוא aggregation של כל התכונות מכל המודלים, וכו' וכו'.

הקשר בין BC ל MSA הוא פשוט: אותן בעיות שהתמודדו איתן במשך שנים ב DDD, ובפרט בעקבות רעיון ה BC – צצות עכשיו בעולם ה MSA. בשני העולמות מאמינים שחלוקת המודל למודלים מקומיים וקטנים / פשוטים יותר – היא הדרך הנכונה להצליח.

 
 
 
 
 

בדיקות

בעוד אנו חווים ב MSA עלות לינארית להוספת שירותים (דבר טוב!), קל להגיע מהר לעלות מעריכית בכתיבת וניהול בדיקות אינטגרציה. אנו רוצים לבדוק את כל השירותים בכל התסריטים, בכל deploy – ויש יותר ויותר כאלו.
דווקא בדיקות יחידה (פשוטות, או של קבוצות של מחלקות) – הן דווקא פשוטות ועובדות היטב. מקסימום "זורקים" כמה Mock Objects לדמות את השירותים בהם השירות שנבדק תלוי – וזה אמור להסתדר בצורה קלה.
הבעיה היא יותר בבדיקה של אינטגרציה של כמה שירותים. כיצד והיכן מרימים סביבה? היכן מנהלים את הקונפיגורציה? האם יש לבדוק גם את התסריטים שתלויים בשירות שלנו – או רק את ה API של השירות עצמו? האם לבדוק עם שירותים אחרים חיים או רק mocks שלהם?
השימוש ב MSA פותח כל מיני שאלות על Testing שלא היינו צריכים להתמודד איתן קודם לכן.
טובי קלמסון ניסה לסכם את כל אפשרויות הבדיקה במצגת דיי מקיפה. קשה לי לתמצת את מה שהוא אמר – כי הוא חוזר על הרבה רעיונות מוכרים ומנסה להתאים אותם לסביבה של MSA:
  • נסו להריץ כמה שיותר בדיקות בזיכרון / עם mocks – שירוצו מהר.
  • כתבו יותר בדיקות יחידה ואינטגרציה ופחות בדיקות End-to-End שקשה לתחזק ("פירמידת הבדיקות").
  • בדקו לוגיקה בעזרת בדיקות יחידה, וקוד יותר "משעמם" עם בדיקות אינטגרציה או בדיקות-רכיב (בעיה: יש פרשנויות שונות לכמעט כל סוג בדיקה שנציין).
גישה אחרת (אציין: מקובלת) היא להשקיע פחות בבדיקות אינטגרציה – ויותר בניטור המערכת והיכולת לבצע root cause analysis מהיר. במקום prevention (בדיקות) – להתמקד בטיפול הבעיה ברגע שהיא צצה. יש הגיון כלכלי ברור לגישה זו, אם כי לוקח זמן להגיע לרמה "מספיק טובה" של ניטור והתאוששות בכדי שנסמוך על המערכת הזו להחליף את תפקידם של בדיקות האינטגרציה.
אם אתם יודעים לכתוב בדיקות אוטומציה – כנראה שתוכלו למצוא את הרכב הבדיקות שיעבוד למערכת שלכם. פשוט קחו בחשבון זמן לתכנון מחדש של מתודולוגית הבדיקות שלכם בעקבות MSA.

סיכום

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

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

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

החלטנו לעבור למיקרו שירותים – אבל הייתה הסתייגות רבה מניהול תהליכים נפרדים המתקשרים ב REST, בעיקר בגלל שזה קוד רב "ומשעמם" שיש להוסיף למערכת. המערכת כיום (כמו רוב מערכות ה Layered Architecture) מלאה בקשרים רוחביים בתוך ה Layers שקשה מאוד לנתק. באמת התרנו לעצמנו לקרוא מכל מקום ב Layer לכל פונקציה אחרת ב Layer – מה שגרם לריבוי תלויות. כמובן שגם ברמת ה DTO בעיות רבות נפתרו בעזרת "joins" – מה שקשר את הפונקציות השונות של המערכת גם בשכבה זו. ניתוח תלויות ראשוני נראה קצת מבהיל במחשבה שכל תלות הופכת לקריאת HTTP.

לכן…החלטנו לוותר על התכונה של "isolation by process" של MSA – ויצרנו וריאציה קצת חדשה: כל שירות מקבל פרויקט נפרד (pom.xml במייבן משלו) עם build משלו, בדיקות משלו, וכו' – והוא נארז לתוך קובץ jar. (המערכת כתובה בשפת ג'אווה + UI בשפת ג'אווהסקריפט). את כל השירותים אנו אח"כ אורזים לתוך קובץ war. גדול – ואז עושים deploy.

כיצד אם כן עושים deploy לשירות בודד?
שומרים תמיד את קובץ ה war. האחרון שעבר deploy, מעדכנים רק את קבצי ה jar. של השירות הרלוונטי (הוא עצמו + תלויות ישירות) – ועושים deploy מחדש.

איך מוודאים isolation בין השירותים?
הגדרנו שבכל שירות יהיה package מיוחד בג'אווה בשם facade המתאר את הממשק החיצוני של השירות – ורק לו שירותים אחרים יכולים לקרוא. אנו מתכוונים לאכוף התנהגות זו בעזרת JDepend שירוץ בעת ה build ויפיל אותו בעת חריגות.
בעת build של כל שירות – ה jar. שנוצר מתעדכן ב maven repository של הארגון, ושירותים אחרים שתלויים בו פשוט מגדירים תלות ל jar הזה ומקבלים גרסה עדכנית בעת ה build שלהם.

ל facade יכולים לקרוא שירותים אחרים או שכבה שנמצאת בתוך השירות (בשם webaccess) – במידה והשירות גם זמין על גבי HTTP.

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

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

אז… אל תפחדו ללמוד את החוקים, להבין אותם – ואז לשנות אותם קצת.

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

—–

לינקים מעניינים

תיאור של חברת SoundCloud על האתגרים במעבר מאפליקציה אחת גדולה ("Monolith") לארכיטקטורה של מיקרו שירותים. מומלץ!
חלק א': http://goo.gl/1ciqbS, חלק ב': http://goo.gl/31Gmy7, חלק ג': http://goo.gl/0aeq3u.

פוסט ידוע, ומצוטט רבות, של ג'יימס לואיס ומרטין פאוולר על מיקרו-שירותים: http://martinfowler.com/articles/microservices.html.
גם שווה קריאה. הם עוסקים בכמה היבטים בהם לא נגעתי בפוסט.

הקלטה של סשן מ Buraco 2012 של Fred George על מיקור-שירותים מיקרו-שירותים: https://www.youtube.com/watch?v=2rKEveL55TY

יש גם מצגת של ג'יימס לואיס בנושא (איך לא?): http://www.infoq.com/presentations/Micro-Services

מצגת מעניינת: http://www.slideshare.net/fuglylogic/microservices-26369481

פרק בפודקאסט "Software Engineering Radio" שעוסק במיקרו-שירותים: http://www.se-radio.net/2014/10/episode-213-james-lewis-on-microservices/

סדרה: רובי (Ruby) למפתחי ג\'אווה ותיקים

לאחרונה אני עובר ל Stack טכנולוגי של: רובי, ריילס, ו AWS (יש גם עניין של מובייל, אבל שם אני יחסית מעודכן).
כחלק המדרך שאני עובר אני כותב בבלוג על הנושאים הללו. באופן דומה למעבר שעשיתי במעבר לג\'אווהסקריפט – אני מנסה לכתוב את הדברים מנקודת המבט שאני הייתי זקוק לה: מתכנת וותיק, שמכיר (נאמר) ג\'אווה ו Object Oriented היטב – אך \"נוחת\" בעולם לא מוכר של רובי.

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

אני מרגיש פספוס קטן שרק עכשיו, אחרי כ 12 שנים בתעשיה, אני נחשף לראשונה באמת להבנה מהם רובי וריילס. פתאום אני מזהה נקודות השפעה שונות שלהן שראיתי שהכרתי כבר שנים – אך לא זיהיתי את מקור ההשפעה. נכון: ריילס נמצאת בדעיכה, מתוך כך שהמשקל של ה UI עובר לצד הלקוח, וכדי לכתוב REST APIs ברובי מספיק כנראה לקחת את Sinatra ו Active Records (כך אומרים). לא צריך את כל \"המשקל\" של ריילס. ההחלשות של ריילס משפיעה גם על רובי, ופתאום יותר מגניב מ\"לעשות רובי\" זה \"לעשות node.js\" [א].

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

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

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


RVM – כלי לניהול סביבות (וגרסאות רובי)
כאשר אתם מתחילים לכתוב רובי קצת יותר ברצינות – זהו כלי שכדאי להכיר.

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

ריילס, רובי on ריילס
שפת רובי איננה שפת רובי ללא ה framework הכ\"כ-מפורסם שלה לפיתוח אפליקציות ווב: Ruby on Rails. בפוסט זה נספק סקירת high level על ריילס.

—–

[א] אפילו מאטצ\' (שם החיבה של Matsumoto Yukihiro – ממציא רובי) עובד (במקביל) על שפה חדשה – Streem.

—–

לינקים מעניינים

Ruby Weekly – דרך טובה להתעדכן על החדש ברובי / ריילס.