מדריך מוצק לעקרונות SOLID

1. הקדמה

במדריך זה נדון את עקרונות ה- SOLID של עיצוב מונחה עצמים.

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

2. הסיבה לעקרונות SOLID

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

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

חמשת המושגים הבאים מרכיבים את עקרונות ה- SOLID שלנו:

  1. סאחריות
  2. אועט / סגור
  3. להחלפת איסקוב
  4. אניהפרדה בין פנים
  5. דהתהפכות אפנדנטית

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

3. אחריות יחידה

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

כיצד עיקרון זה עוזר לנו לבנות תוכנה טובה יותר? בואו נראה כמה מהיתרונות שלה:

  1. בדיקה - בכיתה עם אחריות אחת יהיו הרבה פחות מקרי מבחן
  2. צימוד תחתון - פחות פונקציונליות בכיתה אחת יהיו פחות תלותיות
  3. אִרגוּן - קל יותר לחפש שיעורים קטנים ומאורגנים יותר מאשר שיעורים מונוליטיים

קח, למשל, שיעור שייצג ספר פשוט:

ספר בכיתה ציבורית {פרטי מחרוזת שם; סופר מחרוזת פרטי; טקסט מחרוזת פרטי; // בונה, גטרים וקובעים}

בקוד זה אנו שומרים את השם, המחבר והטקסט המשויכים למופע של a סֵפֶר.

בואו כעת הוסף כמה שיטות לשאילתת הטקסט:

ספר בכיתה ציבורית {פרטי מחרוזת שם; סופר מחרוזת פרטי; טקסט מחרוזת פרטי; // constructor, getters and setter // שיטות המתייחסות ישירות למאפייני הספר public String להחליף WordInText (String word) {return text.replaceAll (word, text); } בוליאני ציבורי isWordInText (מחרוזת) {return text.contains (word); }}

עכשיו, שלנו סֵפֶר הכיתה עובדת היטב ואנחנו יכולים לאחסן כמה ספרים שנרצה ביישום שלנו. אבל, מה מועיל לאחסן המידע אם איננו יכולים להעביר את הטקסט למסוף ולקרוא אותו?

בואו נזרוק את הרוח ונוסיף שיטת הדפסה:

ספר בכיתה ציבורית {// ... void printTextToConsole () {// הקוד שלנו לעיצוב והדפסת הטקסט}}

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

מחלקה ציבורית BookPrinter {// שיטות להפקת טקסט בטל printTextToConsole (טקסט מחרוזת) {// הקוד שלנו לעיצוב והדפסת הטקסט} בטל printTextToAnotherMedium (טקסט מחרוזת) {// קוד לכתיבה לכל מקום אחר ..}}

מדהים. לא רק שפיתחנו כיתה המקלה על סֵפֶר מחובות ההדפסה שלה, אבל אנחנו יכולים גם למנף את המטלות שלנו BookPrinter בכיתה כדי לשלוח את הטקסט שלנו לתקשורת אחרת.

בין אם זה דוא"ל, רישום או כל דבר אחר, יש לנו שיעור נפרד המוקדש לדאגה אחת זו.

4. פתוח להארכה, סגור לשינוי

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

כמובן, ה יוצא מן הכלל אחד לכלל הוא בעת תיקון באגים בקוד קיים.

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

זה מלא ואפילו יש לו כפתור עוצמת קול:

גיטרה ממעמד ציבורי {פרטי מיתרים פרטיים; מודל מחרוזת פרטי; נפח אינטי פרטי; // קונסטרוקטורים, גטרים וקובעים}

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

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

במקום זאת, בואו להיצמד לעקרון הפתוח-פתוח ופשוט להאריך את שלנו גִיטָרָה מעמד:

מעמד ציבורי SuperCoolGuitarWithFlames מרחיב גיטרה {פרטי מחרוזת flameColor; // בונה, גטרים + סטרים}

על ידי הרחבת ה- גִיטָרָה בכיתה אנו יכולים להיות בטוחים כי היישום הקיים שלנו לא יושפע.

5. החלפת ליסקוב

הבא ברשימה שלנו הוא החלפת ליסקוב, שהיא ללא ספק המורכבת מבין 5 העקרונות. פשוט שים, אם בכיתה א הוא תת סוג של כיתה באז נוכל להחליף ב עם א מבלי לשבש את התנהגות התוכנית שלנו.

בואו נקפוץ ישר לקוד כדי לעזור לעטוף את הראש סביב הרעיון הזה:

ממשק ציבורי רכב {void turnOnEngine (); בטל להאיץ (); }

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

בואו ניישם את הממשק שלנו ונספק קצת קוד לשיטות:

יישומי MotorCar ברמה הציבורית {מנוע מנוע פרטי; // קונסטרוקטורים, גטרים + מגדירים פיטורים בטלניים TurnOnEngine () {// הפעל את המנוע! engine.on (); } חלל ציבורי מאיץ () {// קדימה! engine.powerOn (1000); }}

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

אנו חיים כעת בעידן המכוניות החשמליות:

מחלקה ציבורית ElectricCar מיישמת רכב {public void turnOnEngine () {זרוק AssertionError חדש ("אין לי מנוע!"); } חלל ציבורי מאיץ () {// האצה זו מטורפת! }}

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

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

6. הפרדת ממשק

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

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

נתחיל בממשק המתאר את תפקידינו כשומר דובים:

ממשק ציבורי BearKeeper {void washTheBear (); void feedTheBear (); בטל חיית המחמד (); }

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

בואו תקן זאת על ידי פיצול הממשק הגדול שלנו לשלושה נפרדים:

ממשק ציבורי BearCleaner {void washTheBear (); } ממשק ציבורי BearFeeder {void feedTheBear (); } ממשק ציבורי BearPetter {void petTheBear (); }

כעת, הודות להפרדת ממשק, אנו חופשיים ליישם רק את השיטות החשובות לנו:

מחלקה ציבורית BearCarer מיישמת את BearCleaner, BearFeeder {public void washTheBear () {// אני חושב שהחמצנו מקום ...} feed feed void publicTheBear () {// Tuna שלישי ...}}

ולבסוף, אנו יכולים להשאיר את הדברים המסוכנים לאנשים המטורפים:

המעמד הציבורי CrazyPerson מיישם את BearPetter {public void petTheBear () {// בהצלחה עם זה! }}

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

7. היפוך תלות

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

כדי להדגים זאת, בואו נלך לבית הספר הישן ונביא לחיים מחשב Windows 98 עם קוד:

מחלקה ציבורית Windows98Machine {}

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

מחלקה ציבורית Windows98Machine {מקלדת פרטית סופית סופית של מקלדת; צג צג סופי פרטי; Windows98Machine ציבורי () {צג = צג חדש (); מקלדת = מקלדת רגילה חדשה (); }}

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

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

בוא נתנתק את המכונה שלנו מה- מקלדת סטנדרטית על ידי הוספת כללי יותר מקלדת ממשק ושימוש בזה בכיתה שלנו:

מקלדת ממשק ציבורי {}
מחלקה ציבורית Windows98Machine {מקלדת מקלדת סופית פרטית; צג צג סופי פרטי; Windows98Machine ציבורי (מקלדת מקלדת, צג צג) {this.keyboard = מקלדת; this.monitor = צג; }}

כאן אנו משתמשים בדפוס הזרקת התלות כאן כדי להקל על הוספת ה- מקלדת תלות ב Windows98Machine מעמד.

בואו ונשתנה גם את שלנו מקלדת סטנדרטית בכיתה ליישם את מקלדת ממשק כך שהוא מתאים להזרקה לתוך Windows98Machine מעמד:

מחלקה ציבורית מיישמת מקלדת StandardKeyboard {}

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

מְעוּלֶה! ניתקנו את התלות ותוכלו לבדוק את התלות שלנו Windows98Machine עם מסגרת הבדיקה שנבחר.

8. מסקנה

במדריך זה לקחנו א לצלול עמוק לעקרונות ה- SOLID של עיצוב מונחה עצמים.

אָנוּ התחיל בקצת מהיר של היסטוריית SOLID והסיבות שעקרונות אלה קיימים.

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

כמו תמיד, הקוד זמין ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found