DI Hakkında Sıkça Sorulan Sorular (SSS)
- DI, IoC'nin başka bir adı mıdır?
- Servis Bulucu (Service Locator) Nedir?
- DI Ne Zaman Kullanılmamalıdır?
- DI Kullanmanın Dezavantajları Var mı?
- Eski Bir Uygulama DI'ye Nasıl Yeniden Yazılır?
- Neden Kalıtım Yerine Kompozisyon Tercih Edilir?
- Nette DI Konteyner Nette Dışında Kullanılabilir mi?
- Yapılandırma Neden NEON Dosyalarındadır?
- NEON Dosyalarını Ayrıştırmak Uygulamayı Yavaşlatır mı?
- Sınıfımdan Yapılandırma Dosyasındaki Parametrelere Nasıl Erişirim?
- Nette PSR-11: Konteyner Arayüzünü Destekliyor mu?
DI, IoC'nin başka bir adı mıdır?
Kontrolün Tersine Çevrilmesi (IoC – Inversion of Control), kodun nasıl çalıştırıldığına odaklanan bir
ilkedir – kodunuzun yabancı bir kodu mu çalıştırdığı yoksa kodunuzun onu daha sonra çağıran yabancı bir koda mı
entegre edildiği. IoC, olayları, Hollywood İlkesi olarak adlandırılanı ve diğer
yönleri kapsayan geniş bir kavramdır. Bu konseptin bir parçası, Kural No. 3: Fabrikaya
bırak'da bahsedilen ve new
operatörü için bir tersine çevirme temsil eden fabrikalardır.
Bağımlılık Enjeksiyonu (DI – Dependency Injection), bir nesnenin başka bir nesne hakkında, yani bağımlılıkları hakkında nasıl bilgi edindiğine odaklanır. Nesneler arasında bağımlılıkların açıkça aktarılmasını gerektiren bir tasarım desenidir.
Dolayısıyla, DI'nin IoC'nin özel bir formu olduğu söylenebilir. Ancak, tüm IoC formları kod temizliği açısından uygun değildir. Örneğin, anti-desenler arasında global durum ile çalışan teknikler veya Servis Bulucu olarak adlandırılan teknikler bulunur.
Servis Bulucu (Service Locator) Nedir?
Bağımlılık Enjeksiyonu'na bir alternatiftir. Mevcut tüm servislerin veya bağımlılıkların kaydedildiği merkezi bir depo oluşturarak çalışır. Bir nesne bir bağımlılığa ihtiyaç duyduğunda, onu Servis Bulucu'dan ister.
Ancak, Bağımlılık Enjeksiyonu'na kıyasla şeffaflığını kaybeder: bağımlılıklar nesnelere doğrudan aktarılmaz ve bu nedenle kolayca tanımlanamaz, bu da tüm bağlantıları ortaya çıkarmak ve anlamak için kodun incelenmesini gerektirir. Test etme de daha karmaşıktır, çünkü mock nesnelerini test edilen nesnelere basitçe aktaramayız, bunun yerine Servis Bulucu üzerinden gitmemiz gerekir. Ayrıca, Servis Bulucu kod tasarımını bozar, çünkü bireysel nesnelerin onun varlığından haberdar olması gerekir, bu da nesnelerin DI konteynerinden haberdar olmadığı Bağımlılık Enjeksiyonu'ndan farklıdır.
DI Ne Zaman Kullanılmamalıdır?
Bağımlılık Enjeksiyonu tasarım deseninin kullanımıyla ilişkili bilinen herhangi bir zorluk yoktur. Aksine, bağımlılıkları global olarak erişilebilir yerlerden almak bir dizi komplikasyona yol açar, aynı şekilde Servis Bulucu kullanımı da. Bu nedenle, DI'yi her zaman kullanmak uygundur. Bu dogmatik bir yaklaşım değildir, sadece daha iyi bir alternatif bulunamamıştır.
Yine de, nesneleri aktarmadığımız ve onları global alandan aldığımız belirli durumlar vardır. Örneğin, kod hata ayıklarken, programın belirli bir noktasında bir değişkenin değerini yazdırmanız, programın belirli bir bölümünün süresini ölçmeniz veya bir mesaj kaydetmeniz gerektiğinde. Bu gibi durumlarda, daha sonra koddan kaldırılacak geçici görevler söz konusu olduğunda, global olarak erişilebilir bir dumper, kronometre veya logger kullanmak meşrudur. Bu araçlar çünkü kod tasarımına ait değildir.
DI Kullanmanın Dezavantajları Var mı?
Bağımlılık Enjeksiyonu kullanmak, örneğin kod yazma zorluğunun artması veya performansın kötüleşmesi gibi herhangi bir dezavantaj içerir mi? DI ile uyumlu kod yazmaya başladığımızda ne kaybederiz?
DI'nin uygulamanın performansı veya bellek gereksinimleri üzerinde bir etkisi yoktur. DI Konteynerinin performansı belirli bir rol oynayabilir, ancak Nette DI durumunda, konteyner saf PHP'ye derlenir, bu nedenle uygulama çalışma zamanındaki ek yükü (overhead) temelde sıfırdır.
Kod yazarken, bağımlılıkları kabul eden kurucuları oluşturmak gerekli olabilir. Eskiden bu uzun sürebilirdi, ancak modern IDE'ler ve kurucu özellik tanıtımı sayesinde bu artık birkaç saniyelik bir meseledir. Fabrikalar, Nette DI ve PhpStorm için bir eklenti kullanılarak fare tıklamasıyla kolayca üretilebilir. Diğer yandan, singleton'lar ve statik erişim noktaları yazma ihtiyacı ortadan kalkar.
DI kullanan doğru tasarlanmış bir uygulamanın, singleton'ları kullanan bir uygulamayla karşılaştırıldığında ne daha kısa ne de daha uzun olduğu söylenebilir. Bağımlılıklarla çalışan kod bölümleri yalnızca bireysel sınıflardan çıkarılır ve yeni yerlere, yani DI konteynerine ve fabrikalara taşınır.
Eski Bir Uygulama DI'ye Nasıl Yeniden Yazılır?
Eski bir uygulamadan (legacy application) Bağımlılık Enjeksiyonu'na geçiş, özellikle büyük ve karmaşık uygulamalarda zorlu bir süreç olabilir. Bu sürece sistematik olarak yaklaşmak önemlidir.
- Bağımlılık Enjeksiyonu'na geçerken, tüm takım üyelerinin kullanılan ilkeleri ve prosedürleri anlaması önemlidir.
- İlk olarak, mevcut uygulamanın analizini yapın ve anahtar bileşenleri ve bağımlılıklarını tanımlayın. Hangi bölümlerin yeniden düzenleneceğini (refactored) ve hangi sırayla yapılacağını içeren bir plan oluşturun.
- Bir DI konteyneri uygulayın veya daha da iyisi, örneğin Nette DI gibi mevcut bir kütüphaneyi kullanın.
- Bağımlılık Enjeksiyonu'nu kullanmak için uygulamanın bireysel bölümlerini adım adım yeniden düzenleyin. Bu, bağımlılıkları parametre olarak kabul etmek için kurucuların veya metotların düzenlenmesini içerebilir.
- Kodda bağımlılıkları olan nesnelerin oluşturulduğu yerleri, bunun yerine bağımlılıkların konteyner tarafından enjekte edilmesi için düzenleyin. Bu, fabrikaların kullanımını içerebilir.
Bağımlılık Enjeksiyonu'na geçişin kod kalitesine ve uygulamanın uzun vadeli sürdürülebilirliğine yapılan bir yatırım olduğunu unutmayın. Bu değişiklikleri yapmak zorlu olsa da, sonuç daha temiz, daha modüler ve kolayca test edilebilir, gelecekteki genişletmelere ve bakıma hazır bir kod olmalıdır.
Neden Kalıtım Yerine Kompozisyon Tercih Edilir?
Değişikliklerin sonuçları hakkında endişelenmeden kodu yeniden kullanmamıza hizmet ettiği için kalıtım yerine kompozisyonu kullanmak daha uygundur. Dolayısıyla, bir kod değişikliğinin başka bir bağımlı kodun değiştirilmesi ihtiyacına neden olacağından endişelenmemize gerek olmayan daha gevşek bir bağlantı sağlar. Tipik bir örnek, kurucu cehennemi olarak adlandırılan durumdur.
Nette DI Konteyner Nette Dışında Kullanılabilir mi?
Kesinlikle. Nette DI Konteyner, Nette'nin bir parçasıdır, ancak framework'ün diğer bölümlerinden bağımsız olarak kullanılabilecek bağımsız bir kütüphane olarak tasarlanmıştır. Sadece Composer kullanarak yüklemeniz, servislerinizin tanımıyla bir yapılandırma dosyası oluşturmanız ve ardından birkaç satır PHP kodu kullanarak bir DI konteyneri oluşturmanız yeterlidir. Ve hemen projelerinizde Bağımlılık Enjeksiyonu'nun avantajlarından yararlanmaya başlayabilirsiniz.
Kodlar dahil olmak üzere somut kullanımın nasıl göründüğünü Nette DI Konteyner bölümü açıklar.
Yapılandırma Neden NEON Dosyalarındadır?
NEON, uygulamaları, servisleri ve bağımlılıklarını ayarlamak için Nette kapsamında geliştirilmiş basit ve kolay okunabilir bir yapılandırma dilidir. JSON veya YAML ile karşılaştırıldığında, bu amaç için çok daha sezgisel ve esnek seçenekler sunar. NEON'da, Symfony & YAMLu'da ya hiç yazılamayacak ya da sadece karmaşık bir tanım aracılığıyla yazılabilecek bağlantıları doğal olarak tanımlamak mümkündür.
NEON Dosyalarını Ayrıştırmak Uygulamayı Yavaşlatır mı?
NEON dosyaları çok hızlı ayrıştırılsa da, bu bakış açısı hiç önemli değildir. Nedeni, dosyaların ayrıştırılmasının yalnızca uygulamanın ilk çalıştırılmasında bir kez gerçekleşmesidir. Daha sonra DI konteynerinin kodu üretilir, diske kaydedilir ve daha fazla ayrıştırma yapmaya gerek kalmadan sonraki her istekte çalıştırılır.
Bu, üretim ortamında bu şekilde çalışır. Geliştirme sırasında, geliştiricinin her zaman güncel bir DI konteynerine sahip olması için NEON dosyaları içerikleri her değiştiğinde ayrıştırılır. Ayrıştırmanın kendisi, söylendiği gibi, anlık bir meseledir.
Sınıfımdan Yapılandırma Dosyasındaki Parametrelere Nasıl Erişirim?
Kural No. 1: Sana aktarılmasına izin ver'i aklımızda bulunduralım. Eğer sınıf yapılandırma dosyasından bilgi gerektiriyorsa, bilgiye nasıl ulaşacağımızı düşünmemize gerek yok, bunun yerine basitçe isteriz – örneğin sınıfın kurucusu aracılığıyla. Ve aktarımı yapılandırma dosyasında gerçekleştiririz.
Bu örnekte, %myParameter%
, MyClass
sınıfının kurucusuna aktarılan myParameter
parametresinin değeri için bir yer tutucu semboldür:
# config.neon
parameters:
myParameter: Some value
services:
- MyClass(%myParameter%)
Daha fazla parametre aktarmak veya otomatik bağlama kullanmak istiyorsanız, parametreleri bir nesneye sarmak uygundur.
Nette PSR-11: Konteyner Arayüzünü Destekliyor mu?
Nette DI Konteyner, PSR-11'i doğrudan desteklemez. Ancak, Nette DI Konteyneri ile PSR-11 Konteyner Arayüzü bekleyen kütüphaneler veya framework'ler arasında birlikte çalışabilirliğe ihtiyacınız varsa, Nette DI Konteyneri ile PSR-11 arasında köprü görevi görecek basit bir adaptör oluşturabilirsiniz.