הספר Refactoring טבע כמה מושגי יסוד שהושרשו עמוק בתעשייה כמו Refactoring ,Code smells, או Testability של קוד. החלק החשוב בספר הוא לא קטלוג ה Refactoring (הטכני), אלא 4 הפרקים הראשונים העוסקים בכמה רעיונות מאוד חשובים בפיתוח תוכנה:
- בדיקות-יחידה (Unit-Tests), היו אז עוד רעיון חדשני ולא כל-כך מוכר.
- שווה לציין שיותר ממה שבדיקות יחידה פותרים באגים, הם מאפשרים לעשות Refactoring במהירות ובביטחון.
- הרעיון שהשלב הראשון בפתירת באג, היא לכתוב בדיקה שתיכשל – ואז לגרום לבדיקה לעבור (מה שיוכיח שהבאג תוקן, ויוודא שאין רגרסיה והוא חוזר).
- הרעיון שניתן לשנות/לשפר Design של מערכת קיימת אחרי שהקוד נכתב.
- הרעיון הזה תומך ומחזק רעיונות כמו Minimum Viable Products (בקיצור: MVP) ו YAGNI – רעיונות סופר-חשובים ומשמעותיים.
- הרעיון הזה, לצערי, לא חלחל לכל קצוות התעשייה עד היום.
- הרעיון ש Refactoring צריך להיות חלק מובנה מתהליך פיתוח תוכנה, כמו ש Delivery הוא כזה. כמובן שבלי delivery אין פיצ׳רים ללקוחות, בעוד refactoring ניתן לדחות ולדחות עד ה Rewrite הבלתי נמנע.
- בספר פאוולר מקדיש חלק ל״איך לשכנע את המנהל״ לבצע Refactoring. עצה אחת היא שהמנהל לא יאהב את רעיון ה Refactoring, אבל אם האלטרנטיבה היא Rewrite – אז הוא יעדיף אותה. עצה שניה היא פשוט לא לספר למנהל – אלא פשוט לעשות. הדילמה הזו רלוונטית גם היום.
האם רעיון ה Refactoring באמת הצליח?
התשובה היחידה היא שלא – Refactoring לא הוטמע עדיין בצורה נרחבת מספיק כחלק מובנה מתהליך התוכנה. מכיוון שהוא לא בנתיב הקריטי לשחרור פיצ׳רים – ניתן לדחות אותו זמן רב, ולצבור אותו לכדי פרויקטים גדולים.
- כדי לכתוב בדיקה לבאג, אנחנו צריכים לדעת לשחזר אותו. החקירה כיצד בדיוק היא משתחזר יכולה לארוך זמן רב, והיא מוציאה אותנו מה context של כתיבת בדיקה. עד שמצאנו את הבעיה, והתיקון קטן – הנטייה האנושית היא ״כבר לגמור עם זה״.
- לא כל מצב במערכת ניתן לשחזר בעזרת בדיקת יחידה.
- עדיין אנחנו כותבים יותר מדי בדיקות אינטגרציה לקוד שניתן להפריד ולכתוב לו בדיקות יחידה – וזה חבל.
- בדיקות אינטגרציה הן לא קלות לכתיבה, במיוחד לא במצבי-קיצון, וכך פעמים רבות אנו מוותרים על המאמץ לנסות ולכתוב בדיקה שמשחזרת את הבאג.
![]() |
Software Death Spiral ביצוע Refactoring אמור להחזיר אותנו מעט לאחור – ולהאריך את קץ המערכת… |
אז למה לא לעשות Refactoring?
אין הרבה מפתחים שנגד Refactoring, וכנראה שאין מומחים / מובילי דעת-קהל בעולם התוכנה שנגד Refactoring, ובכל זאת, כאשר מעלים להנהלה (מנהלים, מנהלי מוצר, מנהלי פרויקטים) את הרעיון ״לבצע Refactoring״ ישנה הסתייגות, והרבה פעמים זה לא קורה.
למה?
בצורה הפשוטה ביותר אפשר לדבר על אכזבה קולקטיבית מסויימת של שכבות הניהול מתהליך שמתויג כ “Refactoring”. כמה פעמים אנחנו, אנשי התכונה הבטחנו:
״תנו לנו 3 שבועות, נבצע Refactoring באזור ההוא – ואז הכנסה של פיצ׳רים תהיה קלה בהרבה!״
אבל המנהלים, שהם אמונים על ובקיאים בתמונת הפרויקט, רואים לעתים ש:
- ה Refactoring קצת הסתבך וארך בעצם כמעט 5 שבועות.
- פיצ`רים לא תמיד יותר מהירים לאחר ה Refactoring, לפחות לא משמעותית: ״כן, ה Refactoring שיפר מהירות של פיצ`רים מסוג z, אבל זה פי׳צר מסוג y…״
- ה Refactoring עלול לגרום לרגרסיות במערכת ו/או באגים נוספים.
למה Refactoring נכשלים?
ראשית, לצורך הדיון, נגדיר מהו ״כשלון של Refactoring״. בגלל הקושי למדוד דברים בתוכנה, סביר שהדיון מסוג זה יהיה בחלקו סובייקטיבי, כאשר מי שרצה את ה Refactoring מהתחלה ימעיט בבעיות, ומי שהתנגד מלכתחילה – ידגיש אותן.
אגדיר Refactoring ככושל אם הוא לא החזיר את ההשקעה בו לאורך חצי חיי המערכת שנותרו.
אם אנו מעריכים שמערכת תעבור Rewrite בעוד כשנתיים, אז שווה לעשות Refactoring אם הוא מחזיר את ההשקעה תוך כשנה.
השקעה שתחזיר את עצמה בדיוק בזמן החיים שאנו צופים למערכת היא מסוכנת מדי: תמיד יש סיכוי ב Refactoring, ותמיד יש סיכון שמהערכת (או הצורך בה) ישתנו בצורה דרמטית, בשל אילוצים שאנו לא יכולים לחזות. כאשר אנחנו לוקחים סיכונים, וגם משלמים את הכל מראש, נרצה פרמיה טובה מספיק על הסיכון – ולכן שווה להתייחס לחצי מחייה המוערכים של המערכת.
האם אתם לא רגילים לחשוב על מערכות בזמן חיים? נסו את זה – זו תורם. קל יותר לחשוב על אורך חיים של תת מערכת, למשל: מיקרו-שירות.
נזכיר לעצמנו גם כמה זמן נכון להשקיע בשיפור – בכדי לחסוך כמה זמן בעבודה רוטינית. זה נכון לאוטומציה, וזה עוזר גם לבחינה של Refactoring בגודל משמעותי:
אם אני מעריך שמערכת תחייה עוד שנתיים, ויש בעיה ב Design של המערכת שגורם לי פעם בחודש לבלות כחצי יום של הסתבכות (נניח: כל פעם שנוגעים באזור מסוים) – אזי השקעה של עד שישה ימים שתפתור את הבעיה, היא בגדר הצלחה. השעה של שבועיים (10 ימים) למשל – כבר באזור הפחות מוצלח.
כמובן שמדד ההצלחה הוא דיי קשוח. ברור שיש יתרונות נוספים ל Refactoring (מוצלח מבחינה הנדסית) שאי אפשר ממש למדוד:
- התחושה הטובה של המהנדסים שעובדים עם הקוד.
- המסר הפנימי: אנחנו משפרים קוד, ולא חיים בבבלאגן. אל תקבלו את הבלאגן.
- צמצום טעויות ובאגים – אי אפשר למדוד כמה פיצ׳רים נוספים עקומים נבנו – כי היה חסר Design נכון מלכתחילה.
- הכרות טובה יותר של האנשים עם הקוד. Refactoring הוא דרך מעולה להבין את הקוד לעומק – ומכאן גם את המערכת.
- מהנדסים מאומנים לזהות Code Smells, להבין כיצד הקוד היה צריך להראות – ואז לרצות לשפר את הקוד. טוב מאוד שכך (!!), אבל זה גם אומר שיהיה רצון לבצע בקוד גם שיפורים בעלי עלות/תועלת נמוכה מאוד בראייה מעשית.
- לא כל Refactoring מייצר קוד טוב יותר. יש סיכון שה Refactoring יוביל לעיצוב מערכת פחות מוצלח, יהיה ניתן להבין את זה רק לאורך זמן – ואז כבר יהיה מאוחר מדי בכדי להתחרט.
- Refactoring לא עוזבים באמצע. לפעמים אנו מתחילים Refactoring של שבוע – שאורך שבועיים ואף שלושה שבועות.
- אין גבול לזמן שניתן לעשות בו Refactoring. זכיתי להזדמנות הנדירה לחזות ב Refactoring של צוות קטן לאורך חצי שנה. השינויים שנעשו באמת היו משמעותיים – שינו את מודל הליבה של המערכת למודל שונה למדי. סידרו הרים של קוד.
לרוע המזל, לא נראה שמשהו מהותי באמת השתפר. זה היה שונה, אבל קשה מאוד היה לומר שזה היה טוב יותר.
יאללה, המלצות (סיכום)
דיברנו לא מעט על התהליך, מגמות, וכוחות משפיעים, אבל לא פחות חשובה המסקנה: ״אז מה עושים?״
האם מפסיקים לעשות Refactoring ומתכננים כבר ב Schedule מועד ל Rewrite לכל חלקי המערכת?
האם פשוט צריך להחליף את ההנהלה? להחליט שימי ראשון מוקדשים ל Refactoring בלבד?
הנה כמה המלצות קונקרטיות, ממיטב ניסיוני:
- Refactoring גדול = סיכון גדול, Refactoring קטן = סיכון קטן.
- דוגמה קלאסית ל Refactoring עם ROI חיובי ברור הוא Rename לאובייקט מרכזי במערכת שהשם שלו מטעה / פשוט לא נכון. ההשקעה היא במסגרת הדקות – התמורה היא ודאית.
- נסו ליצור תרבות של Refactoring קטנים עליהם לא צריך לספר למנהל (כפי שהציע פאוולר), ולא צריך לשנות בשבילם Schedule של פיתוח. סיכוי טוב שה ROIs יהיה מוצלח, וגם תהליכי ה Code Review יוכלו לספק בקרה ופידבק לגבי הנכונות ההנדסית של ה Refactoring הללו.
- כאשר אתם עושים Refactoring גדול, התייחסו אליו כמו כל פיצ׳ר גדול ומסוכן אחר:
- עשו בקרה לעיצוב המוצע. למשל: Design Review.
- נסו ברצינות לפרק אותו לשלבים קטנים יותר / לבצע MVP שיספק פידבק מוקדם יותר עד כמה השינוי מוצלח/יעיל.
- נסו לצמצם אותו ולחשוב: מה אפשר להוריד מהמודל היפה והאלגנטי הזה שמוצע. על אלו פרטים ניתן לוותר – בלי לאבד הרבה מהערך. מניסיון – זה עובד.
- הכי מסוכן זה Refactoring גדול של מישהו שקיבל לאחרונה אחריות על קוד. למשל: חודש-חודשיים אחרי שצוות מקבל קוד מצוות אחר, הוא ״מיואש״ כבר מהקוד – ודורש לבצע Refactoring גדול.
- יש בכך יתרון: תוך Refactoring כזה, הקוד בהדרגה “יהפוך לשל הצוות”: הוא יהיה מוכר יותר והצוות ירגיש שלם יותר איתו. Refactoring היא דרך מעולה להבין קוד לעומק.
- הסיכון הגדול הוא שהצוות לא מבין את הדומיין טוב מספיק עדיין, וסיכון גדול שהוא יבצע שינוי ל Design שאינו טוב יותר.
- נסו למנוע / לצמצם עבודת Refactoring גדולה של מישהו שלא עבד עם הקוד חצי שנה לפחות. כן עודדו לעשות כמה שיותר Refactoring קטנים (כמה שעות כ״א, למשל). זה כלל האצבע שלי.
- אל תוותרו על Refactoring, גם אם זה קצת מורכב:
- Refactoring הוא אוויר לנשימה למערכת. מערכות דורשות חמצן והתחדשות – ותהליך ה Refactoring מספק להן את זה.
- לא פחות חשוב: Refactoring הוא אויר לנשימה למהנדסים שעובדים על המערכת.
- זה ממש רע לקבל, ולהתרגל לעיוותים וחוסרי-הגיון בקוד – זו דרך טובה להפוך למהנדסים פחות טובים.
- Refactoring הוא גם רענון שכלי למפתח (שאנו לא רוצים ״שיתייבש״): עבודה הנדסית שקצת שונה לפעמים מבוספת פיצ’רים למערכת.
- Refactoring עוזר לקבל רמת עומק גבוהה יותר עם הקוד שמתחזקים, במיוחד לאורך זמן (״הנה המשמעות של מצב A, מול המשמעות של מצב B״)
פוסט מעולה! ככל שיהיה ברור (גם למנהלים) ש-refactoring הוא חלק ממחזור החיים הטבעי של מערכת אז יהיו פחות חיכוכים בנוגע לזה.
מה זה Refactoring ?
כתבתי לא נכון?אם לא – חפש באינטרנט. שווה לך.
מסכים, הסכמה מסביב ל Refactoring היא לא דבר קל..
מעולהמזכיר לי מאמר מענין (וישן מאד) של יואל ספולסקי על rewrite של קוד שרלוונטי גם בנושא הזהhttps://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/
בהחלט רלוונטי. תודה בה על השיתוף!
מספר תהיות:1. האם בכלל צריך להסביר את משימת הREFACTOR למנהלים? הרי בהגדרה הם לא מסוגלים, לדעתי, להבין את הROI של התהליך הזה (אלא אם כן אנחנו נמצאים כבר בסטגנציה מלאה של תהליך הפיתוח, והמנהל נואש ומוכן יהיה לנסות כל מה שיציעו לו).2. אני פוגש בתעשיה יותר ויותר מקרים בהם אירגוני פיתוח, בצורה הומוגנית, מאמינים שיש דבר כזה תיכנון מושלם, ולכן אין להם יכולת להבין שניתן לשנות design של מערכת קיימת. התוצאה? בוא נעשה complete rewrite תוך כדי תחזוקה של המערכת הישנה. לא רק שזה יקר, אלא גם תוקע את ההנהלה בבעיה – ההנהלה לא תסכים לכבות את המוצר הישן כל עוד החדש לא עושה כל מה שהישן עשה. בעצם הם נעולים בנקודה בה יכאב מאוד לכבות את המערכת הישנה.3. חשוב לשים את הדגש על unit tests – בלעדיהם אי אפשר לייצר ביטחון בתהליך שכן אתה רוצה להיות בטוח שהrefactor לא שבר משהו מהותי. לצערנו -הכלי היחיד האפקטיבי הוא בדיקות אוטומטיות (יחידה, אינטגרציה או e2e בתמהיל כזה או אחר). אי אפשר להתחיל לבצע refactor ולהסתמך על בדיקה ידנית – כי אז התהליך (או הפידבר על השינוי) הוא איטי – איטי מידי מכדי שהrefactor יהיה בר ביצוע.חוצמזה מאמר מעולה! בובה של טיפים!
היי חנוך,1. מעולם לא בחנתי את השאלה הזו לעומק. נראה לי שבד\”כ Refactorings גדולים (של שבועות) – דורשים סוג של הסבר / שקיפות בכדי לשמר את רמת האמון. Refactorings קטנים – אין טעם להסביר. זה כמו להסביר שהמפתחים צריכים ללכת לשירותים מדי פעם.2. כן, בעיה קשה – אם כי הרושם שלי דווקא שהשוק מתבגר ומבין יותר את ה tradeoff הזה.3. מסכים לגמרי: בלי testings משמעותיים – אי אפשר לבצע refactorings ביעילות/בטיחות יחסית.תודה על הנקודות!
תודה, פוסט מעולה. המצב . האידיאלי הוא כפי שציינת, לבצע refactoring כחלקמ העבודה הרגילה שלך.