
Nesne Yönelimli Programlama: Sınıf, Arayüz ve Soyutlama
Nesne yönelimli programlama, veriyi ve o veriyi işleyen davranışı bir arada tutar. Kazancı, ilgili parçaların tek yerde toplanması ve dış dünyaya yalnızca gerekli olanın açılmasıdır. Ancak her sorun bu modele uygun değildir.
Girdisini alıp sonucunu döndüren, durum tutmayan işler için serbest fonksiyon hem daha basit hem daha test edilebilirdir. Sınıf, ortak bir durumu paylaşan davranışlar olduğunda anlam kazanır.
Sınıf ne zaman gerekir?
Pratik gösterge, aynı parametrelerin birden fazla fonksiyonda tekrar etmesidir. Bu parametreler aslında bir nesnenin durumudur ve sınıfa taşındığında imzalar sadeleşir:
declare(strict_types=1);
final class SiparisServisi
{
public function __construct(
private PDO $db,
private LoggerInterface $gunluk,
) {}
public function olustur(array $sepet, int $kullaniciId): int
{
// $this->db ve $this->gunluk her metotta hazır
return 0;
}
}Yapıcı içinde özellik tanımı, PHP 8 ile gelen bir kısaltmadır. Aynı ad üç kez yazılmadığı için sınıfların bağımlılık listesi tek bakışta okunur hale gelir.
Kapsülleme
Kapsülleme, nesnenin iç durumunun dışarıdan doğrudan değiştirilememesidir. Tüm özellikleri açık bırakmak, sınıfı üzerinde metot bulunan bir diziye indirger ve tutarlılık denetimini imkansız kılar.
Değişmez olması gereken alanlar readonly olarak işaretlenir. Böylece nesne kurulduktan sonra o alanın değiştirilmesi çalışma anında engellenir:
final class Para
{
public function __construct(
public readonly int $kurus,
public readonly string $birim,
) {
if ($kurus < 0) {
throw new InvalidArgumentException('Tutar negatif olamaz');
}
}
public function ekle(self $diger): self
{
return new self($this->kurus + $diger->kurus, $this->birim);
}
}Doğrulamanın yapıcıda yapılması, geçersiz durumda nesnenin hiç oluşmamasını sağlar. Böylece kodun geri kalanı nesnenin geçerli olduğunu varsayabilir.
Arayüz ve bağımlılık yönü
Arayüz, bir davranışın sözleşmesini gerçekleştiriminden ayırır. Uygulama kodu somut sınıfa değil arayüze bağlandığında, gerçekleştirimin değişmesi çağıran tarafı etkilemez:
interface BildirimGonderici
{
public function gonder(string $alici, string $mesaj): bool;
}
final class EpostaGonderici implements BildirimGonderici { /* ... */ }
final class SmsGonderici implements BildirimGonderici { /* ... */ }
final class SiparisBildirimi
{
public function __construct(private BildirimGonderici $gonderici) {}
}Bu yapının test tarafındaki karşılığı da önemlidir. Arayüz sayesinde testte gerçek eposta gönderimi yerine sahte bir gerçekleştirim verilebilir ve test dış servise bağımlı kalmaz.
Kalıtım yerine bileşim
Kalıtım, alt sınıfı üst sınıfın iç yapısına bağlar. Üst sınıfta yapılan değişiklik tüm alt sınıflara yayılır ve zamanla derin hiyerarşiler ortaya çıkar. Çoğu durumda ihtiyaç duyulan şey yeniden kullanımdır ve bu, nesneyi içeride tutarak da sağlanabilir.
Kalıtım yalnızca gerçek bir alt tür ilişkisi varsa kullanılmalıdır: alt sınıf, üst sınıfın geçtiği her yerde sorunsuz kullanılabiliyorsa ilişki doğrudur. Yalnızca kod paylaşmak için kurulan kalıtım, ilk değişiklikte sorun çıkarır.
Erken soyutlamanın maliyeti
Tek gerçekleştirimi olan arayüzler, gelecekte gerekebilir düşüncesiyle yazılan soyut sınıflar ve her sınıf için otomatik üretilen fabrikalar, çözdüğünden fazla karmaşıklık üretir. Okuyan kişi basit bir işlemi izlemek için beş dosya arasında dolaşmak zorunda kalır.
Uygulanabilir kural şudur: soyutlama, ikinci gerçek gereksinim ortaya çıktığında eklenir. İlk gerçekleştirimde doğrudan sınıf kullanmak, sonradan arayüz çıkarmayı zorlaştırmaz.
PHP 8 ile gelen araçlar
Sabit değer kümeleri için enum kullanmak, sınıf sabitlerine göre çok daha güvenlidir. Beklenen değer kümesi tip sistemine taşındığı için geçersiz değer hiç geçemez:
enum SiparisDurumu: string
{
case Bekliyor = 'bekliyor';
case Hazirlaniyor = 'hazirlaniyor';
case Tamamlandi = 'tamamlandi';
public function iptalEdilebilir(): bool
{
return $this !== self::Tamamlandi;
}
}
function durumGuncelle(SiparisDurumu $durum): void { /* ... */ }Enum içine davranış da yazılabildiği için, duruma bağlı kurallar tek yerde toplanır. Bu kuralın kod içine dağılmış koşullarla tekrarlanmasına gerek kalmaz.
Yapıcı içinde tanımlanan salt okunur özellikler, veri taşıyan sınıfları da sadeleştirir. Getter ve setter yazmadan, değeri korunan küçük nesneler oluşturmak mümkün hale gelir. Böylece veri yapıları hem güvenli hem kısa kalır.
Kontrol listesi
- Durum paylaşılmıyorsa fonksiyon yeterlidir.
- Özellikler dışarıya açılmaz, değişmezler readonly işaretlenir.
- Doğrulama yapıcıda yapılır, geçersiz nesne hiç oluşmaz.
- Bağımlılıklar arayüz üzerinden alınır.
- Kod paylaşımı için kalıtım kurulmaz, bileşim tercih edilir.
- Soyutlama ikinci gereksinim doğduğunda eklenir.
İlgili yazılar
Yorumlar
İlk yorumu sen yap.
İlgili Yazılar

PHP Uygulamasını Üretime Almak: Yapılandırma ve Güvenlik
Geliştirme makinesinde çalışan kod ile üretimde güvenle çalışan kod arasındaki fark yapılandırmadır. Ayarlar, izinler, dağıtım akışı ve son kontroller.

PHP ile REST API Yazmak: Yönlendirme ve HTTP Durum Kodları
Bir API'nin kalitesi çoğunlukla ayrıntılarda belli olur: doğru durum kodu, tutarlı hata biçimi ve öngörülebilir adresler. Saf PHP ile uçtan uca kurulum.

PHPUnit ile Birim Test Yazmak: Kurulum, Sahte Nesneler ve Kapsam
Testin amacı hata bulmak değil, değişikliği güvenle yapabilmektir. Kurulum, ilk test, sahte nesneler ve test edilebilir kodun özellikleri.