Kod Flexability'i geliştirmek için Mvc'de Bağlanma Enjeksiyonunu Uygulayın
MVC'de Bağlanma Enjeksiyonuna Giriş
Model-View-Controller (MVC) deseni, sürekli olarak geri kalan sınıflara dönüşmek için sürekli baskı ile karşı karşıya kalır ve mevcut işlevselliği ihlal eder. Doğrudan veri taban bağlantılarına bağlı olarak, hizmetler anında beton depolayıcılar oluşturur - kendi işbirlikçileri inşa eden katı mimariler yaratır, bu işbirlikçiler dışsal adımlara geçişler yapılır ve mevcut işlevselliği bozabilir.
Bu makale, MVC çerçeveleriyle, dekoratörler ve yaşam yönetimi gibi gelişmiş kalıpların oluşturulmasına ve ortak tuzakların önlenmesine yönelik en iyi uygulamaları inceleyeceğiz. Hedef sizi ASP.NET Core'da somut uygulamalarınızla dondurabilecek pratik bilgilerle dondurmak ve MVC kodbase'inizi değiştirmek için uygun hale getirmektir.
Bağımlılık Enjeksiyonu Nedir?
Bağlanma Enjeksiyonu, bir nesnenin onları içsel olarak yaratmak yerine dış kaynaklardan bağımlılıklarını aldığı bir tasarım modelidir. Geleneksel nesne odaklı kodda, bir kontrol, yapı veya yöntemi içinde belirli bir havuz sınıfı anlık olarak verebilir:
public class UserController {
private SqlUserRepository repository = new SqlUserRepository();
// ...
}
Bu yaklaşım çiftleri doğrudan beton bir uygulamaya yönlendirmektedir. Farklı bir veri mağazasına geçiş yapmanız gerekiyorsa, giriş yapın veya bir caching katmanı uygulayın, kontrol cihazını değiştirmeniz gerekir. DI, kontrolör kendi yapılayıcı (veya bir setter) ve bir dış bileşene bağlı olduğunu ilan eder - sık sık sık bir IoC konteyneri olarak adlandırılır: Beton örnekleri:
public class UserController {
private final UserRepository repository;
public UserController(UserRepository repository) {
this.repository = repository;
}
// ...
}
Şimdi kontrolör yalnızca uygulama ve yaşam döngüsünü kontrol eden nesnelere dokunmadan yenilebilir.Bu ilke, Kontrolün (IoC) felsefesinin daha geniş inversiyonunun bir ifadesidir.
Bağlanma Türleri
Bir sınıfa bağımlı olmanın üç yaygın yolu vardır. Her biri kullanım vakaları vardır, ancak kontraksiyon genellikle zorunlu bağımlılıklar için tercih edilir.
Yapıcı Enjeksiyon
Bağımlılıklar sınıf yapısı ile geçer. Bu, kontrol ve hizmetler için varsayılan model olarak yapılabilmesi için bağlıdır, nesnenin tam olarak başlangıçlı olmasını sağlar ve taklit edilebilirliği destekler. Çoğu modern çerçeveler kontrol ve hizmetler için varsayılan model olarak yapılamaya güvenir.
public class OrderController {
private readonly IOrderService _orderService;
public OrderController(IOrderService orderService) {
_orderService = orderService;
}
}
Setter / Emlak Enjeksiyonu
Bağımlılık, nesne inşa edildikten sonra kamu setleri veya özellikleri ile belirlenir. Bu model, varsayılan bir uygulamanın sağlanabileceği veya anından sonra bir bağımlılık yeniden yapılandırmanız gerektiğinde, ayarlanmamış herhangi bir şekilde kullanılmadığı takdirde, uygun olmayan işbirlikçiler için en iyi şekilde rezerve edilir.
public class NotificationController {
public ILogger Logger { get; set; }
// Default logger if none injected
public NotificationController() {
Logger = new NullLogger();
}
}
Interface Enjeksiyon
Sınıf, bir bağımlılık almak için bir yöntem tanımlayan bir arayüz uygular. IoC konteyneri, çalıştır zamanında bu yöntemin daha az yaygın olduğunu arar. Bu yaklaşım MVC çerçevelerinde daha az yaygındır, ancak birden çok bağımlılıkların eklentileri ile uyumlu bir şekilde enjekte edilmesi gerektiği bazı gelişmiş senaryolarda görünür.
public interface IEmailServiceAware {
void SetEmailService(IEmailService service);
}
public class AccountController : Controller, IEmailServiceAware {
private IEmailService _emailService;
public void SetEmailService(IEmailService service) {
_emailService = service;
}
}
Kontrol konteynerlerinin Inversiyonunun Rolü
Örneğin, bir fabrika veya basit bir hizmet taşıyıcısı kullanarak - üretim uygulamaları bir IoC konteynerinden faydalanır. Bir IoC konteyneri, Java'da kayıt yaptırmadan sorumlu bir kütüphanedir, bağımlılıkları yönetir ve nesne yaşamlarını yönetir.Bu yüzden geliştiricilerin bunları manuel olarak anlık nesnelere sahip olması ve katmanları aracılığıyla geçmesi gerekir.
Konteyner, ilk olarak bir soyutlamadan (yüzlü veya soyut sınıf) bir beton uygulama için bir harita kaydetti. Sonra, bir kontrol talep edildiğinde, konteyner denetimin yapılabilmesini denetim eder ve her bağımlılık için kayıtlı uygulamaları görünür ve bu uygulamaları başka bağımlılıkları tekrar çözer.
Konteynerler ayrıca nesnelerin ömrünü de yönetiyor - atmadan önce ne kadar uzun bir örnek hayatta tutuluyor. Üç en yaygın yaşam:
- [FONT:0)Transient:[Dönetici:[Dönetici:0) Yeni bir örnek her zaman talep edilir. hafif, devletsiz hizmetler için uygun.
- [FONT:0)Scoped:[Dönetici:[Dönetici:0) Tek bir örnek talep için (veya kapsama alanı) oluşturulur. Veritabanı bağlamları veya birim çalışma desenleri için kullanılır.
- [[Dönetici:0) Tekton:[Dönetici:[Dönetici:0) Tek bir örnek tüm uygulama boyunca paylaşılır.
Doğru yaşam seçimi, sabit hataları, sabit veriler veya istenmeyen kaynak paylaşımı gibi engeller.Incorrect yaşamları ayrıca hafıza sızıntılarına veya thread güvenli sorunlara neden olabilir, böylece her bir konteynerin semantikunu anlamak önemlidir.
MVC Architecture'da Bağlanmanın Faydaları
Bir MVC uygulaması içinde DI uygulamak, kodbase'i birkaç ölçülebilir şekilde dönüştürür:
- [FONT:0)Loose Coupling:[Döneticiler ve hizmetler soyutlamalara bağlı, beton sınıflara bağlı değildir. Bu decoupling, tüm alt sistemleri yerine getirmek için mümkün kılar - NoSQL mağazasıyla bir ilişkisel veritabanı takas eder veya bir bulut giriş servisine geçiş yapar - onları kullanan mantıka dokunmadan.
- [FONT:0) Geliştirilmiş Test edilebilirliği:[Dönetici:[Dönetici:0)[Dönetici:0)))) DI ile test edilen yanlış kurulum veya entegrasyon gerektirir, test paketinde ve test paketinde yavaşlayabilir ve testler laky.
- [FONT:0)Increased Flexability:[Dönetici: Yeni özellikler veya çapraz yönlendirme endişeleri (kaching, geçerlilik, log) orijinal sınıflara değiştirmeden mevcut arayüzler üzerinde dekoratörler olarak eklenebilir.Bu ayarlamalar Açık / Kısa bir ilke ile uyumludur - uzatma için açık sınıflar, değişiklik için kapalı.
- [FONT:0)Enhanced maintainability:[Dönetici:[Dönetici:0)[Dönetici:0)[Dönetici:[Dönetici:0)[Dönetici:[Dönetici:[Dönetici: 1 ) Bir bağımlılık değişikliği olduğunda, bir kütüphane API'yi yükseltme modize eder), sadece kayıt ve beton uygulamaları güncellemeniz gerekir. Tüm tüketiciler soyutlama sözleşmesi korunurken uzun süre takip edilir.
- [[Düzücüler: 0)Firmacılar, bağımlılık çözümü genellikle merkezi bir “kompoze kök” (tipik olarak uygulama sınıfı) tarafından ele alınırken HTTP istekleri ve geri dönüş yanıtlarını kullanmaya odaklanırlar.
Çeşitli MVC Framework'lerde DI'yı uygulama
DI kavramı dilbilimci olmasına rağmen, her MVC çerçevesi kendi konteyner ve kongrelerini ortaya çıkarır. Aşağıda üç popüler ekosistemden somut örnekler vardır.
ASP.NET Core (C#)
ASP.NET Core, inşa edilmiş DI konteynerine sahiptir ve bunlar, İLFLT:8'de yapılandırılır. Hizmetler, koleksiyonun içinde kaydedilir ve kontroller otomatik olarak yapılabilmesine bağlı olarak bağımlılık alır.
// 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();
Kontrolörde, sadece bağımlılık ilan edersiniz:
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'un konteyneri ayrıca açık jeneriklerin, fabrika yöntemlerinin ve dekoratörlerin açık kayıtlarını da destekler. Seçmeli bağımlılıklar için, [[Ücretsizlikler için, [[Ücretsizlikler için, kalıp veya setter enjeksiyonu ile 03:9) özelliği kullanabilirsiniz.
Bahar MVC (Java)
Bahar IoC konteyneri en olgun DI çerçevelerinden biridir. Bir Bahar MVC uygulamasında, stereotiplerle ([DÜT: 16) bir notaksiyon veya enjeksiyon alanı ile enjekte edilir.
@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";
}
}
Kurulum genellikle Java annotasyonları veya XML. Bean kapsamı ile yapılır (singleton, prototip, istek, oturum) işlem yönetimi veya güvenlik gibi endişeleri uygulamak için. Spring ayrıca yöntem enjeksiyonu, yaşam döngüsü çağrıları gibi gelişmiş özellikler sunar ve AOP entegrasyonu ile birlikte DI ile birlikte olabilir.
Laravel (PHP)
Laravel, otomatik karar, bağlayıcı arabirimleri uygulama için destekleyen güçlü bir hizmet konteynerini kullanır ve bağlamsal bağlayıcı. Laravel'in MVC yapısı, kontroller, orta sınıflar ve hizmet sağlayıcıları aracılığıyla bağımlılık teşvik eder.
// In a ServiceProvider's register() method
$this->app->bind(PaymentGatewayInterface::class, StripeGateway::class);
$this->app->singleton(LoggerInterface::class, FileLogger::class);
Bir kontrolörde, inşaat veya bir yöntemdeki bağımlılıktan kaçınıyorsunuz. Laravel'in konteyneri otomatik olarak çözüyor:
class InvoiceController extends Controller {
protected $paymentGateway;
public function __construct(PaymentGatewayInterface $paymentGateway) {
$this->paymentGateway = $paymentGateway;
}
public function pay(Invoice $invoice) {
$this->paymentGateway->charge($invoice);
// ...
}
}
Laravel ayrıca kontrol yöntemlerinde otomatik enjeksiyonu destekliyor (kırın yönteminin çözümüyle) ve konteynere bağlı örneklerin taşıyıcı olarak hareket eden cepheler sağlar. Ancak, en iyi uygulama, doğrudan test edilebilirliği sağlamak için cephelere güvenmekten ziyade arayüzleri enjekte eder.
MVC için Gelişmiş DI Desenleri
Temel DI'nın sağlam bir anlayışına sahipseniz, tekrarlanan mimari sorunları çözmek için daha sofistike desenlerden yararlanabilirsiniz.
Dekoratör Desen
Dekorasyon modeli, kodu değiştirmeden mevcut bir hizmete davranış eklenize olanak sağlar. Bir IoC konteyneriyle, orijinal uygulamayı sarmalayan bir dekorasyonatör kayıt olabilirsiniz. Örneğin, bir ürün arama hizmetine neden eklemek isteyebilirsiniz:
services.AddScoped<IProductRepository, ProductRepository>();
services.Decorate<IProductRepository, CachedProductRepository>();
[FONT=FONT] gerçek repository'yi inşaat veya enjeksiyon ve delegeler ile bir caching katmanı ekleyerek alır. Bu, gerçek veri erişim kodu saf ve test edilebilir tutar.
Interception / AOP
Bazı konteynerler, özellikle Castle Windsor (ASP.NET) ve Spring AOP, kayıtlı hizmetler üzerinde yöntem aramalarını engellemenize izin verir. Interceptors, log, performans izleme, izin kontrolü veya işlem yapmadan iş mantığına giriş yapın. Interception, DI ile el elemanları.
Lifetime Scopes and Disposal
Örneğin, nesneler yaratıldığında ve yok edildiğinde anlamak önemlidir. Örneğin, bir veritabanı bağlamı ([Dönetici Framework’te :23) genellikle tekton olarak kayıtlı olmalıdır, birden fazla eş zamanlı istek aynı bağlamı paylaşabilir, yolsuzluk veya durgun verilere yol açabilir.
Ayrıca, konteynerin düzgün bir şekilde uygulama kodu altında bulunan nesnelerden tasarruf etmesini sağlar. Çoğu konteyner otomatik olarak talep sonunda kapsamıştırılır ve geçici örnekler talep edilen konteynerler için, ancak yönetim dışındaki konteynerden nesneleri manuel olarak çözmesi, sızıntılara yol açabilir. Ortak bir kılavuz: Uygulama kodu içindeki konteynerden doğrudan çözümle kalmaz; bunun yerine, inşaatçıklama işlemine izin verir.
Ortak Pitfalls ve Them'dan Nasıl Kaçırmak
En iyi niyetlerle bile, DI, yanlış yorumlanmış olsa sorunları ortaya çıkarabilir. Bu tuzakların farkındalığı temiz bir mimariye yardımcı olur.
- [FONT:0) Servis Locator Anti-Pattern: [Dönetici: [Dönetici:0) Statik bir hizmet taşıyıcı (örneğin,)) bağımlıları gizlemek ve test etmek zor hale getirmek.
- [FONT:0)Over-Injeksiyon:[Dönetici:[Dönetici:0) Üç veya dört yapılı tartışma gerektiren bir kontrol, Tek Sorumluluk Prensipi (SRP)'yi ihlal edebilir. Kontrolün tek bir cepheye veya medyacıya ilişkin hizmetleri birleştirip birleştirebileceğinizi düşünün.
- [FONT:0)Tight Coupling to the Container:) Doğrudan konteyner API'sini referans alan kod yazmaktan kaçının (örneğin, 03: 00). Bu çiftler belirli bir konteynere uygulama, standart bir kontraksiyon veya test etmek için daha zor hale getirir.
- [FONT:0) Yaşam Zamanlarını Tanımlama: [Dönder:[Dönder: 1 ) Daha önce belirtildiği gibi, yanlış yaşam süresi, koncurrency böceklerine neden olabilir. Her zaman konteynerinizin belgeleri varsayılan yaşam sürelerini anlamak ve onları doğru nasıl yapılandırmak için inceleyebilir.
- [[Dönetici Kullanımı: [Dönetici:0) Gayrimenkul enjeksiyonu genellikle sadece kısmen ilklenen nesnelere yol açıyor, bu da zorunlu bağımlılıklar için null referans istisnalarına neden olabilir ve mülk enjeksiyonu sadece gerçekten seçmeli olanlar için kullanılır.
MVC'de Bağlanma Enjeksiyonu için En İyi Uygulamalar
Ortak hatalardan kaçınırken DI faydalarını maksimize etmek, bu yönergeleri takip etmek:
- [FONT:0] Programlamaya yönelik program;[Döneticiler veya soyut sınıflar arkasında Abstract behind UIs or abstract classes so that applicationss can be modified independent.
- [FONT:0) Yapıcılar basit tutun.[[Dönetici:0) Bir inşaatçı sadece özel alanlara bağımlı olmalıdır. Bu, nesnenin kompozisyon sırasında çözülebileceği herhangi bir işi gerçekleştirmemelidir.
- [FONT:0) Kombine uygun olarak; [Döneticileri 1] Tüm konteyner kayıtları tek bir yerde olmalıdır - genellikle uygulama başlangıç sınıfı ([DÜDÜ: 4,00) veya Laravel'daki bir hizmet sağlayıcı.
- [[Düzücüler ile test edin.[Dönetici:0) Taklitler için bir paket kullanın.Test sırasında konteynere ihtiyaç yoktur.
- [FONT:0) Öner kontraksiyon ([Döneticiler için) zorunlu bağımlılıklar için (Dönerge) enjeksiyonu yapılır ve belirli yöntemlerden önce çağrılmalıdır.
- [FONT:0) Yaşamlar hakkında açık olun.[[Döneticiler için en uygun yerle kayıt hizmetleri ve güvenliği dengelemek için en uygun kapsamı ile açın.
- [FONT:0]Leverage konteyneri akıllıca özellikleri taşır.[[Döntgen: 1) Dekorasyoncular, fabrikalar ve çatlakları basitleştiren kişiler, onları aşırı kullanımzlar - yapılandırma çok karmaşık olursa, tasarımı yeniden ele almayı düşünün.
Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç
Bağlanma Enjeksiyonu sadece bir trendsel model değildir; MVC uygulamalarının kablo ve yaşam yönetimi olmadan büyümesini sağlayan temel bir uygulamadır.Rekalatıcı kontrolörler, hizmetler ve veri erişim katmanları beton uygulamalarından, yeni gereksinimlerin adapte olma yeteneği kazanırsınız, teknolojiler ve kolay bir şekilde test yazabilirsiniz. Modern IoC konteynerleri, iş mantığına nesne oluşturmadan ziyade odaklanmanıza izin verir.
ASP.NET Core, Spring MVC veya Laravel'yı kullanıyorsanız, prensipler aynı kalır: Dıştan soyut, ve kompozisyon kök merkezileşmiş tutmak yerine, tek bir kontrole yeniden başlamak, sonra yavaş yavaş tüm uygulama için bir IoC konteyneri ortaya koyar.
Daha fazla okuma için, çerçevenizin DI konteynerinin resmi belgelerini keşfedin veya Martin Fowler'in makalesini [[Düzgöçreleri ve Bağımlılık Enjeksiyonu[Döneticileri) ile ilgili klasik kaynakları danışmak (Düzük)[Düzüğün hizmet konteyneri[Düzüğün hizmet konteyneri[Döneticileri ve örnekleri)