Bağımlılıkları Geçme
Argümanlar veya DI terminolojisinde „bağımlılıklar“ sınıflara aşağıdaki ana yollarla aktarılabilir:
- kurucu tarafından geçiş
- yöntemle geçiş (setter olarak adlandırılır)
- bir özellik ayarlayarak
- yöntem, ek açıklama veya öznitelik ile enjekte
Şimdi farklı varyantları somut örneklerle açıklayacağız.
Kurucu Enjeksiyonu
Nesne oluşturulduğunda bağımlılıklar yapıcıya argüman olarak aktarılır:
Bu form, sınıfın çalışması için kesinlikle ihtiyaç duyduğu zorunlu bağımlılıklar için kullanışlıdır, çünkü bunlar olmadan örnek oluşturulamaz.
PHP 8.0'dan beri, işlevsel olarak eşdeğer olan daha kısa bir gösterim biçimi kullanabiliriz (constructor property promotion):
PHP 8.1'den itibaren bir özellik, içeriğinin değişmeyeceğini bildiren readonly
bayrağı ile
işaretlenebilir:
DI konteyneri, otomatik bağlantı kullanarak bağımlılıkları otomatik olarak kurucuya geçirir. Bu şekilde aktarılamayan bağımsız değişkenler (örn. dizeler, sayılar, booleanlar) yapılandırmada yazılır.
İnşaatçı Cehennemi
İnşaatçı cehennemi terimi, bir çocuğun yapıcısı bağımlılıklar gerektiren bir ana sınıftan miras aldığı ve çocuğun da bağımlılıklara ihtiyaç duyduğu bir durumu ifade eder. Ayrıca ebeveynin bağımlılıklarını da devralmalı ve aktarmalıdır:
Sorun, BaseClass
sınıfının kurucusunu değiştirmek istediğimizde, örneğin yeni bir bağımlılık
eklendiğinde ortaya çıkar. O zaman tüm alt sınıfların kurucularını da değiştirmemiz gerekir. Bu da böyle bir
değişikliği cehenneme çevirir.
Bu nasıl önlenebilir? Çözüm [kalıtım yerine bileşime |faq#Why composition is preferred over inheritance] öncelik vermektir.
Öyleyse kodu farklı bir şekilde tasarlayalım. Soyut Base*
sınıflarından kaçınacağız. MyClass
, BaseClass
'dan miras alarak bazı işlevler elde etmek
yerine, bu işlevselliği bir bağımlılık olarak geçirecektir:
Ayarlayıcı Enjeksiyonu
Bağımlılıklar, onları özel bir özellikte saklayan bir yöntem çağrılarak aktarılır. Bu yöntemler için olağan
adlandırma kuralı set*()
şeklindedir, bu nedenle ayarlayıcılar olarak adlandırılırlar, ancak elbette başka
herhangi bir şekilde adlandırılabilirler.
Bu yöntem, nesnenin bunları gerçekten alacağı (yani kullanıcının yöntemi çağıracağı) garanti edilmediğinden, sınıf işlevi için gerekli olmayan isteğe bağlı bağımlılıklar için kullanışlıdır.
Aynı zamanda, bu yöntem bağımlılığı değiştirmek için setter'ın tekrar tekrar çağrılmasına izin verir. Bu
istenmiyorsa, yönteme bir kontrol ekleyin veya PHP 8.1'den itibaren $cache
özelliğini readonly
bayrağı ile işaretleyin.
Setter çağrısı, kurulum bölümündeki DI konteyner yapılandırmasında tanımlanır. Ayrıca burada bağımlılıkların otomatik geçişi autowiring tarafından kullanılır:
Mülkiyet Enjeksiyonu
Bağımlılıklar doğrudan özelliğe aktarılır:
Bu yöntemin uygun olmadığı düşünülmektedir, çünkü özellik public
olarak bildirilmelidir. Bu nedenle,
aktarılan bağımlılığın gerçekten belirtilen türde olup olmayacağı üzerinde hiçbir kontrolümüz yoktur (bu PHP
7.4'ten önce doğruydu) ve yeni atanan bağımlılığa kendi kodumuzla tepki verme yeteneğimizi kaybederiz, örneğin sonraki
değişiklikleri önlemek için. Aynı zamanda, özellik sınıfın genel arayüzünün bir parçası haline gelir ki bu da arzu
edilen bir durum olmayabilir.
Değişkenin ayarı, kurulum bölümündeki DI konteyner yapılandırmasında tanımlanır:
Enjeksiyon
Önceki üç yöntem genel olarak tüm nesne yönelimli dillerde geçerli olsa da, yöntem, ek açıklama veya inject niteliği ile enjekte etme Nette sunucularına özgüdür. Bunlar ayrı bir bölümde ele alınmaktadır.
Hangi Yolu Seçmeli?
- yapıcı, sınıfın çalışması için gereken zorunlu bağımlılıklar için uygundur
- setter ise isteğe bağlı bağımlılıklar veya değiştirilebilen bağımlılıklar için uygundur
- genel değişkenler önerilmez