Üretimde yıllardır çalışan, kendi genç haliniz tarafından aceleyle yazılmış bir tür kod vardır ki, bu tür kodlar genellikle eğitici makalelerde yer almaz. Bu kod çalışır, fakat görünümü biraz utanç vericidir.
<p>Bu yazıda, <a href="https://kohana.io" target="_blank" rel="noopener noreferrer">Kohana.io</a> - canlı bir CRM/ERP olan - kodu, <strong>LaraFoundry</strong> adında, Laravel için açık kaynak bir SaaS çekirdek olan Composer paketi haline aktarıyorum. Bu tamamen sıfırdan yeniden yazım değil, daha çok bir <em>çıkarma ve modernleştirme</em>. Temel düşünce, savaşta test edilmiş kodun temiz koddan daha değerli olduğu, fakat bu işlemi yaparken kodu yeniden okumak gerektiğidir.</p>
<p>Bu gönderi, ilk gerçek kod aşamasıdır: <code>v0.1.0</code>. Arkayüzün temel bileşenleri ve ön uç altyapısı. Aynı zamanda çıkarım sürecinin, üretimde yer alan iki gerçek hatayı yakaladığı bir yazıdır. Bu nedenle, bu sadece "framework'ümü gösteriyorum" değil, "eski kodu ışığa çıkardığınızda neler oluyor" konusudur.</p>
<h2>
<a name="why-extract-instead-of-rewrite" href="#why-extract-instead-of-rewrite"></a>
Neden yeniden yazmak yerine çıkarmak?
</h2>
<p>Sıkıcı cevap risk. Yeniden yazma, orijinal kodun zor yoldan öğrendiği her durumu yok sayar - gerçek bir tarayıcıdan gelen tuhaf yerel kod, birinin istismar etmeye çalıştığı filtre parametresi, sayfalama hatası. Çıkarma, bu dersleri korur. Maliyeti, orijinal hataları da miras almanızdır; bu yüzden çıkarmanın fayda sağlaması ancak bir gözden geçirme kapısı ile mümkündür.</p>
<p>Bu nedenle her bir parça için iş akışı sabittir:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>extract from legacy -> modernize + harden -> Pest tests-> /security-review + /code-review -> tag -> integrate into host app
<p>Paket, bu akıştaki hiçbir şeyi göndermiyor. Haydi, bu kilometre taşını inceleyelim.</p>
<h2>
<a name="whats-in-v010" href="#whats-in-v010"></a>
v0.1.0'da neler var?
</h2>
<p>On dört PHP sınıfı ve küçük bir Inertia/Vue ön yüzü. Henüz oturum açma modülü yok, çoklu kiracılık yok - bunlar sonraki aşamalar. Bu sürüm, her şeyin dayandığı <em>primitifler</em> içermektedir:</p>
<div class="table-wrapper-paragraph">
<table>
<thead>
<tr>
<th>Alan</th>
<th>Neler var</th>
</tr>
</thead>
<tbody>
<tr>
<td>Locale</td>
<td>Bir <code>SetLocale</code> middleware (çözüm zinciri), bir <code>ValidLocale</code> kuralı, bir <code>Inertia</code> çeviri köprüsü</td>
</tr>
<tr>
<td>Sorgu filtreleri</td>
<td>Yansıma tabanlı bir <code>Filter</code> temeli + <code>Filterable</code> trait</td>
</tr>
<tr>
<td>Middleware</td>
<td>Email doğrulama kapısı, IP izin listesi, hedef URL yakalama, görünüm</td>
</tr>
<tr>
<td>Frontend</td>
<td>vue-i18n başlatma, bir form UI kiti, flash toasts, bir sayfalayıcı, bir temel düzen</td>
</tr>
<tr>
<td>Testler</td>
<td>39 Pest testi</td>
</tr>
</tbody>
</table>
</div>
<p>İlginç olan liste değil, eski sürüm ile çıkarılan arasında neler değiştiğidir.</p>
<h2>
<a name="locale-detection-the-rewrite-that-paid-for-itself" href="#locale-detection-the-rewrite-that-paid-for-itself"></a>
Locale tespiti: kendi kendine maliyetini karşılayan yeniden yazım
</h2>
<p>Eski <code>SetLocale</code>, misafirler için bir middleware sınıfı ve kimliği doğrulanmış kullanıcılar için başka bir orta katman sınıfıydı ve yaptıkları şeylerden biriyle gurur duymuyorum: bir misafirin ilk isteğinde <strong>synchronous HTTP çağrısı yapıyordu</strong> <code>ip-api.com</code>'dan coğrafi konumu belirlemek için; bu çok hızlı bir yoldu, bir şey render edilmeden önce.</p>
<p>Bu süreçteki iki karar yanlıştı ve kodu çıkarmak, bunu kabul etmemi sağladı.</p>
<p><strong>Yanlış şey #1: İstek yolunda engelleyici ağ I/O yapmak.</strong> Üçüncü taraf bir kesinti sizin kesintiniz olur. Bu nedenle çekirdekte coğrafi IP varsayılan yoldan çıkarılmıştır - isteğe bağlı bir sözleşmenin arkasında yer alır, bir ana bilgisayar bunun opsiyonunu seçebilir:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">LocaleGeoResolver</span>{
/
- @param array
$available
*/
public function resolve(string $ip, array $available): ?string;
}


