מה זה?

ה-Task Manager API שנבנה לאורך הקורס — Controllers, Services, Repositories — כולו רץ כתהליך אחד, נפרס יחד. זה מונוליט (Monolith): אפליקציה אחת שלמה. עובד מצוין בהתחלה — עד שהצוות גדל, חלקים שונים צריכים להתעדכן בקצב שונה, וכל שינוי קטן דורש לבנות ולפרוס הכל מחדש. מיקרוסרביסים פותרים את זה, אבל לא בקפיצה אחת — Strangler Fig הוא הדפוס לפירוק הדרגתי.

מילות מפתח שחשוב לזכור

• Monolith — אפליקציה שלמה אחת, נפרסת ורצה כיחידה אחת, גם אם מאורגנת פנימית בשכבות (Controller/Service/Repository)

• Microservices — פירוק לשירותים עצמאיים קטנים, כל אחד נפרס ומתעדכן בנפרד

• Strangler Fig Pattern — פירוק הדרגתי של מונוליט: פונקציונליות חדשה נבנית כשירות נפרד, ישן מהגר בהדרגה, בלי “big bang rewrite”

• Coupling (צימוד) — כמה חלקים תלויים זה בזה; מונוליט לרוב צימוד גבוה בין מודולים פנימיים

  flowchart TB
    subgraph Monolith["Monolith — everything together"]
        C1["Tasks Controller"] --> S1["Task Service"]
        C2["Users Controller"] --> S2["User Service"]
        S1 --> DB[("Single DB")]
        S2 --> DB
    end
  flowchart TB
    subgraph Micro["Microservices — separate and independent"]
        TS["Task Service<br/>(deployed separately)"] --> TDB[("Task DB")]
        US["User Service<br/>(deployed separately)"] --> UDB[("User DB")]
        TS <-.->|"network communication"| US
    end

הסבר עיקרי

מונוליט לא “רע” — הוא ברירת המחדל הנכונה להתחלה — כל הפרויקטים לאורך הקורס עד כה היו מונוליטים, ובצדק: פיתוח, בדיקה ופריסה של מערכת אחת פשוטים בהרבה מניהול כמה שירותים נפרדים. הבעיה מתחילה כשהצוות/המערכת גדלים — שינוי קטן ב-Users דורש לבנות ולפרוס מחדש גם את Tasks, Orders וכל השאר, גם אם הם לא השתנו כלל.

Strangler Fig — למה לא לפרק הכל בבת אחת — “Big Bang Rewrite” (עצירת כל הפיתוח, פירוק מלא, ואז המשך) הוא מסוכן ויקר — לוקח חודשים, בלי ערך עסקי חדש בינתיים, וסיכון גבוה לשבור דברים. Strangler Fig פותר את זה: בונים פונקציונליות חדשה כשירות נפרד מההתחלה; פונקציונליות קיימת מפורקת בהדרגה, מודול אחד בכל פעם, כשיש לכך הצדקה עסקית — המונוליט “מצטמצם” בהדרגה בעוד המערכת ממשיכה לעבוד לאורך כל התהליך.

Coupling הוא הסימפטום שמסמן מתי לשקול פירוק — לא “יש לנו הרבה קוד” אלא “מודול A ומודול B כל כך תלויים זה בזה ששינוי באחד תמיד שובר את השני”. אם TaskService ו-UserService (בתוך אותו מונוליט) כמעט אף פעם לא “נוגעים” זה בזה, הם כבר מועמדים טבעיים לפיצול לשירותים נפרדים — הצימוד הפנימי כבר נמוך.

יתרונות

מונוליט: פיתוח ופריסה פשוטים, עסקאות (Transactions) עקביות בקלות בין מודולים, ניפוי שגיאות (Debugging) ישיר בתוך תהליך אחד. מיקרוסרביסים: כל שירות נפרס ומתעדכן עצמאית, צוותים שונים עובדים במקביל בלי להתנגש, כשל בשירות אחד לא בהכרח מפיל את כולם.

חסרונות

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

נקודות חשובות

• מונוליט הוא ברירת מחדל טובה להתחלה — לא “טעות” שצריך לתקן תמיד

• Strangler Fig מפרק בהדרגה, לא בבת אחת — פונקציונליות חדשה כשירות, ישנה מהגרת לפי הצדקה

• Coupling גבוה בין מודולים הוא הסימן לשקול פירוק, לא “כמות קוד” בפני עצמה

• מיקרוסרביסים פותרים בעיית ארגון/קנה-מידה, לא בעיה טכנית מובנית מאליה בכל פרויקט

טעויות נפוצות

• לפרק לפי מיקרוסרביסים “כי זה מודרני”, בלי בעיה אמיתית של קנה-מידה/צוות שמצדיקה זאת

• לנסות Big Bang Rewrite במקום Strangler Fig — סיכון גבוה מיותר

• להתעלם מ-Coupling פנימי לפני פירוק — שירותים שנחתכו לאורך “קו תפר” שגוי נשארים תלויים זה בזה דרך הרשת, גרוע יותר מבתוך אותו תהליך

סיכום

מונוליט הוא אפליקציה שלמה אחת, נפרסת יחד — ברירת מחדל מצוינת להתחלה. מיקרוסרביסים מפרקים למערכות עצמאיות, פותרים בעיות של קנה-מידה וצוותים גדולים, במחיר מורכבות תפעולית. Strangler Fig הוא דפוס הפירוק המומלץ — הדרגתי, לפי הצדקה עסקית, לא Big Bang Rewrite מסוכן. Coupling נמוך בין מודולים הוא הסימן שמערכת “מוכנה” לפירוק בקו התפר הנכון.

דוקומנטציה רשמית

Martin Fowler — Strangler Fig Application


תרגילים

תרגיל 1 — זיהוי Coupling

המשימה: קחו את ה-Task Manager API (מהפרויקטים המסכמים) וסמנו אילו מודולים (Tasks/Users/וכו’) כמעט לא “נוגעים” זה בזה, לעומת אילו תלויים זה בזה הדוקות.

בדיקה: רשימה עם נימוק לכל מודול — האם הוא מועמד טוב לפיצול, ולמה.

תרגיל 2 — תכנון Strangler Fig

המשימה: תכננו (בכתב, בלי קוד) תוכנית פירוק הדרגתית של מודול אחד מתוך ה-API הקיים לשירות נפרד, בשלושה שלבים.

בדיקה: התוכנית מראה איך המערכת ממשיכה לעבוד בכל שלב, לא רק “לפני” ו"אחרי".


פרויקט מסכם

המשימה: כתבו ניתוח קצר (מסמך) על מונוליט קיים (יכול להיות Task Manager API מהקורס) — מתי (אם בכלל) הגיוני לפרק אותו למיקרוסרביסים.

דרישות:

  1. זיהוי לפחות 2 “קווי תפר” טבעיים (מודולים בעלי Coupling נמוך ביניהם)
  2. נימוק עסקי — למה כדאי/לא כדאי לפרק כרגע (גודל צוות, קצב שינויים, עומס)
  3. תוכנית Strangler Fig בת 3 שלבים לפחות לאחד הקווים שזוהו

בדיקה: הניתוח מבוסס על Coupling אמיתי בקוד, לא רק “מודולים שנשמעים נפרדים”; תוכנית הפירוק הדרגתית ולא Big Bang.

מה בפרק הבא

בפרק הבא — Bounded Context: איך מחליטים בדיוק איפה לחתוך — עקרונות DDD בסיסיים לפירוק לפי יכולת עסקית, לא לפי טבלת DB או שכבה טכנית.