Inversion of control
בהנדסת תוכנה, היפוך שליטה (באנגלית: Inversion of control; בראשי תיבות: IoC) היא תבנית עיצוב בתכנות מונחה-עצמים שבמסגרתה צימוד (coupling) האובייקטים מבוצע בזמן ריצה על ידי אובייקט הרכבה (assembler object), ובדרך כלל אינו ידוע מראש בזמן ההידור באמצעות ניתוח קוד סטטי.
בתכנות מסורתי, בקרת הזרימה של הלוגיקה העסקית נקבעת על ידי אובייקטים שמוקצים סטטית אחד אל השני. לעומת זאת, כאשר עובדים עם היפוך שליטה, הזרימה תלויה בגרף האובייקטים שנוצר על ידי אובייקט ההרכבה, והיא מתאפשרת על ידי הגדרת האינטראקציות בין האובייקטים באמצעות אבסטרקציות. תהליך הקישור בין אובייקטים מושג באמצעות הזרקת תלויות (dependency injection). יש הטוענים כי ניתן להשיג היפוך שליטה גם על ידי שימוש בתבנית העיצוב service locator.
על מנת שאובייקט ההרכבה יקשור אובייקטים אחד אל השני, לאובייקטים חייבות להיות קיימות אבסטרקציות מתאימות. לדוגמה, מחלקה A
יכולה להאציל (delegate) את הפונקציונליות שלה לממשק מסוים I
. כלומר המחלקה A
הופכת להיות תלויה במחלקה אחרת כלשהי שתממש את הממשק I
ותספק לה את הפונקציונליות המוגדרת על ידי ממשק זה. מחלקות B
ו-C
יכולות לממש את הממשק I
, כל אחת בצורה שונה; אובייקט ההרכבה יוצר מופע של A
ושל אחת מהמחלקות B
או C
, בהתאם ללוגיקה בזמן הריצה או בהתאם להגדרה בקובץ קונפיגורציה, ואז "מזריק" את B
(או את C
) ל-A
, ובכך מספק לה את הפונקציונליות הנדרשת. (להסברים ודוגמאות מפורטים יותר, ראו: הזרקת תלויות).
למעשה, היפוך שליטה הוא סגנון של עיצוב תוכנה שבו קוד הניתן לשימוש חוזר שולט בביצוע של קוד המיועד לפתרון של בעיות ספציפיות. המשמעות היא שהקוד שניתן לשימוש חוזר והקוד המיועד לפתרון של בעיה ספציפית מפותחים בנפרד, ולבסוף מאוחדים לקבלת יישום אחד כולל, המשלב את חלקי הקוד השונים.
שימוש בעקרונות העיצוב של היפוך שליטה משרת את המטרות הבאות:
- משיגים הסרת צימוד (decoupling) בין הביצוע של משימה מסוימת מהמימוש שלה.
- כל מודול יכול להתרכז במשימה שעבורה הוא תוכנן.
- מודולים שונים אינם מתבססים על הנחות לגבי מה מערכות אחרות עושות, אלא מסתמכים על ה"חוזים" שלהן (ראו: Design by contract).
- החלפת מודולים אינה גוררת תופעות לוואי במודולים אחרים.
לעיתים מתייחסים בהומור להיפוך שליטה כאל עיקרון הוליווד: "אל תתקשר אלינו, אנחנו נתקשר אליך", בגלל שהלוגיקה של התוכנה רצה כנגד אבסטרקציות כדוגמת פונקציות callback.
טכניקות מימוש
טכניקות מימוש מושפעות משפת התכנות הנבחרת. ב-Java ישנן כמה טכניקות בסיסיות למימוש היפוך שליטה:
- שימוש בתבנית העיצוב Factory method
- שימוש בתבנית העיצוב Service locator
- שימוש ב-dependency injection, לדוגמה:
- הזרקה דרך ה-constructor
- הזרקה דרך פונקציית (set (setter
- הזרקת ממשק
- שימוש ב- contextualized lookup
דוגמאות
public class ServerFacade {
public <K, V> V respondToRequest(K request) {
if (businessLayer.validateRequest(request)) {
DAO.getData(request);
return Aspect.convertData(request);
}
return null;
}
}
מתווה בסיסי זה ב-Java מדגים קוד הפועל על פי מתודולוגיית היפוך השליטה. עם זאת, חשוב לשים לב לכך ש-ServerFacade
מתבסס על הרבה הנחות אודות הנתונים המוחזרים על ידי ה-Data Access Object) DAO). אף על פי שייתכן כי הנחות אלה הן תקינות בזמן מסוים, הן יוצרות צימוד בין המימוש של ServerFacade
למימוש של DAO
. תכנון היישום בצורה של היפוך שליטה יעביר לגמרי את השליטה לאובייקט ה-DAO
. נקבל את הקוד הבא:
public class ServerFacade {
public <K, V> V respondToRequest(K request, DAO dao) {
return dao.getData(request);
}
}
דוגמה זו ממחישה את העובדה שהצורה בה המתודה respondToRequest
מתוכננת קובעת האם יהיה שימוש בהיפוך שליטה. הצורה שבה משתמשים בפרמטרים מגדירה את היפוך השליטה. דבר זה דומה לסגנון העברת המסרים שמשמש בכמה שפות תכנות מונחות עצמים.
ממשקי תכנות יישומים המשתמשים בהיפוך שליטה
SAX הוא דוגמה לממשק תכנות יישומים (API) אשר משתמש בהיפוך שליטה בכל מקום (לאחר אתחול). באופן כללי SAX יעיל יותר מ-DOM, אבל לעיתים קרובות DOM נחשב לנוח יותר לתכנות בגלל שהוא לא מחייב שימוש בהיפוך שליטה.
ראו גם
קישורים חיצוניים
הסבר על Ioc - הבלוג של רון קליין
32770607Inversion of control