EYDefterEmre Yakut
← tüm yazılar
Sistem · Hata avı · derin

On yıllık sistemi çatallamadan taşımak

CRM PHP 5.6’da çalışıyordu. 8.3’e geçmesi gerekiyordu. Klasik yol bir kopya açıp onu modernize etmek — daha önce denenmiş ve %85’te ölmüştü. Bu sefer kopya açmadım.

çatallamak — denenmiş, %85’te ölmüş kopya alındıport durdu · 26 öğecanlıya 545 yeni şey girdi →yerinde — her adımda İKİ SÜRÜMDE de çalışır her düzeltmeden sonra kod hâlâ canlıda · cutover = sunucuda tek anahtaryarın bıraksan: çatalda ölü bir klasör, yerinde biraz daha temiz bir sistem

CRM 2019’dan beri çalışıyor ve PHP 5.6 üzerinde duruyordu. 5.6’nın desteği yıllar önce bitti; sunucuda tutmak her ay biraz daha zor hale geliyordu.

Geçmesi gerekiyordu. Sorun şuydu: bu sistem her gün kullanılıyor, binlerce fatura üretiyor, ve durmasının maliyeti yüksek.

Daha önce denenmişti

Elimde bir klasör vardı: sistemin PHP 8.3’e taşınmaya çalışılmış bir kopyası. Yüzde seksen beş civarı bitmişti ve orada durmuştu.

Neden durduğunu anlamak için ikisini karşılaştırdım:

322 dosya  → iki tarafta da var, farklı
545 öğe    → yalnız güncel sistemde   (kopya yapıldıktan sonra yazılanlar)
 26 öğe    → yalnız kopyada            (port sırasında yazılanlar)

Ortadaki satır her şeyi anlatıyor. Kopya alındıktan sonra canlı sisteme 545 yeni şey girmiş: MCP sunucusu, semantik arama katmanı, ürün entegrasyonu, İK modülünün yeni sürümü, veritabanı göçleri. Hiçbiri kopyada yok.

Yani o kopyayı diriltmek, aradan geçen bir yılın işini çöpe atmak demekti.

çatallamanın gerçek maliyeti

Bir kod tabanını kopyalayıp “yeni sürüm burada olacak” demek, o andan itibaren iki sistemi birden yaşatmaya söz vermek demek. Canlı sistem durmuyor — çünkü müşteri duruyor mu? Her yeni özellik iki yere yazılmalı. Bir süre sonra kimse yazmıyor ve kopya ölüyor.

Bu kopya da tam olarak öyle ölmüştü.

Kararın kendisi

İkinci kopyayı açmadım. Bunun yerine şunu yaptım: canlı kodu yerinde, iki sürümde de çalışacak şekilde düzelt.

Bu ilk bakışta imkânsız görünüyor ama değil — çünkü PHP 8’de kırılan şeylerin neredeyse tamamının 5.6’da da çalışan bir karşılığı var:

5.6’da yazılaniki sürümde de çalışan
mysql_query()mysqli_query()
ereg()preg_match()
each($arr)foreach
$a{0}$a[0]
$undefinedisset($x) ? $x : null

Her düzeltmeden sonra kod hâlâ canlıda, hâlâ 5.6’da çalışıyor. Kimse bir şey fark etmiyor. Ve dosya dosya, sistem 8.3’e hazır hale geliyor.

Geçiş anı (cutover) böylece devasa bir yayına dönüşmüyor: sunucuda PHP sürümünü değiştiriyorsun. Ters giderse geri çeviriyorsun.

İki binary, aynı klasör

Bunu yapabilmek için yerelde her iki sürüm de kurulu duruyor. Her değişiklikten sonra ikisiyle birden söz dizimi denetimi:

php5630\php.exe -l  dosya.php   → 5.6 hâlâ mutlu mu?
php833\php.exe  -l  dosya.php   → 8.3 kabul ediyor mu?
bu makinede dört PHP var

5.6.30, 7.1.3, 7.4.27 ve 8.3.3. Ve PATH’teki php uzun süre 7.1.3’tü — yani “çalıştı” dediğim şeylerin bir kısmı yanlış yorumlayıcıda çalışıyordu.

Bunu fark edip PATH’i düzelttim, ama asıl dersi başka yere yazdım: sürüm koda gömülür, tahmine bırakılmaz. Her betik hangi yorumlayıcıyı istediğini kendisi söylüyor. PATH bir makine ayarıdır; başka bir makinede, başka bir kabukta, ya da bir araç kendi girdisini geri eklediğinde yine yanlışa düşer.

En büyük tek kırılma: şablon motoru

Sistem eski bir şablon motorunun paketlenmiş bir sürümünü kullanıyordu. O sürüm PHP 8’de ilk çağrıda ölümcül hata veriyordu — kaldırılmış bir dil fonksiyonu kullanıyor.

Yani sistem 8.3’te hiç çalışmayacaktı. Modern sürüme geçirdim; başlatma biçimi, ayraçlar, eklenti çözümleme mekanizması değişti.

Ve burada ikinci bir şey çıktı: toplu fatura PDF’i üreten arka plan işçisi de aynı eski motoru kullanıyordu. Kimse onu test etmiyordu, çünkü web arayüzünden hiç geçmiyor. 8.3’e geçseydik binlerce faturalık üretim sessizce ölmüş olacaktı.

O keşif, ayrı bir projeyi başlattı: İş Merkezi.

Ne öğrendim

Büyük göç işlerinde asıl risk teknik zorluk değil, işin ne kadar sürdüğü. Uzun sürerse canlı sistem ilerler ve göç geride kalır.

“Yerinde, iki sürümde birden çalışır halde” yaklaşımının tek gerçek üstünlüğü bu: hiçbir anda geride kalmıyorsun. Yarın bırakırsan elinde biraz daha temiz bir sistem kalır. Çatallarsan yarın bıraktığında elinde ölü bir klasör kalır.

SistemHata avı