קוטלין (Kotlin) למפתחי ג'אווה ותיקים – חלק א': הבסיס

קוטלין?!קוטלין (על שם האי קוטלין) היא שפה static-typed, עם תחביר מודרני, הרצה מעל ה JVM. היא פותחה ע"י JetBrains – חברת ה IDEs הנודעת מרוסיה.

החבר'ה של JetBrains כתבו הרבה קוד בג'אווה כחלק מפיתוח ה IDEs שלהם. התחושה – שהקוד verbose מדי. הם התלבטו בין Ceylon (של RedHat, המתקמפלת גם לג'אווהסקריפט) וסקאלה, אבל ממספר סיבות – החליטו שאף אחת מהשתיים אינה מתאימה להם.

הפתרון: לפתח שפה בעצמם.

שש שנים אחרי, חברות טכנולוגיות כמו Uber, Netflix, Pinterest ועוד – משתמשות בקוטלין: בצד השרת, ובאנדרואיד.
קוטלין היא דיי חדשה, ה GA שלה הוא החל מפברואר 2016.

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

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

בקצרה:

  • לקוטלין יש תחביר דומה מאוד לג'אווה – אבל מודרני ומינימליסטי. אלמנטים רבים בתחביר שלה מזכירים את השפה האחרונה שסקרתי בבלוג – Go.
  • פונקציות הן First Class Citizens. שמעתי טענה ש Kotlin היא "שפת Object-Oriented ו Functional" – טענה מוגזמת לטעמי: immutability ו pure functions הן לא משהו מפותח בשפה.
  • לקוטלין יש Interoperability טוב מאוד עם ג'אווה – הרבה יותר טוב מסקאלה.
  • לקוטלין יש coroutines (יכולת שהיא עדיין ניסיונית) – היכולת להריץ תהליכים רזים ברמת ה runtime של השפה, עם כלים פשוטים לטיפול במקביליות, כמו async, yield ו await.
  • לקוטלין יש IDE מצוין – עם תמיכה מתקדמת. זה חשוב.
  • קוטלין יכולה להתקמפל לג'אווהסקריפט. שימו לב שלא כל תוכן הספריות הסטנדרטיות תומכות גם ב JVM וגם ב JS – ויש סימון מתאים. ה Interoperability עם ג'אווהסקריפט הוא קצת יותר מורכב, בשל האופן הדינאמי של ג'אווהסקריפט.
  • בדומה ל Swift – הגבילו בשפה את השימוש ב Null.
  • אין Checked Exceptions (יששש!)
מצד שני:
  • קוטלין היא שפה עשירה ולא פשוטה. היא יותר מורכבת מג'אווה – אם כי יותר פשוטה מסקאלה.
  • קוטלין מתקמפלת מעט לאט יותר מג'אווה (היינו רוצים שהתהליך יהיה מהיר יותר).

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

שלום, קוטלין!

תודו שפאן (fun) נשמע הרבה יותר טוב מדף' (def – נשמע כמו מוות)

הנה ה Hello World של קוטלין.

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

הקוד בקוטלין מתקמפל ל bytecode של ה JVM (עם הסיומת kt לשם קובץ ה class.):

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

את ה class שנוצר בקומפליציה לא ניתן להריץ, ללא ה runtime של קוטלין: kotlin-runtime.jar.

אם עובדים עם command line הכי פשוט לארוז את הפרויקט ב jar עם הקומפיילר של קוטלין, לצרף את ה runtime – ואז להריץ:

$ kotlinc -include-runtime -d
$ java -jar
משתנים והשמות
  1. משתנה מגדירים בעזרת המילה השמורה var. קודם מופיע שם המשתנה – ורק אז הטיפוס (הפוך מג'אווה או C).
  2. ניתן באותה השורה גם לאתחל ערך.
  3. בעצם, ונראה את זה שוב ושוב: מה שהקומפיילר יכול להסיק לבד – לא צריך להגדיר לו. c יוכר כ Int כי זה הערך שהשמנו לו.
    var אינו "כלי קיבול גנרי". c מעתה והלאה – הוא static type מסוג Int.
  4. המילה השמורה val מגדירה ערכים שהם "immutable" (ליתר דיוק: פשוט לא ניתן לקבוע ערך אחר – בדומה ל final בג'אווה).
    בדומה לרובי, ניתן להשתמש במספר בקו תחתון, בכדי להקל על קריאת אלפים (או כל חלוקה אחרת שתרצו).
  5. בדומה לג'אווה, אני יכול להכריז שערך הוא מטיפוס Long ע"י הוספת האות "L" בסוף המספר.
  6. זו שגיאת קומפילציה. מדוע?
    כי המשתנה a לא אותחל, וקוטלין לא מקבלת השמה לערך שאינו מוגדר. אין אתחול באפס או null.
    בקוטלין כל המספרים הם אובייקטים. אין פרמיטיביים.
    אובייקטים לא יכולים לקבל ערך null, אלא אם הגדרתי אותם ככאלו (על כך בפוסט המשך).
  7. גם זו שגיאת קומפילציה! מדוע?
    אם אני מציב Long ב Integer (או להיפך) – עלי להצהיר על הטרנספורציה במפורש.
    אין casting, ואופן הצרנספורמציה הוא שימוש בפונקציה שהתנהגותה מוגדר היטב.
  8. כך צריך לבצע את ההמרה. להזכיר: b הוא אובייקט לכל דבר – אין פה autoboxing.

מחרוזות

  1. מחרוזת היא עוד אובייקט בקוטלין, כאשר יש ערך – לא צריך להכריז על טיפוס.
  2. כמו בפייטון (או עוד שפות) ניתן להגדיר Raw String בעזרת מרכאות משולשות.
    1. Raw Strings לא מקבלות escaping: הביטוי n\\ הוא מחרוזת, ולא שורה חדשה.
    2. כמו בשפות אחרות, ה margin הוא חלק מהמחרוזת.
    3. בכדי לצמצם margin ניתן לסמן את ה margin הרצוי בעזרת סימן "|" בתחילת כל שורה, ולקרוא ל ()trimMargin.
  3. בקוטלין יש interpolation למחרוזות בעזרת סימן ה $. כאשר הביטוי שם אטומי (יחיד) של משתנה – מספיק רק סימן הדולר.
  4. כאשר הביטוי הוא יותר מאטום אחד – יש לעטוף אותו בסוגריים מסולסלים.
  5. אם רוצים פשוט להקליד $ – יש לעשות לו escaping.
  6. בקוטלין יש custom operators, והשוואה בין מחרוזות מתרחש באמצעות האופרטור == (המקביל ל ()equals)

למען הסר ספק, הנה הפלט של הקוד לעיל:

לולאות

  1. כמו בפייטון, ניתן להשתמש ב range.
    rangeTo (כלומר: ..) הוא בעצם אופרטור של אובייקט ה Int, המחזיר אובייקט מסוג IntRange שהוא <Iterable<Int.
  2. ניתן, כמובן, לעשות איטרציה גם על <Iterable<T. דאא.
    מעניין לציין ש Iterable הוא לא Lazy, והופך לרשימה מלאה בעת ה evaluation שלו. השיקול: ביצועים. זיכרון רציף יעיל יותר לגישה ע"י המעבד.
  3. אפשר גם לספור לאחור, בעזרת downTo ויש גם step.
    downTo ו step הן לא מלים שמורות בשפה, אלא infix functions – כלי דומה לאופרטור, ששווה להסביר עליו בפוסט המשך.
  4. ()listOf היא פונקציה גנרית שמקבל רשימה (varargs) של ארגומנטים – ומחזיר אותם כרשימה <List<T. כמובן ש List, הוא גם Iterable.
  5. אם אני רוצה לבצע איטרציה ולעבוד עם אינדקס – זה התחביר.
  6. אם אני רוצה להתעלם ממשתנה (להימנע ב wanrnings / קוד קריא יותר), כמו בשפת Go – אני מחליף את המשתנה שלא אשתמש בו ב _ .
    (כמובן שבמקרה הזה שלב 4 הוא הדרך הפשוטה לכתוב את הקוד).

הנה הפלט:

נמשיך עוד קצת:

בזריזות:

  1. יש while.
  2. יש do {} while.
  3. בקוטלין אפשר להגדיר Label (מסתיים ב @) אליו אפשר להתייחס בלולאות מקוננות.
    כמה פשוט ונוח לומר: "אני רוצה להפעיל continue, אבל לא ללולאה הפנימית – אלא ללולאה החיצונית".
    הפקודה הן <break@<Label או <continue@<Label.
  4. יש גם repeat. האנוטציה ":times" היא של ה IDE – ואינה חלק מהקוד.
    זה מה שנקרא: "Five Whys".
הנה הפלט:
קצת על Control Flow
 
  1. בקוטלין אין ternary operator, קרי: v = cond ? a: b.
    הדרך המקבילה הכי פשוטה היא one liner if..else.
  2. משהו נחמד הוא ש if..else נחשב כ expression.
    1. אם, ורק אם יש לנו גם if וגם else (הרי אנחנו רוצים להימנע מ null / ערך לא מוגדר) – ניתן "לאסוף" את הערך מתוך ה expression.
    2. הערך הוא תוצאת ה evaluation של השורה האחרונה בכל בלוק – ממש כמו בשפת רובי.
    3. זה בעצם מה שמתרחש בסעיף #1 – רק שסעיף #1 הוא הצורה הפשוטה יותר לתבנית הזו.
  3. במקום switch, יש בקטולין את when.
    1. כפי שאתם רואים אפשר להשתמש במגוון ביטויים.
    2. בניגוד ל switch, ה evaluation של התנאים יפסיקו ברגע שימצא התנאי הראשון שהוא אמת. לכן הפלט יהיה ש "5 הוא ספרה בודדת", אף על פי ש 5 הוא גם מספר ראשוני, ואינו בסדרת ה 20. (בניגוד לג׳אווה / ++C / וכו׳)
    3. הקומפיילר מוודא שתנאי when על Enum או Sealed Class (עליהם נדבר בהמשך) הם Exhaustive (״ממצים״). כלומר: אם יש enum עליו אני רץ ב when אך לא כללתי את כל הערכים – זו שגיאת קומפילציה. זו יכולת חשובה ושימושית – למנוע באגים של ״אי טיפול בכל המקרים״ (ומתכתב נהדר עם עקרונות של Functional Programming).
      כמובן שניתן להוסיף else case ל when, וניתן גם לעשות break ו continue (שימושי לעתים רחוקות).
הנה הפלט:

סיכום

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

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

—-

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

Cheat Sheet למעבר בין ג'אווה לקוטלין. https://github.com/MindorksOpenSource/from-java-to-kotlin

הדומיין שאבד

קרו הרבה דברים לאחרונה. לא דברים קלים.

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

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

אני יודע שזה לא מדויק.

בכל מקרה, הזנחתי את הבלוג. בלוג שהוא קצת מפעל חיים (התחלתי אותו בסוף 2011, עם יותר מ 200 פוסטים, שרובם מושקעים (כ 8 שעות עבודה בממוצע לפוסט).

ב 5 באוקטובר פג לי תוקף הדומיין (החלפתי כרטיס אשראי, והתעלמתי ממיילים של אזהרות) – ואז גיליתי כמה כואבת ויקרה יכולה להיות הזנחה שכזו. ידעתי בראש שיש לדומיינים 90 ימים grace גם אם לא היה תשלום – אבל מסתבר שבתוכנית שלי זה לא היה כלול. $10 שלא שילמתי בזמן – הפכו למפעל חיים שפתאום נעלם.

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

אמנם יש תמונות שלי מנופף להם לשלום – אבל זה לא היה באהבה.

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

בקיצור: עם הדומיין של softwarearchiblog.com, הלכו גם כ 2000 קוראים שלא ימצאו אותו עכשיו, קישורים שלא עובדים, ו reputation בגוגל שנבנה במשך עשור (ובמאמץ קידום רב). לא כיף.

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

הדומיין החדש של הבלוג הוא מעתה https://softwarearchiblog.co.il – אם אתם יודעים להפיץ לאנשים שמתעניינים – אני אודה לכם מאוד. חבל לי שהפרויקט שלי כמעט ובלתי ניתן למציאה (גוגל שכח ממנו לגמרי).

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

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

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

נעלה ונצליח!

לחשוב Developer eXperience (DX)

[הפוסט עודכן קלות ב 2023 – בעיקר שיפור ניסוחים.]

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

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

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

זה עבד! ומאז המטאפורה הזו התפרסמה כדוגמה.

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

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

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

סקר של מקינזי בקרב "מומחים"/מנהלים בכירים מה משפיע על הפריון של מפתחים

Code-level DX

אני רוצה להתחיל בשימוש במטאפורה של DX לרמת הקוד, בכדי לעזור לנו לכתוב קוד טוב יותר.
נתחיל בדוגמה קצת קשוחה… אובייקט ה java.util.Date (שהוחלף לחלוטין בג'אווה 8)

  println(new Date(2020, 5, 35)) // Result: Mon Jul 05 00:00:00 IDT 3920
  println(new Date(120, 4, 1)) // Result: Fri May 01 00:00:00 IDT 2020

כאשר אני מאתחל את אובייקט ה Date בג'אווה ל 35 במאי 2020, אני מקבל את התאריך 5 ביולי 3920.
למה?? איך?!
אובייקט ה Date הציג Interface שהוא פשוט זוועה, במיוחד בגרסאות הראשונות שלו (ה constructor בו השתמשתי הוא deprecated):

  • את השנה מצפים שאספק כהפרש מ 1900 (על משקל Java Epoch 🤯), כך כ 2020 היא 120.
  • את החודש מצפים שאספק באינדקס-0, כך ש 5 הוא יוני (כי 0 הוא ינואר… לא ברור?)
  • אם יש גלישה של ימים (35 ביוני) אז לא תיזרק שגיאה, אלא יוסיפו את הימים כבר לחודש הבא (ההפך מ Fail Fast) – וכך הגענו ל 5 ביולי.

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

קוד טוב = DX טוב.

אם אתם רוצים לעשות DX טוב אתם צריכים לכתוב API/Interface שמפתחים ייהנו לעבוד אתו. לא… לא "יצליחו לעבוד" אתו – ייהנו לעבוד אתו!
השאיפה הזו להנאה עשויה להציב את הרף הנכון לרמת הקוד שאנו מבקשים, כפי ש"כל הפארק הוא במה" עזר לעובדים של דיסני להבין את רף החוויה שהם מצופים היו לתת למבקרים בפארקים של דיסני.

הנה דוגמה הרבה פחות קיצונית:

fun DataPoints.plus(other: DataPoints): DataPoints {
    val intersectKeys = this.keys.intersect(other.keys)
    val intersectEntries = (this.entries + other.entries).filterKeys { it in intersectKeys }
    return DataPoints(intersectEntries)
}

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

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

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

דוגמה אחרונה, הסתכלו על ה interface הבא:

interface NoFun {

  fun updateCustomerDataPoints(customerId: CustomerId, dataPoints: List<DataPoint>)
  
  data class DataPoint(
    val type: DataPointType, 
    val value: DataPointValue, 
    val effectiveDate: LocalDate
  )

}

במקרה הזה אנו מעדכנים את אובייקט הלקוח עם DataPoints מסוימים, אבל בתסריטים מסוימים חשוב לעדכן את ה effective Date על Data Points נוספים שלא היו בעדכון, בשל תלות סמנטית בין ה DPs. ברור למומחה העסקי מדוע זה נכון, אבל אני מקווה שברור לכם הקוראים – מדוע לצרכן של ה API זה לא אינטואיטיבי (במקרה הטוב) או הפתעה גמורה (במקרה הפחות טוב).

איך מסבירים למשתמש לוגיקה מורכבת שכזו? ועוד בחתימה של API?

שינוי קטן ב API (הוספה של שדה אופציונלי של effectiveDate) יכול לשדרג את השימושיות שלו בצורה משמעותית:

fun updateCustomerDataPoints(customerId: CustomerId, dataPoints: List<DataPoint>, effectiveDateForAdditionallyUpdatedDataPoints: LocalDate)

בחתימה הזו אני מציף את ההתנהגות המורכבת / לא-צפויה החוצה. אני מבקש מצרכן ה API – לשחקת את המשחק. הוא קודם כל מבין שיש ״משחק״ שהוא לא מודע לו. ״מה זה effectiveDateForAdditionallyUpdatedDataPoints לעזאזל?״. אם הוא ילך בעקבות זאת לתיעוד (דבר שלא עושים בד״כ) – אז כבר השגתי את שלי.

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

Due to this operation, some additional data points may update their 'effective date'.
Please provide an effective date that matches the effective date of the original DataPoints or read the function doc to understand more.
This check is added to ensure you are aware of this additional functionality.

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

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

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

הטיעון ש "אנחנו רוצים לתת API שכיף ונוח לעבוד אתו" (בלי קשר לרמת המומחיות של הצרכן) עשוי להכריע את הכף לטובת השימושיות הגבוהה / יישום POLA. אולי לא כולם יסכימו שה API הראשון מבלבל / מכשיל את המשתמש, אבל כולם יסכימו בוודאי שהוא לא "מפנק" ואפשר לעשות אותו נוח ו"כיפי" יותר לשימוש. זה מספיק. UX גבוה הוא קונספט מוכר ומוסכם, ואף אחד לא יצפה ש Gmail יבקש ממני להגדיר את ה HTTP Headers של ההודעה – רק בגלל שאני מומחה ואני יכול, נכון?

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

DX ברמת ארגון הפיתוח

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

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

תלונות כמו:

  • "ה Build אטי"
  • "ה Security Tools והדרישה להכניס סיסמה כל פעם – פשוט מטרידים"
  • "לפתוח באג בג'ירה זה פשוט סיוט… למה זה כ"כ מסובך?"

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

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

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

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

מצד שני, התמורה בחוויית פיתוח טובה יותר עשויה להיות מכפיל כוח אמיתי לארגון:

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

קראתי כמה מאמרים שטענו ש DX גבוה יותר (איך מודדים?) משפיע בצורה משמעותית על הצלחת הארגון ("פי 4-5") ועל שביעות הרצון של העובדים – אבל לא מצאתי נתונים משמעותיים ששווה להציג. רק דיבורים.

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

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

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

מונח מתאים מעולם ה UX הוא ה Friction Log – תיעוד אזורים בהם קשה למשתמשים להתקדם ב UI המערכת והם חווים בהם תסכול. באופן דומה כנראה שכדאי לבקש מהמפתחים לשתף ולתעד – היכן הם חווים קושי, עיכובים, ותסכול ברמת הפיתוח, ובטוח שיש הרבה כאלו.

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

כמו בארכיטקטורה של מערכת, כדי להיות יעילים הרבה פעמים שווה להשקיע בלהפוך בעיות ברמת חומרה "High" לבעיות ברמת חומרה "low" או אפילו "רק medium" ולעבור לבעיה הבאה – מאשר לנסות להעלים את הבעיה לגמרי. Build Pipeline איטי מציק אם הוא אורך 30 דקות, אבל כנראה ש 10 דקות זה בסדר. המאמץ להביא אותו ל 2 דקות – עשוי להיות אדיר, ולא משתלם.

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

אני מאמין ש DX גבוה יכול להגיע רק מתוך שיתוף פעולה פרואקטיבי עם המפתחים וגם מניהול של העניין ע"י מישהו שמגיע מעולמות הפיתוח. לא Operations ולא תפעול.

סיכום

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

האם המטאפורה העדיפה (בשאיפה) – תוביל לתוצאות טובות יותר? אתם תגידו – אבל יש לי אופטימיות שייתכן וכן.

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

תכנות מול הנדסת תוכנה: על ההבדל

בפוסט קצר, שיכול להיות שרשור בטוויטר, אני רוצה לחדד את ההבדל בין ״תכנות״ ל״הנדסת תוכנה״.

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

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

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

נושאתכנות
(ברמה גבוהה)
הנדסת-תוכנה
(ברמה גבוהה)
אף אחד מהם
כתיבה שוטפת של קודכתיבת קוד מהירה – שמבצע את העבודה: תוך זמן קצר – הפיצ׳ר עובד.כתיבת קוד סופר-ברור וקריא, שקל להיכנס אליו ולקרוא אותו.כתיבת קוד סופר-מתוחכם המשתמש במגוון יכולות של שפת התכנות / ספריות. קוד שמעטים יכולים לכתוב – ומעטים יכולים להבין בקלות.
מקרי קצהחשיבה על מקרי-קצה שעלולים לצוץ וטיפול בהם. ההבנה אילו מקרים לא מספיק חשובים לצורך העיסקי וניתן להתעלם בהם (למשל: המשתמש לא יוכל לבצע את הפעולה = מגבלה מתוך החלטה)מקרי הקצה מטופלים באופן שקל להבין אותם: מהו מקרה הקצה, ומהי ההתנהגות.
ארגון הקוד של מקרי-הקצה הוא מבנה שמקל על תחזוקת המערכת לאורך זמן״הידע מוטמע בצורה מסודרת בתוך הקוד״ ולא ״ידע מפוזר באקראיות ברחבי הקוד״.
התעלמות ממקרי הקצה, או טיפול ב 100% מהם. שתי הנקודות הללו לא-מיטביות.
שימוש בספריות צד שלישישימוש מושכל בספריות / שירותי צד-שלישי כאשר השימוש חוסך כמות משמעותית של פיתוח.בחירת ספריות עם התאמה גבוהה לארכיטקטורת המערכת: מינימום חפיפה לקיים, מקסימום המשך של גישת המערכת לנושאים שונים (צורת תקשורת, שמירת נתונים, קונבנציות, אבטחה, וכו׳)שימוש (לעתים מנומק) של ספריות צד-שלישי שלא בהכרח מקצרות בהרבה את זמן הפיתוח ולא בהכרח מתיישבות עם ארכיטקטורת המערכת.
איתור תקלותמומחה באיתור תקלות במערכת, יודע היכן לחפש, איך לחשוף ביעילות עוד מידע – ולפתור מהר את הבעיה.מתכנן את המערכת כך שתקלות יקרו פחות, ואם הן קורות – יהיה קל לאתר אותן, ולא יזדקקו ליכולות מיוחדות של איתור תקלות.?
כתיבת בדיוקכתיבת בדיקה שבודקת ביעילות נקודה מסוימת ומוכיחה: עובד או לא עובד.כתיבת בדיקה קלה לתחזוקה (למשל: מיעוט בתלויות, או ב mocks). כתיבת בדיקה ברורה דיה להיות סוג של תיעוד מה היכולות וההתנהגות הצפויה מהמערכת.?
מטאפורהבישול ארוחה טובההרצת מסעדה רווחיתבשלן חובב, שעסוק בעשיית רושם – אבל לא ממש מצטיין בלב המלאכה.
תצורת עבודה אופטימליתלבד.
חברה קטנה שצריכה לזוז מהר.
סט היכולות נדרש גם בחברה גדולה – אך הוא הופך למשני להנדסת תוכנה
ארגונים גדולים ובינוניים, הדורשים עבודה עמוקה-משותפת של גורמים רבים, ובמיוחד אם יש בהם מורכבות גדולה.
היכן ששם המשחק הוא: ״לאפשר למערכת להמשיך ולנוע – בלי להיתקע״.
בעיקר ארגונים גדולים – שם חוסר-יעילות יכולה לפרוח.

כמה נקודות:

  • נוהגים לומר ש״הנדסת התוכנה מתחילה היכן שהתכנות נגמר״. לכאורה נשמע ש״הנדסת תוכנה״ היא הפרקטיקה ה״שווה״ / חשובה יותר. זה נכון, אבל חלקית: הנדסת תוכנה בלי יכולות תכנות טובות – לא שווה הרבה.
  • זה לא שאדם מסוים הוא מפתח או מהנדס תוכנה. הם לא Mutually exclusive (בלעדיים). תיאור מדויק יותר הוא שכל איש-תוכנה הוא במידה מסוימת מתכנת, ובמידה מסוימת מהנדס תוכנה.
    • משה אולי הוא 9/10 מתכנת, ו 3/10 מהנדס תוכנה.
    • רינת היא אולי 6/10 מתכנתת, ו 8/10 מהנדסת תוכנה.
    • כמובן שנרצה אנשים מעולים בשני התחומים – אבל זה לא תמיד מה שנקבל.
  • הצורך בהבנה הזו היא כדי להעריך ולהכווין עובדים. למשל: אם מישהו הוא מתכנת מעולה (אבל מהנדס תוכנה חלש) – כנראה שלא יהיה נכון למנות אותו למוביל טכני או ארכיטקט. מנהלים לפעמים מתבלבלים, שאם אדם הוא מתכנת מצוין – זה לא מעיד על יכולות הנדסת התוכנה שלו.
    • יתרה מכך, ״להטוטני קוד״ שמכירים את כל הטכנולוגיות החדשות, או כותבים קוד סופר-מתוחכם וחדשני, עשויים להיות במקביל לא מתכנתים טובים, ולא מהנדסים טובים. חשוב להבין את זה, ולהכווין אותם לערוץ פרודוקטיבי. לא להתרשם מהפונקציה המתוחכמת-גנרית-רקורסיבית-tailrec-פונקציונלית – שאף אחד לא מבין, וזה כנראה מצביע על זה שהיא פשוט לא טובה.
  • כמובן שארגונים גְּדֵלִים צריכים להיזהר מריבוי מפתחים שהם לא מהנדסים טובים. אפשר להתקדם במהירות בהתחלה – ואז לחוות נפילה גדולה שבה המערכת כ״כ סבוכה / נכתבה אופורטוניסטית / קשה לתחזוקה – שהארגון פשוט ״תקוע״ וההתקדמות הופכת למאוד אטית וכואבת.
    • בחוויה של סטארטאפ קטן, האלתור והשחרור המהיר של הפיצ׳ר – הוא הניצחון.
    • הרבה מאוד ניצחונות תכנותיים – הופכים לניצחון פירוס הנדסי (״עוד ניצחון כזה, ואבדנו״) במיוחד אם הדומיין העסקי הוא מורכב.
  • ההיפך הוא גם נכון: יש מהנדסי תוכנה שרק ירצו לעשות Refactoring ושיפורי תשתית ותחזוקה בלי סוף. אם לא תאזנו אותם – הם יכנסו ל Refactoring רקורסיבי בלי תנאי עצירה. (כלומר: אינסופי. שנה, שנתיים – והיד עוד נטויה).

לא תמיד קל להבחין מהי הדרך הטובה ביותר לעשות דברים.

יש לבחון כל הזמן את הדברים…

סיכום

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

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

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

Staff Engineer: התמודדות עם מורכבויות

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

דוגמאות לדילמות:

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

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

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

מודל ההתקדמות-במורכבות של ליאפולד [1]

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

אתחיל בלתאר את שלבי המודל, בזה אחר זה.

ציטוט מפורסם, אך לא מדויק.

שלב ראשון: דילמה

צעד ראשון: זיקוק

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

  • לתאר אותה.
  • לחדד מה בדיוק יודעים.
  • לחדד מה עוד לא ברור / פתוח.
  • להסיר פרטים מיותרים / לא נחוצים.
  • למצוא דרך פשוטה להסביר לאחרים, שחסר להם הֶקְשֵׁר – מה שאתם כבר יודעים.

אני חושב שאצלי תהליך הזיקוק כבר דיי אוטמטי ומתרחש בדרך כלל בראש, בחצי דקה (״טוב… מה העניין?״ – אני שואל את עצמי) – אבל הוא בחלט קורה. במקרים יותר מורכבים אני אכתוב כמה נקודות על פתק (יש לי פתקיות בשולחן העבודה, ואני משתמש בהן כל יום), או אלך ליצור תרשים (משהו מהיר ב excalidraw). עוד אופציה היא להתחיל מסמך (Google Docs) – ולסכם את הדברים, לרוב בנקודות.

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

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

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

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

צעד שני: איסוף נתונים

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

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

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

קיבלתי תשובה!

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

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

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

צעד שלישי: הצלבת נתונים

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

כאשר יש סתירה במידע שאנחנו אוספים ממקורות שונים (אנשים שונים, מסמכים, קוד וכו׳) – לא פעם אנשים נוטים להעריך שאדם הבכיר יותר /ותיק יותר הוא המקור האמין, ולהעדיף אותו על הסף (״מעולם לא פיטרו מתכנת כי הוא הקשיב למה שה VP אמר״?). זו טעות נפוצה. כל סתירה בנתונים היא פוטנציאל לידע חדש שעוד לא ברשותכם.

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

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

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

אני לא מכיר אתכם אישית, אבל סטטיסטית – אתם כנראה יכולים לעשות את השלב הזה טוב יותר.

—-

עד כה – בסך הכל חידדנו והבנו טוב יותר את הדילמה, ועדיין לא פתרנו אותה.

כמובן שכל הצעדים הם מחזוריים, ואנו עוברים עליהם שוב ושוב:

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

שלב שני: הצעת פתרון לדילמה

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

עלינו להבין מי הפורום הנכון לקבל / להיות שותף להחלטה (אני מניח שזה כבר טבעי לנו, בכל זאת: Staff Engineer…) – ולהכין הצעת פתרון לאישור בפורום הזה.

צעד ראשון: גישוש

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

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

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

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

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

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

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

צעד שני: השגת קונצנזוס

זה השלב להגיע להחלטה בנושא:

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

שלב שלישי: פתרון מוסכם

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

לא כל-כך מהר! פה הרבה מהנדסים נופלים – ולא בעצם מספקים את מה שמצופה מ Staff Engineer.

צעד ראשון: הידוק וסגירת פינות

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

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

בתור מי שהוביל טיפול בדילמה, יצפו מכם כנראה לוודא שהיא סגורה / Done / Finito / Completo. כמובן שזה מעייף – ויותר נחמד לחזור ״להזרים קוד״ או אפילו לעבור לדילמה הבאה… לא סתם לא כל מהנדס מוכר כ Staff Engineer.

צעד שני: איתור השלב הבא

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

זה לא הסוף, עד שענינו ״מה השלב הבא״?

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

  • לתקשר את ההחלטה לגורמים / קבוצות שונות בארגון.
  • יש מציאות חדשה (למשל: דרך פעולה חדשה של המערכת) – נדרשת הדרכה לגורמים מסוימים בארגון.
  • הדילמה עיכבה תהליכים מסוימים – שעכשיו הגיע הזמן להניע מחדש.
  • מקרה קלאסי: דילמה מובילה לעוד דילמה ועוד דילמה. פתרון אחד פתר את הדילמה המסוימת, אבל בצפייה קדימה, אנחנו מבינים שבעצם מעכשיו תהיה דילמה נוספת במקום אחר / לגורם אחר בארגון.
    • למשל: הפתרון כלל תחילת שימוש במערכת חדשה (למשל: Dynamo DB) – אבל עכשיו יש שאלה איך לגבות / לתפעל את הפתרון? זו לכאורה בעיה של ה Cloud Operations (להלן "DevOps״) – אבל לא באמת סגרנו את הפתרון – עד שטיפלנו גם בדילמה הבאה.
    • דוגמה נוספת: יצרנו מנגנון מסוים, אבל הוא יקשה על או יש שאלה כיצד ישתלב בתוכניות של צוות מסוים – שמושפע מהשינוי.
  • לוודא שיש מישהו שיכול ומוכן לטפל בשלב הבא. שהשלב הבא מצא ״בית חם״.

עלינו לבחון ולהבין האם באמת ״זה סוף העניין, ולכולם״.

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

סיכום

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

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

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

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