Bağımlılığın Tersine Çevrilmesi Uygulamada
Bağımlılığın tersine çevrilmesiyle adaptörleri çekirdeğe bağlayın.
Bağımlılığın Tersine Çevrilmesi Uygulamada, CoddyKit'te ücretsiz bir PHP Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, PHP Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. PHP Academy kursu toplamda 4 dersten oluşur.
Tersine Çevirme ve Enjeksiyon
İnsanlar birbirinden farklı iki fikri birbirine karıştırır. Bağımlılık Enjeksiyonu bir tekniktir: çalışma arkadaşlarını oluşturmak yerine dışarıdan geçirirsiniz. Bağımlılıkların Tersine Çevrilmesi (SOLID'deki D), bir ilkedir: üst düzey ilke ve alt düzey ayrıntı bir soyutlamaya dayanır ve soyutlamanın sahibi üst düzey modüldür. Bu ders, ikincisini gerçeğe dönüştürmeyi — somut adaptörleri arayüzleri tanımlayan bir çekirdeğe bağlamayı — ele alır.
İlke, Kesin Olarak
DIP şunları belirtir:
- Yüksek düzey modüller düşük düzey modüllere dayanmamalıdır. Her ikisi de soyutlamalara dayanmalıdır.
- Soyutlamalar ayrıntılara dayanmamalıdır. Ayrıntılar soyutlamalara dayanmalıdır.
İnce nokta şudur: arayüz, uygulayana değil tüketiciye aittir. Alanınız PaymentGateway'i tanımlar; Stripe adaptörü ona uyar — tersi değil.
Soyutlamayı Çekirdekte Tanımlayın
Arayüzü, ona ihtiyaç duyan kodun yanına, alan terimleriyle ifade ederek yerleştirin. Stripe türlerinin sızmasına izin vermeyin.
<?php
// src/Billing/Application/Port/PaymentGateway.php
interface PaymentGateway
{
public function charge(Money $amount, CardToken $token): ChargeId;
}
final class Money {
public function __construct(public readonly int $cents, public readonly string $currency) {}
}
final class CardToken { public function __construct(public readonly string $value) {} }
final class ChargeId { public function __construct(public readonly string $value) {} }Adaptörü Buna Uyumlu Hale Getirin
Altyapı adaptörü çekirdeğin arayüzünü uygular ve satıcının SDK'sına çeviri yapar. Bağımlılık oku, adaptörden (ayrıntı) soyutlamaya (ilke) yönelir — tersine çevirme sağlanmıştır.
<?php
final class StripePaymentGateway implements PaymentGateway
{
public function __construct(private \Stripe\StripeClient $stripe) {}
public function charge(Money $amount, CardToken $token): ChargeId {
$intent = $this->stripe->paymentIntents->create([
'amount' => $amount->cents,
'currency' => strtolower($amount->currency),
'payment_method' => $token->value,
'confirm' => true,
]);
return new ChargeId($intent->id);
}
}Kurucu Enjeksiyonu Varsayılandır
Kurucu aracılığıyla enjekte edin ve soyutlamanın türünü belirtin. Bağımlılıklar açıkça görülür, değişmez olur ve unutulmaları imkânsızlaşır. Zorunlu çalışma arkadaşları için ayarlayıcı yöntemi ve özellik enjeksiyonundan kaçının — bunlar yarı oluşturulmuş nesnelere izin verir.
<?php
final class CheckoutService
{
public function __construct(
private PaymentGateway $payments, // abstraction, not StripeClient
private OrderRepository $orders,
) {}
public function pay(OrderId $id, CardToken $token): ChargeId {
$order = $this->orders->get($id);
$charge = $this->payments->charge($order->total(), $token);
$order->markPaid($charge);
$this->orders->save($order);
return $charge;
}
}Birleştirme Kökü
Tüm somut bağlama işlemleri tam olarak tek bir yerde — birleştirme kökünde — ve mümkün olduğunca main()'e ya da giriş noktasına yakın gerçekleştirilir. Başka hiçbir yer altyapı nesnelerini kendisi oluşturmaz. Stripe'ın var olduğunu bilen tek yer burasıdır.
<?php
// public/index.php — composition root
$stripe = new \Stripe\StripeClient(getenv('STRIPE_SECRET'));
$gateway = new StripePaymentGateway($stripe);
$orders = new PdoOrderRepository(new PDO(getenv('DB_DSN')));
$checkout = new CheckoutService($gateway, $orders);
// Everything below depends only on abstractions
$controller = new CheckoutController($checkout);DI Konteyneriyle Bağlama
Karmaşık uygulamalarda bir konteyner (PHP-DI, Symfony) bağlama işlemini otomatikleştirir. Temel adım, arayüzleri uygulamalara bağlamaktır. Otomatik bağlama, kurucuları türlerine göre çözer; yalnızca arayüz→sınıf eşlemesini tanımlarsınız.
<?php
use function DI\autowire;
use function DI\get;
return [
PaymentGateway::class => autowire(StripePaymentGateway::class),
OrderRepository::class => autowire(PdoOrderRepository::class),
\Stripe\StripeClient::class => fn() => new \Stripe\StripeClient(getenv('STRIPE_SECRET')),
PDO::class => fn() => new PDO(getenv('DB_DSN')),
];Adaptörleri Değiştirmek Noktayı Kanıtlar
Çekirdek yalnızca PaymentGateway'e dayandığından, sağlayıcıları değiştirmek veya çevrimdışı sınama yapmak tek satırlık bir bağlama değişikliğidir. Aşağıda birim sınamasında kullanılan bir sahte bulunmaktadır — CheckoutService değişmeden kalır ve Stripe'ı hiçbir zaman içe aktarmamıştır.
<?php
final class FakeGateway implements PaymentGateway {
public array $charges = [];
public function charge(Money $a, CardToken $t): ChargeId {
$this->charges[] = $a;
return new ChargeId('ch_test_' . count($this->charges));
}
}
$fake = new FakeGateway();
$id = $fake->charge(new Money(2500, 'EUR'), new CardToken('tok_visa'));
echo $id->value, ' charges=', count($fake->charges), PHP_EOL; // ch_test_1 charges=1Hizmet Bulucu Tuzağından Kaçının
Konteynerin kendisini enjekte edip yöntemlerin içinde bağımlılıkları çekmek, hizmet bulucu karşıt örüntüsüdür. Bağımlılıkları gizler, tür denetimini etkisiz kılar ve kodunuzu konteynere yeniden bağlar. İhtiyacınız olanları açıkça enjekte edin.
<?php
// ANTI-PATTERN: hidden dependencies, container leaks everywhere
final class BadCheckout {
public function __construct(private ContainerInterface $c) {}
public function pay($id, $token) {
$gateway = $this->c->get(PaymentGateway::class); // hidden!
// ...
}
}Konteyner Nerede Görünebilir
Konteyner tam olarak tek bir katmanda meşrudur: birleştirme kökünde ve onu çevreleyen çerçeve entegrasyon kodunda (ör. bir denetleyici fabrikasında). Alan ve uygulama sınıflarınız konteynerden bağımsız kalmalıdır — kurucular aracılığıyla yalın nesneler almalı ve elle oluşturulabilmelidir. İyi bir sınama şudur: tüm uygulamayı konteyner olmadan tek bir PHP dosyasında bağlayabilir misiniz? Yanıt evetse bağımlılıklarınız dürüsttür.
Hizmet Bulucu Olmadan Gecikmeli Bağlama
Bazen bir bağımlılığın oluşturulması pahalıdır veya yalnızca koşullu olarak gerekir. Konteyneri enjekte etmeye direnin — bunun yerine bir fabrika kapanışı enjekte edin. Bağımlılık açık ve türü belirli kalırken oluşturma işlemi gerçekten kullanılana kadar ertelenir.
<?php
final class ReportService
{
/** @param Closure():PaymentGateway $gatewayFactory */
public function __construct(private Closure $gatewayFactory) {}
public function refundIfNeeded(bool $needed): void {
if (!$needed) return;
$gateway = ($this->gatewayFactory)(); // built only when required
// $gateway->charge(...) etc.
}
}
// Composition root supplies the factory, not the container
$svc = new ReportService(fn() => new StripePaymentGateway($stripe ?? null));
echo 'lazy dependency wired', PHP_EOL;Hızlı Kontrol
PaymentGateway arayüzünün sahibi kim olmalıdır?
Özet
Adaptörleri çekirdeğe doğru şekilde bağladınız:
- Tersine çevirme ≠ enjeksiyon: enjeksiyon mekanizmadır; tersine çevirme ise soyutlamanın tüketicide bulunmasıdır.
- Çekirdek arayüzü tanımlar; altyapı adaptörleri ona uyar.
- Soyutlamaları kurucu aracılığıyla enjekte edin; tüm somut bağlama işlemlerini tek bir birleştirme kökünde (veya arayüz→sınıf bağlayan konteyner yapılandırmasında) gerçekleştirin.
- Adaptörleri değiştirmek ve sınamalarda sahte kullanmak tek satırlık bir değişikliğe dönüşür.
- Hizmet bulucu karşıt örüntüsünden kaçının — konteyneri yalnızca kenarda tutun.
Sıkça Sorulan Sorular
“Bağımlılığın Tersine Çevrilmesi Uygulamada” dersi ücretsiz mi?
Evet — “Bağımlılığın Tersine Çevrilmesi Uygulamada” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve PHP Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. PHP Academy kursu toplamda 4 dersten oluşur.
“Bağımlılığın Tersine Çevrilmesi Uygulamada” dersinde ne öğreneceğim?
Bağımlılığın tersine çevrilmesiyle adaptörleri çekirdeğe bağlayın. PHP Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
PHP Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te PHP Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Bağımlılığın Tersine Çevrilmesi Uygulamada” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu PHP Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her PHP Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Katmanlı Mimariden Temiz Mimariye
- Portlar ve Adaptörler Açıklaması
- Kullanım Durumları ve Uygulama Hizmetleri
- Bağımlılığın Tersine Çevrilmesi Uygulamada