Inject Metotları ve Attribute'ları
Bu yazı, Nette framework'ünde bağımlılıkları presenter'lara aktarmanın çeşitli yollarını ele alıyor.
Tercih edilen yöntem olan constructor injection'ı, inject metotları ve attribute'ları gibi alternatiflerle
karşılaştıracağız.
Presenter'larda da, diğer sınıflarda olduğu gibi, bağımlılıkları yapıcı üzerinden aktarmak
tercih edilen yaklaşımdır. Ancak diğer presenter'ların türediği ortak bir ata sınıf (örneğin
BasePresenter) oluşturursanız ve bu atanın da bağımlılıkları varsa, constructor hell adıyla
bilinen bir sorun ortaya çıkabilir. Bu, alternatif yöntemlerle, yani inject metotları ve attribute'larıyla (eskiden
açıklamalarla) aşılabilir.
inject*() Metotları
Bu, bağımlılıkları setter'lar üzerinden
aktarmanın bir biçimidir. Bu setter'ların adları inject önekiyle başlamalıdır. Nette DI, bu şekilde
adlandırılmış metotları presenter örneği oluşturulur oluşturulmaz otomatik olarak çağırır ve gereken tüm
bağımlılıkları aktarır. Bu yüzden public olarak bildirilmeleri gerekir.
inject*() metotları, yapıcının birden çok metoda bölünmüş uzantıları gibi görülebilir. Bu,
BasePresenter'ın bağımlılıklarını ayrı bir metotla almasını sağlar ve yapıcıyı torunlarına
bırakır:
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
private Foo $foo;
public function injectBase(Foo $foo): void
{
$this->foo = $foo;
}
}
class MyPresenter extends BasePresenter
{
private Bar $bar;
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
}
Bir presenter istediği kadar inject*() metoduna sahip olabilir ve her biri istediği kadar parametre alabilir. Bu
yaklaşım, presenter'ın trait'lerden kurulduğu ve her
trait'in kendi bağımlılıklarını gerektirdiği durumlara da çok uygundur.
Inject Attribute'ları
Bu, özelliklere enjekte etmenin bir biçimidir. Enjekte edilmesi gereken özellikleri işaretlemeniz yeterlidir; Nette DI, presenter örneği oluşturulur oluşturulmaz bağımlılıkları otomatik olarak aktarır. Enjeksiyonun mümkün olması için bu özelliklerin public olarak bildirilmesi gerekir.
Özellikler bir attribute ile işaretlenir: (eskiden /** @inject */ açıklaması kullanılıyordu)
use Nette\DI\Attributes\Inject; // bu satır önemli
class MyPresenter extends Nette\Application\UI\Presenter
{
#[Inject]
public Cache $cache;
}
Bu bağımlılık aktarma yönteminin üstünlüğü, çok derli toplu söz dizimiydi. Ancak constructor property promotion geldikten sonra yapıcıyı kullanmak çoğu zaman daha basit görünüyor.
Buna karşılık bu yöntem, genel olarak property injection'ın taşıdığı sakıncaların aynısını taşır: değişkenin değişimi üzerinde denetimimiz olmaz ve değişken, sınıfın public arayüzünün bir parçası hâline gelir; bu da genellikle istenmeyen bir durumdur.