יום ראשון, 21 באוקטובר 2018

מחיר הטעות - הורדת הסיכון בגרסה חדשה

“Negative results are just what I want. They’re just as valuable to me as positive results. I can never find the thing that does the job best until I find the ones that don’t.”  - Thomas A. Edison

כשאנחנו מחליטים לפתח משהו, יש לנו השערה (או בשמה המדעי - 'היפותיזה'). יכול להיות שאני סטרטאפיסט שחושב שהעולם רוצה אפליקציה להתאמת בגדים לחתולים, יכול להיות שאני איש UX שחושב שאם כפתור יגדל ב-5px ויהיה בצבע כתום, אז יותר אנשים ילחצו עליו ויקנו מוצרים, ויכול להיות שאני מְפַתֵּח שחושב שאם אשנה את הקונפיגורציה של mongoDB להיות replication.secondaryIndexPrefech: _id_only אז זה יפתור את בעיית הביצועים שיש לי ולא יפריע למשתמשים או שאני חושב שהקוד שלי עובד טוב ועמיד בתקלות רשת.

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


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

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

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

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

כמובן שהחיסרון של אפשרות 2 הוא הסיכון הגבוה שהיא מציגה.

 

בניהול סיכונים לומדים ש:

עוצמת הסיכון היא: סיכוי x נזק

כלומר יש שתי אפשרויות להקטין סיכון: הורדת הסיכוי למימוש הסיכון (זה מה שאפשרות 1 מנסה להשיג) או להוריד את הנזק שיגרום מימוש הסיכון - זה מה שאנחנו נתמקד בו באפשרות 2.

הפחתת הנזק

“One of the reasons people stop learning is that they become less and less willing to risk failure”  - John W. Gardner

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

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

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

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

כמה אנשים מושפעים מהנזק?

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

אחת הדרכים לעשות את זה היא Canary Testing. בקצרה, בשיטה הזו אני מתקין גרסה חדשה לצד הגרסה הקודמת ומפנה אליה משתמשים באופן הדרגתי. למשל, הפנייה של 1% מהמשתמשים ואז השוואת המדדים לגרסה הראשית (אחוז conversion, מדדי ביצועים וכו'). אם המדדים עונים על המצופה, מגדילים את אחוז האנשים בהדרגה עד שמגיעים ל-100%, ואז אפשר להוריד את הגרסה הישנה. האנשים יכולים להיבחר אקראית או לפי מאפיין מסויים (מיקום גיאוגרפי, נרשמים לתוכנית beta וכו'). מדובר בשיטה נפוצה מאד.

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

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

כמובן גם A/B Testing יכול לשמש במקרה הזה, אם כי לעיתים קרובות הוא מערב כמויות גדולות של משתמשים ומשמש להגבלת משך זמן הנזק.

כמה נזק יגרם לנפגעים?

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

שיטה אחת שבה נוקטים כדי להקטין את הנזק מכוּנה "mirroring", "shadowing" או "dark launch" (המושג האחרון משמש לפעמים גם ל-feature toggle). השיטה הזאת אומרת שמתקינים את הגרסה החדשה לצד הקודמת, ושֹם proxy בין בלקוחות לבין המערכת שמשכפל את כל התנועה הנכנסת לשתי הגרסאות. את התשובה מהגרסה הקודמת הוא מחזיר ללקוח, והתשובות משתי הגרסאות נשמרות לטובת השוואה שמוודאת שאין שינויים לא צפויים בין הגרסאות. בנוסף משווים בין מדדי ביצועים שונים בין הגרסאות. לאחר זמן מה במצב כזה, הסיכוי להתממשות הסיכון ירד מספיק שאפשר להעביר את הגרסה לשימוש של משתמשים.

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

במשך כמה זמן ימשיך להיגרם נזק?

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

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

שיטה אחרת שעוסקת בצד ההיפותזות הטכניות היא Green/Blue Deployment. הרעיון הוא שמתקינים את הגרסה החדשה ("ירוקה") של המערכת במקביל לגרסה הקיימת ("כחולה") ומעבירים אליה את המשתמשים (זאת סביבה שלמה ולא רכיב, ולרוב גם לא מדורג - בניגוד ל-canary testing). במקרה שמשהו לא עובד טוב, בלחיצת כפתור מחזירים את המשתמשים לעבוד על הסביבה הכחולה. זה מאפשר לנו להגביל את הנזק לזמן שלוקח לנו להבין שהוא קורה.

גם שילוב של circute-breaker עם automatic degrade (הנ"ל) , כלומר כשה-circute פתוח מפנים להתנהגות ברירת מחדל. זה מאפשר לזהות את הנזק תוך מספר מועט של פניות ולא לחשוף אותו למשתמשים.

הורדת מחיר הטעות

בארגון מודרני הבאת יכולת מהר ל-production היא הכרחית. ולכן חברות רבות אימצו תפיסות של "embrace the change" או אפילו "fail fast + embrace failure" - הן בחרו להתמקד פחות בהורדת הסיכוי להתממשות הסיכון מראש (תהליך שמעכב הגעה ל-production) ולאמץ גישה שמקטינה את הנזק שמימוש הסיכון עשוי ליצור.

עם זאת, צורת העבודה האג'ילית כן מעודדת עבודה שמקטינה את את הסיכוי להתממשות הסיכון - התקנות תכופות ומפגש מוקדם עם משתמשים. ככל שמתקינים לאחר זמן פיתוח קצר יותר נעשו פחות שינויים בתוכנה ולכן הסיכון שמביאה גרסה חדשה הוא נמוך יותר. לכן שילוב של עבודה אג'ילית עם הטכניקות שהזכרנו להקטנת מחיר הטעות מביאות לסיכון נמוך במיוחד בהבאת גרסא חדשה ל-production. אחד המאמרים הכי טובים שיצאו על הנושא הזה ואיך אפשר ליישם עלייה ל-production שבאמת עוזרת לנו לאמת היפותזות הוא Making sense of MVP של Henrik Kniberg.

הערות לסיום:

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