PHP traits, genelde kod tekrarını sağlamak için kullanışlı bir yöntem olarak sunulur. Fakat pratikte, bunlar PHP’deki en karmaşık araçlardan biri olup, mimarinizi, testlerinizi ve kod okunurluğunu kolayca bozabilir.
Traits’in tamamen kötü olduğunu iddia etmiyorum, ama yıllarca PHP ile çalıştıktan sonra ulaştığım sonuç şu: traits bir tasarım kokusudur.
Traits Nedir?
Traits Nedir?
Traits, tekil kalıtımı aşmak için bir uzlaşma olarak ortaya çıkmıştır. Kalıtım, kompozisyon ya da bir arayüz değildir. Kısacası, açık bağımlılıklar olmadan bir sınıfa kod “yapıştırmanın” bir yoludur. İşte tam da burada sorunlar başlar. Düşük seviyede, basit bir kopyala-yapıştır gibi çalışır.
Neden Sorunlara Yol Açarlar?
Neden Sorunlara Yol Açarlar?
Kötü okunabilirlik. use SomeTrait ile bir sınıf gördüğümde, o sınıfın ne yaptığını bilemiyorum. Anlamak için trait’i açmam, beklenen korumalı metodları ve özellikleri kontrol etmem ve bir şeyi geçersiz kılıp kılmadığını çözmem gerekiyor. Sınıfın davranışı anlaşılmaz hale geliyor.
Gizli bağımlılık. Gerçek kodda, trait’ler genellikle sınıfın korumalı özelliklerini kullanır veya sınıfın kendisinin uygulamadığı korumalı metodları çağırır. Sonuç olarak, iki yönlü, örtük bir bağımlılık oluşur – trait, sınıfın iç detaylarını bilirken, sınıf da trait’in iç detaylarına bağımlıdır. Bunu yapıcıdan veya metot imzalarından göremezsiniz.
Kapsülleme bozukluğu. Traits, bir sınıfın iç durumuna erişimi teşvik eder. Net sözleşmeler ve açık bağımlılıklar yerine, “trait nerede ise bir $service bekliyor” gibi ifadelere sahipsiniz. İç yapıyı değiştirdiğinizde, trait bozulur.
Test edilmesi zor. Bir trait’i örnekleyemezsiniz. Test etmek için, sahte bir sınıf oluşturmanız, tüm korumalı bağımlılıkları ayarlamanız ve hiçbir şeyi atlamadığınızdan emin olmanız gerekir. Bu birim testi değil, bir geçici çözümdür.
Mimari karmaşa. PHP, trait’lerin içinde trait’lere izin verir, bir sınıfta birden fazla trait bulunabilir. Bu, “elmas problemleri”, bağımlılık zincirleri ve kodun “çalışması” ama kimsenin nasıl çalıştığını anlayamadığı durumlardan kolayca kaçınmanıza neden olabilir.
PHP 8.x İyileştirmeleri Hakkında Ne Söylenebilir?
PHP 8.x İyileştirmeleri Hakkında Ne Söylenebilir?
PHP 8, trait’lerde soyut metodlar, sabitler ve statik özelliklerde değişiklikler ekledi. Ne yazık ki, SOLID ve temiz mimari bakış açısından bu durum işleri daha da karmaşıklaştırmıştır – trait’ler artık kalıtım düşüncesine daha derinlemesine çekilmektedir.
Tipik Koku
Tipik Koku
Bir trait, korumalı metodlara sahipse ve sınıftan korumalı hizmetler kullanıyorsa, çoğunlukla kendi sınıfına çıkarılması gereken ayrı bir nesne olduğunu gösterir.
Bunun Yerine Ne Kullanıyorum?
Bunun Yerine Ne Kullanıyorum?
Durumların %90’ında cevap basittir:
- Dependency Injection – bağımlılıklar açıktır, kod yapıcıdan okunabilir.
- Kompozisyon – “has-a” yerine “uses”.
- Strateji / Fabrika – özellikle korumalı yardımcı metodlar yerine.
- Bir basit sınıf veya fonksiyon – eğer trait’in durumu yoksa, muhtemelen gereksizdir.
Tüm bunlar, bağımlılıkları görünür kılar, test edilebilirliği artırır ve mimariyi temiz tutar.
Hızlı Yeniden Yapılandırma Örneği
Hızlı Yeniden Yapılandırma Örneği
Önce (trait ile):
trait NotifiableTrait
{
protected function notifyUser(string $message)
{
$this->notificationService->send($this->user, $message);
}
}
final class OrderCreateAction
{
use NotifiableTrait;
public function handle(OrderCreateDTO $dto)
{
...order logic...
$this->notifyUser('Order created!'); // bu nereden geliyor?
}
}
Sonra (DI ile):
final class OrderCreateAction
{
public function __construct(private readonly UserNotifier $notifier) {}
public function handle(OrderCreateDTO $dto)
{
...order logic...
$this->notifier->send($user, 'Order created!'); // açık ve net
}
}
Artık bağımlılıklar görünür, test edilebilir ve açık bir şekilde tanımlanmıştır.
Sonuç
Sonuç
Traits, genellikle sonrasında uzun bir yeniden yapılandırmaya yol açan bir kısayoldur. Davranış ayrı bir nesneye çıkarılabiliyorsa, çıkarılmalıdır. Eğer bir trait’in durumu yoksa, büyük ihtimalle var olmaması gerekir. Traits’i yasaklamıyorum. Sadece sonrasında bunun bedelini ödememek için dikkatli olmaya çalışıyorum.
Kaynaklar
Kaynaklar
Yazar Notu
Yazar Notu
Okuduğunuz için teşekkürler!
Beni dev.to, LinkedIn üzerinden bulabilir veya çalışmalarımı GitHub‘dan kontrol edebilirsiniz.
Gerçek dünya Laravel’inden notlar.
Kaynak: Orijinal Makale


