2017-11-22

Evolutionary Design - הרצאה מתוך רברסים 2017


כמעט שכחתי!!

הנה ההרצאה שלי על Evolutionary Design מברברסים האחרון.

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


2017-11-18

ג'אווה, גרסה 3 - להתעורר מהתרדמה הדוגמטית


שפת ג'אווה. קהילה אדירה, אימוץ משמעותי וארוך שנים...

- אבל גם שפה שהגיל ניכר בה:
  • בעיקר, אבל לא רק: תחביר verbose - מרבה-במילים, שכבר לא מקובל בשפות חדשות (למשל: swift, go, וכו') - ומסיבה טובה.
  • Generics מבוסס "מחיקת טיפוסים" - שהופך את הדברים לקשים יותר, עניין שצץ מחדש בשימוש ב Steams. מחיקת הטיפוסים נעשתה במקור על מנת לשמר תאימות לג'אווה 1.4. למי אכפת היום מקוד שכתוב בג'אווה 1.4?!
  • רעיונות טובים שהתבררו כשגויים לחלוטין לאורך השנים - כמו checked exceptions.
  • פרימיטיביים מול אובייקטים ו auto-boxing.
  • חתימת זיכרון גדולה למדי של ה JVM.
  • ועוד...

הוותיקים שביננו בוודאי זוכרים, ששפת ג'אווה התחילה בתור ״Project Oak״ - כשפה ל"טלוויזיות חכמות" איי שם בשנות ה-90.

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

ואז הבינו שהיכולת של "Write Once, Run Anywhere" (או בקיצור: WORA) היא יכולת שמצוי הפוטנציאל שלה הוא לא בטלוויזיות חכמות (יחסית לשנות ה-90), ולא בדפדפנים - אלא דווקא בצד השרת.

כתוב את קוד השרת על מחשב ווינווס (היכן שקל לפתח) - אבל הרץ אותו על Unix ("שרתים אמיתיים") או Linux ("שרתים זולים - למי שמתעקש").

היום, "שרתים רציניים" מריצים Linux, ופיתוח הכי נוח לעשות על Mac (ה Linux Subsystem על "חלונות 10" מנסה קצת לאזן את התמונה), אבל היתרון שב WORA - חשוב כבעבר.


את התובנה הגדולה זו - הציגו בכך שהכריזו (ובצדק) שג'אווה עברה לשלב הבא: Java 2!

נוספו מאז ה J2EE, ה JVM נפתח כקוד פתוח - והשאר היסטוריה.



מקור: https://plumbr.io/blog/java/java-version-and-vendor-data-analyzed-2017-edition




לעשות שינוי


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

קהילת ג'אווה, שהייתה קנאית ל Backward Compatibility מאז ומעולם - יודעת זאת.
יכולות כמו Generics או Streams הגיעו לשפה באיטיות - ונעשו בהן פשרות מוחשיות.

פרויקט ה Jigsaw ("פאזל", ה Java Module System) החל בשנת 2005. הוא תוכנן להשתחרר כחלק מג'אווה 7 (שהתעכבה ל 2011) - אבל שוחרר עכשיו, רק בג'אווה 9 - עשור ושלוש שנים מאז שהחלה העבודה עליו.

האימוץ של גרסה 9 של ג'אווה עתיד להיות אטי - וכואב. מכיוון שג'אווה 9 איננה backward compatible, אנשי התוכנה יהססו לאמץ אותה גם מסיבות פסיכולוגיות, ולא רק סיבות טכניות גרידא.


אני לא טוען שהתאימות לאחור של ג'אווה היא טעות. אותה תאימות לאחור, מתישה ומכאיבה - היא אחת החוזקות של שפת/קהילת ג'אווה.


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


הפתרון הברור הוא להציג את שפת Java גרסה 3: גרסה מחודשת מהשורש, ולא תואמת-לאחור - של השפה.

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


הרבה מימים אפשר לייצר עם המספר 300


חבלי מעבר



המעבר מ"גרסה 2" ל"גרסה 3" - אמור לצלצל לכם מוכר. מזהים משהו?


לא? ... נסו שוב.



אי אפשר (כך נדמה לי) שלא לחשוב על המעבר ההיסטורי של שפת פייטון מגרסה 2 לגרסה 3 - וההשלכות של המעבר הזה.

המעבר היה מתבקש, מכיוון שהיה כמו תכונות "ישנות" של פייטון שכבר היו "בלתי-נסבלות":
  • מחרוזות לא היו Unicode (אלא ANSI?)
  • התנהגויות בעייתיות של הטיפוס הכ"כ בסיסי int:
    • אופרטור החלוקה / היה מעגל את התוצאה למספר שלם - מקום נפוץ לשגיאות.
    • int היה כמו BigInteger של ג'אווה - שזה נהדר, חוץ מהעובדה שקוד פייטון מרבה להשתמש בספריות ++C/C (עבור יעילות - זה חלק מהמודל ההנדסי של השפה) - אבל אז ההמרה יצרה בעיות.
  • אופרטור השווה (=, <, >, וכו') שהיה מופעל על טיפוסים שונים - היה משווה את ה id של האובייקטים, אם לא הייתה מוגדרת צורת ההשוואה - מקור לצרות אמיתיות.
בדרך הכניסו בגרסה 3 גם שיפורים שימושיים (super ללא פרמטרים, set literal, וכו'). המודעות לחשיבות התאימות-לאחור הייתה קיימת , ובהחלט נמנעו משינויים חשובים, אך לא הכרחיים. למשל: בנאי (constructor) בפייטון עדיין נקרא __init__, עוד מהתקופה שמפתחי השפה הניחו שרק הם זקוקים לבנאים - אבל משתמשי השפה לא יזדקקו להם. זהו שינוי מתבקש, אך לא "הכרחי" - ולכן לא נכלל בפייטון 3.


ראשי הקהילה תיארו זאת כך:

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


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

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

וכך - כל העגלה נתקעה. קריאה לקהילה לבצע את המעבר לא נענתה בחיוב, או לפחות לא בקצב מהיר. הוקמו אתרים כמו http://py3readiness.org ו http://python3wos.appspot.com שמדדו ועודדו - את האימוץ של פייטון 3.


פייטון 3 שוחררה ב 2008.

ב 2010 יצא עדכון 2.7 שהיה אמור להיות העדכון האחרון של פייטון 2 - אך הפך במהרה לגרסה הנפוצה ביותר של השפה.
בלית ברירה מפתחי השפה עשו downport לפיצ'רים רבים מפייטון 3 לגרסה 2.7 - על מנת להקל, בהמשך, על המעבר לפייטון 3.


מקוור: http://blog.thezerobit.com/2014/05/25/python-3-is-killing-python.html

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

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

הגרסה הנוכחית של פייטון 3 היא גרסה 3.6 - וקראתי כתבה שטענה ש 80% מהקוד החדש נכתב כיום בפייטון 3.
95% מהספריות הנפוצות כבר תומך בפייטון 3, וחלקים מהן מפסיק לתמוך בפייטון 2 (דוגמה: Django). במצב הזה, כנראה - קיוו יוצרי פייטון להיות בשנת 2010. זה קרה "רק" 8 שנים מאוחר יותר.


"הגרסה הבאה של פייטון תהיה פייטון 8, והיא לא תתאם לאחור בכלום" - מתיחת 1 באפריל

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

מקור: https://snarky.ca/why-python-3-exists

אם הייתי האחראי העולמי לשפת ג'אווה, ובמיוחד אם אני עובד בתאגיד גדול (שמרן מטבעו) כמו אורקל - בוודאי (!!) שלא הייתי נוגע בתפוח האדמה הלוהט הזה שנקרא Disruption עמוק בשפה עצמה. הייתי משאיר את זה לבא אחרי - שיבוא עוד 10-12 שנים. הוא בטח יעשה את זה, לא?!

נכון, ג'אווה 9 שברה תאימות לאחור לג'אווה 8 - וזה לא עניין של מה בכך. בכל זאת, השינוי נוגע לניהול packages ותלויות - ולא לשפה עצמה. מכיוון שג'אווה היא strongly typed ו static - לא קשה ליצור כלים שיגלו וינחו בשינויים הנדרשים, להלן jdeps. כן צפוי קושי עם ספריות שעושות שימוש כבד ב reflection, ספריות כמו Hibernate או AspectJ.
שינוי בתחביר של השפה - הוא סיפור אחר לגמרי.

מה עושים? האם אין דרך בה ג'אווה תוכל להתחדש - וליישר קו עם שפות מודרניות?



יש פתרון!


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

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

במקרה שלנו: נספק שני סוגי סיומות קבצים:
  • java. - עבור ג'אווה 2.
  • java3. - עבור ג'אווה 3.
כל עוד התחבירים השונים יוכלו לחיות זה לצד זה - גם באותו הפרויקט, ולתקשר זה עם זה (להפעיל פונקציות / לקבל ערכי חזרה) ללא קושי מיוחד - הפתרון יעבוד. תמיכה ל Java.V2 יש לספק לעוד עשור, לפחות. 

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

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





האם נרצה לבצע את השיפורים רק בתחביר השפה, או גם ב JVM?
יש כמה דברים טובים שאפשר לשפר ב JVM:
  • היכולת לצרוך פחות זיכרון (תהליך של ג'אווה מגיע לצריכת זיכרון של חצי GB - דיי בקלות) - הוא שיפור חשוב למיקרו-שירותים, ול FaaS (למשל: AWS lambda).
  • שמירת טיפוסי Generics בזמן ריצה (להלן "reified generics") - הוא שיפור מבורך שיתיר קוד מסובך במקרים רבים. הוא גם יאפשר לכתוב קוד שלא ניתן היום לכתוב בג'אווה.
מצד שני, שינוי ב JVM עלול להיות קשה וארוך לביצוע. לא נרצה לסיים במצב בו עלי להריץ שני תהליכים עבור Interoperatiblity: תהליך של JVM2 ותהליך של JVM3. אני אסיים עם יותר צריכת זיכרון ו overhead משמעותי (IPC) בתקשורת שבין התהליכים.

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



תוכנית עבודה



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

אם נתחיל עכשיו, ונוציא את המטלה מידי ה Java Committee - אנחנו יכולים להגיע לשם כבר בסוף שנת 2023!


הבשורות המשמחות הן שתהליך כזה כבר החל בשנת 2011!

ג'אווה 3 כבר מוכנה ועובדת. יש עשרות אלפי מתכנתים שעובדים בה במשרה מלאה. היא production-ready ועם interoperability מוצלח למדי לג'אווה 2!
אני יכול להעיד זאת לאחר עבודה לאורך החודשיים האחרונים עם JavaV3 בסביבת פרודקשיין.

לא פחות משמח: חברת אורקל תמשיך לתמוך ולפתח את Java.V2 באהבה ובמסירות עוד שנים רבות. זה לא פחות חשוב - כי סביר שקוד Java.V2 עוד יחיה שנים רבות.


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

ולכן, זה הזמן לקהילה החופשית לעשות את השינוי.

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

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

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

מקור: http://pypl.github.io/PYPL.html - בעת כתיבת הפוסט


קוטלין כן הצליחה ליצור spike של adoption - בעיקר על בסיס מתכנתי אנדרואיד.

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

קוטלין היא שפה מודרנית בהחלט: תחביר פשוט, פונקציות הן 1st Class citizens בשפה עצמה, יש לה הגנה בפני nulls, שיפורים לספריות, extension functions, ועוד). קוטלין גם מאפשרת Interoperability מוצלח מאוד מול Java.V2, ויש לה IDE חינמי, הרץ על שלושת מערכות ההפעלה - עם תמיכה מעולה בשפה.

בקיצור:

קוטלין היא המועמדת הטובה ביותר לתפקיד Java.V3!

אני מוכן להעיד על כך מניסיון אישי. זו פשוט שפה טובה.

מה נותר? נותר לנו - הקהילה, לאמץ אותה!

אני באמת לא רואה סיבה מדוע לא לאמץ אותה בחום בצד-השרת. עשינו זאת בחברת Next Insurance - בהצלחה רבה!

השיפור בפריון וקריאות הקוד - הוא לא שיפור ש Java.V2 תוכל איי פעם להשיג - במגבלות שחלות עליה. מודל ה Interoperability למעבר בין גרסאות שפה - הוא מצוין. לא יהיה כאן שוד ושבר.


האם באמת מפתחי הג'אווה שבעו מחידושים, והם מסתפקים בזחילה לכיוון ג'אווה 9, או ב Spring Boot - כהתקדמות בסביבת העבודה שלהם?!

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

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

מי יותר מקהילת הסטאראט-אפים בישראל מתאים להחיל כזה שינוי?



לסיכום (עודכן)


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

בכלל, כמה וכמה חידושים ברמת השפה בג'אווה 9 נראים דומים בצורה מחשידה ליכולות שיש כבר בקוטלין: Stream API improvements? - כבר יש. private interface methods - כבר יש. REPL? - ברור שיש. גם default interface methods הגיעו לקוטלין לפני שהגיעו לג'אווה.
אני חושד שהיוצרים של קוטלין מסתכלים על ה JSRs המתגלגלים של ג'אווה, ומביאים אותם לקוטלין - פשוט יותר מהר.

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


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

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

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


האם אני מפספס משהו? האם אתם יודעים להסביר מדוע מעט כ"כ אנשי ג'אווה (צד-שרת) מתעניינים באימוץ של קוטלין?

אשמח לתגובות :-)