2012-05-09

סיבוכיות: מקבלים את זה בחינם

אני רוצה לדבר על פשטות. פשטות של ארכיטקטורה ומוצר.

כמה פשוט וקל לדבר על פשטות:
  • "בואו נעשה את זה פשוט"
  • Keep It Simple, Stupid
  • Less is More
כמה קל!!

אבל מה היא פשטות, ואיך משיגים אותה?


מה שמעון פרס היה אומר?

פשטות דומה ל"שלום עולמי" - אי אפשר להתנגד אליה.

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

הקונצנזוס החיובי לגבי פשטות - הוא אוניברסלי.

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

...מתי אמרתם שיוצא הספר "World Peace for Dummies"?


מקור: http://everydaybipolar.wordpress.com/

ג'ונגל הסיבוכיות

למי שכתב אפליקציית "Hello World" בחייו ברור שזו אפליקציה פשוטה.
מוסיפים לה עוד פונקציה, ועוד פונקציה - והיא עדיין פשוטה. לאחר שאנו יודעים שיש לנו בסיס פשוט, ורצון כן ואמיתי לפשטות (אולי אפילו יש איזה שלט ענק במסדרון שאומר "!Simplicity" - לוודא שלא נאבד את הדרך) - אנו מתקדמים בקצב. פעם הבאה שנרים את הראש, נשים לב שאנחנו בתוך ג'ונגל סבוך - ג'ונגל הסיבוכיות.

עיקרון #1: התבונה היא לא בייצור פשטות, התבונה היא ביציאה מסיבוכיות ברגע שהגענו אליה.

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

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

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

יצא לי באופן אישי להיות מעורב במחיקה של סט יכולות שלם מ Component Model באחת המערכות, לאחר שנוצרה קואליציה דיי גדולה של מפתחים, מתעדים טכניים ואנשי UX שהיא סיבכה להם את החיים. יצא לנו גם להעביר שירות (service) מרכזי ועתיק יומין משרת אחד לשרת אחר - ולצמצם הרבה תקשורת וסנכרון מיותרים. הדברים הללו פישטו את המערכת והסירו נתח משמעותי מהסיבוך [א].





עיקרון #2: החכמה היא להאריך את הדרך אל הג'ונגל, עד כדי כך שאולי אפילו לא להגיע אליו...

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

"אנחנו מקבלים את זה בחינם", או חוסר ההבחנה בין ממשק public ל published.
נאמר שהיה לכם צורך לבצע חיפוש על שני סוגי אובייקטים במערכת. בגלל שמספר המקרים גדול מ - 1, כתבתם קוד כללי שמבצע חיפוש על n אובייקטים במערכת - הנדסת תוכנה טובה. השלב הבא הוא לומר לכולם (תיעוד, תהליכים או סתם המלצה - תלוי בארגון): יש לנו חיפוש - תשתמשו בו.
אפילו יותר גרוע: תחשפו UI, WebService או Public API שלקוחות יוכלו להשתמש בו: הרי הקוד שם - וכך אתם יכולים בעלות נמוכה להשיג תועלת גבוהה - כלכלה פשוטה, "מקבלים את זה בחינם".

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

שאלות הרות גורל (לנושא הפשטות) הן:
  • האם החיפוש של האובייקטים מחזק את מטרות המערכת וייעודה לטווח הארוך? אני מתנצל על הניסוח המתנשא, אך האם חיפוש הוא חלק עקרוני שסביר שהיה מתפתח בכל מקרה? האם הוא סותר עיקרון כלשהו אחר, לדוגמה Real-time או ביזור? אם לא - ייתכן וזה פתרון זמני, שרירותי, שלא תרצו לקבע.
  • האם החיפוש נכון לכל סוגי האובייקטים? האם יש אובייקטים רגישים (מבחינת אבטחה או הכמסה), שמשתנים בתדירות גבוהה, שמשמשים כ Cache או כצעד חישובי?
  • האם אתם רואים צורך לחיפוש "מעבר לפינה"? יש לכם תכניות ממשיות להשתמש בו במקומות אחרים? אולי זהו צורך מאוד נקודתי.
  • האם ברור לכם איך החיפוש צריך להתבצע? אולי זוהי תכונה חדשה ולא בוגרת שכדאי ש"תבשלו בצד" עד שתיצרו בה עוד תלויות.
יש הרבה סיפוק בלספק פיצ'ר חדש.
אבל, אם אתם רוצים מערכת פשוטה שיהיה קל לתחזק לאורך שנים - נסו לצמצם את השימוש בתכונה החדשה למינימום ההכרחי. נסו להיות "קמצנים" ו"שמרנים" בפונקציות של המערכת. האם יש לכם כבר תהליך מסודר בארגון של "מחיקת דרישות"? - מעבר על הדרישות לפני הספרינט - וניסיון לצמצם אותן?

תמיד תוכלו להרחיב את המערכת בעוד פונקציונליות, אך ההיפך הוא קשה יותר: Public APIs, ממש כמו יהלומים - הם Forever.


"ריבית דריבית"
אם תכפילו 1.2 חמש פעמים תקבלו יותר מ 2. משהו כמו 2 וחצי. החצי הוא ה"ריבית דריבית".
אם תוסיפו פיצ'ר של חיפוש, ועליו יכולת Customization ועליה יכולת X ועליה יכולת Y - הפיצ'ר הבא (נקרא לו "Z"), יהיה יקר יותר מאשר המקרה בו הייתם נמנעים מלהוסיף את יכולות X ו Y. לעיתים - ההבדל בסיבוכיות המערכת הוא משמעותי למדי.

זכרו את הכלל הבא: העלות של יכולת חדשה n היא זמן הפיתוח של n + זמן התחזוקה של n + זמן גבוה יותר לפיתוח יכולת n+1 וזמן תחזוקה גבוה יותר ליכולת n+1. רקורסיבית (lim: n-->m).
עקרון שהתייחסתי אליו גם בפוסט על היעילות האמיתית שב SCRUM: הדרך הטובה ביותר לפריון גבוה יותר בפיתוח הוא לייצר פחות פ'יצרים - וכמעט תמיד יש מה להוריד. YFAGNI[ב]!


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

הייתה לי פעם שיחה עם איש UX שאני מאוד מעריך. מדוע ה UI של המערכות שלנו הוא לא "כזה מגניב" - למרות שאנו באמת מנסים ומשקיעים.
"למה שיצא לנו UX מגניב?" - הוא שאל בתמימות.
"כי אתה ממש תותח...?!" - עניתי.
"האא... זה לא עובד ככה..." הוא החל להסביר. הוא הסביר שלא ניתן לקלוע ל UX מצוין בפעם ראשונה, אפילו איש UX מוצלח. הדרך להגיע לשם היא ע"י השקעה באיטרציות:
  1. תכנון ה UX
  2. בדיקת שימושיות (על משתמשים אמיתיים)
  3. הפקת לקחים - ותכנון שיפורים
  4. וחוזר חלילה
רק לאחר איטרציה ועוד איטרציה ועוד איטרציה - ה UX מתחיל להיות באמת אפקטיבי, "זורם", ומהנה. (רעיונות דומים אגב מתכנסים היום תחת התחום שנקרא כיום "LEAN UX", למשל לעשות usability tests מאוד קטנים, אבל כל ספרינט).

פשטות בתוכנה - היא דומה. אם ניתן למתכנן הגאון עוד שבוע בחדר המובדד - התוצאה לא תהיה משמעותית. אם נקצה 10% מכל כח הפיתוח כל ספרינט ל Reafactoring ושיפור קוד - התוצאה תהיה משמעותית יותר. האם אין דרכי קיצור? האם אין את המתכנן הגאון שייצור את הפשטות במחי מכחול ב Visio? האם אין את המדינאי שיביא שלום עולמי לו רק יתנו לו איזו שנה אחת בשלטון?

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





-----

[א] הערה טכנית: כמובן ש Unit Tests ואוטומציית רגרסיה היא גיבוי רב-עצמה לביצוע שינויים כאלו בפועל.

[ב] ! You Ain't Gonna Need It


3 תגובות:

  1. פ.ס. הווידג'ט של אווטביין הציע לי את הקישור הבא, לא שמעתי - אבל נראה לי קישור טוב:

    http://www.reversim.com/2010/12/086-software-axioms.html

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

    - Domain Driven Design שליאור כתב עליו פה - http://www.softwarearchiblog.com/2011/12/domain-driven-design.html

    - Refactoring - להתאים את התוכנה לתובנות חדשות שעולות עם הזמן.

    - End Of Life למה שלא הכרחי - כמו שגוגל עושים בימים אלו.

    השבמחק