כל מערכת שכתבתם תמיד שמרה על תאימות לאחור. ברור!
זו היתה דרישה מספר 1 (או 0, אם אתם אנשי C) במסמך הדרישות שקיבלתם: Backward Compatibility.
אבל, תאימות לאחור… זה באמת פשוט כמו שזה נשמע?
בפוסט הזה אני סוטה לרגע מסדרת הפתרונות למעבר בין ארכיטקטורות, לטובת נושא לא פחות רלוונטי למעבר כזה: מהי המשמעות של תאימות לאחור.
תאימות לאחור: מה זה, בעצם, בדיוק?
הקאץ' העיקרי במושג הזה נובע דווקא מהעובדה שהוא נשמע כל כך ברור וטריוויאלי. בכל פעם שישנו שדרוג של מערכת או של רכיב במערכת – הדרישה לתאימות לאחור מופיעה בצורה ברורה. כל כך ברורה, שבדרך כלל מסתפקים בדיוק בזה: תאימות לאחור. כמעט ולא יצא לי לשמוע, לעומת זאת, מסמכי דרישות המגדירים במפורש מהי אותה תאימות לאחור.
מה שאיש הפרודקט לא מגדיר כי זה נראה לו ברור לגמרי, יכול להיות בדיוק אותו דבר שאיש הפיתוח לא מבצע כי זה נראה לו בלתי אפשרי.
דוגמא אחת קטנה
אם מה שכתבתי קודם נשמע לכם מוגזם או מופרך, הנה דוגמא קטנה, אמיתית, בה נתקלתי לפני מספר שנים.
באחת החברות בהן עבדתי, בתחום התקשורת, לקוח יכל לקנפג את המוצר שלו בדרכים שונות. אחד הפרמטרים קבע כללים להפניית תעבורת רשת, כך שלכל כלל הוצמד מספר שקבע את קדימותו ביחס לאחרים. כלל מספר 10 – ייבדק לפני כלל מספר 20, כלל מספר 20 – לפני כלל מספר 30, וכך הלאה. קונפיגורצית ברירת המחדל התבססה על שלושה או ארבעה כללים, הממוספרים 10, 20, 30, 40. הלקוח, כמובן, יכול להוסיף כללים משלו, ולמספר אותם כרצונו: 5, 17, 52…
בשלב מסויים, מסיבות כלשהן, הוחלט כי יש למספר את הכללים מ-1 ועד 16, ולא יותר. הכללים של ברירת המחדל הפכו, לפיכך, להיות ממוספרים כ-2, 4, 6, 8. כאשר הפיתוח של הגרסא החדשה הסתיים וביקשתי להבין את מהות השינוי, הסבירו לי בדיוק את זה.
"ומה עם תאימות לאחור?",
שאלתי. התשובה היתה –
"אין שום בעיה. כאשר הלקוח יעלה את הגרסא החדשה, אם יש לו כללים שמספרם גבוה מ-16, המערכת פשוט מחלקת אותם בעשר. מספר 20 יהפוך ל-2, 50 יהפוך ל-5, וכך אנו מוודאים שאין שום כלל הממוספר יותר מ-16".
מי שסיפק לי את ההסבר הזה היה אחד המפתחים הטובים ביותר שיצא לי להכיר. הסתכלתי עליו קצת המום, ואמרתי לו שאין כאן תאימות לאחור. הוא התעקש שדווקא יש: המערכת תהפוך את כל הערכים הישנים לחוקיים על פי הכללים החדשים, ולכן תמשיך לעבוד ללא שגיאות. ניסיתי להבין ממנו מה יקרה אם הלקוח קינפג במערכת הישנה כללים הממוספרים, נניח, כ-24, 26, 28. כעת שלושתם יהפכו לבעלי אותה רמת קדימות בדיוק – 2 – ולא ניתן לדעת בוודאות מי מהם יתבצע ראשון. כך ייתכן שלאחר עדכון המערכת, המוצר יפעל פתאום אחרת מאשר בגרסא הקודמת! אבל מבחינתו זו היא כבר "בעיה של הלקוח". הדבר היחיד שהיה חשוב מבחינתו הוא שלא יהיו שגיאות ריצה, וזה, מבחינתו, היווה "תאימות" מספקת.
ברור שלא תמיד ניתן למצוא פתרון. למשל, אם ללקוח היו במוצר שלו יותר מ-16 כללים, באמת לא נוכל למספר אותם מחדש בהתאם למגבלות החדשות. במקרה כזה, אולי ניתן לכתוב קוד שיטפל במקרה הקצה (למשל, יחזיק מספור משני אך ורק למערכות עם קונפיגורציה ישנה), ואולי לא ניתן לעשות זאת, ואולי זה באמת אפשרי אבל גובה מחיר יקר מאוד. כל החלטה שתתקבל, כל עוד היא מושכלת ומובאת לידיעת הלקוח, יכולה להיות נכונה – אבל היא חייבת להתקבל כהחלטה, לאחר שנשקלו האפשרויות השונות, ולא לקרות כתוצאה מהתעלמות או הזנחה.
הפתרון הנכון למקרה הזה יכול להיות:
- כל עוד המערכת מקונפגת עם 16 כללים או פחות – מספור מחדש שלהם בצורה התואמת את סדר המספרים המקורי (למשל – 10, 20, 22, 24, 26, 30 – יהפוך ל-1, 2, 3, 4, 5, 6, ולא ל-1, 2, 2, 2, 2, 3).
- אם המערכת מקונפגת עם יותר מ-16 כללים – לא להתחיל שדרוג עד שהמפעיל מסדר אותם מחדש.
אפשר לחשוב גם על אפשרויות יותר מתוחכמות, אבל היה כדאי לבדוק בשטח, כמה כללים מקונפגים על מערכת טיפוסית. אם נגיע למסקנה שהרבה מפעילים משתמשים ביותר מ-16 כללים – נצטרך לטפל בזה בצורה מסודרת. אם נגלה שכמעט ואין כאלו – נוכל להסתפק באופציה המוצעת כאן. אבל, מה שחשוב באמת הוא – שנקבל את ההחלטה הזו לאחר שנשקלו המשמעויות שלה ושל חלופות אפשריות.
נקודה למחשבה: מוכנות הלקוח
אחד הנושאים שפחות נלקחים בחשבון כאשר מתוכנן שדרוג רכיב או מערכת, הוא מוכנות הלקוח לשינוי כזה. הנה, למשל, מספר דוגמאות לעדכוני תוכנה שונים:
- אפליקציה מציעה למשתמש שיתקין גרסא חדשה יותר מזו שבה הוא משתמש כרגע.
- לקוח קונה טלפון מדגם דומה לדגם הקודם שלו, אבל בעל עיצוב חדשני יותר, ומשתמש בפונקציה של היצרן להעברת כל נתוני הטלפון הישן.
- לקוח רכש רשיון שימוש במערכת SaaS גרסא 2.3 תמורת $30,000 לשנה, לצורך התממשקות עם המערכות הארגוניות שלו, ורכיבים בשרתי ה-SaaS מוחלפים ללא ידיעתו.
- אפליקציה אינטרנטית בנויה מרכיב שרת ורכיב לקוח:
- רכיב הלקוח (FrontEnd) נשאר זהה, אולם השרתים (Backend) הוחלפו לחלוטין.
- רכיב הלקוח שינה עיצוב בצורה משמעותית, אולם השרתים נשארו ללא שינוי.
- שני הרכיבים, גם צד השרת וגם צד הלקוח, עברו שינוי במקביל.
- מכונת כביסה חכמה הורידה באופן אוטומטי גרסה חדשה שאמורה לשנות את תאוצת המנועים לצורך שמירה על חייהם.
בכל הדוגמאות שתיארנו, חלקים במערכת התוכנה הוחלפו, כאשר הציפיה היא שהם ימשיכו לעבוד בדיוק באותה הצורה בה הם עבדו קודם לכן. בכל הדוגמאות הללו, אפשר להניח שעלולים להיות באגים, קלים או חמורים, וגם שינויים, מינוריים או מאז'וריים, בהתנהגות המערכת, חלקם ידועים וחלקם עלולים רק להתגלות בהמשך. ובכל זאת, בכל אחד מהמקרים, באגים או שינויים יגרמו לנזק שונה בתכלית. אפשר לחלק את המשמעות ללקוח לשלושה צירים: ציר המחוייבות, ציר המשמעות וציר ההבנה.
ציר I: מחוייבות ללקוח
מבחינת המחוייבות ללקוח, הדוגמא של מערכת ה-SaaS היא כמובן הקיצונית ביותר מבין אלו שהזכרנו כאן. הלקוח שילם סכום גבוה עבור שימוש במערכת הזו לאורך זמן נתון, ולכן הוא מצפה שלפחות לאורך פרק זמן זה, הוא יקבל בדיוק את מה שעליו הוא שילם. לעומת זאת, כאשר לקוח שדרג מכשיר טלפון, כלל אין מחוייבות מולו (אלא אם כן זהו אחד הפיצ'רים העיקריים של המוצר, שגורם לו להיות מועדף על פני מתחרים). יצרן הטלפון מציע שירות לתאימות לאחור, אולם זהו פיצ'ר "אקסטרה" ולא חלק מהמוצר הבסיסי.
בשאר המקרים שהזכרנו, ובכל מקרה שהוא, צריך לקחת בחשבון מה מידת המחוייבות ללקוח. ככל שאנו מחוייבים יותר ללקוח, כך ניזהר שלא ליצור שינויים לא אחראיים או להשאיר נקודות פתוחות. לא מדובר כאן בעניין מוסרי בלבד, כמובן (למרות שהוא שיקול חשוב בעיניי) אלא בעניין עסקי. לכן, למשל, חברות ענק מחליטות לפעמים על שינוי מערכת, גם אם זה מנוגד לציפיות הלקוח – פשוט כי הן יכולות. אם היתה להן תחרות קשה באותו ענף, וללקוח לא היתה בעיה להחליף ספק – רמת המחוייבות שלהן היתה גדולה בהרבה, גם אם מדובר בלקוח חינמי. לכן, משמעות המחוייבות היא המשמעות העסקית של השפעת השינויים. האם בעקבות השינויים הללו נפסיד לקוחות/עסקאות/הכנסות או להיפך.
ציר II: משמעות השינוי
למוצרים שונים יש תפקידים שונים, ולכן המשמעויות של כל שינוי יכולות להיות בעלות השלכות מגוונות. למשל, שגיאת כתיב בעיצוב מסך יכולה להיות מביכה, אבל לא תפגע כנראה ביכולת השימוש במוצר. לעומת זאת, שגיאת כתיב ב-API של שירות SaaS תגרום למערכות צד שלישי לקרוס בלי שום יכולת להתגבר על כך. שינוי במיקום הלוגים של אפליקציה כלשהי יכול שלא לפגוע בתפעול השוטף ומצד שני יכול להפוך תקלה קטנה שבעבר צוות התמיכה היה פותר בקלות לבעיה שתעבור אסקלציה במהירות. לכן, חשוב למפות את השינויים הידועים, ולא פחות מכך (אם כי כמובן הרבה יותר קשה) לנסות ולמפות את השינויים האפשריים, בהתבסס על האיזורים בקוד ששונו ועל אופי השינוי. כך ניתן יהיה להיערך לתקלות צפויות או פתאומיות מראש, או, אפילו טוב יותר – למנוע אותן.
ציר III: הבנת הלקוח
לקוחות לא אוהבים שינויים. בכל אופן, לא שינויים שגורמים להם לשנות הרגלים. אבל הם מעדיפים לדעת. במצב בו לקוח מבצע שידרוג תוכנה יזום, או מאשר שדרוג תוכנה אוטומטי, הוא מצפה לשינויים ויקבל אותם בהבנה. לעומת זאת, כאשר מערכת SaaS משתנה ללא ידיעתו, או מכונת כביסה מנסה לבצע שידרוג עצמאי, הלקוח לא יבין את מקורן של בעיות בהמשך, והתוצאה עלולה להיות משבר אמון קשה מול הלקוח (או מטוס נוסעים נופל – תלוי כמובן בסוג התוכנה והשינוי…) עדכון הלקוח בדבר השינוי יכול להיעשות לפני השינוי או לאחריו, יכול להיות מפורט או כללי, יכול להיעשות באמצעות מסך שמחייב לחיצת "אישור" באמצעות קובץ readme.txt שממתין בספריה אבודה לגיק שיטרח לפתוח אותו.
אפשר גם "לעדכן" לקוח באופן בלתי מפורש: בדוגמאות שלמעלה, הצגנו את האפשרות של שינויים באפליקציה אינטרנטית: שינוי בצד השרת, שינוי בצד הלקוח ושינוי במקביל. האם מדובר בשינויים זהים מבחינת המשתמש? התשובה היא, כמובן, שלילית. כאשר הלקוח מבחין בשינוי בעיצוב האפליקציה או האתר, הוא יניח שדברים התעדכנו ויקבל בהבנה גדולה יותר שינויי לוגיקה או באגים קטנים. לעומת זאת, אם הלקוח מרגיש שהוא גלש בדיוק לאותו אתר או אפליקציה בהם הוא משתמש כבר שנה, ויחווה פתאום דברים ש"לא עובדים" או באגים – התגובה תהיה הרבה פחות אוהדת.
קבלת החלטה
כל מה שנכתב כאן, אינו אומר שבהכרח נכון תמיד לקבל את אישור המשתמש מראש או אפילו לעדכן אותו בדיעבד. גם לא שאסור ליצור שום שינוי בהתנהגות ויש לשלם כל מחיר על מנת לשמר במדוייק את ההתנהגות המקורית.
ישנם שיקולים רבים ושונים לכל החלטה. האם משתמש במכונת כביסה ירצה להיות מעורב בתהליך עדכון שהוא לא מבין את משמעותו? כנראה שלא. הוא עלול אפילו לחשוד אחר כך בכל חריקה קטנה של המכונה ולהאשים את העדכון. האם נעדיף להתקין על שרתי אחסון לצד שלישי מנגנוני אבטחה באופן עצמאי, או שנחכה לאישור כל הלקוחות, ובינתיים נמצא את עצמנו תחת תביעה על פרצות שאפשרו לגנוב להם סודות מסחריים?
ייתכן בהחלט שבכמה מהדילמות, מהנדסים וארכיטקטים לא יוכלו לספק את כל התשובות, ויהיה צורך גם בעורכי דין, רואי חשבון, כלכלנים ואקטוארים. אבל… כארכיטקטים, תפקידנו יהיה להבהיר את מלוא התמונה, המשמעויות והאופציות השונות לאותם יועצים ומנהלים, ולוודא שאנו (והם) מבינים היטב את כל האפשרויות הנתונות ואת השלכותיהן הברורות, הסבירות והאפשריות.
אם יש לכם דוגמאות מעניינות לבעיות תאימות בהן נתקלתן, אשמח אם תשתפו אותי, בתגובות מתחת לפוסט או באופן פרטי.
[…] הפוסט פורסם לראשונה בבלוג ״ארכיטקט בכפכפים״. […]
[…] הפוסט פורסם לראשונה בבלוג ״ארכיטקט בכפכפים״. […]
[…] יש לנו מספר גרסאות בשטח שלא ניתן לאחד בקלות ולשמור על תאימות לאחור עבור המשתמשים. במקרים אחרים, נוכל לבחור בין אפשרויות […]
[…] באמינות מול לקוחות (זמן מצויין להיזכר כמה חשובה התאימות לאחור). אם זה אפשרי מבחינת המערכת, טוב יותר במקרה כזה להשאיר […]