TL;DR
- Kurumsal kurallar – bir planın kaç ücretsiz koltuk aldığı, toptan koltuk satın alıp almadığınız ve vergilerin nasıl uygulandığı gibi – sürekli değişim gösterir. Bunları kodda sabitlemek, Satış departmanı fikrini değiştirdiğinde her seferinde yeniden dağıtım yapmayı gerektirir.
- Bu nedenle, bunları bir
BillingProvidersözleşmesi ve yapılandırma/ayarlar arkasına taşıdım: sayı veri, davranış ise değiştirilebilir bir sürücü (manuel veya Stripe). - Öğüt: Eğer bir değer iş kararıysa, mühendislik kararı değilse, bu yapılandırma veya ayarlar içinde yer almalıdır – bir
ififadesinde değil.
Üç koltuk içeren “ücretsiz katman” masum görünebilir, ta ki biri 5 istemeye kadar. Sonra kod tabanını ararsınız, dört yerde 3‘ü bulur, birini atlar ve faturalandırma hatası ile gönderirsiniz. Bugünkü iş, bu sayının – ve birkaç arkadaşının – bir daha asla kodda yaşamaması için çalışmaktı.
The seam: one contract, two drivers
Faturalama iki modda işler: elle fatura kesme (erken/ağır ağır müşteriler) ve Stripe (kendi kendine hizmet). Arayanların hangisi olduğu umurlarında olmamalı. Her şey bir sözleşme üzerinden geçer:
interface BillingProvider
{
public function freeSeatDefault(): int;
public function purchaseSeats(Account $account, int $quantity): SeatPurchase;
public function appliesTax(): bool;
// ...
}
ManualBillingProvider ve StripeBillingProvider bunu uygular. “Bu hesabın bir koltuğu var mı?” sorusunu soran yetki kapısı, sözleşmeye hitap eder, asla doğrudan Stripe’a gitmez. Aynı Filesystem diski gibi – arayan “bunu depola” der, sürücü nereye depolayacağına karar verir.
The free-seat default is config, not a constant
// config/billing.php
'seats' => [
'free_default' => env('BILLING_FREE_SEATS', 1),
'bulk_enabled' => true,
],
Manuel sağlayıcı yapılandırmayı okur; Stripe sağlayıcı ise abonelik verilerinden plan başına geçersiz kılabilir. Müşteriyle ilgili değişiklikler (ücretsiz koltukları 5’e çıkaran bir promosyon) DB destekli ayarlara taşınır, bu sayede bir yönetici bunu, yeniden dağıtım yapmadan değiştirebilir. Kod tek bir yoldan okur; değerin kaynağı bir uygulama ayrıntısıdır.
Bulk seats: quantity is a first-class input
Koltukları tek tek eklemek sorun değil, ancak bir müşteri 40 kişilik bir onboard yapıyorsa durum farklıdır. Toplu, sadece purchaseSeats($account, 40) demektir, sağlayıcı fiyatlandırmayı ve kaydı nasıl yapacağına karar verir. Kazanç, kapı mantığının değişmemesidir – hala “kullanılan koltuklar” diye sorulur.
Tax belongs to the provider, not the checkout view
Vergi kuralları bölgeden bölgeye değişir ve hiçbir uyarı olmadan değişebilir. Vergi hesaplamasını bir Blade görünümünde veya denetleyicisinde koymak, faturalama kodunu denetlemekte zorlanmanıza yol açar. Bunun yerine vergi, bir sağlayıcının konusudur – Stripe sürücüsü Stripe Tax’a yönlendirir (müşterinin lokasyonunu ve mevcut oranları zaten biliyor), manuel sürücü ise “fatura üzerinde vergi işlenir” döner. Uygulama sadece appliesTax() ifadesini sorar.
checkout ──► BillingProvider (contract)
├─ ManualBillingProvider ─► invoice handles tax
└─ StripeBillingProvider ─► Stripe Tax computes it
Test the rule, not the vendor
Bir politika‘yı kanıtlamak için canlı bir Stripe çağrısına ihtiyacınız yok. Sahte bir sağlayıcı bağlayarak davranışı doğrulayın:
it(, function () {
config([=> 3]);
$account = Account::factory()->create();
expect(app(BillingProvider::class)->freeSeatDefault())->toBe(3);
expect($account->availableSeats())->toBe(3);
});
Sözleşme hem dikiş noktası hem de test sınırıdır – manuel sağlayıcıyı değiştirin, yetki kapısının koltukları doğru saydığını doğrulayın, tamam. Ağ yok, belirsizlik yok.
Decision rule
| Eğer değer… | Şuraya koyun… |
|---|---|
| Asla değişmez, mühendislik içindir | bir sabit |
| Ortama/gönderime göre değişir | config() + .env |
| Bir müşteri veya yönetici canlı olarak değiştirmelidir | DB destekli ayarlar |
| Değiştirilebilir bir davranış ise | bir sözleşme arkasındaki sürücü |
Ücretsiz koltuklar, toplu fiyatlandırma, vergi yönetimi – bunların her biri, kod değerleri şeklinde giydirilmiş bir iş kararıdır. Bunları dışarı taşıyın, “5 yapabilir miyiz?” sorusu bir ayar geçişi olsun, bir sürüm değil.
Kaynak: Orijinal Makale


