# מערך שיעור: SOLID — LSP, ISP ו-DIP📋 מערך מרצה

משך: 2 שעות אקדמיות (90 דקות).

מטרת השיעור: הסטודנטים ישלימו את חמשת עקרונות SOLID, ויבינו את הבסיס הרעיוני ל-Dependency Injection שיפגשו ביחידת ASP.NET Core.

בסוף השיעור הסטודנטים צריכים: לזהות הפרת LSP בהיררכיית ירושה, לפצל ממשק "שמן" לפי ISP, ולכתוב מחלקה שתלויה ב-Interface במקום במימוש קונקרטי (DIP).

דגש קריטי: הזכירו במפורש בסוף השיעור ש-DIP הוא בדיוק העיקרון שעומד מאחורי Dependency Injection — יחידת ASP.NET Core הבאה תשתמש בו בפועל דרך ה-Framework.

---

## מהלך השיעור

| חלק בשיעור | משך | הערות ודגשים |
| --- | --- | --- |
| פתיחה וחיבור | 5 דקות | הזכירו את דילמת Square:Rectangle מיחידת הירושה |
| הרעיון: LSP | 20 דקות | הדגימו את ההפתעה בפועל (Width משנה Height) |
| הבעיה: ממשק שמן | 10 דקות | IWorker עם Eat() שרובוט מוכרח "לזייף" |
| הרעיון: ISP | 15 דקות | פיצול ל-IWorkable/IEatable |
| הבעיה: תלות ישירה במימוש | 10 דקות | OrderService עם new EmailNotifier() בפנים — קשה להחליף |
| הרעיון: DIP | 20 דקות | הזרקת INotifier דרך קונסטרוקטור |
| תרגול מודרך | 10 דקות | תרגיל 1+2 |

---

## דגשים להעברת השיעור

- LSP קשה יותר להפנמה משאר העקרונות כי ההפרה "מתקמפלת" בסדר גמור — חשוב **להריץ** את הדוגמה בפועל ולא רק לתאר אותה, כדי שהסטודנטים יראו את ההפתעה בעיניים.
- קשרו DIP במפורש קדימה ל-ASP.NET Core ("`services.AddScoped<IRepository, SqlRepository>()` שתראו בקרוב זה בדיוק DIP בפעולה") — נותן לעיקרון עוגן קונקרטי בעתיד הקרוב של הקורס.
- ISP קליל יחסית להעברה — מספיק דוגמה אחת טובה (IWorker) בלי להכביד.

---

## מושגים

**LSP** — מחלקה יורשת חייבת להתנהג נכון במקום הבסיס.
**ISP** — עדיף כמה ממשקים ממוקדים על ממשק "שמן" אחד.
**DIP** — תלות בהפשטה (Interface), לא במימוש קונקרטי.

---

## תרגיל חשיבה

**שאלת פתיחה:** "יש לכם `CheckoutService` שיוצר `new CreditCardGateway()` בתוכו. עכשיו רוצים לבדוק אותו (Unit Test) בלי לחייב כרטיס אשראי אמיתי בכל הרצת בדיקה. איך תעשו את זה?"

**מהלך:** תנו לסטודנטים לחשוב על הבעיה לפני שמציגים DIP — התשובה האינטואיטיבית ("פשוט תשנו את הקוד בזמן בדיקה") היא בדיוק מה ש-DIP פותר בצורה נקייה: אם `CheckoutService` תלוי ב-`IPaymentGateway` (הפשטה) במקום ב-`CreditCardGateway` הספציפי, אפשר "להזריק" `MockPaymentGateway` רק בבדיקות, בלי לגעת בקוד המקורי כלל.

**מה המרצה מראה בסוף:** הריצו את אותו `CheckoutService` פעמיים — פעם עם `CreditCardGateway` אמיתי (מדפיס "מחייב כרטיס") ופעם עם `MockPaymentGateway` (מדפיס "תשלום מדומה הצליח") — בלי לשנות אף שורה בתוך `CheckoutService` בין ההרצות.
