לדלג לתוכן

עקרונות SOLID מוסברים בפשטות - בלי הבלבול

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

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

S - עיקרון האחריות היחידה

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

הפתרון פשוט - תפצלו את זה. User מנהל נתוני משתמש, EmailService שולח מיילים, TaxCalculator מחשב מסים. כל אחד עומד בפני עצמו, וכשמשהו נשבר אתם יודעים בדיוק איפה לחפש.

O - עיקרון הפתיחות והסגירות

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

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

L - עיקרון ההחלפה של ליסקוב

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

הדוגמה הידועה היא ציפור שלא יכולה לעוף. אם Ostrich (יען) יורשת מ-Bird ול-Bird יש מתודה fly, ואתם צריכים לזרוק שגיאה בתוך fly של היען כי היא לא באמת יכולה לעוף - שברתם את העיקרון. מישהו שמשתמש ב-Bird באופן כללי יקבל הפתעה לא נעימה. הפתרון הוא לתכנן היררכיה שמשקפת התנהגות אמיתית, לא רק דמיון מושגי.

I - עיקרון הפרדת הממשקים

עדיף כמה ממשקים קטנים וממוקדים מממשק אחד ענק. אם יש לכם ממשק Worker עם מתודות work ו-eat, וגם רובוט צריך לממש אותו - רובוט לא אוכל, אז הוא ייאלץ לממש מתודה שלא שייכת אליו בכלל.

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

D - עיקרון היפוך התלויות

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

בפועל זה אומר שאם קלאס OrderService שלכם עובד ישירות מול MySQLDatabase, כל שינוי במסד הנתונים ישבור אתכם, ואי אפשר לבדוק את השירות בלי מסד נתונים אמיתי. הפתרון הוא לעבוד מול ממשק כמו Database, ורק אז להזריק את המימוש הספציפי - MySQL, Postgres, או מסד נתונים מדומה לבדיקות.

אז זה חוקים או המלצות?

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

השאלה הנכונה היא תמיד - האם השינוי הזה עוזר לי לשנות קוד בעתיד בלי כאב, או שהוא רק מוסיף שכבות בירוקרטיה? אם התשובה היא השנייה, תוותרו.

איך לומדים את זה ברמת עומק אמיתית

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

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

לסיכום

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