Kendi sıkı bağlı Laravel uygulamamı test edilebilir ve sürdürülebilir bir kod temeline dönüştürmek için Service Container desenini nasıl kullandım.
<h3>
<a name="the-problem-i-couldnt-ignore" href="#the-problem-i-couldnt-ignore">
</a>
Göz ardı edemeyeceğim sorun
</h3>
<p>Laravel projemin altıncı ayında kodum şöyle görünüyordu:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">OrderController</span> <span class="kd">extends</span> <span class="nc">Controller</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">store</span><span class="p">(</span><span class="kt">Request</span> <span class="nv">$request</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$paymentGateway</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StripePaymentGateway</span><span class="p">();</span>
<span class="nv">$emailService</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SendGridEmailService</span><span class="p">();</span>
<span class="nv">$inventoryManager</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">InventoryManager</span><span class="p">();</span>
<span class="c1">// Sıkı bağlı bir kâbus</span>
<span class="c1">// Test yazmak imkânsız</span>
<span class="c1">// Sürdürmek zor</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<h3>
<a name="the-problems-were-real" href="#the-problems-were-real">
</a>
Sorunlar Gerçekti:
</h3>
<p>🔴 Stripe API'sine erişmeden test edemedim.<br/>🔴 Ödeme sağlayıcılarını değiştirmek controllerları yeniden yazmayı gerektiriyordu.<br/>🔴 Sıfır birim testi (test yazmak imkân dışıydı).<br/>🔴 Her yeniden yapılandırma beklenmedik bir soruna yol açıyordu.</p>
<h3>
<a name="the-solution-laravels-service-container" href="#the-solution-laravels-service-container">
</a>
Çözüm: Laravel'in Service Container'ı
</h3>
<p>Laravel'in Service Container'ı + Dependency Injection her şeyi dönüştürdü:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="c1">// Sözleşmeyi tanımla</span>
<span class="kd">interface</span> <span class="nc">PaymentGatewayInterface</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">charge</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">,</span> <span class="kt">array</span> <span class="nv">$details</span><span class="p">):</span> <span class="kt">PaymentResult</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// Bağımlılıkları enjekte et</span>
<span class="kd">class</span> <span class="nc">OrderController</span> <span class="kd">extends</span> <span class="nc">Controller</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span>
<span class="k">private</span> <span class="kt">PaymentGatewayInterface</span> <span class="nv">$payment</span><span class="p">,</span>
<span class="k">private</span> <span class="kt">EmailServiceInterface</span> <span class="nv">$email</span><span class="p">,</span>
<span class="k">private</span> <span class="kt">InventoryManager</span> <span class="nv">$inventory</span>
<span class="p">)</span> <span class="p">{}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">store</span><span class="p">(</span><span class="kt">Request</span> <span class="nv">$request</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Artık test edilebilir, esnek, sürdürülebilir</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<h3>
<a name="bind-in-your-service-provider" href="#bind-in-your-service-provider">
</a>
Servis Sağlayıcınızda Bağlayın:
</h3>
<p>Gerçek Etki: Dönüşüm<br/>Önce:</p>
<p>❌ 0 birim testi<br/>❌ Ödeme sağlayıcılarını değiştirmek 3 gün<br/>❌ Her bağımlılık değişikliği için 12 dosya değiştirildi<br/>❌ Yeniden yapılandırma korkusu</p>
<p>Sonra:</p>
<p>✅ %94 test kapsamı<br/>✅ Sağlayıcıları değiştirmek için 15 dakika (yapılandırma sadece)<br/>✅ Tek bir servis sağlayıcı değişikliği<br/>✅ Yeniden yapılandırma konusunda güven</p>
<h3>
<a name="testing-became-actually-enjoyable" href="#testing-became-actually-enjoyable">
</a>
Test Yapmak Gerçekten Eğlenceli Hale Geldi
</h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">OrderProcessorTest</span> <span class="kd">extends</span> <span class="nc">TestCase</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">test_successful_order</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// Bağımlılıkları taklit et</span>
<span class="nv">$mockPayment</span> <span class="o">=</span> <span class="nc">Mockery</span><span class="o">::</span><span class="nf">mock</span><span class="p">(</span><span class="nc">PaymentGatewayInterface</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="nv">$mockPayment</span><span class="o">-></span><span class="nf">shouldReceive</span><span class="p">(</span><span class="s1">'charge'</span><span class="p">)</span>
<span class="o">-></span><span class="nf">once</span><span class="p">()</span>
<span class="o">-></span><span class="nf">andReturn</span><span class="p">(</span><span class="k">new</span> <span class="nc">PaymentResult</span><span class="p">(</span><span class="n">success</span><span class="o">:</span> <span class="kc">true</span><span class="p">));</span>
<span class="c1">// Taklitleri enjekte et - gerçek API çağrısı yok!</span>
<span class="nv">$processor</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OrderProcessor</span><span class="p">(</span><span class="nv">$mockPayment</span><span class="p">,</span> <span class="nv">$mockEmail</span><span class="p">,</span> <span class="nv">$mockInventory</span><span class="p">);</span>
<span class="nv">$result</span> <span class="o">=</span> <span class="nv">$processor</span><span class="o">-></span><span class="nf">process</span><span class="p">(</span><span class="nv">$order</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-></span><span class="nf">assertTrue</span><span class="p">(</span><span class="nv">$result</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<h3>
<a name="advanced-pattern-contextual-binding" href="#advanced-pattern-contextual-binding">
</a>
İleri Düzey Desen: Bağlamsal Bağlama
</h3>
<p>Farklı bağlamlar farklı uygulamalar gerektirir:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="c1">// Admin ayrıntılı kayıt alır</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">app</span><span class="o">-></span><span class="nf">when</span><span class="p">(</span><span class="nc">AdminController</span><span class="o">::</span><span class="n">class</span><span class="p">)</span>
<span class="o">-></span><span class="nf">needs</span><span class="p">(</span><span class="nc">LoggerInterface</span><span class="o">::</span><span class="n">class</span><span class="p">)</span>
<span class="o">-></span><span class="nf">give</span><span class="p">(</span><span class="nc">DetailedLogger</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="c1">// API en az kayıt alır</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">app</span><span class="o">-></span><span class="nf">when</span><span class="p">(</span><span class="nc">ApiController</span><span class="o">::</span><span class="n">class</span><span class="p">)</span>
<span class="o">-></span><span class="nf">needs</span><span class="p">(</span><span class="nc">LoggerInterface</span><span class="o">::</span><span class="n">class</span><span class="p">)</span>
<span class="o">-></span><span class="nf">give</span><span class="p">(</span><span class="nc">MinimalLogger</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<h3>
<a name="common-pitfalls-to-avoid" href="#common-pitfalls-to-avoid">
</a>
Kaçınılması Gereken Ortak Tuzaklar
</h3>
<p>*<em>1. Aşırı Mühendislik Yapmayın<br/>*</em><br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="c1">// ❌ Basit durumlar için gereksiz</span>
<span class="kd">interface</span> <span class="nc">UserFormatterInterface</span> <span class="p">{</span> <span class="p">}</span>
<span class="c1">// ✅ Basit tutun</span>
<span class="kd">class</span> <span class="nc">UserFormatter</span> <span class="p">{</span> <span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<p><strong>2. Döngüsel Bağımlılıklara Dikkat Edin</strong><br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="c1">// ❌ Bu hata verir</span>
<span class="kd">class</span> <span class="nc">OrderService</span> <span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="kt">InvoiceService</span> <span class="nv">$invoice</span><span class="p">)</span> <span class="p">{}</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="nc">InvoiceService</span> <span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="kt">OrderService</span> <span class="nv">$order</span><span class="p">)</span> <span class="p">{}</span>
<span class="p">}</span>
<span class="c1">// ✅ Olayları kullanarak ayrıştırın</span>
<span class="nf">event</span><span class="p">(</span><span class="k">new</span> <span class="nc">OrderCreated</span><span class="p">(</span><span class="nv">$order</span><span class="p">));</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<p> 3. Servis Sağlayıcılarını Düzenleyin<br/> Her şeyi AppServiceProvider'a koymayın. Özelleştirilmiş sağlayıcılar oluşturun:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="c1">// PaymentServiceProvider.php</span>
<span class="kd">class</span> <span class="nc">PaymentServiceProvider</span> <span class="kd">extends</span> <span class="nc">ServiceProvider</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">register</span><span class="p">()</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">app</span><span class="o">-></span><span class="nf">bind</span><span class="p">(</span><span class="nc">PaymentGatewayInterface</span><span class="o">::</span><span class="n">class</span><span class="p">,</span> <span class="nc">StripePaymentGateway</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">app</span><span class="o">-></span><span class="nf">singleton</span><span class="p">(</span><span class="nc">PaymentProcessor</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<h2>
<a name="quick-wins-you-can-implement-today" href="#quick-wins-you-can-implement-today">
</a>
Bugün Uygulayabileceğiniz Hızlı Kazançlar
</h2>
<h3>
<a name="1-use-method-injection-for-oneoff-dependencies" href="#1-use-method-injection-for-oneoff-dependencies">
</a>
1. Tek Seferlik Bağımlılıklar için Metot Enjeksiyonunu Kullanın:
</h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="k">public</span> <span class="k">function</span> <span class="n">generate</span><span class="p">(</span><span class="kt">Request</span> <span class="nv">$request</span><span class="p">,</span> <span class="kt">ReportGenerator</span> <span class="nv">$generator</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Laravel sadece gerektiğinde otomatik olarak çözer</span>
<span class="k">return</span> <span class="nv">$generator</span><span class="o">-></span><span class="nf">create</span><span class="p">(</span><span class="nv">$request</span><span class="o">-></span><span class="nf">input</span><span class="p">(</span><span class="s1">'type'</span><span class="p">));</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<h3>
<a name="2-tag-related-services" href="#2-tag-related-services">
</a>
2. İlgili Servisleri Etiketleyin:
</h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="nv">$this</span><span class="o">-></span><span class="n">app</span><span class="o">-></span><span class="nf">tag</span><span class="p">([</span>
<span class="s1">'payment.stripe'</span><span class="p">,</span>
<span class="s1">'payment.paypal'</span><span class="p">,</span>
<span class="p">],</span> <span class="s1">'payment.gateways'</span><span class="p">);</span>
<span class="c1">// Tüm etiketlenmiş servisleri kullan</span>
<span class="nv">$gateways</span> <span class="o">=</span> <span class="nf">app</span><span class="p">()</span><span class="o">-></span><span class="nf">tagged</span><span class="p">(</span><span class="s1">'payment.gateways'</span><span class="p">);</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<h3>
<a name="3-use-singletons-for-expensive-operations" href="#3-use-singletons-for-expensive-operations">
</a>
3. Pahalı İşlemler için Singleton Kullanın:
</h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="c1">// Aynı örneği yeniden kullan</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">app</span><span class="o">-></span><span class="nf">singleton</span><span class="p">(</span><span class="nc">ExpensiveService</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action">
</div>
</div>
</div>
<p>*<em>Önemli Noktalar<br/>*</em></p>
<ul>
<li>Abstraksiyonları temel al - esneklik için arayüzler kullanın</li>
<li>Laravel'in çözmesine izin verin - konteyner güçlüdür, onu kullanın</li>
<li>Her şeyi test edin - DI test etmeyi mümkün kılar</li>
<li>Basit başlayın - ihtiyacınız olduğunda soyutlama ekleyin</li>
<li>Bağlamaları düzenleyin</li>
<li>Özel servis sağlayıcıları kullanın</li>
</ul>
<p>*<em>Sonuç olarak<br/>*</em><br/>Service Container yalnızca bağımlılıkları yönetmekle ilgili değildir - ihtiyaçlarınızla birlikte evrilen bir kod yazmak içindir; büyük yeniden yazmalar olmaksızın.<br/>Stripe'dan PayPal'a geçmek 3 gün sürüyordu ve 12'den fazla dosyayı etkiliyordu. Artık? Bir yapılandırma dosyasında bir satırı değiştirmek. Maksimum 15 dakika.<br/>Doğru bağımlılık enjeksiyonunun gücü budur.</p>
<h2>
<a name="want-the-full-deep-dive" href="#want-the-full-deep-dive">
</a>
📚 Tam Derinlemesine İnceleme İster Misiniz?
</h2>
<ul>
<li>Bu, yoğunlaştırılmış bir versiyon. Tam kılavuz için:</li>
<li>Ödeme geçidi soyutlaması ile gerçek üretim örnekleri</li>
<li>Adım adım yeniden yapılandırma stratejileri</li>
<li>Performans optimizasyon teknikleri</li>
<li>Tam test stratejileri</li>
<li>Daha ileri düzey desenler ve tuzaklar</li>
</ul>
<p>Tam makaleyi Medium'da okuyun: <a href="https://medium.com/@masteryoflaravel/mastering-laravels-service-container-from-pain-points-to-production-ready-solutions-0e0f24acaab3" target="_blank" rel="noopener noreferrer">Laravel'in Service Container'ını Mastering: Acı Noktalarından Üretime Hazır Çözümlere<br/></a><br/><strong>_<br/>Sıkı bağlı Laravel kodlarıyla mı mücadele ettiniz? Deneyiminizle ilgili bir yorum bırakın! 👇_</strong></p>Kaynak: Orijinal Makale


