הזרקת התלות ב- MVC

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

מאמר זה חוקר כיצד הזרקת התלות משתלבת עם מסגרות MVC כדי ליצור מערכות מתועלות באופן רופף.We להגדיר DI ואת שלושת צורות ההזרקה העיקריות שלה, לדון בתפקיד של Inversion of Control (IoC) כדי ליצור מערכות מתועשות באופן רופף ב-ASP.NET Core, Spring MVC, ול-Laarvel, לבחון דפוסים מתקדמים כגון מעצבי משנה וניהול חיים, ולסיים עם הטוב ביותר כי למנוע התנגשויות נפוצות כדי להתאים את הקוד שלך באופן מיידי ל-Mientatives.

מה זה שטף תלות?

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

public class UserController {
 private SqlUserRepository repository = new SqlUserRepository();
 // ...
}

גישה זו היא זוגות הבקר ישירות ליישום קונקרטי.אם אתה צריך לעבור לחנות נתונים אחרת, להוסיף כניסה, או ליישם שכבת צ'נג, עליך לשנות את הבקר.עם DI, הבקר מצהיר על התלויות שלו באמצעות בונהו (או סטטר), ומרכיב חיצוני - לעתים קרובות נקרא מיכל IoC - מספק את המופעים קונקרטיים:

public class UserController {
 private final UserRepository repository;
 public UserController(UserRepository repository) {
 this.repository = repository;
 }
 // ...
}

עכשיו הבקר תלוי רק בממשק ה-FLT:2 או בכיתה מופשטת.ניתן להחליף את היישום בפועל מבלי לגעת בקר.עקרון זה הוא ביטוי של העיוות הרחב יותר של שליטה (IoC) הפילוסופיה, שבו המסגרת שולטת על זרימת היישום ואת מחזורי החיים של אובייקטים, ולא אובייקטים השולטים באמינותם.

סוגים של פיזור תלות

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

הזרקת בנייה

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

public class OrderController {
 private readonly IOrderService _orderService;
 public OrderController(IOrderService orderService) {
 _orderService = orderService;
 }
}

המונחים: Property

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

public class NotificationController {
 public ILogger Logger { get; set; }
 // Default logger if none injected
 public NotificationController() {
 Logger = new NullLogger();
 }
}

מיפוי Interface

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

public interface IEmailServiceAware {
 void SetEmailService(IEmailService service);
}
public class AccountController : Controller, IEmailServiceAware {
 private IEmailService _emailService;
 public void SetEmailService(IEmailService service) {
 _emailService = service;
 }
}

התפקיד של Inversion of Control Containers

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

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

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

  • (ב) ,0) ,התמדה: 1 (ב) ,הדוגמה חדשה נוצרת בכל פעם שהיא מתבקשת.
  • (ב) ,0) ,Scoped:FLT:1; מקרה אחד נוצר לפי בקשה (או לכל היקף) בשימוש בהקשרים של מסד נתונים או דפוסים של יחידות.
  • (ב) [15] ,ב"ד: "ב"ד: "ב"א," (ב)"ב"ה, "הראשונה" (ב"ב) היא אחת מכולן.

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

היתרונות של הזרקת התלות ב- MVC

החלת DI בתוך יישום MVC הופכת את בסיס הקוד במספר דרכים מדידה:

  • (FLT:0)Loose Coupling::FLT:1 Controller ושירותים תלויים בהפשטות, לא שיעורים קונקרטיים.הההפצה הזו מאפשרת להחליף את כל תת-מערכות - החלפת מסד נתונים יחסי עם חנות NoSQL, או מעבר ממגרש מבוסס קובץ לשירות אחסון בענן - ללא נגיעה בהגיון המשתמש בהן.
  • (ב) [15] , ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇
  • (FLT:0) ניתן להוסיף את הגמישות:FLT:1 תכונות חדשות או חששות חתכים (הקגרד, אימות, חסימה) כמעצבים על ממשקים קיימים מבלי לשנות את המעמדות המקוריים.זה תואם את העיקרון הפתוח / הסגור - כיתות פתוחות להרחבה, סגורות לשינוי.
  • (FLT:0) שמירה על עצמה:FLT:1 כאשר תלות משתנה (למשל, שדרוג ספריה משנה API), אתה רק צריך לעדכן את הרישום ואת היישום קונקרטי.
  • (FLT:0) ,השוואה של חששות: ההרחבה 1 (DI) מאחסן גבול נקי בין יצירת אובייקטים לבין לוגיקה עסקית.מפקחים מתמקדים בטיפול בבקשות HTTP ובתגובה חוזרת, בעוד שרזולוציה תלותית מטופלת על ידי המכולה, לעתים קרובות ב"שורש ייצוג" מרכזי (בדרך כלל שיעור הסטארט-אפ).

יישום DI במסגרות MVC שונות

למרות שהרעיון של DI הוא שפה-אגנוסטית, כל מסגרת MVC חושפת את מיכלה ואת המוסכמות שלה. להלן הן דוגמאות קונקרטיות משלוש מערכות אקולוגיות פופולריות.

ASP.NET Core (C#)

ASP.NET Core יש מיכל DI מובנה אשר מוגדר בקובץ ההרחבה 8.שירותים רשומים בתוך אוסף 9 של FPLT, ובקרים מקבלים באופן אוטומטי תלות באמצעות הזרקת בנייה.

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Register services
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
builder.Services.AddTransient<IEmailService, SmtpEmailService>();
builder.Services.AddSingleton<ILogger, ConsoleLogger>();

builder.Services.AddControllersWithViews();

var app = builder.Build();
// ... middleware configuration
app.Run();

בבקר, אתה פשוט מצהיר על התלות:

public class OrderController : Controller {
 private readonly IOrderRepository _repository;
 private readonly IEmailService _emailService;
 public OrderController(IOrderRepository repository, IEmailService emailService) {
 _repository = repository;
 _emailService = emailService;
 }
 public IActionResult Index() {
 var orders = _repository.GetAll();
 return View(orders);
 }
}

מיכל ASP.NET Core תומך גם ברישום מפורש של גנרים פתוחים, שיטות במפעל, ומתכננים. עבור תלות אופציונלית, ניתן להשתמש דפוס ה-FLT:12 או זריקת סטטר עם ה-FLT:13 תכונת.

Spring MVC (Java)

מיכל IoC של האביב הוא אחד ממסגרות DI בוגר ביותר.ב יישום MVC האביב, אתה לא מזין רכיבים עם סטריאוטיפים (ראה FLT:14, FLT:15:15, 15, 16) וניתן לאביב לסרוק את התלויים בכיתה מוזרקים באמצעות הזרקת בנייה (עדיף) או זריקת שדה.

@Controller
public class ProductController {
 private final ProductService productService;
 // Constructor injection – Spring automatically wires the ProductService
 public ProductController(ProductService productService) {
 this.productService = productService;
 }
 @GetMapping("/products")
 public String listProducts(Model model) {
 model.addAttribute("products", productService.findAll());
 return "productList";
 }
}

קונפדרציה מתבצעת בדרך כלל באמצעות אנטנות Java או XML.Bean יקיעות (Singleton, אבטיפוס, בקשה, ישיבה) מפורטות עם ה-FLT 18). אנטרציה מספקת גם תכונות מתקדמות כמו הזרקת שיטה, מעבורת מחזור חיים, ושילוב AOP, אשר ניתן לשלב עם DI כדי ליישם חששות ממושכים כגון ניהול עסקה או אבטחה.

Laravel (PHP)

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

// In a ServiceProvider's register() method
$this->app->bind(PaymentGatewayInterface::class, StripeGateway::class);
$this->app->singleton(LoggerInterface::class, FileLogger::class);

בבקר, אתה מקליד את התלות בבונים או בשיטה.הכלי של לארהvel פותר אותו באופן אוטומטי:

class InvoiceController extends Controller {
 protected $paymentGateway;
 public function __construct(PaymentGatewayInterface $paymentGateway) {
 $this->paymentGateway = $paymentGateway;
 }
 public function pay(Invoice $invoice) {
 $this->paymentGateway->charge($invoice);
 // ...
 }
}

Laravel גם תומך הזרקת אוטומטי בשיטות בקר (באמצעות החלטת שיטת המכל) ומספק חזיתות שפועלות כפרוקסיות למקרים מאוישים מכולה.

DI תבניות מתקדמות עבור MVC

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

תבנית דקורטיבית

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

services.AddScoped<IProductRepository, ProductRepository>();
services.Decorate<IProductRepository, CachedProductRepository>();

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

אפשרות / AOP

כמה מכולות, במיוחד Castleוינדזור (ASP.NET) ו- Spring AOP, מאפשרות לך ליירט שיטות על שירותים רשומים. Interceptors יכול ליישם את הביצועים, ניטור, בדיקות אישור, או טיפול עסקאות ללא לוגיקה עסקית. Interception הוא צורה של תכנות מונחה-פן (AOP) שעובדת יד ביד עם DI.

חיים שלמים ודיסקואליים

הבנה כאשר חפצים נוצרים והושמדה היא חיונית.לדוגמה, ההקשר מסד נתונים (ראה FLT:23 ב-Entity Framework) צריך להיות מושווה לפי בקשה.אם הוא רשום כטון, בקשות מרובות מקבילות עשויות לחלוק את אותו ההקשר, המוביל לשחיתות או לנתוני stale.converse, רישום transient עבור שירות כבד עשוי ליצור מקרים רבים מדי ופוגע בביצועים תמיד להתאים את החיים של הטבע של תלות.

כמו כן, ודא כי מיכל להיפטר כראוי של אובייקטים אשר ליישם את ה-FLT:24 באופן אוטומטי [רוב המכולות] להיפטר מקרים קבועים ו transient בסוף הבקשה, אבל באופן ידני פתרון אובייקטים מן המכולה מחוץ לניהול שלה יכול להוביל לדלפות. a מדריך משותף: לעולם לא לפתור ישירות מתוך קוד יישום בתוך יישום; במקום זאת, להשתמש הזרקת בנייה כך מיכל שולט במחזור החיים.

מלכודות נפוצות וכיצד להימנע מהם

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

  • (ה)השירות ל-Lcator Anti-Pattern:BuildFLT:1) באמצעות מאתר שירות סטטי (למשל, FLT:25) מסתיר תלותיות ועושה בדיקה קשה.במקום, להסתמך על הזרקת בנין לאורך בסיס הקוד.
  • (ב) [ה]בהמשך: [ה]: [ה] [ה] [ה] [ה]] [הקור] דורש יותר משלושה או ארבעה טיעונים מבניים או ארבעה טיעונים עשויים להפר את עיקרון האחריות הבודד (SRP) אם הבקר עושה יותר מדי.
  • (ב) [ה]ה']: [ה] [ה] [ה]] [ה]] [ה]], [ה]], [ה], [ה], [ה]]], [ה]], [ה]], [ה], [ה]], [ה], [ה]]], [ה]]], [ה]]], [ה], [ה]]], [ה]], [ה]]]]]]]]], [ה], [ה], [ה]], [ה], [ה], [ה], [ה], [ה]]], [ה]]]]]]]]]]]]]], [ה]]]], [ה], [ה]]]]]], [ה], [ה], [ה], [ה], [ה], [ה], [ה]], [ה]], [ה], [ה]]]]]]]]]]]]]]]]], [ה]]]], [ה]
  • (ב) ,0) אבחון כל החיים: FLT:1 כפי שהוזכר קודם לכן, חיי חיים לא טובים יכולים לגרום באגים מטבעיים עדינים.תמיד לבדוק את תיעוד של מיכל שלך כדי להבין את חיי ברירת המחדל וכיצד להגדיר אותם כראוי.
  • (FLT:0) השימוש בזריקת נכסים:IRLT:1) הזרקת נכסים לעתים קרובות מוביל אובייקטים שרק הם ראשוניים חלקית, אשר יכול לגרום למעטים התייחסות אפס בזמן ריצה.

שיטות טובות לזריקת תלות ב- MVC

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

  • (ב) [15] ,ההסבר לממשקים (ב"ב) ,ב"הבא"ר: "הבא" (ב) ,"החלים" (ב"ב) ,"ה) ,"התחילו על ידי הממשקים" (התחילה) באופן עצמאי.
  • (ב) ⁇ :0) , שמורים על מבנים פשוטים (FLT:1) 1 A constructor צריך רק להקצות תלויים בתחומים פרטיים.אין לבצע כל עבודה שיכולה להיכשל, כפי שניתן לפתור את האובייקט במהלך ההרכב.
  • (ב) כל רישום המיכל צריך לקרות במקום אחד - בדרך כלל שיעור הסטארט-אפ של היישום (FLT:27, FLT:28, או ספק שירות ב- Laravel) להפיץ רישומים על פני בסיס הקוד הופך את האדריכלות ל-PT.
  • (ב) ⁇ (ב) ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇
  • (ב) עיין:0) זרקה של טיהור מבניין (Prefer constructorturesFLT:1 for Dutyתלויים בזריקת סטטר (Supter הזרקת ריצוף) ותיעוד כי יש לקרוא לפני שיטות מסוימות.
  • (FLT:0) להיות מפורש על חיי החיים.FLT:1ir שירותים עם ההיקף המתאים ביותר כדי לאזן ביצועים ובטיחות.כאשר ספק, להתחיל עם היקף ורק לקדם ל-oneton לאחר אימות בטיחות חוט.
  • (FLT:0) מיכלי משנה תכונות בחוכמה.FLT:1 השתמש מעצבנים, מפעלים, וירוטורים שבהם הם מפשטים את החששות החצוצרות.אל תשתמש בהם יתר על המידה – אם התצורה הופכת מורכבת מדי, לשקול מחדש את העיצוב.

מסקנה

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

בין אם אתה משתמש ב-ASP.NET Core, Spring MVC או Laravel, העקרונות נשארים זהים: מופשט מאחורי ממשקים, מזרקת מבחוץ, ולשמור את ההרכב ממורכז.התחל על ידי מתן בקר אחד לשימוש הזרקת בניה, ולאחר מכן מציג בהדרגה מיכל IoC עבור היישום כולו. ההשקעה משלמת בחזרה פחות באגים, מחזורי פיתוח מהירים יותר, וקוד כי הוא מקבל בברכה במקום לשנות את זה.

(בקריאה נוספת, חקרו את התיעוד הרשמי של מיכל DI של המסגרת, או להתייעץ עם משאבים קלאסיים כגון המאמר של מרטין Fowler על FLT:0) ,ההסתה של מברשות הבקרה ואת דפוס הזרקת התלות FLT:1 , מדריכי DI הרשמי עבור FLT:2ASP.NET CoreFLT 3, LT:4 ו-ICLT5 דוגמאות יותר מפורטות ו-FLT.