Lesson 12 of 22

Legacy Refactoring intro

Duration: 16:23 Watch on YouTube (external link, opens in new tab) Spoken in Hebrew

Markdown version

In this lesson

Roy Osherove turns to dependencies that cannot be injected through a constructor, such as a call to a static logger, and introduces extract and override (external link, opens in new tab) from Michael Feathers' (external link, opens in new tab) book Working Effectively with Legacy Code (external link, opens in new tab), which he recommends. He moves the call into a protected virtual method with no logic and has a testable subclass (external link, opens in new tab) of the login manager override it and save the text in a public field for the test to check, noting that in real legacy code (external link, opens in new tab) he would first have an integration test (external link, opens in new tab) in place. To concerns about exposing such methods he answers with internal methods and InternalsVisibleTo (external link, opens in new tab).

Transcript

1,933 words

[00:03] (external link, opens in new tab) אתה יודע שזה מה שיש לך להגיד למה testing is good testing נכון רדג אתה רוצה להגיד מה שמצן

[00:38] (external link, opens in new tab) טוב בואו נסתכל על logic פה אנחנו נכנסים קצת לדומיין שקצת רגע סיכוי ואנחנו נדבר על איך לעשות רפקטורים לקוד כדי שנוכל לכתוב אותו עם פריורקים שהם קונסטר כי לפעמים הדיזיין הוא כן משהו שהם רוצים לשנות אז אנחנו הולכים לראות בקורס הזה גם טכניקות של ריפקטורים כדי שנוכל שנות קוד קיים וגם טכניקות בלי ריפאקטורים. אז היום היום בעיקר נלמד על טכניקות של ריפקטור. עכשיו במקרה הזה בתרגילים שאתם יכולים לעשות עכשיו יהיה לנו כמה סוגים שלפנency שאנחנו נצטריך להתגבר עליהם.

[01:13] (external link, opens in new tab) הסוג הראשון של dependency זה dependency static במקרה הזה אחת הדרישות יהיו בoger static יש קרי לstatic logger right אין logger אין קונסטר פה בעצם גם מה שעשינו עד עכשיו אנחנו עשינו מה שנקרא constructor inction לקחנו dependen ועשינו להם inקטור constructor יש הרבה סוגים של inctionקש שאפשר לעשותקסטור זה אחת הדרכים הבסיסיות בגלל שזה לא אופציות

[01:43] (external link, opens in new tab) אבל פה אין בכלל מאיפה לעשות in עכשיו השתלה איך אנחנו יכולים לוודא שatic logo r באמת נקרא נניח יש לי פה באג שחסר לי פהספיס או יש לי באג וחסר לי פה איזשהו מידע מאוד חשוב איך אני יכול להוכיח בטest שהמידע הזה חסר אז הדרך שאנחנו נראה עכשיו נקראת extract and over היא נלקחת מספר שאני ממליץ עליו בחום שנקרא Working Effectively with Legacy Code (external link, opens in new tab) יש לכם אותו פה

[02:14] (external link, opens in new tab) תקנו אותו פשוט ככה שמייקל פדרס הוא שווה את המשקל שלו בזהב מבחינתי המון מהדברים שאני למדתי על ריפאקטורינג למדתי מהספר הזה יש בו הרבה יותר דברים ממה שאנחנו נלמד בקורס אבל בגדול הספר הזה מדבר על מה קורה כשאתה בעולם שבו וודקה זה פתרון מאוד טוב לבעיות גסי שלך שפל וסלב התלהבו מהצלו דווקא בסדר הזה ויש יש שם המון המון חוכמה המון סוגים של ריפקטורים באמת ספר ספר נורא מעניין. המון מהדוגמאות הם ב-C++ ובג'אבה, אבל זה עדיין אף ספר מאוד קרי.

[02:48] (external link, opens in new tab) אחת הד אחד הטכניקות הכי הכי פשוטות היא נקראת אקסטרct ואיד והרעיון הוא ככה. אם אין אם יש לנו depפendנסי ישיר ואנחנו לא יכולים להחליף אותו ישירות אז אנחנו נעשה שכבת אבסטרקציה קטנה מעל ואנבדוק שהשכבת אבסטרקציה נקראה. אבל במקום לעשות פה קלאס אנחנו נעשה אבטרקציה רק למתודה לקריאה למתודה. במקום לוודא שatic loger right נקרא אני אעשה לו אact method

[03:28] (external link, opens in new tab) ולמטודה אני יכול לקרוא call the logoer אני לא רוצה לעשות אותו statטיק אני רוצה לעשות אותו וירטואלית וtectד במקרה שלנו אוקיי אז זה בעצם מה שאני אקבל היא עדיין לא תהיה מספיק טובה בגלל ש יש פה את הסטרינג הזה מבחינתי מה שאני הולך לעשות זה בטestטים שלי אני הולך להרשת מהקלאס הנוכחי

[03:58] (external link, opens in new tab) למרות שזה הקלאס שאני בודק ולעשות אורייד רק לפונקציה הזאת אז ככה שכל שאר הקוד עדיין יעבוד אבל הפונקציה הזאת יהיה להover ואז אני בעצם אתגבר על הדפנenנy אבל אני לא אני רוצה גם לבדוק את ‏string אז אם אני אעשה over strיing אני לא יוכל לבדוק אותו צריך לקבל את כל המידע בפרמטר אז אני אעשה פה contנטרול altפct paramet te ועכשיו מה שיש לי זה cologer עם login requested בעצם הפונקציה

[04:30] (external link, opens in new tab) היא טיפשה לחלוטין אין לה שום מידע אבל לא שיניתי את הפונקציונליות של הקוד הפונקציונליות עדיין עושה בדיוק אותו דבר ההבדל היחיד הוא שעשיתי את הקוד יותר testable עכשיו שימו לב שבמקרה הזה בגלל שזה לגסוד הצד הראשון שלי הוא לעשות ריפקטורing הוא לא לכתוב test בלגסי קוד אמיתי לא הייתי עושה את הרפקטור הזה אפילו בלי שהיה לי אינטגרש test אחד רציני פות שעובר דרך הדבר הזה בדרך כלל שניים אבל כשיש את הנטגרation test אני יכול להתחיל לעשות את הדבר הזה

[05:05] (external link, opens in new tab) אז עשיתי פה exract method עשיתי את המתprcted virtual ופה אני מוודא שאין שום לוגיקה וזה הקוד הכי טיפה שיכול להיות כי אם יש לי פה לוגיקה מכיוון שאני הולך לעשות לה אורייד בטestטים שלי לא יהיה לי שום סיכוי לבדוק אותה אז אם יש פה באג אני בחיים לא אמצא אותו אז עכשיו הנחת יסודי שאם כל דלוגoger נקרא אז הלוגר נקרא בגלל שהקוד הזה כזה פשוט אני יכול להרשות לעצמי להניח את זה בטestים אני אצור קלאס חדש ונקרא לו testableגog

[05:44] (external link, opens in new tab) ‏manager with stat והוא יורש לי login manager stat אוקיי תשימו לב אני יורש מהקלא שאני הולך לבדוק אבל במקום לעשות פייק לכל הקלאס אני הולך לעשות בעצם פיק אבריד רק לפונקציה אחת אז זה פיקד מבחינתנו אוקיי הדבר הבא אני יכול לעשות overri לכל ואני לא רוצה לקרוא לבי b כי בעצם זה הדפendנency שלי אם אני אקרא להסטיקלג אז יהיה לי את אותם בעיות שהי גם קודם אולי זה יקח הרבה זמן אולי זה יזרוק את הבאג שהיה גם קודם אז כל מה שאני עושה עכשיו זה כמעט מה שעשיתי בפיק לוגoger הנר שכתבתי אני אכתוב

[06:30] (external link, opens in new tab) שטקסט אל create fieldד נעשה אותו publicק וזהו עכשיו את הטestטים שלי אני אכתוב כנגד הקלאס הזה כל שאר הקוד בקס הזה הוא producion cod בגלל זה תשימו לב זה לא נקרא fake (external link, opens in new tab) זה נקרא testable זה מאוד חשוב כי זה testable verion של אותו clס אחרי זה אני יכול לכתוב test שנראה ככה

[07:01] (external link, opens in new tab) Test is login senario ‏Cold calls static loger עכשיו כתבתי statטיק loger פה בשביל הדמו אתם אצלכם לא תכתבו שהלוגר הוא סטטיק אף אחד לא אכפת שהלוגר הוא סטטיק בוא סיכון שתכתבו לoger מכירה הלוגר הוא סטטיק אבל במקום ליצור את האנסט של הקלאס האמיתי אני אכתוב

[07:34] (external link, opens in new tab) פה מכיוון שאני יוצר אותו ישירות אני יכול לקצר את השורה ולהגיד זה כבר עכשיו אין לי מה לעשות פה להשתמש בטest בisolation framewor או כל דבר אחר אני פשוט יכול להגיד lm is login ו string assert conסני אוקיי וm

[08:05] (external link, opens in new tab) לא טס בדיוק כמו שעשינו עם הפייקל בהתחלה שהטest הזה יעבור סימן שהסטיקל נקרא אז הרפקטינג שעשיתי הוא לקחת קריאה לסטאטיק סו אה בסדר אי אפשר לזמור את הדלת >> שניה >> אוקיי חבר'ה תתרגזוזר רק עוד שתי דקות אתם הולכים לכתוב קוד תחסיקו מעמד אוקיי

[08:37] (external link, opens in new tab) זה מרגיש יש למוכון של מונטיפ אז כל מה שעשיתי זה ללכת ללוגog manager ולהגיד protected virtual הקוד עצמו עושה בדיוק את אותו דבר זה נקרא אrct and over שאלות לגבי אני שבק בתוך הבית שלסטיק >> אני לא קורא לו אז מה אכפת לי אתה קורא לו >> תראה לסטטיקלגר יהיו טסים משלו היוט הור שלנו לא קשור אליו כרגע כי אין לנו שליטה עליו ‏static lower אתה צריך להניח שיהיה לא טסים משלו וגם test שלך זה באג בסטיקל כנראה שיהיה בוא נניח ככה אבל בשביל זה החברה שלו גם עושים

[09:16] (external link, opens in new tab) בסדרסים >> אין בעל שזה יותרנו עד קוד לתחלק כלומר כל הדבר הזה בשביל קירת מתודה אחת אם יש לנו הרבה מתודות כאלה זה >> נפח את הקוד בצורה >> זה נראה כזה יוצר הרבה קוד אבל הקוד הזה הוא מאוד מאוד פשוט אחרי שימוש זה בקוד לגסי אמיתי, אחד הדברים שאתה תגלה שהטכניקה הזאת היא מאוד חזקה ומאוד פשוטה. היא הרבה יותר קלה ממה שעשינו עד עכשיו כי היא לא מחייבת אותך ליצור אינטרפייס חדש במערכת היא לא מחייבת אותך לממש את האינטרפייס הזה היא לא מחבת אותך לעשותק היא פשוט עושה אקסטר לאיט פשוט עושה אקסטר ואחרי שתי שניות יש לך את הקוד הזה ותשים לב כמה הקוד הזה פשוט

[09:59] (external link, opens in new tab) הוא דווקא ממש לא מסובך יש לי פה שהמטוריות הרמנית רק לפרויקט של הטסטים ש אני לא אוכל לראות אותם ממקום אחר >> שאני לא אוכל לראות אותם ממקום אחר את >> כל תלכ כל דלוגר לתוך שלא יהיה מצב שאני מישהו יקרא לזה בטעות שלא כאילו מפחיד אותך שיקראו לפונקציות האלה בטעות זה >> זאת אומרת אצלכם לא עושים קוד >> גם אם עושים זה לא >> אז איך אז לא יתסו את זה אתה חושב >> בר שיש הרבה כאלה זה בעיה

[10:30] (external link, opens in new tab) זה בעיה לעשות קוד ריבו אם יש הרבה כאלה >> לא אבל קוד ריבו זה לא פתרון לכל דבר בקוד של אז יש תמיד סיכוי שמישהו יקרא >> כן אבל שיש >> בואו נגיד חבר'ה אני יכול ברפלקשן לקרוא לכל מתודה prvט שיצרתם מ פעם יש סיכוי שאני אעשה את זה לא משנה איך הפ שלכם יר >> לא אבל זה גם שנגיד אם אני משתמש באובייקט ואני רואה את הפאבליק מת שלו אז אני אראה כמה שפחות שאני לא אתזה 400 >> המתודה הזאת היא טקט היא לא פאבליק חשוב שתזכור את זה נכון >> נכון עכשיו סתם גם בתור דוגמה בג'אבה כל הדברים מביא את שואל בדפולט

[11:13] (external link, opens in new tab) מה אנשים עושים בעולם הג'אבה משתמשים רק >> צריך להבין שבדרך כלל ואם אנחנו נסתכל ועוד פעם זה יותר שיש שקשור לדיזיין אוקיי אם תחפשו נושא של solוליד אתם תראו שקסים שהם extendable extensible זה אחד הדברים שהם דווקא כן מוסיפים דיזין מבחינת התמישות שלו. אמ אבל מבחינתנו אם אנחנו באמת רוצים, מכיוון שאין פה דת, זה לא שאני מאמין שזאת הדרך הכי טובה, זאת דרך שלא צריך להיות לכם בעיה איתה.

[11:50] (external link, opens in new tab) אבל אם יש לכם בעיה איתה, תמיד אפשר לעשות if the bug. אתם מכירים את הפ? אז תעשו ותעשוט או private זה נגמר העניין. זאת אומרת אתם יכולים להגיד אנטרנal גם על מתודות אתם יכולים להגיד InternalsVisibleTo (external link, opens in new tab) על הtest assembly אם אתם מכירים את הנושא הזה אני אסביר אדed

[12:24] (external link, opens in new tab) Internal אוקיי אם עשית את זה interטרנal אז כביכול אף אחד לא יראה את זה אבל אז אני יכול ללכת לאassemly infו שלי אה בוא נראה איפה איפו זה פה אני יכול להוסיף InternalsVisibleTo ואני יכול לתת פה את השם של הtest assembly אז מאותו רגע מבחינת הtest assembly זה פליט אבל מבחינת כל אחד אחר זה prיבט

[12:54] (external link, opens in new tab) אוקיי אז זה משהו שעושים כשבאמת יש בעיה עם לחסוף את הדברים אני אישית אין לי שום בעיה עם הדבר הזה זה איזשהו פחד אחד בגלל שזה בסדר, זה בסדר שזה מפחיד, אבל אני אומר לכם שמבחינת השימוש בעולם האמיתי אנשים לא עושים בביוז לדברים האלה במיוחד שזה הכל באותה חברה אם הייתם עושים איזה פריורק שאתם עושים דליבר ואנשים עושים לו ומשתמשים בו ועושים לו אוברייד וכל מיני דברים כאלה מילא פה זה הכל קונטינט בתוך חברה אחת יש לכם כאילו באותה מידה שאתם מוודאים שלכל פרמטר מתחיל באות A אם אתם מצליחים לעשות את זה אז אין שום סיבה שלא תצליחו גם לבדוק את הנושא הזה בוא נפת ככה וגם זה באמת מבחינתי זה די שטויות אבל אם צריך אפשר למצוא דרך לפתור את זה

[13:39] (external link, opens in new tab) אה עוד שאלות ואני גם יכול לעשות כן if ולעשות ככה prate protected בדרך כלל לא צריך לעשות את זה אוקיי אז זה הדבר הראשון עכשיו בוא נסתכל על עוד מקרה

[14:17] (external link, opens in new tab) נלך ללגן man statס lws אוקיי אחרי זה יש לנו יהיה לכם יהיה לכם עוד דרישה לבדוק גם שסטיקוב סרביס נקרא כביכול זה נראה אותו דבר אבל בין השר יש פה גם את הדרישה שמשינם גם ישלח עכשיו משני nameים זה גם מכיוון שמשינם משתנה בין מכונה למכונה אז כל פעם שתריצו את הטest במכונה אחרת זה בעצם test אחר אז גם על משינם אנחנו נצטרך להתמודד איתו וזה גם זה עוד statטיק propפרerטy גם פה אפשר להשתמש באקסטרct ואover כדי לשלוט על המשי שלנו עוד פעם להוסיף את זה לtestable verion

[14:57] (external link, opens in new tab) אמ עוד דברים חשובים חבר'ה אנחנו כשנגיע לזה אנחנו עוד מעט גם נפתור את נושא הזמן מה יקרה אם אני אבקש ממכם להוסיף את הurentate and time למage >> אותו דבר בזה לא >> מה >> אותו דבר >> כן זה משהו שכבר מתחיל להיות קצת בעייתי בשיטה הזאת אנחנו נדבר על עוד שיטות כשנגיע לתרגיל הזה אז מה שאני מבקש ש נעשה הפסקה בינתיים ז אומרת לא הפסקה אנחנו נתחיל לעבוד בינתיים

[15:32] (external link, opens in new tab) כשתגיעו לתרגיל הזה staticס מה שאני מבקש שתעשו לי תרגיל ת ו10 אה וכשנגיע לתרגיל 11 תנסו לעשות אותו בעצמכם ואנחנו ניפגש פה נראה כמה זמן זה יקח אני מקווה שעוד חצי שעה כבר נוכל להיפגש פה עוד פעם אם יקח שעה יקח שעה זה גם בסדר אל תנסו למר יותר מדי חשוב שתלמדו בקצב שלכם זה שתנה אני אסתכל לראות מה הקצב כרגע לנסות לעשות את 9 10 ו1 ואז אנחנו נחזור וניפגש יש שאלות לפני זה

[16:22] (external link, opens in new tab) אוקיי ‏Yeah.