הורשה היא הפרה בוטה של עקרונות ה Object-Oriented!

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

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

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

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

  • הורשה (inheritence)
  • ריבוי-צורות (polymorphism)
  • הכמסה (encapsulation) – או כימוס, כפי שהעירו. תודה.

זהו בדיוק סדר החשיבות ההפוך של עקרונות ה OO!

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

  • הכמסה (private)
  • ריבוי-צורות (implements / instanceof / interface / upcasting / downcasting)
  • הורשה (extends / protected / super / @Override)

(בסוגריים ציינתי את הכלים בג’אווה המשרתים כל עקרון. #C הוא דומה למדי).

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

זוהי קפיצת המדרגה העיקרית מול שפות פרוצדורליות שניהלו את המידע בצורה גלובלית (נאמר C).

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

הסבר קצר: שפת ++C הכילה יכולת מקבילה ל abstract בג’אווה / #C שנקראה virtual. מפתחים יכלו להגדיר מחלקות שכל המתודות שלהן virtual (מה שנקרא pure virtual class) וכך לקבל באופן עקיף משהו מקביל ל interface בג’אווה / #C. לא היה לממשק, כפי שאנו מכירים אותו בשפת ג’אווה, שום ייצוג רשמי בשפה – זה היה [1] Pattern.

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

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

מה הבעיה עם הורשה?
התובנה על המגבלות/בעיות בהורשה לא נתגלו עם ג’אווה. עוד בשנת 1992 הציג סקוט מאיירס, בספרו האלמותי “++Effective C” מספר בעיות עם הורשה והזהיר: “use inheritance judiciously”. שנתיים אחר-כך, בספרם המפורסם של GoF, הדבר נאמר יותר במפורש: “Favor object composition over inheritance” – נדבר על כלל זה בהמשך.

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

רוב הסיכויים שמפתחים ותיקים ומנוסים ירצו עדיין להשתמש בהורשה [2] ועבור מפתחים צעירים (הייתי אומר 5 שנים או פחות) – מומלץ לדסבלה (disable it).

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

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

public class InstrumentedHashSet extends HashSet {
  privateint addCount = 0;
  …
  @Override publicboolean add(E e) {
    addCount++;
    returnsuper.add(e);
  }
 
  @Override publicboolean addAll(Collection c) {
    addCount += c.size();
    returnsuper.addAll(c);
  }
 
  publicint getAddCount() {
    returnaddCount;
  }
}
InstrumentedHashMap היא הורשה שנוצרה על מנת לספור את מספר הפעולות על הרשימה.הריצו לרגע את הקוד בראש: אם אוסיף אוסף של עשרה איברים, מה תהיה התוצאה של getAddCount?
התשובה היא: It Depends.
אם אני רץ ב JDK 5 או ישן יותר התוצאה תהיה 20, אולם החל מ JDK 6 התוצאה תהיה 10. באופן רשמי ה API של HashSet לא השתנה כלל בין גרסאות ה JDK, אולם כאשר אני משתמש בהורשה אני נחשף ל API לא מפורש ולא מתועד: הקשר בין המתודות. במקרה שלנו זוהי הנקודה האם addAll קורא למתודת add או לא. כאשר אני יורש, אני יורש גם את הקשר הזה בין המתודות. בJDK 6 החליטו לוותר על הקריאה ל add מתוך addAll (עבור שיפור ביצועים) וכך שינו את החוזה הלא מפורש – אך שמשפיע בהחלט על המימוש שלי ל InstrumentedHashSet.
זהו בדיוק ה”שינוי הפנימי” שלא צריך להפריע לאף אחד אך במקרה שלנו, בעקבות ההורשה, הוא שובר פונקציונליות.הורשה פוגעת בהכמסה: מתודות כמו equals, compareTo, toString ו hashCode, שמומשו באב, מאבדות את נכונותן בעקבות הורשה. יש לכתוב אותן מחדש ולתת גם למחלקת האב (שעשויה להשתנות) לומר את דברה. לא פשוט.

הורשה פוגעת בהכמסה: אם מחלקת האב הכריזה על Serilazible, Clonable, Entity וכו’ – המחלקה היורשת יכולה לשבור הגדרה זו בכל רגע בלי יכולת להכריז על ההיפך. יותר גרוע: ירשתי ממחלקה שלא הייתה Serializable ולאחר שנה מחלקת האב הפכה לכזו – הקומפיילר לא יאמר לי דבר. הבעיה תשאר בעינה.

נו… אני מקווה שהבהרתי את הנקודה.

מה הפתרון? הפתרון הוא להשתמש בקשר הרכבה בין אובייקטים, מה שנקרא Composition. הוא כ”כ נפוץ ושימושי כך שהוא קיבל סימון משלו ב UML. אני אמנע מלכתוב על נושא שכבר תועד רבות. למי שמתעצל לחפש, הנה מקור קצת ישן, אך שנראה טוב:
http://www.artima.com/designtechniques/compoinh.html

סיכום
המסקנה ברורה: אם העיקרון החשוב (הכמסה) סובל מעקרון משני (הורשה) – זו סיבה מספיקה להחרים את העיקרון הסורר והפחות חשוב.
לצערי, עם כל זרם השפות החדשות שנוחת עלינו בשנים אלו (לינק) אף אחד לא הכחיד את ההורשה. הייתי שמח לראות וריאנט של ג’אווה או #C שהופך את extends, ברמת השפה, לפעולת composition במקום הורשה. זה פשוט ואפשרי.
עד אז – השמרו לכם מהורשה. ואם אתם שומעים את את עצמכם, או אנשים אחרים לידכם, אומרים “זה ממש וודו. התנהגות תוכנה זה לפעמים משהו מיסטי שלא ניתן להסביר” – בדקו שוב. אולי השתמשתם בכלי בעל flaws, כמו הורשה – ופשוט לא שמתם לב / אתם לא מודעים לפרטים.
—–[1] אם רוצים לדייק יש לקרוא לזה Idiom, שזה Pattern שנכון לשפת תכנות ספציפית. Patterns הם נכונים בכלל ולא רק לשפה ספציפית.

[2] הנה בשפת סקאלה הם החזירו לחיים את ההורשה המרובה. אבוי!

ארבעה דברים טובים שנוספו עם Java 7

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

סיכמתי כמה דברים חיוביים לאלו שיעברו ל Java 7, במקרה או בכוונה, ששווה להכיר:
פחות צורך במשמעת עצמית ב Exception Handling
Java נבנתה בצורה שתקל על המפתח להמנע משגיאות, הפחזבל (Garbage Collector) חסך מיליוני שנות פרך של debug וחיפוש אחר זליגות זכרון. בכל זאת, חברה שלא אנקוב בשמה, שילמה 17 מיליון דולר השתתפות בנזקים של הלקוח בעקבות הבאג הבא (חפשו אותו):

  Connection conn = null;
  Statement stmt = null;
  try {
    conn = connectionPool.getConnection();
    stmt = conn.createStatement();
    // Do the lookup logic
    // return a list of results
    } finally {
      if (stmt != null) {
        stmt.close();
      }
      if (conn != null) {
        conn.close();
    }
  }

אני מניח שהבאג לא צועק, הקוד נראה במבט ראשון מסודר ונכון. אבל מה – אם ()stmt.close יזרוק exception (בגלל מנגנון ה keep alive  של Oracle?), ה connection לא יתנקה וכשפעולה זו תחזור שוב ושוב, Oracle יסרב לקבל עוד קריאות. במערכת Mission Critical המשמעות היא לבצע restart לבסיס הנתונים כל מספר דקות, חוסר יכולת לעבוד, יום בטלה לעובדים והפסד אדיר ללקוח.

הפתרון הוא לעטוף ב try-catch נוספים (ה catch יישאר כנראה ריק) את קריאות ה ()close של stmt ו conn. זה היה ה best practice שדרשנו ממפתחים לעשות, שוב ושוב, וברגשות מעורבים.

איך מוודאים שבקשה זו תיושם בפועל? ביצוע תחוף של Code Reviews, הגדרת המודעות בקרב המפתחים ובארגון שעובד נכון – בניית Connection Pool שיודע לזרוק Connections בשעת לחץ.
בג\’אווה 7 ניתן לכתוב את הקוד הבא:

  try (Connection conn = connectionPool.getConnection();
       Statement stmt = conn.createStatement()) {
    // Do the lookup logic
    // return a list of results
    } catch {
      // respond to exception

    }

  }


שדואג ש conn ו stmt ייסגרו, אם לא שווים ל null ולמרות exceptions שיכולים להזרק. הוא מקביל לקוד הארוך והמכוער שתארתי למעלה. נחמד!

פחות חזרה חזרה חזרה ב catch statement
תופסים שלושה סוגי Exception ורוצים לעשות אותו הדבר?
מעכשיו כתבו:

} catch (IOException | SQLException | SQLStatementException ex) {
  log.warn(ex);
  throw ex;
}
המשתנה ex יתייחס לסוג ה Exception (מתוך השלושה) שנזרק. יופי.

Performance Profiling: שחרור VistualVM
אם תחפשו בתוך ספריית Bin ב JDK שהורדתם, תגלו שיושב לו שם Profiler בשם VisualVM. מלבד כך שהוא חינמי, מתחבר לכל ה IDEs החשובים (עם plugin) ויש לו ממשק משתמש נחמד, הוא מספק נקודת איזון מאוד מוצלחת של פשוטות מול עוצמה. הוא ידידותי – אבל גם אינו צעצוע. הוא יכול להספיק לרוב משימות ה profiling הנפוצות, גם בתוך tomcat, ואינו דורש הגדרות מיוחדות לJVM או לשרת שאתם עובדים איתו.

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

נ.ב. – אופס, תפסתם אותי. VisualVM מסופק החל ממרץ כבר ב JDK 1.6 ואינו חידוש של Java 7. בכלל הוא יכול לעבוד (תחת מגבלות) עם אפילקציות שקומפלו ב JDK1.4. הוספתי אותו לכאן מכיוון שהוא תוספת מכובדת ל JDK שקל לפספס בגלל שיצא ב update ולא ב major release.

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

בהצלחה!

האם Java גוססת?

כבר בסביבות שנת 2008 התחיל לצבור תאוצה הקרב על הירושה: איזו שפה תחליף את שפת Java? אם היה קרב לרשת את סטלין בעודו בחיים, מחנות החינוך מחדש בסיביר היו מקבלים מספר חברים חדשים לשורותיהם, אבל שפת Java עם הקהילה הפתוחה שלה, היא רחוקה מאוד מדיקטטורה*. אחת התלונות הקשות על Java היא הקצב האיטי בו גוף התקינה של Java מקבל החלטות. JDK 1.7 יצא לאחר חמש שנים ולא כלל שיפורים יוצאי דופן. C#, שפה מאוד דומה, מציגה שיפורים משמעותיים (לדוגמה LINQ, closures) באופן תדיר.

האם צריך להחליף את Java? מה רע בה?
if it’s not broken – don’t touch it!” יאמרו רבים.
if it’s ain’t broke – break it” יענו המהפכנים. “חובה עלינו לחפש שיפורים כל הזמן”, בתרגום חופשי. “ואם נוח לנו במצב הקיים, אדרבא”
התלונות העיקריות לגבי Java הן הבאות:

שפה  verbose (מרבה במילים) ומסורבלת.
יש אינספור דוגמאות של: 10 שורות בג’אווה, 4 שורות ב X (שפה אחרת) . דברים מרגיזים כוללים:

  • Checked exceptions
  • Java Beans (הסינטקסט המסורבל של getXXX/setXXX שהופך משפטים לקשים לקריאה)
  •  הצורך לכתובanonymous class  בכדי להעביר פונקציה פשוטה כפרמטר (שפות אחרות פשוט נותנת להקליד את הקוד הרצוי במקום הנכון)

גוף התקינה הוא שמרן ואיטי.

“מדוע היה צריך לחכות לג’אווה 7 בכדי שמשפט switch יוכל לקבל String?” היא תלונה נפוצה וקלה להבנה (אך קצת קטנונית). הבעיה האמיתית היא ריבוי ה cores שהפך למציאות תיכנותית, וחוסר היכולת של Java להתאים את עצמה למציאות החדשה. Fork-Join שהגיע באיחור ולא יושב יפה בתוך השפה ו Actors (בדקו בתחתית הפוסט בבלוג זה להסבר על Actors) שמתכנתי Java אוספים משדות זרים.

האם שפה שהיא verbose (מרבה במילים) משפיעה באופן משמעותי על פריון המתכנתים? השאוות הראו שלספריות העומדות לרשות המפתח, ה IDE, ניסיון והכישרון של המפתח יש השפעה גדולה מהשפה עצמה. רק אסמבלי (ואולי קצת קובול) נשארה משמעותית מאחור (מקור: ספר Code Complete) אני מכיר היטב את הטענה שכתיבה ברובי או פייטון היא הרבה יותר מהירה אך אין לזה חיזוק אמפירי. הסיכוי לטעויות בשפות אלה בגלל שאין בדיקת קומפיילר מפצה לרעה על ה syntax הקליל. אני מניח שזו עניין של הרגשה ואולי מתכנתים מעולים שלא צריכים קומפיילר (שמעתי TDD?) באמת כותבים מהר יותר בשפות סקריפט. 
בואו נתבונן בשני האלמנטים האובייקטיבים (לא תלוי במתכנת) שכן משפרים את הפריון, וכיצד השפות החדשות יכולות להתמודד מול Java:
1.כלים – auto-complete, קומפיילר טוב, Refactoring וכו’. כל שפה חדשה שמוצגת לשוק מהר מאוד מייצרת כלים בסיסיים (לפחות syntax highlighting ו auto-complete), קשה לשכנע שהשפה שלך תקצר זמני פיתוח אם אתה אמור לעבוד ב Notepad. כל מערכות ה IDE המרכזית (Eclipse, VS, IntelliJ ו NetBeans) בנויות להרחבה ותמיכה בשפות נוספות.
2.  ספריות – האם עלייך לכתוב ספריית Scheduling בעצמך, או שאתה מוריד את Quartzומתחיל לעבוד? ב C++ לא היו הרבה ספריות משותפות, אולי בגלל שהיו קומפיילרים שונים למערכות הפעלה שונות. ברגע שJava הציגה את “Write Once, Run Everywhere“** – כמות הספריות הזמינות להורדה (ובחינם) נערמה והפכה לכוחה הגדול של Java – ה Community. אז איך מציגים שפה עם 0 ספריות מול Java עם אלפי ספרות בדוקות ובוגרות? רובי הצליחה להתרומם בעזרת Rails – ספרייה חדשנית ומוצלחת במיוחד לפיתוח אפליקציות Web (וגם בעזרת שפה מוצלחת בפני עצמה, כמובן) – אבל זה לא הספיק. ואז – נתגלתה השיטה: ב JDK 1.6, ה JVM – Java Virtual Machine הורחב לתמוך ב JavaScript שיתקמפל ל Byte Code – וירוץ בצד השרת. לצורך העניין נעשו שינויים שאפשרו ל JVM לתמוך בתכונות של שפה דינמית (כלומר פונקציה היא evaluated רק ברגע שצריך להריץ אותה, שמאפשר לתוכנה לבצע שינויים עד אותו הרגע). הסכר נפרץ ושפות רבות קפצו על ה JVM: בוגר, יעיל, מוצלח,highly optimized, עם התקנה לעשרות מערכות הפעלה ואולי הכי חשוב – היכולת  להשתמש באופן טבעי בכל מאגר ספריות הJava הקיימות. אפילו שפות שהיה להן Virtual Machine – פיתחו וריאציה עבור ה JVM.
 
היכן המהפכה?
אוקיי, אז עברו שלוש שנים, וJavaעדיין כאן. השפות שעשו זינוק בשנה האחרונה הן דווקא LUA ו F# – שאינן קשורות ל JVM. השפות המדוברות תופסות הרבה נפח בכנסים ובבלוגים, אך עדיין הנוכחות שלהן סה”כ קטנה.
ברוכים הבאים לעולם העסקי (ניתן לומר: האמיתי). מקום שבו טכנולוגיה טובה לא מבטיחה הצלחה, מקום שבו שיתופי פעולה והרגלים הם בעלי כוח מכריע.
הדעיכה של Java כנראה התחילה, אבל Java לא עתידה להעלם סתם כך. הייתי מעריך שיעברו עוד שנים רבות עד שJava תחשב כשפה לא רלוונטית. כמות הקוד הקיים, הספרות והכי חשוב – האנשים שמושקעים באופו אישי בJava הוא עצום והוא לא יעלם סתם כך. (בעולם הJVM) תמיכת ה IDE בJava היא עדיין הטובה ללא עוררין, וכך גם כמות החומר הלימודי. יתרונות השפות המדוברות – הן עדיין הדרגתיות וצריך סיבה טובה כדי לעשות מעבר.למשל: אם יש לי בעיות Concurrency קשות באמת, אני יכול לכתוב מודול ב Scala, לייצר .jar ולצרף אותו לפרוייקט הJava הקיים.

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

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

Scala  – כנראה המתמודדת הבולטת ביותר. משלבת אלמנטים פונקציונליים ו Object Oriented. מאפשרת גם תכנות דינמי (כמוJavaScript  או רובי) אבל גם Static Typing – כלומר הקומפיילר יתפוס לכם את רוב הבעיות. הייחוד שלה היא ההצלחה לשלב פרדיגמות שונות בצורה מוצלחת והתכנות מהיסוד לשפה לתכנות מקבילי. היא תהיה יחסית נוחה למתכנת Java, C++ או C# אבל תציע הרבה כוח ואפשרויות שלא היו זמינות בשפות אלה.
Groovy– שפה מגניבה, שכוללת אלמנטים של python Syntax ותאימות רבה לJava. קוד Java ללא שינוי צפוי להתקמפל בגרובי ב 95% מהמקרים. נעשתה עבודה לא כ”כ מסודרת בפרטים – וכבר יצאה גרובי++ שמטפלת בכמה מהבעיות. הביאה לעולם את Grails שזה העתק של Rails של רובי, ואת Griffon – שזו גרסת ה Desktop לאותה ארכיטקטורה. נראתה מועמדת מובילה לפני שנתיים-שלוש (בעיקר בעקבות backward compatibility), אך לאחר שהמפתח שלה הצהיר “אם הייתי מכיר את סקאלה – לא הייתי טורח לפתח את גרובי” גורלה כנראה נחרץ.
JRuby– רובי היא רביזיה Pure-Object-Oriented של שפת Python מתחילת שנות ה-90 שהוזכרה קודם. יש לה את ספריית Rails שזכתה להצלחה רבה. JRuby היא פשוט מאוד גרסת ה של רובי JVM, שילוב שגרם לרובי לרוץ מהר הרבה יותר. יש לה מומנטום חזק כ”כ בעולם ה web – כך שנראה שהיא כאן בכדי להשאר. השאלה בעיקר היא האם תתפשט מחוץ ל Web UI לכיוונים אחרים.
Closure– מין LISP מודרני, דינאמי ופונקצינאלי. גמישה מאוד ביכולת הביטוי. משפט אחד בלתי-קריא יכול להיות שקול ל 10 שורות בכל שפה אחרת. האם זה ייתרון? אם אתם באקדמיה, אוהבים קדרים וקודרים (המבין יבין) – לבריאות. אני לא נהנה לקרוא אותה ואיני מבין על מה המהומה. 
Jython – פייטון (ע”ש להקת מונטי-פייטון, כדרך אגב) היא הותיקה בשפות, אפילו ותיקה מ Java. מאז הצלחת Java ירדה מהכותרות אך חזרה אליהן לאחרונה, אולי גם בגלל Jython ה porting ל JVM. היא פחות סקסית וחדישה, אך יש בעולם הרבה מאוד קוד פייטון ומתכנתי פייטון (יותר מרובי, למשל) בעוד שרובי תפסה את הנישה הוובית, פייטון נשארה general purpose. באופן אישי, אני מכיר בעיקר סקריפטים וכלים שכתובים בה ומעט מוצרים ולכן יש לי רושם שנתוני השימוש היבשים קצת מזייפים. כמו לשאול כמה מתכנתי Bash יש בעולם…המצב הקיים:

< הלינק מת… היה כאן תרשים של אחוזי השימוש בשפות JVM שונות + לאורך זמן >

 
לסיכום: קרב הירושה בעיצומו ועוד עשוי להמשך זמן רב. לא חייב להיות בהכרח מנצח אחד. הJVM  יאפשר למספר שפות לחיות זו לצד זו, כאשר כל אחת תוכל להתמקד בנישה שלה. 
Java עשתה את שלה, עכשיו ה JVM הוא העיקר.
* מאז שאורקל, חברה דיי כוחנית, לקחה שליטה על Java היא הצליחה בעיקר להבריח מפתחים מקהילת המפתחים של Java ולייצר תביעות שונות, בחשד להפרת פטנטים של Java. היא ניסתה לדלל את כוחה של הקהילה הפתוחה, אך עם הצלחה מוגבלת.
** Java לא הייתה המערכת הראשונה שרצה על מערכות שונות: פייטון הגיע לשם כמה שנים מוקדם ממנה עם Virtual Machine משלה. מה שהכריע את הכף הוא כנראה ש Java קסמה למפתחי ה C++ (שהיו אז הרוב) בכך שאימצה תחביר דומה וגם תמיכה גורפת מגופי ענק כמו IBM, אורקל, SUN ועוד.