AQC (Atomic Query Construction) tasarım deseninin tanıtımında, bazı kişiler “Bu yeni bir şey mi? Yoksa zaten var olan bir şeyin sadece yeniden adlandırılmış hali mi?” diye sordu.
<p>Bu adil bir soru. Ve dürüst cevap: her ikisi de.</p>
<p>AQC, bu fikirler havadan kapılmıyor. İyi tanımlanmış üç yazılım tasarım ilkesinin dikkatli bir kombinasyonudur; query mantığını yönetmek için odaklanmış, pratik bir yaklaşım olarak paketlenmiştir. Bu temelleri net bir şekilde gördüğünüzde, AQC'nin ne yaptığına değil, neden etkili olduğuna da anlayacaksınız.</p>
<p>Üç temel ilke şunlardır:</p>
<ol>
<li> Query Object Pattern</li>
<li> Single Responsibility Principle (SRP)</li>
<li> Pipeline / Composition Pattern</li>
</ol>
<h2>
1. Query Object Pattern
</h2>
<p>Query Object deseni, Martin Fowler'ın Patterns of Enterprise Application Architecture adlı çalışmasından daha az bilinen ancak iyi belgelenmiş bir modeldir. Temel fikir, bir veritabanı sorgusunu bir nesne olarak temsil etmektir. Sorgu mantığını denetleyiciler, hizmetler ve yardımcılar arasında dağıtmak yerine, onu adanmış bir sınıfta kapsüllemektir.</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">ActiveProducts</span>
{
public function get()
{
return Product::query()
->where(‘active’,1)
->paginate();
}
}
<p>AQC'de de aynı fikir uygulanmaktadır. Belirli bir tür işlem için özel bir sınıf oluşturulur. Örneğin, ürünleri almak için. Sınıf, parametreleri kabul eder ve sonuçları döndürür. Çağıran, sorgunun nasıl oluşturulduğuyla ilgilenmez. Sadece sınıfı arar ve ihtiyaç duyduğu şeyi alır.</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="cp"><?php </span?>
namespace App\AQC\Product;
use App\Models\Product;
class GetProducts
{
public static function handle($params = [], $columns = [‘*’])
{
$query = Product::latest(<span class=”s1>’id’);
<span class="c1">// diğer kod buraya gelecek</span>
<span class="k">return</span> <span class="nv">$query</span>
<span class="o">?</span> <span class="nv">$query</span><span class="o">-></span><span class="nf">paginate</span><span class="p">(</span><span class="nc">Product</span><span class="o">::</span><span class="no">PAGINATE</span><span class="p">)</span>
<span class="o">:</span> <span{nv}>$query</span><span class="o">-></span><span class="nf">get</span><span class="p">();</span>
<span class="p">}</span>
}
<p>Bu, bir sorgu nesnesidir. Tek işi vardır. Girdi kabul eder. Sorguyu içsel olarak oluşturur. Sonuçları döndürür.</p>
<p>Sorgu mantığı yönetici, depolayıcı veya yardımcılar içinde yer almak yerine, sorgu kendi sınıfında yaşar. Ne bir yöntem depolayıcı içinde gömülüdür ne de bazı yardımcı sınıflardaki statik bir yardımcıdır. Sorgu nesnedir. Bir adı, bir ad alanı ve net bir sözleşmesi vardır.</p>
<p>AQC, ham Query Object deseninin üzerine dinamik parametreler ve senaryolar kullanarak birden fazla durumu tek bir sınıf içinde ele almayı ekler. Örneğin <code> GetActiveProducts </code> ve <code> GetProductsByCategory </code> için ayrı bir sınıf oluşturmak yerine, her iki durumu ve her kombinasyonu yönetebilen tek bir <code> GetProducts </code> sınıfı vardır.</p>
<p>Bunu bir denetleyiciden çağırarak kullanırsınız:</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="c1">// Yönetim paneli</span>
$columns = [<span class=”s1>’*’];
$products = GetProducts::handle([], $columns);
// Kategori ile filtrelenmiş frontend
$params = [<span class=”s1>’category_id’ > 5, <span class=”s1>’active’ > true];
$products = GetProducts::handle($params , $columns);
// Mobil API – stokta yok raporu
$params = [<span class=”s1>’out_of_stock’ > 5];
$products = GetProducts::handle($params , $columns);
<p>Aynı sınıf. Aynı yöntem. Farklı parametreler, farklı sonuçlar. İşte <strong>Query Object pattern</strong> işini yapıyor.</p>
<p>Yine, bu yapı çerçeve bağımsızdır. Desen, Eloquent, Doctrine, SQLAlchemy veya ham PDO kullanıp kullanmadığınızdan bağımsızdır. Kavram aynıdır: sorguyu bir nesne içinde kapsülleyin.</p>
<h2>
2. Single Responsibility Principle (SRP)
</h2>
<p>SRP, beş SOLID ilkesinden biridir. Robert C. Martin tarafından tanımı basittir: bir sınıfın, sadece bir ve yalnızca bir değişme nedeni olmalıdır.</p>
<p>Çoğu geliştirici bunu duymuştur. Ancak pratikte çoğu zaman ihlal edilir; özellikle de sorgu mantığıyla ilgili. Bir hizmet sınıfı, <code> getActiveProducts() </code>, <code> getProductsByCategory() </code>, <code> getExpiredProducts() </code> ve on beş diğer yöntemle dolup taşar. Bu durumda sınıfın değişme nedenleri birbirine karışmıştır. Bu, SRP'nin tam tersidir.</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">ProductRepository</span>
{
// temek yöntemler
public function create(array $data) { / … / }
public function update(Product $product, array $data) { / … / }
public function delete(Product $product) { / … / }
public function find(int $id): ?Product { / … / }
public function all(): Collection { / … / }
<span class="c1">// yeni getirme yöntemleri</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">getActiveProducts</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nc">Product</span><span class="o">::</span><span class="nf">where</span><span class="p">(</span><span class="s1>'active'</span><span class="p">,</span> <span class="mi>1</span><span class="p">)</span><span class="o">-></span><span class="nf">get</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">getProductsByCategory</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$categoryId</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nc">Product</span><span class="o">::</span><span class="nf">where</span><span class="p">(</span><span class="s1>'category_id'</span><span class="p">,</span> <span class="nv">$categoryId</span><span class="p">)</span><span class="o">-></span><span class="nf">get</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">getActiveProductsByCategory</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$categoryId</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nc">Product</span><span class="o">::</span><span class="nf">where</span><span class="p">(</span><span class="s1>'active'</span><span class="p">,</span> <span class="mi>1</span><span class="p">)</span>
<span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'category_id'</span><span class="p">,</span> <span class="nv">$categoryId</span><span class="p">)</span>
<span class="o">-></span><span class="nf">get</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">getProductsByStore</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$storeId</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nc">Product</span><span class="o">::</span><span class="nf">where</span><span class="p">(</span><span class="s1>'store_id'</span><span class="p">,</span> <span class="nv">$storeId</span><span class="p">)</span><span class="o">-></span><span class="nf">get</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">getActiveProductsByStore</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$storeId</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nc">Product</span><span class="o">::</span><span class="nf">where</span><span class="p">(</span><span class="s1>'active'</span><span class="p">,</span> <span class="mi>1</span><span class="p">)</span>
<span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'store_id'</span><span class="p">,</span> <span class="nv>$storeId</span><span class="p">)</span>
<span class="o">-></span><span class="nf">get</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">// ve daha fazlası...</span>
}
<p>AQC, SRP'yi yapısal bir seviyede uygular. Her sorgunun kendi sınıfı vardır. Tek bir sınıf, tek bir iş.</p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>app/
└── AQC/
└── Product/
└── CreateProduct.php
└── UpdateProduct.php
└── GetAllProducts.php
└── GetProduct.php
└── DeleteProduct.php
<p><strong>GetProducts</strong> yalnızca bir ürün listesi almak ile ilgilidir. <code> StoreProduct </code> ise yalnızca yeni bir ürünü saklamayı bilir. Birbiri içine geçmezler. Bir gereksinim değiştiğinde — örneğin, listeleme sorgusuna yeni bir filtre eklenmesi gerektiğinde — yalnızca bir sınıfa gidip yalnızca bir şeyi değiştirirsiniz.</p>
<p>AQC, genişlemeyi kolaylaştırır. Uygulamanız büyüdükçe, yeni sınıflar eklersiniz; mevcut olanları büyütmezsiniz. Yapı düz, keşfedilebilir ve beklenmedik durumlardan uzak kalır, kod tabanınızın boyutundan bağımsız olarak.</p>
<p>Bu, Laravel'e özel değildir. Node.js, Python veya .Net üzerinde çalışıyorsanız, bu ilke geçerlidir. Bir sınıf, bir sorgu, bir neden değişmesi.</p>
<h2>
3. Pipeline / Composition Pattern
</h2>
<p>Bu, en son fark edilen bir yapıdadır, ancak AQC'yi gerçekten güçlü kılan özelliktir.</p>
<p>Yukarıdaki <code> GetProducts </code> sınıfına bakın. <code> handle() </code> yöntemi her şeyi tek bir blokta yapmaz. Dahili olarak, sorguyu aşamalar halinde inşa etmektedir:</p>
<ul>
<li>Filtreleri uygula</li>
<li>Senaryoya göre sütunları seç</li>
<li>Sıralamayı uygula</li>
<li>Paginasyonu yönet</li>
</ul>
<p>Her adım ayrı bir endişedir. Daha somut bir uygulamada, bu aşamalar sorguyu kabul eden, parça ekleyen ve onu devam ettiren özel yöntemler haline gelir.</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="cp"><?php </span?>
namespace App\AQC\Product;
use App\Models\Product;
class GetProducts
{
public static function handle(<span class=”nv>$params = [], <span class=”nv>$columns)
{
<span class=”nv>$query = Product::latest(<span class=”s1>’id’);
<span class="k">self</span><span class="o">::</span><span class="nf">applyFilters</span><span class="p">(</span><span class="nv>$query</span><span class="p">,</span> <span class="nv>$params</span><span class="p">);</span>
<span class="k">self</span><span class="o">::</span><span class="nf">selectColumns</span><span class="p">(</span><span class="nv>$query</span><span class="p">,</span> <span class="nv>$params</span><span class="p">);</span>
<span class="k">self</span><span class="o">::</span><span class="nf">applySorting</span><span class="p">(</span><span class="nv>$query</span><span class="p">,</span> <span class="nv>$params</span><span class="p">);</span>
<span class="k">return</span> <span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'paginate'</span><span class="p">])</span>
<span class="o">?</span> <span class="k">self</span><span class="o">::</span><span class="nf">handlePagination</span><span class="p">(</span><span class="nv>$query</span><span class="p">,</span> <span class="nv>$params</span><span class="p">)</span>
<span class="o">:</span> <span class="nv>$query</span><span class="o">-></span><span class="nf">get</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">static</span> <span class="k">function</span> <span class="n">applyFilters</span><span class="p">(</span><span class="nv>$query</span><span class="p">,</span> <span class="nv>$params</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">}</span>
<span class="k">private</span> <span class="k">static</span> <span class="k">function</span> <span class="n">selectColumns</span><span class="p">(</span><span class="nv>$query</span><span class="p">,</span> <span class="nv>$params</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">}</span>
<span class="k">private</span> <span class="k">static</span> <span class="k">function</span> <span class="n">applySorting</span><span class="p">(</span><span class="nv>$query</span><span class="p">,</span> <span class="nv>$params</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">}</span>
<span class="k">private</span> <span class="k">static</span> <span class="k">function</span> <span class="n">handlePagination</span><span class="p">(</span><span class="nv>$query</span><span class="p">,</span> <span class="nv>$params</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">}</span>
}
<p>Bu bir pipeline'dır. Sorgu nesnesi, bir dizi aşamadan geçer. Her aşama bir şeyi yapar. Her aşama bağımsız olarak okunabilir, test edilebilir ve değiştirilebilir.</p>
<p><strong>Composition pattern</strong> bunu daha ileri taşır — karmaşık davranışları daha küçük, odaklanmış parçaları birleştirerek oluşturursunuz, tek bir büyük işlev yazmak yerine. AQC'de, sorgu koşullarını birleştirirsiniz. Daha gelişmiş uygulamalarda, karmaşık raporlama sorguları oluşturduğunuzda birden fazla AQC sınıfını bir araya getirebilirsiniz.</p>
<p>Bir sınıfın bir yöntem içinde on işi yapması, on farklı şekilde kırılabileceği anlamına gelir. Aşamaları ayırın. Sonucu birleştirin.</p>
<p>AQC sınıflarının doğal olarak birim testlerinin kolay olması da bunun bir nedenidir. 200 satırlık bir yöntemi test etmiyorsunuz. Her aşamada net bir girdi ve çıktı ile bir pipeline test ediyorsunuz. Filtre aşamasını bağımsız olarak test edebilirsiniz. Paginasyon aşamasını bağımsız olarak test edebilirsiniz. Bu, bileşimin faydalarını sağlıyor.</p>
<h2>
The Underlying Power of Composition Pattern
</h2>
<p>Bileşimin AQC'nin en güçlü yönlerinden biri, filtrelerin sorguya geçirilen parametrelere bağlı olarak dinamik bir şekilde bir araya gelmesidir. Her bir filtre koşullu olarak uygulanır; yani sorgu sabit bir yol izlemez. Bunun yerine, her parametre, sorguya bir kısıtlama ekleyip eklemeyeceğine karar veren bir anahtar gibi çalışır. Birden fazla parametre sağlandığında, sonucu sorgu, geçerli tüm filtre kombinasyonlarının birleşimi olur. Pratikte, bu esnek bir sorgu sistemi yaratır; tek bir sorgu sınıfı, onlarca özel sorgu yöntemine ihtiyaç duymadan bir dizi filtre kombinasyonunu destekleyebilir.</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="k">private</span> <span class="k">static</span> <span class="k">function</span> <span class="n">applyFilters</span><span class="p">(</span><span class="nv>$query</span> <span class="p">,</span> <span class="nv>$params</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// uygulanan filtreler</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'category_id'</span><span class="p">])</span> <span class="o">&&</span> <span class="nv>$params</span><span class="p">[</span><span class="s1>'category_id'</span><span class="p">]</span> <span class="o">></span> <span class="mi>0</span><span class="p">)</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'category_id'</span><span class="p">,</span> <span class="nv>$params</span><span class="p">[</span><span class="s1>'category_id'</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'brand#{]/span> <span class="p">])</span> <span class="o">&&</span> <span class="nv>$params</span><span class="p">[</span><span class="s1>'brand_id'</span><span class="p">]</span> <span class="o">></span> <span class="mi>0</span><span class="p">)</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'brand_id'</span><span class="p">,</span> <span class="nv>$params</span><span class="p">[</span><span class="s1>'brand_id'</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'keyword'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'name'</span><span class="p">,</span> <span class="s1>'like'</span><span class="p">,</span> <span class="s1>'%'</span> <span class="mf">.</span> <span class="nv>$params</span><span class="p">[</span><span class="s1>'keyword'</span><span class="p">]</span> <span class="mf">.</span> <span class="s1>'%'</span><span class="p">)</span>
<span class="o">-></span><span class="nf">orWhere</span><span class="p">(</span><span class="s1>'sku'</span><span class="p">,</span> <span class="s1>'like'</span><span class="p">,</span> <span class="s1>'%'</span> <span class="mf">.</span> <span class="nv>$params</span><span class="p">[</span><span class="s1>'keyword'</span><span class="p">]</span> <span class="mf">.</span> <span class="s1>'%'</span><span class="p">)</span>
<span class="o">-></span><span class="nf">orWhere</span><span class="p">(</span><span class="s1>'description'</span><span class="p">,</span> <span class="s1>'like'</span><span class="p">,</span> <span class="s1>'%'</span> <span class="mf">.</span> <span class="nv>$params</span><span class="p">[</span><span class="s1>'keyword'</span><span class="p">]</span> <span class="mf">.</span> <span class="s1>'%'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'low_stock'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'stock'</span><span class="p">,</span> <span class="s1>' <span class="p">,</span> <span class="s1>'low_stock_point'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'out_of_stock'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'stock'</span><span class="p">,</span> <span class="mi>0</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'expired'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">whereDate</span><span class="p">(</span><span class="s1>'expired_date'</span><span class="p">,</span> <span class="s1>'<span class="p">,</span> <span class="nf">today</span><span class="p">())</span><span class="o">-></span><span class="nf">get</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'featured'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'is_featured'</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'trending'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'is_trending'</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv>$params</span><span class="p">[</span><span class="s1>'product_id'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv>$query</span><span class="o">-></span><span class="nf">where</span><span class="p">(</span><span class="s1>'related_product_id'</span><span class="p">,</span> <span class="nv>$params</span><span class="p">[</span><span class="s1>'product_id'</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nv>$query</span><span class="p">;</span>
<span class="p">}</span>
<p>Tipik bir Repository veya naif Query Object yapısında, her anlamlı filtre kombinasyonu çoğu zaman ayrı bir yöntem veya sınıf haline gelir. Bir filtreleme ihtiyacını kapsamak için birçok katı sorgu biçimi yazmak yerine, geliştiriciler, parametrelere tepki veren tek bir esnek sorgu oluşturmayı gerçekleştirirler.</p>
<h2>
Neden Bu Üçü Birlikte
</h2>
<p>Bireysel olarak, bu kalıpların hiçbiri tam bir çözüm değildir.</p>
<p>SRP, şeyleri ayırmayı öğütler — fakat sorgu mantığını özellikle nasıl yapılandıracağınızı anlatmaz.</p>
<p>Query Object deseni, yapı şablonu sunar — ancak temiz iç organizasyonu zorunlu kılmaz.</p>
<p>Pipeline / Composition deseni içsel netlik sağlar — fakat sınıfın kamu sözleşmesinin nasıl yapılacağı konusunda bilgi vermez.</p>
<p>Birlikte, AQC'yi oluştururlar:</p>
<ul>
<li><strong>SRP sınırı tanımlar</strong>: bir sınıf, bir sorgu.</li>
<li><strong>Query Object deseni yapı tanımlar</strong>: sorgu oluşturmasını kapsülleyen bir adlandırılmış sınıf.</li>
<li><strong>Pipeline deseni iç organizasyonu tanımlar</strong>: nihai sonucu üretmek için aşamalar.</li>
</ul>
<p>Sonuç, modüler, yeniden kullanılabilir, test edilebilir ve öngörülebilir bir desenin oluşumudur. Her sorgunun bir evi vardır. Her evin bir sözleşmesi vardır. Her sözleşme, birleştirilebilir aşamalarla oluşturulur.</p>
<h2>
A Note on Class Naming and Static Methods
</h2>
<p>Bazı modern nesne yönelimli kurallara uygun olarak, sınıf adları genellikle <code> Product </code>, <code> Order </code> veya <code> User </code> gibi varlıkları temsil eder. Ancak AQC'de sınıf adı genellikle bir eylemi veya niyeti temsil eder, örneğin <code> GetProducts </code>, <code> GetOrders </code> veya <code> GetUsers </code>. Bu , ilk başta tuhaf gelebilir fakat birçok yerleşik desen, örneğin Query Objects, Actions ve Command desenleri, bir sınıfın belirli bir işlemi temsil ettiği fikrini takip eder.</p>
<p>AQC'deki bir diğer stilistik tercih, statik yöntemlerin kullanılmasıdır. Bazı geliştiriciler, basitlik için statik giriş noktalarını tercih ederken, diğerleri daha iyi bağımlılık işleme veya test edilebilirlik için örnek yöntemleri tercih etmektedirler. Desen, her iki yaklaşımı da gerektirmez; takımlar, belirledikleri kodlama standartlarına ve mimarilerine göre AQC'yi statik ya da örnek yöntemlerle uygulama özgürlüğüne sahiptir.</p>
<h2>
The Framework Agonist Pattern
</h2>
<p>Ben Laravel kullanıyorum, bu yüzden yukarıdaki örnekler Eloquent kullanıyor. Ancak AQC, bir Laravel deseni değildir. Yazılım tasarım desenidir ve Laravel ile gösterilmiştir.</p>
<p>Aynı düşünceyi Node.js, Python, .Net Framework veya kullandığınız herhangi bir dilde uygulayabilirsiniz.</p>
<p>Üç temel ilke — SRP, Query Object, Pipeline/Composition — dil bağımsızdır. AQC, bu üç ilkenin belirli bir uygulamaya yönetimi için uygulanmış bir biçimidir.</p>
<h2>
Final Thoughts
</h2>
<p>İlk defa AQC'yi görenler, aldatıcı bir şekilde basit görünebilir. Sadece bir sınıf ve <code>handle()</code> yöntemi. Ancak basitlik kasıtlıdır; bazı iyi anlaşılmış kalıpların temiz bir şekilde birleştiğinde elde edilen sonuçtur.</p>
<p>SRP der ki: Her sorguya özel bir ev verin. Query Object der ki: sorguyu net bir sözleşmeyle birinci sınıf bir nesne haline getirin. Pipeline/Composition der ki: sorguyu aşamalar halinde oluşturun, her biri tam bir şey yapsın.</p>
<p>AQC budur. Sihir değil. Yeniden icat değil. İyi düşünülmüş üç fikrin doğru kombinasyonu.</p>
<p>Bu ilkeleri zaten kullanıyorsanız, AQC tanıdık bir zeminle bir isim ve yapı bulacaktır. Eğer kullanmadıysanız, iyi bir başlangıç noktasıdır.</p>
<p>Bu makalenin sorguları yazma ve düşünme biçiminizde yeni bir yol sunmasını umuyorum. Bunun hakkında ne düşündüğünüzü benimle paylaşın.</p>