Table of Contents
עיצוב מערכות בלתי צפויות באמצעות החלפת Liskov
בניית מערכות נשגבות נותרה אתגר מתמשך בהנדסת תוכנה. as הדרישות להתפתח, היכולת להוסיף התנהגויות חדשות ללא כתיבת קוד קיים מפרידה ארכיטקטורות שמירה על מבנים מקודרים.הליסקוקוב החלפת Principle (LSP) מספקת בסיס קפדני להשגת מטרה זו על ידי הגדרת כללים מדויקים להתנהגות תת-סוג.כאשר ליישם נכון, LSP מבטיח כי רכיבים חדשים יכולים להיות מוצגים עם ביטחון, תיקון של תכונות אחרות, כדי ליצור מותאמות אישית, עיצוב.
הבנת ההשתתפות של Liskov
ברברה ליסקוב הציגה את העיקרון הנושא את שמה במאמר של כנס משנת 1987 שכותרתו "תיאור נתונים והירארכיה" (Data Modelion and Hierarchy) "ההגדרה הרשמית קובעת: FLT:0" אם לכל אובייקט מסוג S יש אובייקט או 2 מסוג T כזה, כי עבור כל התוכניות המיוצרות באופן שווה בהתאם ל-T, התנהגותו של P היא ללא שינוי כאשר O1 מוחלפת עבור 2, אז Stype של סוג של אובייקט בעל מעמד פשוט יותר מורכב מרמה של מטרה אחת, אם הוא בעל שיעור עבודה של סוג 1 של סוג של מטרה, אם הוא בעל בסיס קבוע, כלומר, כלומר, אם הוא בעל שיעור עבודה לא צפוי, אם הוא בעל שיעור עבודה לא צפוי, אם הוא בעל שיעור עבודה לא צפוי, אם הוא בעל שיעור עבודה, אם הוא בעל שיעור אחד, ללא שינוי של סוג 1 של סוג של סוג של סוג של סוג של סוג 1 של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של סוג של מטרה, אם הוא בעל שיעור עבודה, אם הוא בעל בסיס קבוע, אם הוא בעל שיעור זה חייב להיות בעל שיעור עבודה, אם הוא חייב להיות בעל שיעור אחד של סוג 1 של סוג 1 של סוג 1
העיקרון משתרע מעבר לחתימות שיטה פשוטות.LSP דורש תאימות התנהגותית: תת-המעמד חייב לא רק להיות אותה שיטות אלא גם לכבד את הנחות שקוד הלקוח עושה על מעמד הבסיס.זה כולל תנאים מוקדמים (מה צריך להיות אמיתי לפני שתקרא שיטה), תנאי דואר (מה צריך להיות נכון לאחר), ו invariants (תנאים שעדיין קבועים לאורך כל תקופת חייו של האובייקט).
(ב) אם אתה טוען כי מערכת יחסים "ה-א" (ה) היא מערכת יחסים "ה-א" (ה) אם אתה טוען כי (ה-FLT:0) היא מערכת יחסים של 1 (ה) היא מערכת יחסים של 1 (ה) אם אתה טוען כי אין שינוי עם השוויון הקלאסי הוא הבעיה של כפל-ה-המס, כאשר ה-F:4 מאריך את ה-FLT:5, אם לא ניתן ל-F).
ארבעת התנאים העיקריים של LSP
כדי להבטיח תאימות תת-סוג התנהגותית, LSP כופת ארבעה תנאים ספציפיים אשר תת-classes חייב לספק. תנאים אלה, נגזר מן העיקרון של עיצוב על ידי חוזים, לספק רשימת בדיקה להערכת היררכיות בכיתה.
תנאים מוקדמים לא ניתן לחזק
תנאי מקדים הוא תנאי שחייב להחזיק לפני שיטה מופעלת, אם שיטת מעמד הבסיס מאפשרת פרמטר פרמטר (FLT:8) להיות כל integer, תת-קבוצה המגבילה את FLT:9 לפולשים חיוביים מחזקת את ה-Preconconence. Customer Code שנכתב נגד מעמד הבסיס עשוי לעבור אינטגרטור שלילי ולצפות שהוא עובד, אבל תת-המחלקה תדחה אותו.
תנאים לא ניתן להחלש
תנאי דואר מגדירים את השיטה מבטיחה לאחר ביצוע.אם שיטת הבסיס מבטיחה ערך החזרה לא-נול, תת-קבוצה שלפעמים מחזירה את אפס מחלישה את תנאי הדואר. לקוחות שתלויים בחוזה המעמדי הבסיס לא יכשלו עם יוצא דופן של נקודות קצה.
יש לשמר את
השחלות הן תנאים שנותרו נכונים לכל החיים של האובייקט.לדוגמה, ל-FLT:10 יש את השחלות כי אלמנטים הם תמיד הורה.אם תת-קבוצה מפרה את זה (למשל, על ידי הוספת אלמנט מתוך סדר), זה שובר את הציפיות של התוכנית.
ההיסטוריה מעצירת
לאובייקטים יש היסטוריה של שינויים ממלכתיים.ההיסטוריה מדגישה כי תת-מעמד לא צריכה לאפשר שינויים המדינה כי מעמד הבסיס אוסר עליהם.לדוגמה, אם למחלקה בסיסית של 11 אין שיטות מסובכות, תת-קבוצה שמוסיפה סטטר מפרה LSP כי קוד הלקוח עלול להניח חוסר יכולת.
מדוע LSP הוא קריטי עבור יכולת
יכולת הרחבה מסתמכת על היכולת להוסיף רכיבים חדשים מבלי לשנות את הלקוחות הקיימים.כאשר LSP הוא מכובד, פולימורפיזם עובד כמתוכנן. תת-קבוצה חדשה יכולה להיות מחוברת קוד ישן עם אפס שינויים.זה מקטין את הסיכון התוקפנות ומהירויות של התפתחות.ללא LSP, מעמד הבסיס הופך לשברירי.מפתחים חייבים לבדוק כל תת-קבוצה כדי להבין התנהגות מיוחדת, המוביל לתחזוקה מוגברת ופוטנציאל באגים מוגבר.
(ה) יש לקחת בחשבון את השיטה (ה-FLT) של ⁇ (ה-) ,(ה-) ,(ה-) ,(ה-) , ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇
LSP גם מעודד עיצוב על ידי חוזה, אשר משפר תיעוד ותקשורת צוות.מפתחים יכולים להסתמך על מפרט מעמד הבסיס ללא קריאה כל יישום תת-כיתה.זה חשוב במיוחד בבסיסי קוד גדולים עם תורמים רבים.בנוסף, LSP תומך במערכת על ידי מתן אפשרות רכיבים להחליף את הביצועים או תכונות ללא שינוי האדריכלות הכוללת.
הפרות נפוצות של LSP וכיצד להימנע מהם
זיהוי הפרות LSP הוא חיוני לכתיבת מערכות שמירה. להלן הם דפוסים תכופים המפרקים את העיקרון, יחד עם אסטרטגיות לתקן אותם.
בעיית Rectangle-Square
כאמור, מודל ריבוע כמעמד תת-מעמד של מלבן מפר את LSP כי רוחב הריצוף וגובה להיות שווה. עיצוב טוב יותר הוא להפוך את המעמדות המלבניים והריבועיים השונים שמילאים ממשק משותף (FLT:17), או להשתמש בשיטה במפעל אשר מחזירה אובייקטים מתאימים.
« « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « « «
אם שיטת הבסיס אינה מכריזה על חריגות, שיטה תת-כית שזרקה יוצאת דופן נבדקה מפרה LSP.גם לזרוק יוצא דופן לא נבדק כמו FLT 18) יכול להפתיע את הלקוחות אם שיעור הבסיס מעולם לא עשה זאת. סובייקטים צריכים לזרוק רק יוצאים מן הכלל שמעמד הבסיס מאפשר, או אף אחד בכלל לא בדק חריגים, ולתעד התנהגות יוצאת דופן בחוזה.
המונחים: override Returns Weaker type
בשפות כמו Java ו- C#, ניתן להחזיר סוגים של החזרת מפרקים (שיטה תת-כיתה עשויה להחזיר סוג מסוים יותר) עם זאת, ההפך הוא לא: החזרת סוג חלש או פחות ספציפי שובר את החוזה.לדוגמה, אם שיעור הבסיס חוזר ל-FLT:19, תת-קבוצה מחזירה FLT:20 מפרה את LSP.
צוללות מבטלות את ההתנהגות
לפעמים תת-מחלקה מעצימה שיטה עם גוף ריק, ביעילות הסרת פונקציונליות.אם הלקוח מסתמך על שיטה זו שיש לה השפעה, ההתנהגות משתנה.לדוגמה, AFLT:21 אשר מרחיבה את ה- mtable FLT:22 ו-Overrides (FLT:23) כדי לא לעשות שום דבר שובר את החוזה של מעמד הבסיס.
חיזוק תנאי קדם
(הופנה מהדף שיטות סודיות לקבל פרמטרים אופציונליים, אם מעמד הבסיס מקבל (FLT:24 עבור פרמטר, תת-מעמד שזרק יוצא דופן על FLT:25) יוצר הפרה תנאי מראש.
כדי להימנע מהפרתיות, להתחיל עם ממשקים המגדירים התנהגויות מינימליות וממוקדות.הרכב Favor על הירושה כאשר מערכת היחסים "is-a" ניתנת להשאלה. לכתוב בדיקות חוזה שמאמתות הן את הבסיס והן את התנהגות תת-מעמדית, ולנהל אותן באינטגרציה רציפה.
שימוש ב-LSP בעיצוב מערכת
תכנון ל-LSP דורש מחשבה מכוונת הן אדריכלות והן יישום.כאן הן הנחיות מעשיות לשלב את זרימת העבודה לפיתוח שלך.
שימוש בהסכמים מופשטים
Define בסיס שיעורים או ממשקים המבטאים את ההתנהגות הצפויה ללא יישום.כולל תיעוד של תנאים מוקדמים, תנאי דואר, ו invariants. בשפות שמתמכות בעיצוב על ידי חוזים (כמו אייפל), אתה יכול לאכוף את אלה באופן חוזי ברוב השפות המרכזיות, להסתמך על תיעוד ובדיקות יחידה.
תוספת של Inheritance
כאשר הקשר בין שני שיעורים אינו "אי-א" בלבד, השתמש בהרכב.לדוגמה, במקום ההרחבה של ה-FLT:27 המשתרעת על ידי ה-FLT:28, יש שיעור סקייפ המכיל FLT:30 עם ממדים שווים.
תגית: contract Tests
יצירת חבילת מבחן עבור מעמד הבסיס כי כל תת-השכבות חייבות לעבור.מבחנים אלה צריכים לאמת כי תנאים מוקדמים, תנאי דואר, ו- invariants להחזיק.לדוגמה, מבחן עבור FLT:31 עשוי לאמת את הערך המוחזר חיובי עבור ממדים מסוימים.כל תת-מחלקה חייבת לעבור את אותם בדיקות כדי להבטיח תאימות LSP.טכניקה זו, הנקראת לעתים קרובות "מבחן החלפה", תופס הפרות מוקדמות.
שימוש ב-Competation
כאשר יורשים, חישבו על ההיבט ההתנהגותי קודם לכן, שאלו: "אם אני מחליפה מקרה של מעמד הבסיס עם תת-קבוצה זו, האם הלקוחות יבחינו בכל הבדל בהתנהגות?", אם התשובה היא כן, עיצבו מחדש את הירושה.
פיצויים כאשר נמצאו
במהלך ביקורות קוד או לאחר כשלי מבחן, לספק את ההיררכיה.לנצל התנהגות משותפת למחלקה או ממשק בסיס מופשט, ודוחף התנהגות מיוחדת בכיתות נפרדות.
שפות תכנות מודרניות
הדרך ל-LSP חלה על שפות שונות בשל הבדלים במערכות הקלדה, מודלים של ירושה, וטיפול יוצא דופן.
ג'אווה ו-C#
שתי השפות תומך ממשקים ושיעורים מופשטים. השתמש בממשקים עבור חוזים מופשטים ולהבטיח כי יישום שיעורים לספק את כל התנאים.הפרות LSP שהוזכרו קודם לכן (מלבד נחלש, חיזוק תנאי מוקדם) נפוצים ב- Java ו- C# השתמש ב- C. השתמש ב-Aunation ב- Java או מילת המפתח FLT:33 ב- C# כדי למנוע חתימות מקריות.
סוגScript
מערכת הטיפציה המבנית של TypeScript הופכת את LSP אפילו יותר קריטית.מכיוון שהתאמה מסוג מבוססת על מבנה ולא על היררכיה נומינלית, שיעור שיש לו את אותה השיטות אבל התנהגות שונה עשויה להיות מיושמת באופן סינקטי אך לא התנהגותי.מפתחים חייבים לאכוף את LSP באופן ידני על ידי כתיבת בדיקות ותיעוד חוזים.
Python
Python הוא דינאמי, כלומר הפרות LSP רק להיות גלוי בזמן ריצה.ללא בדיקות מפרש, לכתוב בדיקות יחידה חזקות ולהשתמש מעמדות בסיס מופשט (ABC) מן מודול FLT:34 כדי להגדיר שיטות נדרשות.
Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go
Go משתמש בממשקים באופן בלתי נמנע.סוג מספק ממשק אם הוא מיישם את כל השיטות.LSP ב Go הוא מאוכפיף על ידי העובדה כי ממשקים הם קטנים וממוקדים.עדיין, להיות זהירים: אם שני סוגים לספק את אותו ממשק אבל להתנהג אחרת, קוד הלקוח מצפה שהחוזה ייכשל.
עקרונות SOLID אחרים
LSP אינו קיים בבידוד.הוא אינטראקציה עם ארבעת העקרונות האחרים של SOLID בדרכים חשובות.
עקרון אחריות יחיד (SRP)
SRP עוזר לשמור על מעמדות ממוקדים, אשר מפחית את הסיכויים להפרה LSP. מחלקה עם אחריות אחת קל יותר תת-סוג ללא שינוי התנהגות. לדוגמה, הפרדת לוגיקה אימות מאחסון נתונים הופכת את הבסיס ואת תת-מעמד פשוט יותר.
Open/Closed Principle (OCP)
OCP קובע כי שיעורים צריכים להיות פתוחים להרחבה אך סגורים לשינוי.LSP מאפשר ל-OCP על ידי מתן מעמדות להרחיב את ההתנהגות מבלי לשנות קוד קיים.אם LSP הוא מופרת, אין באפשרותך להוסיף בבטחה תת-מעמדות חדשות ללא שינוי לקוחות, ובכך לשבור את OCP.
Interface Segregation Principle (ISP)
ISP מעודד ממשקי שומן להיות שבור לתוך קטן, ספציפי.זה מקטין את הסבירות כי תת-קבוצה חייבת ליישם שיטות שאינן רלוונטיות, אשר לעתים קרובות מוביל להפרות LSP (למשל, ריק או זריקת יישומים).
הסתברות להורדת Principle (DIP)
DIP ממליץ בהתאם לפשטות, לא קונפירציות.כאשר אתה תלוי בממשקים, LSP מבטיח כי כל יישום קונקרטי ניתן להחליף בחופשיות.ללא LSP, שכבת ההפשטה הופכת לא ראויה, ומפתחים עשויים להיות תלויים ביישום ישירות, מפר DIP.
בדיקות עבור LSP Compliance
בדיקת LSP אינה תמיד פשוטה.עם זאת, מתודולוגיות בדיקה שיטתיות יכולות לעזור לתפוס הפרות מוקדם.כאן אסטרטגיות לשלב בדיקות LSP לתוך זרימת העבודה שלך.
יצירת מחלקה של חוזים בסיס
כתוב כיתת מבחן מופשטת או חבילת מבחן המתפעלת את החוזה המעמדי של כל תנאי מקדים ותנאי דואר, לכתוב מבחן.לדוגמה, אם שיטת ה-FLT:35 הבסיסית על FLT:36 זורקת יוצא דופן כאשר הערימה ריקה, כולל מבחן התואם כי אז, עבור כל תת-כיתה, להפעיל את אותם הבדיקות אם כל תת-קבוצה נכשלת, מפר את LSP.
שימוש ב-Destin Based
כלים כמו QuickCheck (עבור Haskell, זמינים גם בשפות אחרות באמצעות ספריות כמו LT:37 או FLT:38) לייצר קלטות אקראיות ולוודא כי invariants להחזיק. for LSP, אתה יכול לבטא תכונות כגון: "עבור כל רצף תקף של שיחות שיטה, המדינה לאחר קריאה שיטה על תת-כיתת משנה תואם את התנהגות מעמד הבסיס."
אכיפה פנימית
כמה שפות מאפשרות טיעוני ריצה ב- Java, ניתן להשתמש במילת המפתח (FLT:39 או בספריה כמו LT:40 ).
דוגמאות אמיתיות ל-LSP בפעולה
ספריות ומסגרות סטנדרטיות רבות מסתמכות על LSP כדי לתפקד כראוי.הבנת הדוגמאות האלה מעמיקת הערכה לעיקרון.
Java Collections Framework
[ה]הממשק [ה] מתאר התנהגות של אוספים ורושמים, כמו , ו-'CopyOnWriteArrayList', כולם דבקים בחוזה הממשק, הם תומכים ב-FLT:46,FLT:47, FLT:48 וכו ', עם ה-Silmantics, אם חדש LTF:49 מפר את יישום (לא ניתן ל-F).
מסד נתונים Access Layers
כאשר יישום מאגר נתונים, ממשק בסיס LT:52 מגדיר שיטות כמו FLT:53 ו-FLT:54 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
המונחים:
בתכנות פונקציונליות, שינויים על זרמים (כמו מפה, סינון, צמצום) מוגדרים על ידי חוזים.כל פונקציה שעברה ל-FLT:55 חייב להיות טרנספורמציה טהורה שמירה על השחלות של הזרם (למשל, לא שינוי מצב חיצוני).זה LSP החל לתפקד: הפונקציה מגדירה חוזה, ומימושים חייב לספק אותו.
מסקנה
ה- Liskov Substitution Principle הוא יותר מאשר מושג תיאורטי – זהו כלי מעשי לתכנון תוכנה בלתי צפויה, שמירה על עצמה. על ידי הבטחת ש subclasses יכול לעמוד בשיעורי הבסיס שלהם מבלי לשנות התנהגות נכונה, מפתחים בונים מערכות שגדלות באופן אורגני עם תכונות חדשות. Adhering to LSP מפחית אינטגרציה, משפר את הבהירות הקוד, ומתאים עם הפילוסופיה הרחבה יותר.
כדי ליישם את LSP ביעילות, להתמקד חוזים התנהגותיים, לכתוב בדיקות מקיפים ולהשתמש בהרכב כאשר ירושה מרגישה מאולצת.להכרה בארבעת התנאים - תנאים מוקדמים, תנאי דואר, שחלופים, ומגבלות היסטוריה - כמו בדיקות לכל תת-קבוצה חדשה.עם דיאליגנס, LSP הופך לחלק טבעי של תהליך העיצוב שלך, המוביל לאדריכלות כי הם גמישים והתאמה.
(ב) לקריאה נוספת, חקרו את המאמר המקורי של ברברה ליסקוב (FLT:0) דיסאינפורמציה אבסטרקציה וה Hierarchyof 1:1), רוברט C. Martin:2discussion of SOLID Principles of SOLIDעקרונות FLT 3, ו- Martin FLT:4 של מרטין על תת-titsutabilityFLT:5 משאבים אלה מספקים תובנות עמוקות יותר לתוכנה מעשית.