Akıllı çözümler peşinden koşmayı bıraktım ve bir şeye odaklandım: Bunu bir yıl sonra hızlıca anlayabilir miyim?
Bu tek soru, kod yazarken takip ettiğim bir dizi kural oluşturmama yardımcı oldu.
1) Controller’ları ince tutun.
1) Controller’ları ince tutun.
Bir Controller metodu doğrulama, iş mantığı, eşleme, yanıt vb. yapmaya başladığında çok fazla iş yapıyor demektir.
Bu nedenle controller’larım şu hale geldi:
Request in -> Action Call -> Response out.
public function store(StoreInvoiceRequest $request, CreateInvoiceAction $action)
{
$invoice = $action->execute($request->validated());
return InvoiceResource::make($invoice);
}
2) İş mantığını Action/Servislere taşıyın.
2) İş mantığını Action/Servislere taşıyın.
Domain için kritik olan mantığı controller’larda veya modellere gömmem. Bu mantığın, net bir sorumluluğa sahip bir sınıfta yer alması gerekir.
final class CreateInvoiceAction
{
public function execute(array $data): Invoice
{
return DB::transaction(function () use ($data) {
$invoice = Invoice::create([
'customer_id' => $data['customer_id'],
'due_date' => $data['due_date'],
'status' => 'draft',
]);
foreach ($data['items'] as $item) {
$invoice->items()->create([
'description' => $item['description'],
'qty' => $item['qty'],
'unit_price' => $item['unit_price'],
]);
}
return $invoice->refresh();
});
}
}
3) Doğrulama için Form Requests kullanın.
3) Doğrulama için Form Requests kullanın.
Gerçekten çok küçük doğrulamalar olmadığı sürece, controller’larda satır içi doğrulamadan kaçınıyorum.
final class StoreInvoiceRequest extends FormRequest
{
public function rules(): array
{
return [
'customer_id' => ['required', 'exists:customers,id'],
'due_date' => ['required', 'date'],
'items' => ['required', 'array', 'min:1'],
'items.*.description' => ['required', 'string', 'max:255'],
'items.*.qty' => ['required', 'integer', 'min:1'],
'items.*.unit_price' => ['required', 'numeric', 'min:0'],
];
}
}
4) “Sihir” yerine açık sorguları tercih edin.
4) “Sihir” yerine açık sorguları tercih edin.
Eloquent güçlü bir araçtır, ancak belirsiz sorgu zincirleri gerçekten hızlı bir şekilde acı verici olabilir.
Bu yüzden:
- Sık kullanılan filtreleri scope haline getirin.
- Eager loading kullanın.
- Ağır uç noktalar için yalnızca gerekli sütunları seçin.
$invoices = Invoice::query()
->with(['customer:id,name', 'items:id,invoice_id,qty,unit_price'])
->where('status', 'sent')
->whereDate('due_date', 'latest('due_date')
->paginate(20);
5) API Yanıtları için Resources kullanın.
5) API Yanıtları için Resources kullanın.
API’lerden ham modeller döndürmeye gerek yoktur.JsonResource yanıtı yapılandırılmış ve sabit tutar.
final class InvoiceResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'number' => $this->number,
'status' => $this->status,
'total' => $this->total,
'customer' => [
'id' => $this->customer->id,
'name' => $this->customer->name,
],
];
}
}
6) Daha iyi isimlendirme.
6) Daha iyi isimlendirme.
Niyet odaklı isimlerin kendini belgelediğine inanıyorum.
Örnekler: CalculateInvoiceTotalsSendReminder
7) Çok adımlı yazımlar için transaction kullanın.
7) Çok adımlı yazımlar için transaction kullanın.
Birden fazla kaydın başarılı olması gerekiyorsa, DB::transaction() kullanırım.
8) Sözleşmelere değil, kararları yorumlayın.
8) Sözleşmelere değil, kararları yorumlayın.
Örnek: // Ürün fiyatları daha sonra değişirse, fatura toplamlarının değişmemesi için değişmez bir anlık görüntü kullanın
Bu tür bir yorum, gerçek hata ayıklama zamanı kazandırır.
Sistemimi sürekli geliştirmeye çalışıyorum. Projelerinizde hangi yöntemlerin sürekli işe yaradığını düşünüyorsunuz?
Kaynak: Orijinal Makale
- 1) Controller’ları ince tutun.
- 2) İş mantığını Action/Servislere taşıyın.
- 3) Doğrulama için Form Requests kullanın.
- 4) “Sihir” yerine açık sorguları tercih edin.
- 5) API Yanıtları için Resources kullanın.
- 6) Daha iyi isimlendirme.
- 7) Çok adımlı yazımlar için transaction kullanın.
- 8) Sözleşmelere değil, kararları yorumlayın.


