Table of Contents
למה SOLID ו-TDD שייכים ביחד
פיתוח תוכנה מודרני דורש הן שלמות מבנית והן נכונות התנהגותית. מתודולוגיות מועטה לספק את אלה ביעילות כמו עקרונות SOLID ופיתוח Test-Driven (TDD) על פני השטח, SOLID מתמקד בעיצוב - כיצד שיעורים ומודולים מתייחסים זה לזה - בעוד TDD מתמקד בתהליך - כתיבת בדיקות לפני קוד הייצור.אבל בפועל, הם מחזקים אחד את השני באופן שהולך הרבה מעבר לדו-קיום פשוט.
הסינרגיה בין SOLID ו-TDD יכולה להיות מובנת משוב.TDD nudges מפתחים לעבר יחידות קטנות, ניתנות לבדיקה של התנהגות.יחידות אלה, כאשר נועדו עם SOLID בראש, להיות מבודדת באופן טבעי ומשוחררת. בתורו, אדריכלות מבוססת SOLID עושה את TDD מהר יותר ואמינה יותר, כי כל מבחן מכוון אחריות מסוימת ללא צורך לסובב מערכת שלמה זה מספק אסטרטגיות כדי לכתוב, כך טוב יותר, כך, כך, כך שמתרגלים שיטות פעולה, כדי לתאר את זה יכול להיות מסוגל לשלב שיטות פעולה.
הבנת העקרונות של SOLID
על ידי רוברט C. Martin (Uncle Bob) בתחילת שנות ה -2000, ראשי התיבות של SOLID מסכמת חמישה עקרונות עיצוב שמטרתם ליצור מערכות שקל לשמור ולהרחיב לאורך זמן.כל עיקרון מתייחס לסוג מסוים של קשיחות או שבריריות שלעתים קרובות מדביקות פרויקטים של תוכנה. בואו נבחן כל אחד בהקשר של פיתוח מונחה.
עקרון אחריות יחיד (SRP)
(FLT:0SRPGFLT:1) קובע כי שיעור צריך רק סיבה אחת לשנות.בפרקטיקה, זה אומר שמעמד צריך לבודד פונקציונליות אחת או כלל עסקי.כאשר שיעור עושה יותר מדי דברים, זה הופך קשה לבודד התנהגות אחת במהלך הבדיקה. לדוגמה, לשקול שיעור כי שניהם קורא תצורה ומעבדים מבחנים.
מנקודת מבט של TDD, SRP הוא בעל ברית טבעי.כאשר אתה כותב מבחן ראשון, אתה נאלץ לחשוב על התנהגות אחת - "מה צריך המערכת לעשות בתרחיש זעיר זה?", מיקוד התנהגותי תואם עם SRP.כפי שאתה צובר בדיקות, אתה תבחין כאשר שיעור מתחיל לקחת על עצמו מספר רב של אחריות: הבדיקות שלך להתנהגות אחת יתחילו להתקין עבור התנהגויות לא קשורות.
Open/Closed Principle (OCP)
(FLT:0)OCPigFLT:1 טוען כי ישויות תוכנה צריכות להיות פתוחות להרחבה אך סגורות לשינוי.המטרה היא להוסיף תכונות חדשות ללא שינוי קוד קיים, נבדק.בפרקטיקה, זה מושג באמצעות אבסטרקטיונים - ממשקים או כיתות מופשטות המגדירים חוזה, בעוד יישום קונקרטי ניתן להחליף או להוסיף.
TDD ו- OCP הם חיזוק הדדי. כי TDD דורש חבילה של בדיקות חולפות, אתה מאוד מוטיבציה להימנע שינוי הבדיקות האלה או הקוד שהם מכסים. כאשר אתה צריך גרסה חדשה של התנהגות (למשל, שער תשלום חדש), אתה יכול להציג יישום חדש של ממשק ללא נגיעה במעבדי התשלום הקיימים.זה מקטין את הסיכון ושומר על חבילת ההחלמה שלך ירוק, בניגוד לניסוי חדש, לעתים קרובות, כי הוא מוביל לבדיקות הפעלה חדשה של CP כדי לשבור את הבדיקה, כי הוא לעתים קרובות, כי הוא מנסה לפרק את הבדיקה.
Liskov Substitution Principle (LSP)
(ב) נאמר כי יש להחליף את סוגי הבסיס שלהם מבלי לשנות את נכונות התכנית.במילים אחרות, אם לקוח מצפה ל-FLT:0 אובייקט, עובר צדי בסיס ללא שינוי של תיקון התכנית.
TDD יכול לחשוף הפרות LSP מוקדם.כאשר אתה כותב מבחן המשתמש ממשק או מחלקה מופשטת, אתה מקבל הנחה על החוזה.אם יישום שונה של ממשק זה גורם המבחן להיכשל גם כאשר הבדיקה נכונה, העיצוב עשוי להפר את LSP. טוב TDD פועל כוחות אתה להגדיר חוזים ברורים מראש, אשר באופן טבעי מתאים עם LSP.
Interface Segregation Principle (ISP)
(FLT:0)ISPIRLT:1 ממליץ כי אין צורך בלקוח להיות תלוי בשיטות זה לא משתמש ממשקי שומן - ממשקים המכילים שיטות רבות שאינן קשורות - ליצור הפיכה מיותרת.כאשר מבחן דורש שיעור המיישם ממשק כזה, עליך להזיז או ללעג שיטות רבות למרות שהמבחן משתמש רק כמה.
על ידי כתיבת בדיקות קטנות, כפייתות, אתה באופן טבעי משיכה לממשקים ספציפיים לתפקיד, לדוגמה, במקום מונותי FLT:4 ממשק עם FLT:5, FLT:6, ; ⁇ 7, ו-FLT:8, ו- FLT:8, אתה יכול לחלק אותו לתוך FLT:9, ו- LT:11 כל מבחן יכול להיות ממוקד יותר, רק על ידי לעג, לעשות את זה רק לעג, לעשות את זה, לעשות את זה רק לעג, לעשות את זה רק לעג, לעשות את זה רק לעג, לעשות את זה רק לעג, לעשות את זה רק לעג, לעשות את זה יכול להיות לעג, לעשות לעג, לעשות את זה רק לעג, לעשות את זה רק לעג, לעשות את זה רק לעג.
הסתברות להורדת Principle (DIP)
(ב) אומר ה-FLT:0.DIPIRLT:1; כלומר, תלוי בפשטות, לא בקונפיגורציות.מודולים ברמה גבוהה לא צריכים לייבא מודולים ברמה נמוכה; שניהם צריכים להיות תלויים בממשקים.זהו אבן הפינה של המבחנים.כאשר ההיגיון העסקי תלוי ישירות ב-FLT:12, בדיקות כי לוגיקה בבידוד הופכת לבלתי אפשרית ללא מסד נתונים אמיתי.
אלוף TDD DIP כי בדיקות הן הלקוחות הראשונים של הקוד שלך.כאשר אתה כותב מבחן לפני יישום בכיתה, אתה באופן טבעי עיצוב ממשק כי הבדיקה תצרכו.הממשק הופך להיות הפשטות.המימוש קונקרטי נכתב מאוחר יותר, ואתה יכול להחליף אותו ללא מאמץ.זה הפוך של אדריכלות באמצעות בדיקות הוא אחד הדרכים החזקות ביותר להשגת DIP.
מה זה Test-Driven Development?
התפתחות Test-Driven אינה רק "מבחן ראשון" היא תרגול ממושמע, אשר עוקב אחר לולאה משוב הדוק:0 אדום, ירוק, מספק: 1.
- [01:0] RedveFLT:1]: כתוב מבחן כושל המגדיר התנהגות רצויה.המבחן צריך להיות ספציפי ככל האפשר (למשל, "משתמש ללא מנויים צריך לראות את לוח המחוונים ברירת המחדל").
- [01:0] ירוק: כתוב את כמות מינימלית של קוד הייצור כדי להפוך את המבחן לעבור.
- (FLT:0)RefactorveFLT:1; לנקות את קוד הבדיקה והייצור תוך הבטחת כל הבדיקות נשאר ירוק.
מחזור זה חוזר על עשרות פעמים ביום.כל מחזור מייצר קצבה זעירה של פונקציונליות נבדקת.היתרונות מתועדות היטב: פחות באגים, כיסוי רגרסיה טוב יותר, זמן ניתוק מופחת, ועיצוב שעולה מדפוסי שימוש אמיתיים ולא ספקולציות על פי FLT:0 Martin Fowler מאמר על TDDFLT:1, הפרקטיקה גם מעודד "קוד של ראי" פועל ישירות של מטרות רזולוציה.
הסינרגיה בין SOLID ו-TDD
הצומת של SOLID ו-TDD הוא המקום שבו עיצוב אדריכלי פוגש אימות.כל עיקרון מגבר על היבט אחר של חוויית ה- TDD. להלן אנו בודקים את מערכות היחסים האלה בפירוט עם דוגמאות קונקרטיות.
שיפור יכולת באמצעות SRP ו- DIP
(המבחן הוא ככל הנראה הסגולה הגדולה ביותר שבסיס קוד יכול להיות בעל יכולת תחזוקה.SRP מבטיח שלכל מחלקה יש מיקוד צר, מה שהופך את הבדיקות שלה קצרות וקלות להבנה.DIP מבטיח כי שיעורים אלה יכולים להיות מחוסנים מתשתית (בסיסים נתונים, שירותי אינטרנט, מערכות קבצים מופשטים יחד, הם מאפשרים לך לכתוב בדיקות לרוץ באופן מיידי ולא מתפתל.
OCP ו-TDD's Refactoring Safety Net
אחת מנקודות המכירה העיקריות של TDD היא שהיא מעניקה לך את האומץ לספק מחדש.חבילת הבדיקה פועלת כרשת בטיחות. OCP בונה על זה על ידי צמצום הצורך לשנות קוד קיים בעת הוספת תכונות חדשות.כאשר אתה עוקב אחר OCP, אתה בדרך כלל להוסיף תת-קבוצות חדשות או plugins במקום לערוך בדיקות ליבה. כי אלה כבר נבדקו ביסודיות, הסיכון של רגרסיה הוא נמוך וניתן להבטיח את ה- TDD החדש עם שינויים אלה לא ניתן לבדוק את המשתנים, ולא לשנות את המשתנים שלמים.
LSP ו- ISP בעיצוב מבחן
לעיתים קרובות, בדיקות כתיבה מכריחות אותך לחשוב על חוזים וממשקים.LSP מזכיר לך שמבחן שנכתב נגד מעמד בסיס או ממשק צריך לעבור עבור כל יישום בתוקף.אם אתה מוצא כי מבחן נכשל כאשר פועל נגד תת-קבוצה מסוימת, חשפה הפרת LSP - וזה הפיכה של דבר טוב, ISP מעודד אותך לעצב, תפקיד קטן, ספציפי, כאשר אתה כותב מבחן עבור רכיב עבור רכיב של 16 צריך רק כדי להפחית את ההגדרה המלאה של נתונים.
דוגמה מעשית: בניית שירות Notification
תארו לעצמכם שאתם מחויבים בבניית מערכת הודעה שיכולה לשלוח הודעות באמצעות דואר אלקטרוני, SMS ודחוף.מפתח פחות מנוסה עשוי ליצור שיעור מונוליטי FLT:17 עם שיטה כמו FLT 18 המשתמש תיק מתג כדי להחליט כיצד לספק.בדיקה זה יהיה כואב - ללעג שלושה מנגנוני אספקה שונים במבחן אחד, וכל שינוי בתבנית דואר אלקטרוני ישפיע על כל הבדיקות.
על ידי יישום SOLID לצד TDD:
- [01:0] , [ה]: שיעור ה-FLT:19 [השורה] רק מתזמר לשלוח.כל ערוץ משלוח (דואר אלקטרוני, SMS, דחיפה) חי בכיתה שלו עם אחריות אחת.
- (ב) [ה]: [ה], [ה], [ה], [ה], [ה],] [ה'], [ה']], [ה']'[ה']']'[ה']'[ה']'[ה']'[ה']']'[ה']']'[ה']']'[ה'[ה']']']'[ה'[ה']'[ה'[ה']'[ה'[ה']'[ה'[ה'[ה']']']'[ה'[ה'[ה'[ה']']']']'[ה']']'[ה'[ה']'[ה']']']']']'[ה'[ה']']'[ה'[ה']'[ה']']']'[ה']']']'[ה'[ה'[ה']']'[ה']']'[ה'[ה'[ה'[ה'[ה
- (ב) ,0) ,LSPIRLT:1: כל יישום ממשק 22 החלפה מנקודת המבט של ה-FLT:23.
- (ב) [ה]: [ה], [ה], [ה], [ה], [ה],] הממשק כולל רק שיטות רלוונטיות להגשת הודעה – אין שיטות לא רלוונטיות כמו FLT:24 או FLT:25.
- (ב) ,0) ,DIPIRLT:1: The FLT:26 תלוי בהפשטה של ה-FLT:27, לא על כיתות ערוץ קונקרטיות.
עם TDD, אתה מתחיל על ידי כתיבת מבחן עבור ה-FLT:28 - מבחן פשוט כי אימות דוא"ל הוא "שגרת" (אולי באמצעות מרגל) ולאחר מכן אתה כותב מספיק קוד כדי לעשות את זה לעבור את המבחן הבא, אתה בודק את שיעור ה-FLT:29 עם ערוץ לעג. כי העיצוב דבק SOLID, כל בדיקה הוא מבודד ומהיר יותר, וכתוצאה מכך, ייצור גמיש וניתן לשמור על קשר.
טיפים מעשיים לאינטגרציה
אימוץ הן SOLID והן TDD בו זמנית יכול להרגיש מכריע בהתחלה.אסטרטגיות קונקרטיות הבאות יעזרו לך לבנות את ההרגל.
- (FLT:0)Start with a SingleמודולFLT:1: בחר תכונה קטנה, המכילה עצמי (כמו שירות ההודעות לעיל) לכתוב את הבדיקות שלו קודם.כפי שאתה מיישמת, לכפות את עצמך ליישם SRP ו- DIP. הבדיקות באופן טבעי להנחות את העיצוב שלך.
- (FLT:0) מבחן מבחן כמטרה עיצובית של SOLID1; לאחר כתיבת מבחן שמרגיש מביך - אולי כי זה דורש יותר מדי התקנה או לעג - לשאול את עצמך איזה עיקרון SOLID הוא לעתים קרובות התשובה היא DIP (תלויה קונקרטית) או ISP (ממשק שומן).
- (FLT:0) כלי הזרקת התלות של הזרקת התלות בשקיקה במהלך בדיקות ibph:1: עבור בדיקות יחידה, מעדיף זריקה ידנית או מסגרות לעג פשוטות.זה שומר בדיקות מפורשות ומחזק חשיבה SOLID.כפי שאתה קנה מידה, לשקול שימוש במיכל קל לבדיקות אינטגרציה, אבל תמיד לשמור על בדיקות יחידה מבודדות.
- (FLT:0) מספק לאחר כל מבחן ירוק 1R: הצעד "הספק" של TDD הוא הזמן המושלם לשיפור הדבקות ב-SOLID.לדוגמה, אם שיעור גדל שתי אחריות, לחלץ מעמד חדש (SRP) אם מבחן תלוי בשיטות רבות מממשק, פיצול ממשק זה (ISP).
- (FLT:0) Introduce קוד ביקורות עם SOLID ChecklistlistlistlistsFLT:1: ביקורות אוויר עם TDD על ידי חברי צוות לבדוק כי כל חבילת בדיקה חדשה מכסה רכיבים חד-צדדיים בודדים.
לקריאה נוספת, (FLT:0) המאמר המקורי של רוברט מרטין על עקרונות SOLID SOLID 1 הוא עדיין אחד ההפניות הטובות ביותר.עבור צלילה עמוקה יותר לתוך TDD,FLT:2Kent Beck's Test-Driven Development byדוגמהFLT 3: נשאר העבודה הנשנית.
מלכודות נפוצות להימנע
אפילו מפתחים מנוסים יכולים ליפול למלכודת כאשר משלבים את שתי המתודולוגיות הללו.להיות מודע למכשולים אלה ישמור אתכם זמן.
- (FLT:0) בדיקות כי הם קוארסלמבייט 1: מבחן יחיד שמשתלב בזרימת עבודה שלמה (למשל, "login and Create a order) מפר את SRP למבחנים.Break It into Small, מבודדים שממקדים התנהגויות אינדיבידואליות.זה הופך את זה לקל יותר לשמור על עיצוב SOLID.
- (הדגשה:0) נוקבת כל דבר מה-FLT:1: בעוד שלעגים הם הכרחיים עבור DIP, over-mocking יכול להסתיר פגמים בעיצוב.If you need to לעג חמישה ממשקים שונים כדי לבדוק מחלקה אחת, שיעור זה עשוי להיות תלוי יותר מדי דברים - סימן להפרת SOLID.
- (ב) [ה]ההבאת [ה]: [ה] [ה] [ה]] [ה]] [ה]]][ה]] [ה][ה]]]][ה]]]] [התחילות ה-[[המאה ה-20], ומבחנים שלך הופכים לאדריכלות מבולעתית.
- (FLT:0) הגדלת בתחילת ה-FLT:1: מתחילים לפעמים מנסים ליישם את כל חמשת עקרונות SOLID לפני כתיבת קו הייצור הראשון.זה לא איך TDD עובד. תן למבחנים לחשוף את הצורך בהפשטות.התחל עם יישום פשוט ולהציג ממשקים כאשר הכאב הופך גבוה מדי.
מסקנה: תרבות של איכות
הסינרגיה בין עקרונות SOLID ופיתוח Test-Driven אינה מקרית. שתי הפילוסופיות חולקות שורש משותף: הרצון לכתוב קוד מובן, משתנה, ותיקון. SOLID מספק את ההנחיות המבניות - "איך" של עיצוב טוב.TDD מספק משוב התנהגותי - "מה" של פונקציונליות נכונה. כאשר הם מייצרים קצב פיתוח שהוא קושח עצמי - עושה בדיקות LINSOL: הופך את ה-DD למעבדהות פשוטות לאימון טבעי.
צוותים אשר מאמצים את שניהם לעתים קרובות מדווחים על צמצום משמעותי במחזורי האגרה ויכולת גדולה יותר להגיב לדרישות משתנות.ההשקעה העליונה בלמידה לכתוב בדיקות ראשון ועיצוב עם SOLID בראש משולם פעמים רבות על החוב הטכני מופחת.כפי שאמר דוד בוב עצמו ב-FLT שלו:0article על מחזורי TDDFreaplerated:1LT, "פעולת כתיבת מבחן עושה לך חשיבה על קוד זה, עיצוב מחדש של מערכת יחסים.