Dependency Injection
Dependency Injection, nesne yönelimli kodu daha esnek, test edilebilir ve bakımı yapılabilir hale getirmek için kullanılan bir yazılım tasarım tekniğidir. Bir sınıfın ihtiyaç duyduğu nesneleri dahili olarak oluşturmak yerine dışarıdan almasına olanak tanır.
Object-Oriented Programming'da bağımlılık, başka bir sınıfın işini gerçekleştirmek için ihtiyaç duyduğu herhangi bir nesne, hizmet veya bileşendir. Dependency Injection bu bağımlılıkların temiz bir şekilde yönetilmesine yardımcı olur ve sınıflar arasındaki sıkı bağlantıyı azaltır.
Giriş
Bu OOP ve Design Patterns serisinin önceki makalelerinde sınıflar, nesneler, kapsülleme, kalıtım, polimorfizm, soyutlama, arayüzler, Design Patterns, Repository Pattern, Strategy Pattern, Observer Pattern ve Command Pattern gibi önemli kavramları tartışmıştık.
Dependency Injection bu kavramların çoğuyla güçlü bir şekilde bağlantılıdır. Özellikle arayüzler, soyutlama, polimorfizm, depolar, hizmetler ve clean architecture ile iyi çalışır.
Laravel, Symfony, Spring, NestJS ve ASP.NET gibi birçok modern çerçeve, Dependency Injection'yu yoğun bir şekilde kullanır. Bunu anlamak, geliştiricilerin daha temiz kod yazmasına ve profesyonel backend çerçevelerinin hizmetleri nasıl yönettiğini anlamalarına yardımcı olur.
Dependency Injection Nedir?
Dependency Injection, bir sınıfın bağımlı olduğu nesneleri kendisi oluşturmak yerine harici bir kaynaktan aldığı bir tekniktir.
Basit bir ifadeyle bu sınıf “İhtiyacım olanı yaratacağım” yerine “bana ihtiyacım olanı ver” diyor.
Örneğin, bir OrderService'in bir PaymentService'e ve bir EmailService'e ihtiyacı olabilir. Dependency Injection olmadan OrderService bu hizmetleri kendi içinde oluşturur. Dependency Injection ile bu hizmetler dışarıdan OrderService'e aktarılır.
Bağımlılık Nedir?
Bağımlılık, başka bir sınıfın kullanması gereken herhangi bir nesne veya hizmettir. Bir sınıf, başka bir sınıf olmadan işini tamamlayamıyorsa, o diğer sınıf bir bağımlılıktır.
Örneğin:
Bir UserService, bir UserRepository'ye bağlı olabilir.
Bir OrderService, PaymentGateway'e bağlı olabilir.
Bir ReportService, bir PdfExporter'a bağlı olabilir.
NotificationService bir EmailSender'a bağlı olabilir.
Bir CheckoutService, bir İndirim Strategysine bağlı olabilir.
Dependency Injection, sınıfı doğrudan bunları oluşturmaya zorlamak yerine bu bağımlılıkları sınıfa verir.
Dependency Injection Olmadan Sorun
Dependency Injection olmadan bir sınıf, new anahtar sözcüğünü kullanarak bağımlılıklarını dahili olarak oluşturabilir.
class OrderService
{
private PaymentService $paymentService;
private EmailService $emailService;
public function __construct()
{
$this->paymentService = new PaymentService();
$this->emailService = new EmailService();
}
public function placeOrder(Order $order): void
{
$this->paymentService->charge($order);
$this->emailService->sendConfirmation($order);
}
}Bu kod çalışıyor ancak tasarım sorunu var. OrderService, PaymentService ve EmailService ile sıkı bir şekilde bağlantılıdır. Hangi somut sınıfların kullanılacağına ve bunların nasıl oluşturulacağına karar verir.
Uygulamanın daha sonra farklı bir ödeme sağlayıcısı, test için sahte bir ödeme hizmeti veya farklı bir e-posta göndereni kullanması gerekirse OrderService sınıfının değiştirilmesi gerekir.
Dependency Injection ile Çözüm
Dependency Injection ile bağımlılıklar sınıfa dışarıdan aktarılır.
class OrderService
{
public function __construct(
private PaymentService $paymentService,
private EmailService $emailService
) {
}
public function placeOrder(Order $order): void
{
$this->paymentService->charge($order);
$this->emailService->sendConfirmation($order);
}
}Artık OrderService bağımlılıkları kendisi oluşturmuyor. Bunları yapıcı aracılığıyla alır. Bu, sınıfın yapılandırılmasını, test edilmesini ve değiştirilmesini kolaylaştırır.
Dependency Injection Neden Önemlidir?
Dependency Injection önemlidir çünkü sınıflar arasındaki sıkı bağlantıyı azaltır. Bir sınıf, ihtiyaç duyduğu tüm hizmetleri oluşturup yapılandırmaya değil, ana sorumluluğuna odaklanmalıdır.
Bağımlılıklar enjekte edildiğinde sınıf daha esnek hale gelir. Ortama, konfigürasyona veya test senaryosuna bağlı olarak farklı uygulamalara geçilebilir.
Bu, özellikle hizmetlerin birçok bağımlılığa sahip olabileceği ve kodun güvenilir bir şekilde test edilmesi gereken büyük uygulamalarda önemlidir.
Dependency Injection ve Arayüzler
Dependency Injection, arayüzlerle birleştirildiğinde daha güçlü hale gelir. Bir hizmet, somut bir sınıfa bağlı olmak yerine bir arayüze bağlı olabilir.
Örneğin, CheckoutService doğrudan StripePaymentGateway'e bağlı olmak yerine PaymentGatewayInterface'e bağlı olabilir.
interface PaymentGatewayInterface
{
public function charge(Order $order): bool;
}
class StripePaymentGateway implements PaymentGatewayInterface
{
public function charge(Order $order): bool
{
// Charge using Stripe
return true;
}
}
class PayPalPaymentGateway implements PaymentGatewayInterface
{
public function charge(Order $order): bool
{
// Charge using PayPal
return true;
}
}Artık uygulama aynı arayüzü uygulayan herhangi bir ödeme ağ geçidini enjekte edebilir.
Arayüz Tabanlı Dependency Injection Örneği
class CheckoutService
{
public function __construct(
private PaymentGatewayInterface $paymentGateway
) {
}
public function checkout(Order $order): bool
{
return $this->paymentGateway->charge($order);
}
}CheckoutService, ödemenin Stripe, PayPal, banka havalesi veya başka bir sağlayıcı tarafından mı işlendiğini bilmiyor. Bu yalnızca PaymentGatewayInterface'e bağlıdır.
Bu, sistemin genişletilmesini kolaylaştırır. CheckoutService değiştirilmeden yeni bir ödeme sağlayıcı eklenebilir.
Dependency Injection Türleri
Bağımlılıkları bir sınıfa enjekte etmenin birkaç yolu vardır. En yaygın türler şunlardır:
Yapıcı Enjeksiyonu: Bağımlılıklar yapıcı aracılığıyla iletilir.
Ayarlayıcı Enjeksiyonu: Bağımlılıklar ayarlayıcı yöntemler aracılığıyla aktarılır.
Yöntem Enjeksiyonu: Bağımlılıklar doğrudan onlara ihtiyaç duyan yönteme aktarılır.
Her türün farklı kullanım durumları vardır ancak yapıcı enjeksiyonu genellikle gerekli bağımlılıklar için en yaygın ve önerilen yaklaşımdır.
Yapıcı Enjeksiyonu
Yapıcı enjeksiyonu, bağımlılıkların sınıf yapıcısı aracılığıyla aktarılması anlamına gelir. Bu, Dependency Injection'nun en yaygın biçimidir.
class ReportService
{
public function __construct(
private ReportRepository $repository,
private PdfExporter $exporter
) {
}
public function generate(int $reportId): string
{
$report = $this->repository->findById($reportId);
return $this->exporter->export($report);
}
}Yapıcı enjeksiyonu, sınıfın çalışması için bir bağımlılık gerektiğinde kullanışlıdır. Bağımlılığı açıkça ortaya koyar ve nesnenin geçerli bir durumda oluşturulmasını sağlar.
Ayarlayıcı Enjeksiyon
Ayarlayıcı enjeksiyonu, nesne oluşturulduktan sonra bir bağımlılığın ayarlayıcı yöntemi aracılığıyla geçirilmesi anlamına gelir.
class NewsletterService
{
private ?LoggerInterface $logger = null;
public function setLogger(LoggerInterface $logger): void
{
$this->logger = $logger;
}
public function send(string $email): void
{
// Send newsletter
if ($this->logger) {
$this->logger->info('Newsletter sent.');
}
}
}Ayarlayıcı enjeksiyonu isteğe bağlı bağımlılıklar için yararlı olabilir. Ancak nesne, bağımlılık ayarlanmadan da var olabileceğinden dikkatli kullanılmalıdır.
Yöntem Enjeksiyonu
Yöntem enjeksiyonu, bir bağımlılığı doğrudan ona ihtiyaç duyan yönteme aktarmak anlamına gelir.
class FileImportService
{
public function import(string $filePath, FileParserInterface $parser): array
{
return $parser->parse($filePath);
}
}Yöntem enjeksiyonu, yalnızca belirli bir yöntem için bağımlılığa ihtiyaç duyulduğunda ve nesne durumunun bir parçası olarak saklanmasına gerek olmadığında kullanışlıdır.
Dependency Injection ve Test
Dependency Injection'nun en büyük avantajlarından biri daha kolay test edilmesidir. Bir sınıf dışarıdan bağımlılıklar aldığında, testler gerçek hizmetler yerine sahte veya sahte bağımlılıkları geçebilir.
Örneğin, gerçek bir ödeme ağ geçidi harici bir API'yu arayabilir. Birim testleri sırasında geliştiriciler gerçek ödeme sağlayıcısını aramamalıdır. Bunun yerine sahte bir ödeme ağ geçidi enjekte edebilirler.
class FakePaymentGateway implements PaymentGatewayInterface
{
public function charge(Order $order): bool
{
return true;
}
}Test artık sahte uygulamayı kullanabilir:
$checkout = new CheckoutService(new FakePaymentGateway());
$result = $checkout->checkout($order);Bu, testleri daha hızlı, daha güvenli ve daha öngörülebilir hale getirir.
Dependency Injection ve Gevşek Kaplin
Gevşek bağlantı, sınıfların belirli somut uygulamalara büyük ölçüde bağlı olmadığı anlamına gelir. Dependency Injection, bağımlılıklar dışarıdan sağlandığı için gevşek bağlantıyı destekler.
Bir sınıf bir arayüze bağlı olduğunda birçok farklı uygulamayla çalışabilir. Bu, değişimin etkisini azaltır.
Örneğin, StripePaymentGateway'den PayPalPaymentGateway'e geçiş, eğer her iki sınıf da PaymentGatewayInterface'i uyguluyorsa, CheckoutService'in değiştirilmesini gerektirmez.
Dependency Injection ve SOLID İlkeleri
Dependency Injection, SOLID ilkeleriyle, özellikle de Bağımlılığı Ters Çevirme İlkesi ile yakından ilgilidir.
Bağımlılığı Ters Çevirme İlkesi, yüksek seviyeli modüllerin düşük seviyeli modüllere bağlı olmaması gerektiğini söylüyor. Her ikisi de soyutlamalara bağlı olmalıdır. Ayrıca soyutlamaların ayrıntılara bağlı olmaması gerektiğini de söylüyor. Ayrıntılar soyutlamalara bağlı olmalıdır.
Dependency Injection, üst düzey hizmetlerin somut sınıflar yerine arayüzlere bağlı olmasına izin vererek bu prensibin uygulanmasına yardımcı olur.
Dependency Injection ve Bağımlılığın Tersine çevrilmesi
Dependency Injection ve Bağımlılığı Tersine Çevirme birbiriyle ilişkilidir ancak aynı değildir.
Bağımlılığın Tersine çevrilmesi bir tasarım ilkesidir. Kodun somut uygulamalardan ziyade soyutlamalara dayanması gerektiğini söylüyor.
Dependency Injection, bir sınıfa dışarıdan bağımlılıklar sağlamak için kullanılan bir tekniktir. Bağımlılığı Ters Çevirmeyi uygulamanın pratik bir yoludur.
Basit bir ifadeyle, Bağımlılığı Tersine Çevirme fikirdir ve Dependency Injection bu fikri uygulamanın bir yoludur.
Dependency Injection Konteyner
Dependency Injection kapsayıcısı, nesneleri otomatik olarak oluşturan ve bağımlılıklarını enjekte eden bir araçtır. Her hizmeti manuel olarak oluşturmak ve bağımlılıkları iletmek yerine, konteyner bunları otomatik olarak çözer.
Modern çerçeveler kapsayıcıları yoğun olarak kullanır. Konteyner, hizmetlerin nasıl oluşturulacağını, bir arayüz için hangi uygulamanın kullanılması gerektiğini ve bağımlılıkların nasıl birbirine bağlanması gerektiğini bilir.
Örneğin, bir denetleyicinin UserService'e ihtiyacı varsa ve UserService'in de UserRepository'ye ihtiyacı varsa kapsayıcı, tam nesne grafiğini otomatik olarak oluşturabilir.
Kılavuz Dependency Injection Örneği
Konteyner olmadan bağımlılıklar manuel olarak bağlanabilir:
$repository = new UserRepository();
$emailService = new EmailService();
$userService = new UserService($repository, $emailService);Küçük uygulamalarda bu durum açıktır ancak birçok hizmet başka hizmetlere bağlı olduğunda bu durum daha da zorlaşır.
Bir DI konteyneri bu işlemi otomatikleştirir.
Laravel'da Dependency Injection
Laravel, Dependency Injection'yu yöneten güçlü bir servis konteynerine sahiptir. Laravel, bağımlılıkları denetleyicilere, hizmetlere, işlere, dinleyicilere, ara yazılımlara ve komutlara otomatik olarak ekleyebilir.
Örneğin, bir Laravel denetleyicisi, yapıcısı aracılığıyla bir hizmet alabilir:
class UserController
{
public function __construct(
private UserService $userService
) {
}
public function store(Request $request)
{
return $this->userService->create($request->all());
}
}Laravel, UserService'i servis kapsayıcısından otomatik olarak çözer.
Laravel'da Bağlama Arayüzleri
Bir sınıf bir arayüze bağlı olduğunda, Laravel'nun hangi uygulamanın kullanılması gerektiğini bilmesi gerekir. Bu bağlama yoluyla yapılır.
use App\Contracts\PaymentGatewayInterface;
use App\Services\StripePaymentGateway;
public function register(): void
{
$this->app->bind(
PaymentGatewayInterface::class,
StripePaymentGateway::class
);
}Bu bağlamanın ardından PaymentGatewayInterface gerektiren herhangi bir sınıf, bağlama değiştirilmediği sürece StripePaymentGateway'i alacaktır.
Laravel Tek Tonlu Bağlama
Laravel ayrıca bir hizmeti tekil olarak bağlayabilir; bu da aynı örneğin yeniden kullanıldığı anlamına gelir.
$this->app->singleton(
SettingsRepository::class,
DatabaseSettingsRepository::class
);Bu, sınıfın kendisini Singleton Pattern'yu manuel olarak uygulamaya zorlamadan, hizmet kapsayıcısı aracılığıyla paylaşılan örnek davranışı sağlar.
Symfony'da Dependency Injection
Symfony ayrıca bir Dependency Injection kapsayıcısı kullanır. Hizmetler tanımlanır ve yapılandırılır ve Symfony, bağımlılıkları yapıcılar veya hizmet yapılandırması aracılığıyla otomatik olarak ekler.
Örneğin, bir Symfony hizmeti, yapıcısı aracılığıyla bir depo ve günlükçü alabilir:
class ReportService
{
public function __construct(
private ReportRepository $repository,
private LoggerInterface $logger
) {
}
}Symfony, hizmetler doğru şekilde kaydedildiğinde bu bağımlılıkları otomatik olarak bağlayabilir.
Otomatik kablolama
Otomatik kablolama, çerçevenin tür ipuçlarından bağımlılıkları otomatik olarak algıladığı ve doğru hizmetleri enjekte ettiği bir özelliktir.
Örneğin, bir kurucu LoggerInterface'e ihtiyaç duyuyorsa konteyner, yapılandırılmış günlükçü hizmetini otomatik olarak sağlayabilir.
Otomatik kablolama, manuel yapılandırmayı azaltır ve özellikle modern PHP çerçevelerinde Dependency Injection'nun kullanımını kolaylaştırır.
Dependency Injection ve Design Patterns
Dependency Injection birçok tasarım modeliyle iyi çalışır. Genellikle Repository Pattern, Strategy Pattern, Adapter Pattern, Decorator Pattern, Command Pattern ve Observer Pattern ile birlikte kullanılır.
Örneğin, bir hizmet bağımlılık enjeksiyonu yoluyla bir depo alabilir. Bir ödeme hizmeti bir ödeme stratejisi alabilir. Bir bildirim hizmeti, harici bir SMS sağlayıcısı için bir bağdaştırıcı alabilir. Bir komut işleyicisi depoları ve hizmetleri alabilir.
Dependency Injection bu kalıpları daha esnek hale getirir çünkü bağımlılıklar onları kullanan sınıfı değiştirmeden değiştirilebilir.
Dependency Injection ve Repository Pattern
Repository Pattern sıklıkla Dependency Injection'yu kullanır. Bir hizmet, somut bir depo uygulaması yerine bir depo arayüzüne bağlı olabilir.
class UserService
{
public function __construct(
private UserRepositoryInterface $users
) {
}
}Bu, hizmeti Eloquent, Doctrine, PDO veya herhangi bir belirli veri kaynağından bağımsız hale getirir.
Dependency Injection ve Strategy Pattern
Strategy Pattern ayrıca Dependency Injection ile de doğal olarak çalışır. Bir bağlam sınıfı, yapıcı aracılığıyla bir strateji alabilir.
class DiscountService
{
public function __construct(
private DiscountStrategy $strategy
) {
}
public function calculate(float $total): float
{
return $this->strategy->calculate($total);
}
}Strategy, İndirim Hizmeti değiştirilmeden değiştirilebilir.
Dependency Injection ve Decorator Pattern
Decorator Pattern genellikle Dependency Injection'yu kullanır çünkü bir dekoratör aynı arayüzü uygulayan başka bir nesneyi sarar.
class CachedProductRepository implements ProductRepositoryInterface
{
public function __construct(
private ProductRepositoryInterface $repository,
private CacheInterface $cache
) {
}
}Dekore edilmiş depo ve önbellek servisi dışarıdan enjekte edilerek dekoratör esnek ve test edilebilir hale getirilir.
Dependency Injection ve Servis Bulucu Karşılaştırması
Hizmet Bulucu, bir sınıfın merkezi bir nesneye veya kapsayıcıya bağımlılıklarını sorduğu başka bir kalıptır. Örneğin, bir sınıf dahili olarak app(PaymentGateway::class) öğesini çağırabilir.
Bağımlılıklar yapıcıda veya yöntem imzasında görülebildiğinden genellikle Dependency Injection tercih edilir. Bu, sınıfın anlaşılmasını ve test edilmesini kolaylaştırır.
Hizmet Bulucu bağımlılıkları gizleyebilir. Bir sınıfın hiçbir bağımlılığı yok gibi görünebilir, ancak dahili olarak konteynerden birçok hizmeti alır. Bu, kodun analiz edilmesini zorlaştırır.
Kötü Örnek: Gizli Bağımlılıklar
class CheckoutService
{
public function checkout(Order $order): bool
{
$paymentGateway = app(PaymentGatewayInterface::class);
return $paymentGateway->charge($order);
}
}Bu, yöntemin içindeki bağımlılığı gizler. Ödeme ağ geçidini yapıcı aracılığıyla enjekte etmek daha iyidir.
Daha İyi Örnek: Açık Bağımlılıklar
class CheckoutService
{
public function __construct(
private PaymentGatewayInterface $paymentGateway
) {
}
public function checkout(Order $order): bool
{
return $this->paymentGateway->charge($order);
}
}Artık bağımlılık açık ve testlerde değiştirilmesi daha kolay.
Dependency Injection'nun Faydaları
Dependency Injection, nesne yönelimli yazılım tasarımında birçok fayda sağlar.
Ana faydalar şunları içerir:
Sınıflar arasındaki sıkı bağlantıyı azaltır.
Bağımlılıkları açıkça ortaya koyar.
Sahte veya sahte bağımlılıklarla test edilebilirliği artırır.
Arayüz tabanlı tasarımı destekler.
Kodun genişletilmesini ve bakımını kolaylaştırır.
SOLID prensipleriyle iyi çalışır.
Uygulamaların daha kolay değiştirilmesine olanak tanır.
Büyük uygulamalarda proje organizasyonunu geliştirir.
Bu avantajlar Dependency Injection'yu profesyonel yazılım geliştirmede en önemli tekniklerden biri haline getirir.
Dependency Injection'nun dezavantajları
Yanlış kullanıldığında Dependency Injection'nun dezavantajları da olabilir. Projeye daha fazla sınıf, arayüz ve konfigürasyon ekleyebilir.
Küçük uygulamalar için manüel nesne oluşturma daha kolay olabilir. Büyük uygulamalarda Dependency Injection genellikle yapıya değer.
Diğer bir dezavantaj ise yapıcının aşırı enjeksiyonudur. Bir sınıfın çok fazla enjekte edilmiş bağımlılığı varsa, bu, sınıfın çok fazla sorumluluğa sahip olduğunun ve daha küçük sınıflara bölünmesi gerektiğinin bir işareti olabilir.
Yapıcı Aşırı Enjeksiyonu
Yapıcının aşırı enjeksiyonu, bir sınıfın yapıcısında çok fazla bağımlılığa ihtiyaç duyması durumunda meydana gelir.
class ReportService
{
public function __construct(
private A $a,
private B $b,
private C $c,
private D $d,
private E $e,
private F $f
) {
}
}Bu, ReportService'in çok fazla şey yaptığını gösterebilir. Çözüm, bir hizmet bulucu kullanarak bağımlılıkları gizlemek değildir. Daha iyi çözüm, sınıf sorumluluklarını gözden geçirmek ve gerekirse mantığı bölmektir.
Dependency Injection Ne Zaman Kullanılır?
Bir sınıf hizmetlere, depolara, harici APIs'ya, stratejilere, bağdaştırıcılara, günlükçülere veya değişebilecek veya test edilmesi gerekebilecek diğer nesnelere bağlı olduğunda Dependency Injection'yu kullanın.
Dependency Injection şu durumlarda faydalıdır:
Bir sınıf başka bir hizmete veya nesneye bağlıdır.
Sahte bağımlılıklara sahip bir sınıfı test etmek istiyorsunuz.
Somut sınıflar yerine arayüzlere güvenmek istiyorsunuz.
Uygulama gelecekte değişebilir.
Proje bir çerçeve hizmet kapsayıcısı kullanıyor.
Sıkı bağlantıyı azaltmak istiyorsunuz.
Bağımlılıkların görünür ve açık olmasını istiyorsunuz.
Bu koşullar mevcutsa Dependency Injection genellikle güçlü bir tasarım seçeneğidir.
Dependency Injection Ne Zaman Kullanılmamalı?
Dependency Injection her küçük nesne için her zaman gerekli değildir. Basit değer nesneleri, DTOs, varlıklar ve küçük yardımcı program nesnelerinin eklenen hizmetlere ihtiyacı olmayabilir.
Aşağıdaki durumlarda gereksiz Dependency Injection'dan kaçının:
Sınıfın gerçek bir dış bağımlılığı yoktur.
Nesne, basit bir veri taşıyıcısı veya değer nesnesidir.
Manuel oluşturma daha basit ve anlaşılırdır.
Bağımlılık asla değiştirilmeyecek veya alay edilmeyecektir.
Desen, tasarımı iyileştirmeden karmaşıklık katar.
İyi tasarım pratik olmalıdır. Dependency Injection, kodu daha karmaşık değil, daha anlaşılır hale getirmelidir.
Dependency Injection ile Yapılan Yaygın Hatalar
Yaygın bir hata, bir sınıfa çok fazla bağımlılık enjekte etmektir. Bu genellikle sınıfın çok fazla sorumluluğu olduğu anlamına gelir.
Başka bir hata, bir arayüzün daha iyi olacağı durumlarda somut sınıflara bağlı olmaktır. Uygulama değişebilirse, bir arayüz esnekliği artırabilir.
Üçüncü bir hata, hizmet kapsayıcısını doğrudan işletme sınıflarının içinde kullanmaktır. Bu, bağımlılıkları gizler ve testi zorlaştırır.
Dördüncü hata ise gerçek bir sebep olmadan her sınıf için arayüz oluşturmaktır. Arayüzler, birden fazla uygulama mevcut olduğunda veya konuyu test ederken ve ayrıştırırken kullanışlıdır.
Dependency Injection için En İyi Uygulamalar
Dependency Injection'yu etkili bir şekilde kullanmak için geliştiricilerin bağımlılıkları açık, anlamlı ve odaklanmış tutması gerekir.
Yararlı en iyi uygulamalar şunları içerir:
Gerekli bağımlılıklar için yapıcı enjeksiyonunu tercih edin.
Birden fazla uygulamanın mevcut olabileceği durumlarda arayüzleri kullanın.
Bağımlılıkları yapıcıda açık tutun.
Servis kapsayıcısını gizli servis bulucu olarak kullanmaktan kaçının.
Bir tasarım uyarısı olarak yapıcının aşırı enjeksiyonuna dikkat edin.
Ayarlayıcı enjeksiyonunu yalnızca isteğe bağlı bağımlılıklar için kullanın.
Yalnızca bir yöntemin ihtiyaç duyduğu bağımlılıklar için yöntem eklemeyi kullanın.
Sınıfları tek bir sorumluluğa odaklayın.
Büyük uygulamalarda servis kablolaması için çerçeve kaplarını kullanın.
Bu uygulamalar Dependency Injection'nun temiz ve kullanışlı kalmasına yardımcı olur.
Dependency Injection Kullanmadan Önce Pratik Kontrol Listesi
Dependency Injection'yu kullanmadan önce geliştiriciler şu soruları sorabilir:
Bu sınıf başka bir hizmete veya nesneye bağlı mı?
Testlerdeki bu bağımlılığı değiştirmem gerekecek mi?
Bu bağımlılığın birden fazla uygulaması olabilir mi?
Bu sınıf bağımlılığın nasıl yaratılacağını bilmeli mi?
Bağımlılığın enjekte edilmesi eşleşmeyi azaltır mı?
Bağımlılık gerekli mi yoksa isteğe bağlı mı?
İnşaatçı çok fazla sorumluluk mu gösteriyor?
Bu soruların birçoğunun cevabı evet ise Dependency Injection muhtemelen iyi bir tasarım tercihidir.
Sonuç
Dependency Injection, Object-Oriented Programming'da sınıfların bağımlılıklarını dahili olarak oluşturmak yerine dışarıdan almasına olanak tanıyan güçlü bir tekniktir. Sıkı bağlantıyı azaltır, bağımlılıkları açık hale getirir, test edilebilirliği artırır ve temiz yazılım mimarisini destekler.
Dependency Injection özellikle arayüzler, depolar, stratejiler, bağdaştırıcılar, dekoratörler, komut işleyicileri ve hizmet katmanlarıyla iyi çalışır. Laravel ve Symfony gibi modern çerçevelerdeki temel bir kavramdır.
Ancak Dependency Injection dikkatli kullanılmalıdır. Çok fazla bağımlılık zayıf sınıf tasarımını ortaya çıkarabilir ve gereksiz soyutlamalar basit kodu daha karmaşık hale getirebilir. Doğru uygulandığında Dependency Injection temiz, bakımı yapılabilir ve ölçeklenebilir nesne yönelimli yazılım yazmaya yönelik en önemli uygulamalardan biridir.

