DI Hakkında SSS
DI, IoC için başka bir isim mi?
Inversion of Control (IoC), kodun yürütülme şekline odaklanan bir ilkedir – kodunuzun harici kodu başlatması
veya kodunuzun harici koda entegre olması ve daha sonra onu çağırması. IoC, olayları, Hollywood İlkesi olarak adlandırılan ilkeyi ve
diğer unsurları içeren geniş bir kavramdır. Kural #3:
Bırakın Fabrika Hall etsin'in bir parçası olan ve new
operatörü için tersine çevirmeyi temsil eden
fabrikalar da bu kavramın bileşenleridir.
Dependency Injection (DI), bir nesnenin başka bir nesne hakkında nasıl bilgi sahibi olduğu, yani bağımlılık ile ilgilidir. Nesneler arasında bağımlılıkların açık bir şekilde aktarılmasını gerektiren bir tasarım modelidir.
Dolayısıyla DI'nin IoC'nin özel bir biçimi olduğu söylenebilir. Bununla birlikte, IoC'nin tüm biçimleri kod saflığı açısından uygun değildir. Örneğin, anti-paternler arasında, küresel durumla çalışan veya Hizmet Bulucu olarak adlandırılan tüm teknikleri dahil ediyoruz.
Hizmet Bulucu Nedir?
Hizmet Bulucu, Bağımlılık Enjeksiyonuna bir alternatiftir. Mevcut tüm hizmetlerin veya bağımlılıkların kaydedildiği merkezi bir depolama alanı oluşturarak çalışır. Bir nesne bir bağımlılığa ihtiyaç duyduğunda, bunu Hizmet Bulucu'dan talep eder.
Bununla birlikte, Bağımlılık Enjeksiyonu ile karşılaştırıldığında, şeffaflık kaybeder: bağımlılıklar doğrudan nesnelere 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 etmek de daha karmaşıktır, çünkü sahte nesneleri test edilen nesnelere basitçe geçiremeyiz, ancak Hizmet Bulucu'dan geçmemiz gerekir. Ayrıca, Service Locator kodun tasarımını bozar, çünkü her bir nesnenin onun varlığından haberdar olması gerekir, bu da nesnelerin DI konteyneri hakkında hiçbir bilgiye sahip olmadığı Dependency Injection'dan farklıdır.
DI kullanmamak ne zaman daha iyidir?
Dependency Injection tasarım modelinin kullanımıyla ilgili bilinen herhangi bir zorluk yoktur. Aksine, bağımlılıkları global olarak erişilebilir konumlardan elde etmek, bir Hizmet Bulucu kullanmak gibi bir dizi komplikasyona yol açar. Bu nedenle, her zaman DI kullanılması tavsiye edilir. Bu dogmatik bir yaklaşım değildir, ancak daha iyi bir alternatif bulunamamıştır.
Ancak, nesneleri birbirlerine aktarmadığımız ve global alandan elde etmediğimiz bazı durumlar vardır. Örneğin, kodda hata ayıklama yaparken ve programın belirli bir noktasında bir değişken değerini dökmek, programın belirli bir bölümünün süresini ölçmek veya bir mesajı günlüğe kaydetmek gerektiğinde. Daha sonra koddan kaldırılacak geçici eylemlerle ilgili olan bu gibi durumlarda, global olarak erişilebilir bir dumper, kronometre veya logger kullanmak meşrudur. Sonuçta bu araçlar kodun tasarımına ait değildir.
DI kullanmanın dezavantajları var mı?
Bağımlılık Enjeksiyonu kullanmanın kod yazma karmaşıklığının artması veya performansın düşmesi gibi dezavantajları var mıdır? DI'ye uygun kod yazmaya başladığımızda ne kaybederiz?
DI'nin uygulama performansı veya bellek gereksinimleri üzerinde hiçbir etkisi yoktur. DI Konteynerinin performansı bir rol oynayabilir, ancak Nette DI durumunda, konteyner saf PHP'ye derlenir, bu nedenle uygulama çalışma zamanı sırasında ek yükü esasen sıfırdır.
Kod yazarken, bağımlılıkları kabul eden yapıcılar oluşturmak gerekir. Geçmişte, bu zaman alıcı olabilirdi, ancak modern IDE'ler ve yapıcı özellik tanıtımı sayesinde artık birkaç saniye meselesi. Fabrikalar Nette DI ve bir PhpStorm eklentisi kullanılarak sadece birkaç tıklama ile kolayca oluşturulabilir. Öte yandan singleton ve statik erişim noktaları yazmaya da gerek kalmıyor.
DI kullanan düzgün tasarlanmış bir uygulamanın, tekli sınıf kullanan bir uygulamaya kıyasla ne daha kısa ne de daha uzun olduğu sonucuna varılabilir. Bağımlılıklarla çalışan kod parçaları basitçe tek tek sınıflardan çıkarılır ve DI konteyneri ve fabrikaları gibi yeni konumlara taşınır.
Eski bir uygulama DI için nasıl yeniden yazılır?
Eski bir uygulamadan Dependency Injection'a geçiş, özellikle büyük ve karmaşık uygulamalar için zorlu bir süreç olabilir. Bu sürece sistematik bir şekilde yaklaşmak önemlidir.
Bağımlılık Enjeksiyonuna geçerken, tüm ekip üyelerinin kullanılan ilke ve uygulamaları anlaması önemlidir.
-
İlk olarak, temel bileşenleri ve bağımlılıklarını belirlemek için mevcut uygulamanın bir analizini yapın. Hangi parçaların hangi sırayla yeniden düzenleneceğine dair bir plan oluşturun.
-
Bir DI konteyneri uygulayın ya da daha iyisi Nette DI gibi mevcut bir kütüphaneyi kullanın.
-
Bağımlılık Enjeksiyonunu kullanmak için uygulamanın her bir parçasını kademeli olarak yeniden düzenleyin. Bu, bağımlılıkları parametre olarak kabul etmek için kurucuları veya yöntemleri değiştirmeyi içerebilir.
-
Kodda bağımlılık nesnelerinin oluşturulduğu yerleri değiştirin, böylece bağımlılıklar bunun yerine kapsayıcı tarafından enjekte edilir. Bu, fabrikaların kullanımını içerebilir.
-
Dependency Injection'a geçmenin 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 zor olsa da, sonuçta daha temiz, daha modüler ve kolayca test edilebilir, gelecekteki uzantılara ve bakıma hazır bir kod ortaya çıkacaktır.
Neden kalıtım yerine kompozisyon tercih edilir?
Kalıtım yerine bileşimin kullanılması tercih edilir çünkü değişikliklerin sonuçları hakkında endişelenmek zorunda kalmadan kodun yeniden kullanılmasına hizmet eder. Böylece, bazı kodların değiştirilmesinin diğer bağımlı kodların değiştirilmesine neden olacağından endişelenmemize gerek kalmayan daha gevşek bir bağlantı sağlar. Tipik bir örnek, kurucu cehennemi olarak adlandırılan bir durumdur.
Nette DI Container Nette dışında kullanılabilir mi?
Kesinlikle. Nette DI Container, Nette'in bir parçasıdır, ancak çerçevenin diğer bölümlerinden bağımsız olarak kullanılabilen bağımsız bir kütüphane olarak tasarlanmıştır. Composer'ı kullanarak kurun, hizmetlerinizi tanımlayan bir yapılandırma dosyası oluşturun ve ardından DI konteynerini oluşturmak için birkaç satır PHP kodu kullanın. Böylece projelerinizde Dependency Injection'dan hemen yararlanmaya başlayabilirsiniz.
Nette DI Container bölümü, kod da dahil olmak üzere belirli bir kullanım durumunun neye benzediğini açıklar.
NEON dosyalarındaki yapılandırma neden?
NEON, uygulamaları, hizmetleri ve bunların bağımlılıklarını ayarlamak için Nette içinde geliştirilen 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 & YAML'de yazılması mümkün olmayan bağları doğal olarak ya hiç ya da sadece karmaşık bir açıklama yoluyla tanımlayabilirsiniz.
NEON dosyalarını ayrıştırmak uygulamayı yavaşlatıyor mu?
NEON dosyaları çok hızlı bir şekilde ayrıştırılsa da, bu özellik gerçekten önemli değildir. Bunun nedeni, dosyaların ayrıştırılmasının uygulamanın ilk başlatılması sırasında yalnızca bir kez gerçekleşmesidir. Bundan sonra, DI konteyner kodu oluşturulur, diskte saklanır ve sonraki her istek için daha fazla ayrıştırmaya gerek kalmadan yürütülür.
Üretim ortamında bu şekilde çalışır. Geliştirme sırasında, NEON dosyaları içerikleri her değiştiğinde ayrıştırılarak geliştiricinin her zaman güncel bir DI konteynerine sahip olması sağlanır. Daha önce de belirtildiği gibi, gerçek ayrıştırma bir anlık bir meseledir.
Sınıfımdaki yapılandırma dosyasından parametrelere nasıl erişebilirim?
Kural #1'i aklınızda tutun : Bırakın Size İletilsin. Bir sınıf bir yapılandırma dosyasından bilgi gerektiriyorsa, bu bilgiye nasıl erişeceğimizi bulmamız gerekmez; bunun yerine, örneğin sınıf kurucusu aracılığıyla basitçe sorarız. Ve aktarma işlemini yapılandırma dosyasında gerçekleştiririz.
Bu örnekte %myParameter%
, MyClass
kurucusuna aktarılacak olan myParameter
parametresinin değeri için bir yer tutucudur:
# config.neon
parameters:
myParameter: Some value
services:
- MyClass(%myParameter%)
Birden fazla parametre geçirmek veya otomatik bağlantı kullanmak istiyorsanız, parametreleri bir nesneye sarmak yararlı olacaktır.
Nette PSR-11 Konteyner arayüzünü destekliyor mu?
Nette DI Container PSR-11'i doğrudan desteklemez. Ancak, Nette DI Container ile PSR-11 Container Interface'i bekleyen kütüphaneler veya çerçeveler arasında birlikte çalışabilirliğe ihtiyacınız varsa, Nette DI Container ile PSR-11 arasında bir köprü görevi görecek basit bir adaptör oluşturabilirsiniz.