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] המודל אינו קשור לשום ליאפולד. ציירתי את התרשים תוך כדי כתיבת הפוסט, ונתתי לו כותרת מפוצצת במאמץ מעט פתטי לגרום לכם, הקוראים, להתייחס ביתר רצינות – לנושא הבאמת חשוב הזה.

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

Generative AI – כמה רשמים מ Dall-E 2.0

Generative AI נכנס לחיינו בסערה! אם לא בשנתיים האחרונות, אז בחודשים האחרונים, עם Dall-E 2.0 ו ChatGPT שהצליחו גם לחדש, אבל בעיקר להביא את הבשורה וההתקדמויות בתחום – לקהל הרחב. אני בטוח שכבר יש חברות סטארט-אפ שמוסיפות לתיאור שלהן ״Generative AI״ (כי זה עוזר לגייס כסף, ואולי גם עובדים), ואני לא מפסיק לקרוא מאמרים וציוצים – על הכלים הללו.

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

רשמים, בתפזורת

  • Dall-E 2.0 הוא מדהים (!!) – היכולת של תוכנת מחשב ליצור תמונות מלאות דמיון ולא פעם ״בעלות קסם״ או ״סגנון״ הוא מפתיע בעליל. אני זוכר שלמדתי באוניברסיטה (לפני 20 שנה+) קורס בבינה מלאכותית, ונאמר שאמנים הם האחרונים שישרדו את השתלטותה של הבינה המלאכותית. ההנחה שמחשב יתקשה ליצור ״יצירתיות״ – הופרכה, ולאמנים רבים יש מקום לדאגה.
  • באותה נשימה ניתן לומר שרוב התוצרים של Dall-E 2.0 כרגע הם עדיין לא מספיק איכותיים לשימוש מיידי. מעטים מהם אפשר לקחת ״as-is״ ולשים במגזין או אתר אינטרנט בלי שהקוראים לא יבחינו שמשהו חסר / לא-שלם. העין הביקורתית תזהה בקלות מרחב של פגמים בתמונות ש Dall-E מייצר, החל מאזורים בתמונה שאינם ברורים / נראים שגויים, הצללות לא נכונות, עיוות בפנים אנושיים (בעיקר בעיניים ובשיניים), קושי ביצירת טקסט כתוב, ועוד.
    • למרות ש Dall-E 2.0 כולל מנגנון להערכת האיכות של התמונות (והוא ירוץ עד שהתמונה תראה לו איכותית מספיק) – הוא עדיין זקוק לבני-אדם שיבררו בין תוצרים המוצלחים והלא מוצלחים שלו, ולעתים אנחנו נדרשים לנסות מספר רב של איטרציות (10 ויותר) עד שנגיע לתוצר משביע-רצון.
    • מקצוע שהולך ומתפתח הוא ״מתקשרי Dall-E לעולם״: עם קצת התמקצעות וריבוי ניסיונות – ניתן לגרום ל Dall-E ליצור תוצרים איכותיים יותר. נוסיף קצת פוטושופ, ותוכנות משלימות – אפשר להגיע לתוצרים איכותיים. לא נמנע שגרפיקאי אחד המתמחה בשימוש ב Dall-E (וחלופות / כלים משלימים) ושעושה השלמות בתוכנות עריכה (כגון PhotoShop) – יכול להגדיל את הפריון שלו פי 10. להלן 10X Graphic Artists.
    • אין סימן עדיין ש Dall-E (או כלים מקבילים) התקרב למיצוי. תוך שנה הייתה קפיצה דיי משמעותית ביכולות בין Dall-E 1.0 ל Dall-E 2.0. מה שמשנה הוא לא מהן היכולות של Dall-E 2.0, אלא לאן יגיעו Dall-E 5.0 או Dall-E 7.0. היכן תהיה עצירה ביכולות, וכמה רחוק מיכולות של אמנים זוטרים הן תהיינה (לכיוון א׳, או ב׳). בגזרת הסבלנות / מהירות / עלות – Dall-E כבר ניצח בגדול.
  • בפן החברתי, התפתחויות ה Generative AI (כמו Dall-E, ChatGPT ואחרים), יגרמו ככל הנראה לסבל רב. ההתפתחויות הן מאוד מהירות, ולא ישאירו זמן מספיק לאנשים בכדי להסתגל. הרבה אנשים אשר מבססים את הערך העצמי ו/או הפרנסה שלהם על ״יצירת תוכן״ – עומדים (כנראה) לאבד הרבה מערכם. מזכיר לי קצת את מה שאיקאה עשתה לנגרים: היא לא העלימה אותם – אבל מה שהיה כבר לא יחזור.
  • בצד הטכני: Dall-E מבוסס על GPT-3 (התקדמות משמעותית בתחום העיבוד של שפה טבעית) ועל CLIP (מודל של OpenAI שיודע לקשר בין טקסט לתמונות). Dall-E קודם כל מצליח לנתח (בצורה מרשימה ביותר) בעזרת GPT-3 את הטקסט של ה Prompot וההקשרים הלשוניים שלו – ואז למצוא מאגר של תמונות רלוונטיות שהוא חומר הגלם לתמונה שתיוצר. הוא בעצם עושה את הפעולה ההפוכה ל AI שמנסה לתאר במילים תמונה שהזנו לו (קונספט שעובד יפה כבר כמה שנים).
    • המנגנון של ייצור התמונה מחומרי הגלם שנבחרו, נקרא diffusion (תהליך של הוספת רעש לתמונה עד שהיא מאבדת מהמשמעות שלה, והתהליך ההופכי: הסרת רעש מתמונה עד שהיא מקבלת משמעות). המודל של OpenAI ל difusion נקרא GLIDE. דרך הפעולה של GLIDE היא להרכיב ״בגסות״ את חומרי הגלם בהקשר נכון (ע״פ ההבנה של CLIP) ואז להתחיל להסיר אלמנטים לא-רצויים מהתמונה – עד אשר ניתח התמונה כטקסט – עומד בהגדרות ה Prompt. כמובן שיש פעמים שבה הסרנו יותר מדי – וצריך לחזור לאחור.
    • הסבר מפורט ומדויק יותר – אפשר למצוא ב How Dall-E 2.0 actually works. הסבר נוסף.
הסבר ויזואלי על העבודה של GLIDE
  • Dall-E הוא מרשים, ועורר גלים – אבל הוא לא היחיד. ל Dall-E יש מתחרים ישירים כמו Stable Diffusion או Midjourney. יש גם את Imagen של גוגל, שלא יצא לי לבדוק. בהתרשמות מהירה נראה שלא פעם הם מייצרים תוצרים באיכות גרפית יותר גבוהה מ Dall-E אבל מפספסים יותר במה בהבנת ה Prompt. כלומר: תמונה יפה שהיא לא בדיוק מה שביקשתם.
    • שווה לציין שמאגר התמונות עליהם הכלים הללו מתבססים הוא תמונות מרחבי האינטרנט, למשל: מקור טוב הוא חשבונות אינסטגרם של אנשים בהם יש תמונות מוצמדות לטקסט. זכויות היוצרים של התמונות שנוצרות ע״י הכלים הללו – עדיין לא הובהר.
  • ספציפית לגבי השימוש ב Dall-E:
    • השימוש הבסיסי ב Dall-E הוא הזנת טקסט תיאורי – שיהפוך לתמונה.
    • Dall-E מגיב טוב יותר לתיאורים מסוג מסוים – מאשר סוג אחר. למשל: כדאי להתחיל עם Prompt כללי – ולהמשיך ולדייק/לפרט אותו בכדי להכווין את הכלי לתוצאה שאנו רוצים. Dall-E מכיר סגנונות אומנותיים ושמות של אמנים – ומגיב אליהם היטב. Dall-E מגיב, למשל, לטקסט ״4K״ – כרמז שרוצים תמונה יותר מפורטת. ה Dall-E-2 Prompt book מכיל עצות ודוגמאות הרבה מעבר למה שאוכל לספק בפוסט זה.
    • אם אנחנו בסה״כ אוהבים תמונה שנוצרה, אבל פרט מסוים מפריע לנו – יש אפשרות ב Dall-E ללחוץ על Edit ולמחוק את החלק שלא נראה לנו – ולתת לנסות ל Dall-E ליצור את האזור הבעייתי מחדש.

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


נלחץ על כפתור העריכה.

נמחוק את אזור הפה, האזור שבו אנחנו רוצים Re-Generation ונעדכן את ה Prompt שיכיל גם שפם ענק. Dall-E זקוק ל prompt הקודם / המלא – בכדי להמשיך להבין את ההקשר המלא של התמונה. נלחץ על Generate.

הנה התוצאה: התמונה נשמרה – והשפם לתפארת.

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

  • את אותו העקרון, של שלמת תמונה ע״פ תיאור – ניתן לעשות גם על תמונה שלכם. נניח צילום שלכם במקום שעבר רכב או סתם חלק בתמונה שמוצל מדי / לא בפוקוס. אתם יכולים להעלות את התמונה ל Dall-E (יש לינק של Upload), למחוק את החלק שאינכם רוצים, לתאר את הסצנה – ולתת ל Dall-E לעבוד ולהשלים את החסר. לפעמים זה לוקח מספר ניסיונות – אבל Dall-E יכול לעשות עבודה לא רעה בכלל.
  • עוד אופציה מעניינת של Dall-E נקראת Variations – היכולת לקחת תמונה, לזהות לבד את האלמנטים בה, והסגנון שלה – וליצור תמונה אחרת, עם אותם אלמנטים ובאותו הסגנון.
    • כדי שהפיצ׳ר יעבוד, יהיה עליכם לעשות crop לתמונה ליחס ריבועי. Dall-E עובד על תמונות ריבועיות.
    • הנה תמונת נוף שלקחתי מגוגל, וביקשתי מ Dall-E שיעשה לה וריאציות (המקור משמאל). אתם יכולים לראות שהאלמנטים והסגנון – נשמרו, בעוד הקומפוזיציה והפרטים – שונים במידה ניכרת. רמת הפרטים אמנם נפגעה – אזור ש Dall-E פחות מוצלח בו, אלא אם מדובר בטקסטורה שהוא מצליח לאפיין בדיוק (בד מסוים, זיפים של זקן, וכו׳) ויש לו דוגמאות רבות שלו ברמת פירוט גבוהה.
  • כבר ציינתי ש Dall-E לא מוצלח כ״כ בציור של פנים אנושיות, ונוטה לעוות עיניים ושיניים. בחרתי תוצר טוב מהממוצע של Dall-E (הקלט היה ״an engineer excited by a new technology, realistic״) אבל שעדיין יש בו עיוותים שמפריעים (הגדילו את התמונה בכדי לראות בבירור. ברזולוציה נמוכה – הכל נראה טוב יותר).
    • התוצאה מימין היא שיקום שלי כלי בשם GFPGAN (נדרש GitHub Login) – מודל שנבנה לשיקום תמונות ישנות, אך עושה עבודה מצוינת עם AI Generated Images.
      • חדי העין יבחינו שאבדו פרטים / חדות בתמונה. ניתן לפתור את זה עם masking של photoshop – בו נאחד לתמונת המקור רק את השיניים / עיניים – מהתוצר של GFPGAN.
  • אתם יכולים להשתמש ב Dall-E להרחיב תמונה: לקחת תמונה ולהוסיף לה חלל לבן, לתאר את הסצנה – ולתת לדאלי להמשיך ולחבר לתמונה עוד חלקים שמעולם לא היו בה. חשוב שהשטח הלבן לא יהיה גדול מדי – אחרת Dall-E עלול לאבד את הסגנון. כלומר: התוצאה הטובה ביותר היא כאשר ההרחבה נעשית כסדרה של הרחבות קטנות. התוצאות – מרשימות מאוד.
אני כבר גמרתי את הקרדיט שלי ב Dall-E תוך כדי כתיבת הפוסט. הדוגמה הזו היא מהאתר של OpenAI.

סיכום

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

Dall-E כפילטר בפוטושופ? להשלמת תוכן / חיפוש וריאציות של תוכן? – טבעי ושימושי.

Generative AI של מדיה נוספות? אודיו? – הנה דמו מרשים של VAll-E. שימוש מעשי: דיבוב למשחקי מחשב, Audio Books. יהיו עוד.

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

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

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

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

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

נ.ב. – האם הבחנתם שאת הפוסט הזה, כתב AI?

מחשבות על טופלוגיה של צוותי תוכנה

מודל ה Squads של ספוטיפי

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

הערכים הבולטים של המודל:

  • הרכבת צוותים אוטונומיים (״self-organizing team״), להלן Squads.
    • תקשורת בין צוותים היא תקורה, ולכן נרצה צוות הכולל את כל מגוון הדיסיפלינות (״cross-functional״: בעיקר מהנדסים, אבל גם פרודקט, ניהול פרויקט, אנשי-נתונים, וכו׳) – כך שהצוות יוכל לעבוד עצמאית, ועם מינימום (בשאיפה: אפס) תלויות בצוותים אחרים.
    • הדגש הוא על מהירות. מה יאפשר לנו לנוע מהר יותר? אוטונומיה? אז בואו ניתן הרבה ממנה.
  • לצוות תהיה אחריות קצה לקצה על התוצר. הצוות יעבוד על הדרישות מול אנשי המוצר עד לשחרור לפרודקשיין ותמיכה בתוצר.
  • Guilds ו Chapters, כמנגנון המפצה על חוסר בבסיס משותף ברמה המקצועית הנובעת מהעצמאיות של ה Squads. הגילדה הוא פורום של בעלי עניין (למשל: פיתוח Backend, אבטחה, או UX) שבו מתקיימת הפריה הדדית והעברת ידע בין אנשים עם מומחיות / תחומי עניין דומים. ה Chapter הוא יותר ממוקד (מערכות Payment, או Graph Databases) המשתפים ידע, בין אנשים באותו הלוקיישן / אותו Tribe. כ 10% מהזמן של המהנדסים אמור להיות מושקע ב Chapter ופעילויותיו.
    • בעצם, כל מפתח שייך ל Squad שמוביל פעילות עסקית, וגם ל Chapter שמוביל מומחיות מקצועית ממוקדת, ואולי גם חבר בכמה Guilds.
    • ה Services ותתי המערכות הן באחריות ה Squads (ע״פ ספוטיפי). לפעמים מאמצים את המודל של ספוטיפי אך מנהלים את השירותים / תתי-המערכות ברמת ה Chapter (מה שדומה יותר למודל הבא שאסקור: Product/Platform Teams).

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

  • איזו צלע נכונה שתהיה יותר דומיננטית עבור המפתח? ה Squad (קרי: delivery) או ה Chapter (קרי: מומחיות מקצועית)? על פניו נראה מקריאה, שה Squad הופך להיות הצלע הדומיננטית ברוב הפעמים.
  • איך בעצם מפתחים פיצ׳רים שנוגעים ב services שבאחריות כמה squads? ברור שהאידאל הוא שכל פיצ׳ר יוכל להיתרגם ל service יחיד, או לפחות לאלו שבבעלות squad יחיד, אך במערכות מורכבות – השאיפה הזו לרוב לא מושגת.
  • מה קורה כאשר יש שינוי עדיפויות בארגון, וזקוקים להרבה עבודה באזור ב׳ ולא באזור א׳? מה קורה עם ה squads שעובדים על א׳ – ואיך מחלקים מחדש את האחריויות?

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

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

  • בניית תשתיות מקומיות ומאוד ספציפיות ל use case לו נדרש הסקוואד => מעט שימוש חוזר => תשתיות כפולות => חוסר יכולת להשקיע בתשתיות ארוכות טווח שישתלמו לארגון עם הזמן.
    • כידוע, שימוש חוזר אינו חזות הכל, ולעתים נכון לשכפל קוד ומנגנונים כדי להסיר תלויות בין חלקי המערכת. במבנה הסקוואדים התמריץ הדומיננטי הוא לכיוון עצמאות מרבית (מינימום תלויות) – כך שב Tradeoff הקלאסי בין עצמאות מרבית לשימוש-חוזר מירבי – סביר שנמצא את עצמו בקצה הראשון של הסקאלה, שהוא לעיתים נדירות רק יהיה נכון לארגון לטווח ארוך.
  • חוסר התלות עשוי לחלחל גם ל Technology Stack וארכיטקטורת המערכת, אזורים הקשים מאוד לשינוי. אם וכאשר הארגון ירצה ״ליישר״ את ה Stack או ארכיטקטורה – זו עשויה להיות עבודה גדולה מדי מלהחיל (״too big to happen״).
  • הסכנה המצטברת היא שהארגון יגיע ל״דרך ללא מוצא״ כאשר השקעה גדולה מדי נעשתה בראייה מקומית (קרי: צורכי הסקוואד הבודד), והדרך היחידה הישימה לאחד את המערכת לראיה אחת הוא לכתוב אותה מחדש. לא פעם ארגונים מגיעים לרגע שהשלב הבא בביזנס דורש יישור רוחבי עמוק, שלא ייתכן כאשר המערכת בנויה כמערכת של Silos.

צוותי מוצר ופלטפורמה

מודל ה Product / Platform Teams צמח במקביל למודל ה Squads. הוא דומה לו בכמה אופנים, אבל כולל גם כמה הבדלים משמעותיים.

  • בדומה ל Squads, צוותי המוצר (Product Teams) הם Cross-functional (קרי, מכילים מגוון מומחיויות) ועצמאים במידת האפשר.
    • הם יכולים להיות אחראים על Flow קבוע, לקוח קבוע וכו׳ – או להיות מוקמים ולפעול לצורך משימה ספציפית (פיצ׳ר X).
    • צוותי מוצר אחראים למיקרו-שירותים הקבועים לתחום האחריות שלהם: אפליקציות / UI, ושירותים המנהלים Flows רוחביים במערכת (הרבה פעמים צוות מוצר אחראי על Flow).
  • בניגוד למודל ה Squads, ישנו עוד סוג של צוותים, צוותי התשתית (Platform) המפתחים יכולות רוחביות בארגון, בהם ישתמשו מספר צוותי מוצר. הדוגמאות הקלות הן שירותים תשתיתיים בהגדרה, כגון Authentication/Authorization, שירותי Notification, תשלומים, וכו׳. שירותים נוספים שיהיו אצל צוותי הפלטפורמה הם שירותים ב core business של החברה, שמשמשים למגוון Flows / אפליקציות. למשל: שירות לניהול לקוחות, שירות לניהול הזמנות, שירות המנהל את מוצרי החברה, וכו׳.
    • אפשר לומר שצוותי תשתית, הם צוותי מוצר, כאשר הלקוחות שלהם הם פנימיים: צוותי המוצר. יש אפילו ארגונים המצרפים אנשי מוצר לצוותי תשתית.
    • צוותים כמו צוותי Operations (גם אם נקראים בטעות ״צוות DevOps״), או אבטחה – נופלים לקטגוריה של צוותי תשתיות.

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

המודל מספק איזון טוב יותר מהמודל של ספוטיפי, לאיזון בין השקעה בתשתית / חשיבה ארוכת-טווח (שטבעי יותר שתקרה בתוך צוותי תשתית), אך הוא מציב בעית חדשות, בעיקר פחות מהירות ויותר תקורה. אפשר לומר שהמודל של ה Product/Platform Teams מאפשר המשכיות ארוכה יותר לארגון והמערכת, על חשבון מהירות.

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

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

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

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

לסיכום, מודל ה Product/Platform Teams מתאים יותר לארגון בטווח הארוך, אך הוא דורש השקעה ותיאומים גדולים הרבה יותר => פחות פריון פר מפתח. אני מדמיין שארגונים שמתחילים במודל ה Squads מגיעים לנקודה בה הם לא יכולים להמשיך לפעול במודל שמעודד ראייה קצרת טווח ונאלצים לעבוד למודל קרוב יותר למודל ה Product/Platform Teams.

סתם צוותי Components

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

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

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

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

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

  • המודל הזה הוא בעצם המודל ההופכי למודל של סופטיפי – המון מומחיות ועומק, אבל מעט מאוד עצמאות של צוותים וקושי גדול לספק Deliveries תדירים. אני מאמין שהרוב המודלים האחרים בפוסט הם תגובה לאכזבה ותסכול מהמודל הזה.
  • אני לא חושב שהמודל בהכרח רע. עם TPM מצויינים, ותרבות ארגונית של שיתוף וחתירה לעזרה – הדברים יכולים לעבוד טוב. כמובן שהמודל מתאים למערכות הכבדות, המסובכות ביותר – ושבהן מוכנים להקריב את את המהירות הכללית – בכדי לשמר מערכת נכונה לאורך זמן.
    • כמובן שבניית טופולוגיה שטוחה של צוותי רכיב (Component) היא לא ערובה למצויינות הנדסית. המצוינות ההנדסית צריכה לנבוע מתרבות ומפעילויות נוספות של הארגון בכדי לבנות ולשמר אותה.
  • בעייה נפוצה של המודל הזה היא התחפרות ב Silos טכנולוגיים: צוותים שמתקשים לעבוד זה עם זה, ושבנו ארכיטקטורה מקומית של השירותים שלהם – שלא ידידותית לשאר הסביבה, כי אין להם מספיק חיבור לתמונה הגדולה, ולהיכן הארגון מתקדם. דרושה הרבה תקשורת יזומה כדי לחדור לכל הצוותים וליישר אותם לכיוון שאליו הארכיטקטורה והביזנס מתקדמים – וכדי לעזור שכולם יתקדמו ביחד לאותו הכיוון.
  • קושי גדול נוסף הוא חוסר גמישות ארגונים לאזן בין משאבים. נניח שבשנה מסוימת הארגון זקוק להרבה יותר פיתוח באזורים A ו B והרבה פחות באזורים C ו D. תהליך הגיוס של צוותים C ו D לעבודה באזורים A ו B – אינו פשוט מכיוון שלצוותם יש זהות חזקה מאוד עם הרכיב הטכנולוגי עליו הם עובדים. הצוותים האחראיים על A ו B יגלו כנראה התנגדות וביקורת למפתחים נוספים שמגיעים ו״משנים להם את הקוד, מבלי שיהיו כאן שנה הבאה להתמודד עם התוצאות ארוכות הטווח של השינויים האלו״.

מודל ה Stream-Aligned Teams

מודל זה חדש יחסית (הוצג בספר Team Topologies: Organizing Business and Technology Teams for Fast Flow, שפורסם ב 2019) אך זוכה לאזכורים רבים. המודל הוא בעצם שילוב בין המודל ספוטיפי למודל ה Product/Platform Teams. האם זהו הפתרון האידאלי? שילוב בין שתי הגישות?

לתחושתי, הספר הנ״ל מציג תאוריה מהונדסת להפליא שמסתדרת יפה מאוד עם עצמה, מקשרת כמה וכמה רעיונות משפיעים בעולם התוכנה (Conway's Law (ביטוי המופיע בספר 110 פעמים), הספר ״Accelerate״, Cognitive Load Model, מצטטים את דניאל פינק, מיקל ניגארד – ועוד כמה של כוכבים) תוך כדי שהכל ״מתקמפל״ ברמת הסיפור – ונשמע נהדר. בפועל הוא קצת יותר דומה למודל של סופטיפי, גם בדגש שלו על Velocity, וגם בזה שיש לו המון PR בצד אחד – וחורים ושאלות פתוחות גדולות, מצד שני. כמו Black Adam (דוגמה עדכנית ליום כתיבת הפוסט) – בהחלט מדובר ברב-מכר, עם ספקות להיותו קלאסיקה מאריכת ימים. זה טוב מאוד ל Team Topologies Academy (חברת יעוץ) – וספק עד כמה משרת באמת את התעשיה.

  • המודל מציג ארבע סוגים של צוותים בארגון:
    • Stream Aligned Team (להלן צוות רצף-עבודה; בספר מציינים במפורש שנמנעו מלקרוא להם Product Team או Feature Team) – צוות המיושר (Aligned) לשטף מתמשך של עבודה: פיצ׳ר (גדול), רצף של פיצ'רים בעלי אופי מסוים, או סוג משתמש מסוים, כאשר הדגש הוא על רצף מתמשך של עבודה, שלא ידרוש פירוק/הרכבה כאשר הצרכים והעדיפויות של הארגון משתנים. הצוותים האלו (להלן צוותי רצף-עבודה) מהווים את עיקר הצוותים בארגון, והם אוטונומיים ו Cross-Functional, כמו Squads. הם גם בעלי אחריות ארוכת טווח על מיקרו-שירותים שהם מנהלים (מלבד כמה יוצאי דופן). שאר סוגי הצוותים מכוונים לתמוך ולסייע לצוותי רצף-העבודה לעבוד מהר ויעיל יותר.
    • Enabling Team (להלן צוותים מאפשרים) – צוותים המרכזים ידע בתחום מסוים, ומנגישים אותו לצוותי רצף-העבודה, ע״פ הצרכים של צוותים אלו. למשל: צוות שמתמחה ב SQL ובסיסי-נתונים, ויכול לספק לצוותי רצף-העבודה את ההדרכה והעזרה שהם צריכים, תוך כדי שהוא מפתח את הידע בצוות (כדי שצוות רצף העבודה יהיה אוטונומי יותר) – ולא מקבל ממנו משימות ספציפיות. במקרים בהם נדרש מחקר עמוק, פתרון בעיה מסובכת במיוחד בתחום – הצוות המאפשר ייקח את העבודה על עצמו. בקיצור: חכה ולא דגים, מלבד דגים שמנים במיוחד.
    • Complicated Subsystem Teams (להלן: צוותי עומק) – אלו בעצם סוג של צוותי פלטפורמה (ע״פ המודל הקודם) אך הם בודדים ומוגבלים לנושאים המורכבים ביותר, שלא סביר שצוותי רצף-עבודה יכולים לקחת. הדוגמאות כוללות בעיקר צוותי אלגוריתמים / ML / אנליזה עמוקה (מזכירים שאם יש דוקטורים בחברה, הם כנראה יהיו בצוות כזה). מטרת הצוותים היא להוריד עומס קוגניטיבי מצוותי רצף-העבודה, כך שיוכלו להתמקד במשימה העיקרית שלהם. נחזור לנושא זה בהמשך.
      • על פניו, הורדת עומס קוגניטיבי זה לא רק אלגוריתמים, אלא גם לוגיקה עסקית מורכבת – ולעתים יש הרבה כזו בארגון. לא הצלחתי להתחבר שסוג הצוות הזה נדרש רק במקרים ספורים וקיצוניים כל-כך.
    • Platform Teams (להלן צוותי פלטפורמה) – על אף השם הזהה, אין הכוונה לצוותי פלטפורמה בנוסח מודל ה Product/Platform Teams בכך שאלו פחות צוותי תוכנה ויותר צוותי Infrastructure/Operations. למשל: צוותי Cloud Operations/Security/Data Engineering/Devex וכו׳. צוותי הפלטפורמה במודל הם הצוותים שמספקים את הפלטפורמה למערכת, ולא מפתחים את המערכת עצמה (עליה אמונים צוותי רצף-עבודה). מטרתם כמובן היא לשרת את צוותי רצף העבודה, לייעל את עבודתם, ולהוריד מהם עומס קוגניטיבי.
  • רעיונות מרכזיים במודל הם:
    • יישום ה Inverse Conway manoeuvre – קרי, יש לארגן את הצוותים ע״פ הארכיטקטורה הרצויה, ולא לצפות שהצוותים יתאימו את עצמם לארכיטקטורה במבנה ארגוני אקראי. כל רכיב / תת-מערכת בארכיטקטורה – צריכה להתמפות לצוות רצף-עבודה שאחראי עליה, ורכיבים קרובים ברמת הארכיטקטורה צריכים להיות מנוהלים ע״י צוותים קרובים במבנה הארגוני.
    • צמצום ה Cognitive Load על צוותי-רצף העבודה, בכדי שיהיו יעילים. כלי אחד הוא הצוותים התומכים, כלי נוסף הוא מין סקר ששואלים כל פרק זמן את צוותי רצף-העבודה, וממנו מסיקים כיצד להשתפר. כלומר: מנגנון קבוע על מדידה (לא מדויקת, אבל בכל זאת) של העומס הקוגניטיבי (=> יעילות) של צוותי רצף-העבודה, ושיפור מתמיד שלו.
    • צמצום התקשורת בין צוותים (״Fast Flow requires restricting communication between teams״). ״תקשורת היא לא תמיד דבר טוב״ והשאיפה היא להחליף Collaboration (תקשורת עמוקה) בתיעוד, Self-Serve APIs ונוהלים מסודרים איך לפנות לצוות בבקשות. בספר ממש ממליצים להימנע מ Open Space כי לא כולם צריכים לדבר עם כולם, וה Open Space מעודד תקשורת אקראית ולא דרך המנגנונים היעילים יותר. כנ״ל לגבי כלי כמו Slack.

כפי שאמרתי, המודל דומה למודל של ספוטיפי, עם כמה צעדים לכיוון של מודל ה Product/Platform Teams. יש במודל צוותים שאחראים על נושאים מורכבים / עומק / ראייה לטווח-ארוך, אבל ה Guideline הוא שכל הצוותים שאינם צוותי רצף-עבודה ירכיבו ביחד כ 10% מהארגון. הרבה מהשיח במודל הוא על Velocity ברמת הצוות – מה שבאופן טבעי מטה את הארגון לחשיבה קצרת טווח.

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

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

מחשבות

לאחר הקדמה ארוכה, וסקירה של כמה מודלים פופולאריים, אנסה לשתף בכמה מחשבות:

  • בטופולוגיה של צוותי-תוכנה יש כמה Tradeoffs שהם כמו חוקי-טבע, שאין דרך להימנע מהם:
    • חשיבה לטווח קצר (צוותים ממוקדי Delivery) מול חשיבה לטווח ארוך (צוותים ממוקדי רכיבים טכניים – והאחריות עליהם לזמן ארוך).
      • בווריאציה: אוטונומיה מול ריכוזיות.
      • בווריאציה נוספת: יישור למוצר (Product-Alignment) מול יישור למודל המערכת (Architecture-Alignment). כמובן שטוב שהארכיטקטורה תתמפה בצורה ישירה עד כמה שניתן לצרכי המוצר – אך לא תמיד ניתן להשיג זאת.
      • חשוב לי לציין ש Delivery הוא מרכיב חשוב לא רק לביזנס, אלא גם לארכיטקטורה: הצורך לספק משהו מוחשי וספציפי בטווח נראה לעין עוזר לצוותים לבנות ארכיטקטורה מעשית יותר. ברגע שמצמצמים את לחץ ה Delivery מתחת לרף מסוים – הארכיטקטורה והיכולת לטפל בטווח הארוך דווקא יורדים, ולא ממשיכים להעלות.
    • התמחות ועומק מול גמישות להזיז את הכח בין נושאים – ע״פ צורכי הארגון המשתנים.
      • משליך על: האם להשקיע הרבה בתשתיות / כלים / תיעוד / הדרכה – כדי לאפשר למהנדסים לזוז מאזור לאזור? זה עוד Tradeoff בין השקעה בתשתית, מול גמישות.
      • וריאציה: האם זה נכון שיהיו בארגון 30 סוגי מהנדסים (המשקפים עומק והתמחויות שונות, אפילו שכולם הם מהנדסי ג׳אווה) או שהארגון חייב שלא יהיו יותר מ 10 סוגי מהנדסים, והוא מוכן להשקיע רבות בכדי לאפשר זאת?
  • נקודת האופטימום, תשתנה כמובן בין ארגון לארגון, ובתקופות או שלבים שונים של כל ארגון.
    • ארגון שמפתח תריסר אפליקציות מובייל פשוטות ובלתי תלויות – מוטב שיאמץ מודל הדומה למודל של ספוטיפי. אפילו: אם הוא קרוב לשם, כדאי שיתאמץ ויפרק את המערכת שלו למבנה כזה, כדי שיוכל להיות שם.
    • ארגון שמפתח מערכת מורכבת, עם הרבה תלויות פנימיות – מוטב שיאמץ מודל יותר קרוב למודל ה Product/Platform Teams או אפילו מודל ה Component Teams. כמובן שלו היה יכול לחלק את המערכת / לעצב ארכיטקטורה ללא תלויות פנימיות רבות – עדיף היה, אבל לא תמיד זה אפשרי.
    • הניסיון להגדיר מודל יחיד לכל הארגונים, לאורך כל ימי חייהם – הוא שטותי כמובן. אפילו אם יש גמישויות מסוימות במודל (נניח: צורת התקשורת).
  • חשוב שמובילי הארגון יבינו את ה Tradeoffs האלו לעומקם, ויבינו שאין ״מודל קסם״ טוב יותר: השמיכות שבמְצַאי הן כולן קצרות, וההחלטה הנדרשת היא האם להשאיר את הרגליים חשופות, או את הראש – איפה ועד כמה.
    • ארגון בוודאי יכול לומר לעצמו (ברגע של כנות) האם הוא מפתח מערכת מורכבת ואינטגרטיבית, או סדרה של תתי מערכות פשוטות. האם יש לו יכולת לחזות / לתכנן לטווח הארוך היכן ידרשו המהנדסים, או שהוא חייב להיות גמיש ולהיות מסוגל להזיז תדיר מהנדסים ממקום למקום (על אף המחיר הגבוה של זה).
      כמובן שהתשובה הפופולארית היא ״המערכת שלנו היא סופר מורכבת ומאתגרת, והשוק דינאמי – אז אנחנו זקוקים למירב המומחיות ולמקסימום גמישות״, אבל זה לא תמיד המצב, ובחירה בנקודה הזו במודל ה Tradeoffs אומר הרבה תקורה, תקשורת, וגופים מרכזיים בארגון => פחות מהירות.
    • ארגונים משתנים, וכמובן שכל פרק זמן נכון להעריך מחדש היכן נמצא הארגון, ומה הטופולוגיה הארגונית שנכונה לו בשלב זה. שווה להזכיר שטופולוגיה של צוותים היא יותר מקום-מגורים מגרביים – להחליף אותה זה יקר מאוד, ועלול ליצר הרבה After shocks (בניגוד לגרביים).
    • ל Coupling במערכת יש מחיר אסטרטגי, כלומר: ברמה הגבוה ביותר של הארגון. חשוב מאוד לנסות ולפרק את המערכת ואת הארגון, לתתי-מערכות ותתי-ארגונים יותר עצמאיים, גם במחיר מסוים.
      • למשל: כשעבדתי בחברת נייס, שכפלו את חטיבת ההקלטות לשתי חטיבות מקבילות בכדי לתת להן יותר עצמאות: חטיבת הקלטות הקול, וחטיבת הקלטות הוידאו. הקוד שוכפל ומספר המהנדסים כמעט הוכפל – אך בדיעבד נראה שזו הייתה החלטה נכונה.
      • בחברת SAP רצו ליצר הפרדה משמעותית יותר בין ה Core לבין ה UI ברמת ה Backend. הם כל הזמן התערבבו – והמערכת מאוד הסתבכה. החליטו להעביר את כל פיתוח ה UI ל Stack Technology אחר (במקרה: ג׳אווה) בכדי שהחיבור בין הרכיבים יהיה רק דרך API מוגדרים היטב, ולא יאפשר (או לפחות יקשה) על Tight coupling. כמובן שנדרשה כתיבה מחדש של כל ה UI Backend, והעברת מאות (אולי אלפי) מהנדסים ל Stack חדש. חשבו איזו השקעה זו.
  • כמובן שניתן לשחק בפרמטרים וב Tradeoffs השונים:
    • אפשר בהחלט להחליט שחלק מסוים מהארגון / מוצר (אזור) עובד במודל א׳, וחלק אחר במודל ב׳. זה מוסיף בלבול ומורכבות ניהול – אבל היא עשויה להיות שווה זאת, בכדי להקל על היומיום של הצוותים.
  • נושא טופולוגית הצוותים בארגון הוא נושא מורכב, שקל להרים בו ידיים, ולחפש עזרה. עזרה כזו תמיד זמינה (יועצים, מנהלים מקבילים בחברות אחרות שישמחו לעזור) – אך כנראה שהכי טוב שתעשו את זה בעצמכם, מתוך מחויבות עמוקה (מה לעשות: לכם תמיד יהיה אכפת יותר) ומתוך הבנה עמוקה של האפשרויות והקיים. זה לפחות הניסיון שלי.

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

איך לנהל דיונים טכניים (Software Design)?

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

עד כמה הדיונים האלו יעילים?

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

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

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

העקרונות של דיון טכני מוצלח

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

הכנה

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

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

ההכנה אמורה להשתלם. קרי: ישבתי שעתיים בכדי להכין חומר לדיון באורך שעה בו יש ארבעה משתתפים והדיון הסתיים – הוא מוצלח הרבה יותר מ ״נפגשנו ארבעתנו לשעה – אבל העניין לא נסגר*״ ואז ״קבענו לעוד שעה וכמעט סגרנו״ ואז ״אני ומשה נפגשנו לעוד חצי שעה לסגור פרטים אחרונים״.
במספרים: 6 = 1*2+4*1 < 4*2 + 2*2 = 10.

* קול פאסיבי. זה ״העניין״ שלא נסגר – לא שזה אנחנו, או משהו…

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

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

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

מהי ההכנה?

  • הגעה עם העובדות הקריטיות לדיון, או יכולת מלאה לענות עליהן (דוגמה שלילית: ״האא… חשבתי שאחד מכם ידע <שאלה טכנית>. בואו נחפש אולי עכשיו את התשובה ביחד״) – חשוב להבין מראש האם יש שאלות קריטיות לדיון, ודאו מראש שיש לכם תשובות ו/או מי שמגיע לדיון ידע לספק בשלמות את העובדות הנדרשות. קשה לי לספור כמה דיונים ראיתי שנמרחו סתם כי פשוט היה חסר ידע לנהל דיון יעיל. לא פחות חבל: הרבה פעמים יש נטייה לנסות להמשיך למרות שברור שהדיון לא עומד להתקדם בצורה סבירה. הרבה דיונים עדיף לחתוך באמצע – מאשר להמשיך סתם. תהיו רציניים בבקשה, ואל תמשיכו דיון רק כי כמה אנשים התכנסו כבר ביחד.
  • ודאו מראש ששיבוץ האנשים מאפשר להגיע ל "Delivery״ (תוצאה מוצלחת של הדיון).
    דוגמה שלילית: ״אוי… שרון מה זה הייתה תורמת לנו לדיון. חבל שלא הזמנו אותה, אך היא עכשיו בפגישה אחרת״.
    הבינו מי באמת צריך להיות בדיון וודאו שהוא שם. ברוב הארגונים אנשים לא זמינים מהרגע להרגע – ואי הזמנה של אדם יכולה לעכב את הדיון בימים => הארכת ה Lead Time להחלטה.
    • שאלה קצרה ב Slack ״היי… אנחנו רוצים להבין <בעיה טכנית> – אתה יכול לכסות את הנושא, או שאנחנו זקוקים למישהו נוסף?״ – יכולה להכריע בין דיון יעיל לבזבוז זמן.
    • נסו גם לצמצם אנשים לא-רלוונטיים. חבל לעכב דיון רק כי אדם לא-רלוונטי לא מסוגל להגיע. היום בעידן הזום קל הקליט דיונים – וכך לאפשר לאנשים להקשיב לדיון מבלי להופיע.
  • תעדו ופשטו את תיאור הבעיה – בכדי לאפשר דיון יעיל. (דוגמה שלילית: ״לא… בפעם הרביעית: X קורה לפני Y כי ….״). במיוחד כאשר הנושא הוא מורכב / רב בפרטים – הכינו תרשים ו/או רשימת נקודות שתעזור לכולם להתכנס מסביב לנושא. קשה לי להסביר כמה חומר כתוב, ושעבר איטרציה או שתיים של פישוט והבהרה – יכולים לקצר את הדיון.
    • חשבו על החומר שאתם מכינים כמפת-ניווט לדיון. בניית מסלול לדיון כדי שאנשים לא יצטרכו להחזיק יותר מדי פרטים בראש. מוביל הדיון הוא מדריך פעולת ניווט, ובלי מפה טובה סביר הדיון יסתיים בהתברברות. הכנת מפה טובה לדיון הוא מיומנות שלוקח קצת זמן (אבל מאוד משתלם) לפתח.
    • ליצור תרשים שמסביר Flow מורכב – הוא דבר שלוקח זמן. הקדישו פעם אחת את הזמן הזה לפני הדיון, במקום לנסות לייצר אותו חמש פעמים במהלך הדיון – וכך למרוח את הדיון.
    • ראוי שחומר כתוב וברור – יהיה ציפייה מקדימה לדיון טכני.
      • מדי פעם יהיו כאלו שיכינו חומר ארוך מדי / מתיש / מפורט מדי. עזרו להם לקצר. זה לא תמיד קל.
    • הבינו מי המשתתפים בדיון. הרבה פעמים מגיעים לדיון אנשים שלא בקיאים בנושא, וחשוב להכין להם רקע קצר שיכניס אותם לדיון ביעילות: מה הבעיה, מה קרה עד עכשיו? מה אנחנו יודעים? על מה יש הסכמה, ועל מה יש אי-הסכמה?
    • הכנת חומר לדיון בפעם הראשונה עלולה להיות פעולה לא מתגמלת. זה קשה, אורך זמן, ואולי בסוף לא יהיה דיון מוצלח. אני אנסה להבטיח לכם שזה משתפר בכל הממדים עם הזמן. 3-5 דיונים שהכנתם להם חומר – וזה יתחיל להראות אחרת: קל יותר, ומועיל יותר.
  • עומק הדיון נגזר מעומק החומר שהוכן. כמו ב Designs, סכנה היא שמי שמכין את החומר / מתווה את הדיון – ידלג על נקודות מפתח, ואז הדיון ידלג עליהן (כי כולם ״שבויים״ ברצף שהוגדר). כמובן שאנחנו מצפים ממשתתפים לאתגר ולשים לב לחסר – אך בנושאים מורכבים לא פעם הכנה חסרה נגמרת בדיון חסר. אין לי פתרון לזה, מלבד להקפיד וללמד את מי שמכין את החומר שיעשה מעבר יסודי ויעיל על נקודות הממשק של הבעיה – בכדי להקטין את הסיכון לפספוסים.

התנהלות הדיון

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

  • התייחסו לדיון כ Delivery. הוא כזה, אם תחליטו ותצרו תרבות מתאימה. תרבות דיון יעיל – תשרת אתכם בהחלטות מהירות יותר, וסביבת עבודה שאנשים רציניים – יעריכו יותר.
    • חשוב שמי שמנהל את הדיון יהיה במנטליות של חתירה לסגירת הדיון. זו האחריות שלו לוודא שהדיון מתקדם בצורה יעילה. לא תמיד דיון יסתיים בזמן שתוכנן – וזה לגיטימי. לפעמים קשה להעריך מראש את המורכבות של הדיון. מצד שני – דיונים שסתם נמרחו – הם משהו שלא צריך לקבל. חבל על הזמן והכוחות של כולם.
    • מומלץ מאוד להתחיל את הדיון בהצהרה מה מטרת הדיון. ״אנחנו עושים Barinstorming ומחפשים כיוונים אפשריים לפתרון בעיה X״ או ״אנחנו רוצים לקבל החלטה מה הפתרון לבעיה Y – בהתאם לאלטרנטיבות שנמצאו״ – הם שני דיונים בעלי אופי שונה, וחשוב שכולם יבינו איזה דיון מתנהל.
  • המנעו מזליגה לדיונים אחרים. ״הא? הנושא מאוד קרוב גם לדיון ג׳? יופי. את דיון ג׳ אפשר לנהל במקום וזמן אחר – עכשיו אנחנו בדיון א״.
    • עוד ואריאציה בעייתית היא אנשים שמעלים הגיגים פילוספיים ולא משמעותיים לדיון ״אם היה לנו …, מה זה היה אומר?״ או ״חשבתם על …? (משהו תאורטי לגמרי)״. חשוב לזהות את ההתברברויות האלו – ולעצור אותן מוקדם. לעצור מצבים שבו אנשים מבדרים (מלשון הִתְבַּדְּרוּת) את הדיון במקום לקדם ולהניע את הדיון לכיוון של Delivery.
    • אם מישהו מתנהל בצורה לא יעילה, קרי: חופר יותר מדי – הציפיה שמי שמנהל את הדיון יחתוך אותו. צרו תרבות דיון שמאפשרת ומחייבת לעשות את זה. ״מה? לא דילברת את ההחלטה הטכנולוגית כי שרית לא הפסיקה לחפור? זו לא סיבה מספיק טובה. פעם הבאה – בבקשה עצור את החפירה. האחריות ל Delivery של ההחלטה – היא עליך״.
    • ניהול זמן. לא סביר שעוד 10 דקות נגמר הדיון, ולא התחלנו להתכנס להחלטה. זה עוד היבט במנטליות של דיון = Delivery.
  • דיון תמיד מתחיל ביצירת בסיס משותף. זוכרים את שלב ההכנה? מישהו הכין רקע להכניס את כולם לסדר העניינים. מישהו פירט ותאיר בצורה ברורה ואחידה את הבעיה עבור הדיון: אחידות בהבנת / הגדרת הבעיה – מסייעים מאוד לדיון יעיל. עכשיו זה הזמן ״לצרוך״ את ההכנה הזו, ולהביא את המשתתפים לבסיס משותף שיאפשר דיון יעיל.
    • דרך טובה היא פשוט לקבוע ש 15 הדקות הראשונות של הדיון (או כל זמן אחר שיתאים) משמשות לקריאה פרטנית של החומר שהוכן. כל אחד קורא את המסמך (בשקט, לעצמו), מוסיף הערות – ואז עוברים עליהן לפני / תוך כדי הדיון. הפרקטיקה הזו עובדת לנו בנקסט מצוין – ואני בהחלט ממליץ עליה.
    • כאשר הנושא הוא טעון / במחלוקת – חשוב להגיע להסכמה משותפת של הבעיה. ״צוות א׳ לא אוהב את פתרון הראשון כי <סיבה מנקודת מבט של צד א׳>, וצוות ב׳ לא אוהב את הפתרון השני כי הוא מוטרד מה <משהו>״. עצם ההסכמה של שני הצדדים על מה מדאיג כל צד – מאוד עוזרת לנהל דיון יעיל. אל תפספסו את זה. זכרו לנהל את הדיון כדרך למצוא את הפתרון הנכון ביותר בארגון – ולא כמאבק כוחות.
  • המנעו מ Design באמצעות דיון. לא פעם, תוך כדי דיון מגלים בעיה חדשה שלא חשבו עליה. בעיה שדורשת חידוד, יצירת חלופות (alternatives), ניתוח החלופות – והערכה איזו טובה יותר. מין ״מיני תהליך דזיין״.
    • דיון בקבוצה הוא דרך גרועה לביצוע דזיין. המנעו מהטעות הזו, בחרו אדם או שניים (בעלי אחריות) שיבצעו את התהליך: הגדרת חלופות, ניתוח שלהן וכו׳, יכתבו את הדברים בצורה ברורה לדיון – וכך תוכלו לקחת החלטה טובה – בדיון המשך.
      • ברגע שאתם מזהים שבעצם מתנהל דזיין לא מתוכנן – עצרו זאת. זה יהיה דזיין חפוז ולא מדויק. לא מתקנים פנצ`ר תוך כדי נסיעה.

תרבות דיון

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

  • צרו ושָׁמְרוּ על Psychological Safety – אף אחד לא אמור להיות מובך / מושפל / מותקף בשל דיון או דברים שנאמרו בו. אם דיונים מגיעים למחוזות הפגיעה, אזי אנשים יעסקו בהתגוננות – ולא בעצם הדיון עצמו.
  • אגרסיביות ובריונות קיימים גם אצל חְנָנוֹת בחברות הייטק. אי אפשר להכחיד אותם, אך הדפו אותם אחורה כאשר הם מופיעים. לא פעם בדיונים בין צוותים, הטיעון מדוע לפתח משהו בצוות אחד ולא אחר הוא ״אז לנו זה ייקח יותר זמן מכם״ או ״אנחנו פשוט נעביר לכם את כל הבאגים שקשורים לנושא, סבבה״. לא פעם, יש שמץ של אמת בטיעונים האלו – אבל חשוב לעשות דיון ענייני ולבחון את הערך לחברה, ולא לפעול לפי אינטרסים מקומיים.
  • צרו סביבה שמאפשרת לכולם לדבר, גם אם הם ״זוטרים״. לא פעם, טוב שמוביל הדיון ישאל ויערב את הביישנים – גם אם הם לא יוזמים. ״משה – מה אתה חושב על זה? זה פתרון טוב מבחינתך?״. מצד שני – שימו לב שהדיון לא מתבדר רק כי רצינו שכולם ידברו.

סגירת הדיון

אם אנחנו ממשילים דיון ל Delivery, אנחנו לא רוצים תרבות שבה פיצ׳ר נגמר כשהמפתח לא מודע לעוד קוד שצריך להכתב. סיום – משמע קוד בדוק, ב master, שרץ בפרודקשיין.
באופן דומה, דיון לא מסתיים כאשר נגמר הזמן בפגישה. דיון מסתיים נכון כאשר יש סיכום ברור של הדברים – שאנשים מבינים, כאשר יש Action Aitems ודיוני משנה – אם נדרשים.

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

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

  • בשלב הבסיסי ביותר אנחנו זקוקים למסקנה. מסקנה לפעמים היא משפט יחיד ״לא עושים X״ ולפעמים זה שורה של החלטות ופרטים שחשוב להגדיר ולפרט בצורה ברורה.
  • המסקנה צריכה להיות כתובה, באופן שניתן להבין אותו אח״כ. הכי מטופש זה לנהל דיון, לשכוח את המסקנה – ואז לפעול באופן אחר, כי אין זמן לעוד דיון. אני לכאורה אומר את המובן מאליו, אך נכחתי כבר בהרבה דיונים עם אנשים נבונים – שפספסו בנקודה הזו.
  • חשוב לוודא שהמסקנה מוסכמת וברורה. גם כאן, באופן מפתיע – נופלים לא פעם גם אנשים נבונים. Minutes שנשלח בסוף הפגישה הוא כלי נפוץ ויעיל. גם תוך כדי הדיון לעצור ולהכריז: ״טוב, אז לגבי נושא … כולנו הסכמנו שעדיף … על פני … כי …״ – היא פרקטיקה מועילה. במיוחד כאשר, מדי פעם, אתם בטוחים שזה המצב ואז אנשים עונים: ״לא, מה פתאום! זה לא מה שאמרנו.״
  • תפיסת קצוות ״קשים לתפיסה״ הם עוד תופעה ידועה: יש איזה עניין שהוא מבלבל ומורכב ולכן משתתפי הדיון פשוט מתעלמים ממנו ומסכמים אותו בצורה מעורפלת. הקצוות הללו נוטים להתגעגע ולחזור אלינו, חודשים מאוחר יותר, בפרודקשין, באמצע הלילה. סגירה רצינית היא לתפוס גם את הקצוות הקשים האלו – ולא לתת להם להתחמק. הרבה פעמים יידרש עוד דיון, ועוד הכנה מורכבת – עבור דיון-ההמשך הזה. צרו תרבות שדורשת ומבצעת סגירה של הקצוות, ולא כזו שמשאירה מדיונים טכניים ״שיירים אבודים״.

סיכום

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

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

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

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

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

הפרדת רשויות: מדוע להשקיע ב DTOs ו Entities?

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

תוכנה מתחילה למות ביום בו מפסיקים לשנות אותה.

עקרון תכנותיקה

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

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

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

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

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

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

מדוע לבצע הפרדת רשויות?

לפעמים יש לנו אובייקט מרכזי במערכת. למשל: Person. אנחנו משתמשים בו לשלושה שימושים עיקריים:

  • ב APIs או Events – כדי להעביר מידע אודות Person למערכות אחרות.
    • לפעמים ע״י serialization של המחלקה ל JSON
    • לפעמים אנחנו משתמשים במחלקה על מנת להפיק (generate) ייצוג ב IDL (שפת ביניים)
  • ב Business Logic – בכדי להעביר מידע אודות Person בין חלקים שונים של ה business logic.
  • בשכבת העבודה של בסיס הנתונים – בכדי לשמות מידע של Person בבסיס הנתונים לאורך זמן.
    • לפעמים ע״י serialization של המחלקה ל JSON (למשל: Document databases, או semi-document DB כמו mySQL או Postgres).
    • לפעמים דרך ORMs כמו Active Records או Hibernate (שיצרו סכמת בסיס נתונים בהתבסס על מבנה האובייקט).

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

  • האובייקטים, הרבה פעמים, יהיו זהים ביום היצירה שלהם? אז למה לשכפל קוד?
  • למה לתרגם בין אובייקטים זהים (נניח: ברגע שאוביקט ב Business Logic צריך לעזוב את המערכת כחלק מ Event / קריאת API)

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

Entity Object
(e.g. PersonEntity)
Model
(e.g. Person,
no suffix)
Data Transfer Object (e.g PersonDTO)
שמות מקובלים אחריםPersonDBEntity (clarify the direct relation to DB).PersonModel, PersonDomain, PersonBL (= Business Logic)None I know of.
סיבה להשתנותהוספת מידע שנדרש לצורך שמירה בלבד: ID, זמן / תאריך שמירה או שינוי. שדה נוסף שיקל על פעולת אינדוקס.
אולי רוצים לפצל את שמירת הנתונים ל-2 טבלאות או פורמט אחר לצורך שיפור ביצועים.
העשרת ה BL בשדות / תכונות נוספות שפנימיות למערכת.
שינוי שמות שדות בעקבות תובנות ואפשרות לתאר אותם בצורה נכונה יותר, ייצוג נתונים באופן שקל יותר למערכת לעבוד איתו. למשל LocalDate ולא מחרוזת של תאריך, Money ולא Integer.
התאמת מבנה נתונים ללקוח, נניח אפליקציות FE שייהנו ממבנים ידידותיים יותר ל JS.הוספת שדות מחושבים שלא נמצאים במודל, אך יקלו על הלקוחות (BE או FE).
כיצד משתנה בצורה תואמת-לאחור
(למשל הוספת שדה חדש שניתן לקבוע לו default value)
תאימות לאחור חשובה כי ייתכן ונרצה לקרוא מחר מידע שנשמר לפני שנה-שנתיים. ללא תאימות לאחור – לא נוכל לאחזר מידע ישן.גמישות רבה בשינויים, כי אובייקט המודל לא נשמר ולכן כל אתחול של המערכת (deploy) יכול לעבוד עם גרסה חדשה.תאימות לאחור חשובה כי ישנם לקוחות שימשיכו לצפות ולשדר את המבנה בגרסאות קודמות שלו – ואין לנו שליטה עליהם (אם הלקוחות הם שירותים שלנו – עדיין יש צורך בשינוי הדרגתי).
כיצד משתנה בצורה שאינה תואמת-לאחוראפשרות א: תיקון כל הנתונים בבסיס הנתונים (migration) כך שיתאים ל entity החדש. זה שינוי שיכול להיות קשה, יקר, ומועד-לטעויות יקרות. כיף!אפשרות ב: ליצור גרסאות של ייצוג בבסיס הנתונים, ולהחזיק קוד שמזהה את הגרסה – ויותר לטפל בכל גרסה באופן שונה.אפשרי ברמת הקוד בלבד (refactoring). כל עוד הקוד מתקמפל, והבדיקות עוברות – כנראה מאוד שאנחנו בסדר.לרוב נאלץ לפתור גרסה חדשה של ה API / event (למשל V2) בו יש את המבנה החדש, ולהעביר לקוחות לגרסה החדשה. עבור לקוחות שאין לנו שליטה עליהם – זה יכול להיות תהליך של חודשים הכולל פשרות מסוימות.
הערותלפעמים אנשים מבלבלים בין Entity ו DAO:
Entity – ה object שחוזר.
DAO – הממשק שממנו שולפים את ה Entity.
לא פעם מכיל מתודות / פונקציות – ולא רק נתונים.
מומלץ מאוד שאלו יהיו רק מתודות המקלות על גישה / פענוח הנתונים (מה שנקרא access logic), ולא Business Logic של ממש.
לא פעם מקובל להגדיר Coarse-grained DTO (אובייקט ״גדול״ יותר) – על מנת לצמצם את מספר הקריאות ברשת.
השוואה בין ההבדלים החשובים בין Entity, Model, ו DTO.

דוגמאת קוד

המודל:

@JsonIgnoreType
public class Person {
  @JsonIgnore public final String name;
  @JsonIgnore public final LocalDate birthDate;

  private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PersonDTO.birthDateFormat);

  public Person(String name, LocalDate birthDate) {
    this.name = name;
    this.birthDate = birthDate;
  }

  public PersonDTO toDTO() {
    return new PersonDTO(name, birthDate.format(formatter));
  }

  static public Person fromDTO(PersonDTO dto) {
    return new Person(dto.name, LocalDate.parse(dto.birthDate, formatter));
  }
}

הערות:

  • לא השתמשתי ב record, בהנחה שזה מבנה פחות מוכר, אז למה לבלבל.
    • שימוש ב public members עבור Entities – הוא דבר שעשיתי בתחילת שנות האלפיים, ותמיד האמנתי שהוא נכון (למרות מעט ביקורת מצד תאורטיקני ג׳אווה שתמיד רצו getters).
  • שורות 1, 3, ו4: JsonIgnoreType@ ו JsonIgnore@ הם ביטחונות של ספריית Jackson (ל seralize/deseralize JSON) שהמחלקה לא תסורייל (seralized) ל JSON ושהמידע שלה לא יישמר/ישלח איכשהו. אנשים נוטים לשכוח שיש DTO ו/או Entity – וחשוב להגן בפני הטעויות הללו. אם התחלנו לשמור את המודל לבסיס הנתונים – התיקון עלול להיות יקר.
    • האם שניהם נחוצים? (ולא מספיק אחד) – אני לא בטוח, אבל Better be safe than sorry.
    • לא כולם משתמשים ב Jackson כמובן – עליכם למצוא את הפתרונות שלכם להגן על המודל שלא ייצא מגבולות ה business Logic ולא יישמר באופן שיחסום אתכם לשינויים עתידיים.
    • האם יש משהו לא-אלגנטי שדווקא המחלקה שאמורה להיות ״הנקיה ביותר״ צריכה להשתמש בתלות לספריית ה serialization ולהצהיר – שהיא ״לא במשחק״? בהחלט לא אלגנטי – אם תמצאו פרונות אלגנטיים יותר אך מעשיים – לכו עליהם.
  • שורות 13 ו 17: אנו רוצים פונקציות עזר פשוטות בכדי להמיר בין מודל ו DTO.
    • לרוב קוד ה DTO יאוכסן בספריה נפרדת, כחלק מה API של המיקרו-שירות / המערכת – ולכן ל DTO לא תהיה גישה ל Model (והגיוני שכך). קוד ההמרה חייב לשבת במודל.

ה (Data Transfer Object (DTO:

public class PersonDTO {
  public final String name;
  public final String birthDate;

  @JsonIgnore public static final String birthDateFormat = "dd/MM/yyyy";

  public PersonDTO(String name, String birthDate) {
    this.name = name;
    this.birthDate = birthDate;
  }
}

הערות:

  • שורה 5 – הפורמט שבו ה DTO שומר את התאריך כמחרוזת (נניח: פורמט שקל לצרוך מתוך JavaScript) הוא פרט מומחיות שלו, ולכן יושב על ה DTO ולא על מחלקת המודל.
    • בהנחה שאנו עובדים עם Jackson – לא נרצה שפרט זה יעבור על הרשת כחלק מהאובייקט – ולכן השימוש ב JsonIgnore@.

ה Entity:

class PersonEntity {
  public final String name;
  public final String birthDate;

  private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

  PersonEntity(String name, String birthDate) {
    this.name = name;
    this.birthDate = birthDate;
  }

  public Person toModel() {
    return new Person(name, LocalDate.parse(birthDate, formatter));
  }

  static public PersonEntity fromModel(Person model) {
    return new PersonEntity(model.name, model.birthDate.format(formatter));
  }

}

הערות:

  • שורות 12 ו 16 – ה Entity הוא זה שמכיר את המודל, כי נרצה שמי שיעשה את ההמרה הוא שכבת ה Data Access ולא ה business Logic. למשל: DAO או Repository המקבלים את המודל ושומרים אותו, או שולפים אובייקט מודל לפי שאילתה נתונה.
  • שורה 5 – הפורמט שבו אנחנו שומרים את התאריך (נניח: פורמט ידידותי ל DATE column בבסיס הנתונים) הוא מידע פרטי של ה Entity.
    • לא הוספתי JsonIgnore@ – כי זה שדה פרטי.

סיכום התלויות:

סיכום

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

שאלה גדולה היא מתי לעשות את זה?

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

ברור לי ששתי הקיצוניות הן לא נכונות. היו תקופות שפיתחתי ״J2EE״ וכתבנו Enity ו DTO ל 100% מהמחלקות, גם APIs שוליים שרק ביקשו מידע קטן, והיה להן צרכן יחיד – זה מיותר ומחליש את הבנת/חשיבות הצורך.

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

מה עם אובייקטים חצי-חשובים? בשימוש לא-קטן אבל גם לא כבד? זה כבר עניין של ניהול סיכונים ותרבות ארגונית. למרות שמבחינת חישוב ROI פשוט (נשקיע השקעה קטנה בכתיבת Entity+DTO ל 20 מחלקות, אבל אחת שתידרש לזה באמת – תחזיר את ההשקעה בכתיבת 20 צמדים כאלו, כי זה חסך לנו Refactoring אחד גדול וקשה) ההשקעה משתלמת, קשה לפעמים לאנשים לראות את הערך ביחסי השקעה שכאלו.

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

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

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

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

הערה אחרונה: אפשר לכתוב גם לפעמים רק Entity או אולי רק DTO. אם אתם יודעים לאבחן מתי – אדרבא.

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

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

———

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