Legacy Yazılım Modernizasyonu: Yeniden Yazım mı, Strangler mi?
'Sistemi baştan yazalım' kararı, kurumsal yazılımda en pahalı ve en sık pişman olunan karardır. Beş modernizasyon yaklaşımını risk, süre ve maliyetle karşılaştırıyor; kesintisiz geçişi mümkün kılan strangler fig desenini adım adım, en zor kısım olan veri katmanı stratejisiyle birlikte anlatıyoruz.
On beş yıllık bir sistem, artık desteklenmeyen bir uygulama sunucusu, kaynak kodunu bilen tek bir geliştirici ve her sürümde bir şeyin bozulduğu bir dağıtım süreci. Bu noktada masaya gelen cümle hep aynıdır: "Baştan yazalım." Kurumsal yazılımda en pahalı ve en sık pişman olunan karar budur; iki yıl sonra ortada iki sistem, yarım kalmış bir geçiş ve eski sistemde hâlâ çalışan gizli iş kuralları vardır.
Bu yazıda önce doğru teşhisi — sistemin gerçek sorunu ne? — sonra beş modernizasyon yaklaşımını risk, süre ve maliyetle karşılaştırıyor; yeniden yazımın neden çoğunlukla yanlış olduğunu, kesintisiz geçişi mümkün kılan strangler fig desenini adım adım, en zor kısım olan veri katmanı stratejisini ve sahada gördüğümüz hataları anlatıyoruz.
Önce teşhis: neyi çözmeye çalışıyorsunuz?
Belirti | Asıl sorun genellikle | Uygun ilk adım |
|---|---|---|
Küçük bir değişiklik haftalar sürüyor | Test yok, dağıtım elle, kod spagetti | Test ve dağıtım otomasyonu; kod değişmeden |
Platform desteği bitti (JDK 8, eski uygulama sunucusu) | Güvenlik ve uyumluluk riski | Rehost/replatform: kod aynı, altyapı yeni |
Bilen tek kişi var | Bilgi riski, doküman yok | Karakterizasyon testleri ve mimari kayıt |
Yeni özellik eklenemiyor, iş bekliyor | Mimari değişimi taşıyamıyor | Strangler fig: yeni özellikler yeni modülde |
Lisans ve operasyon maliyeti yüksek | Ticari altyapıya bağımlılık | Replatform ya da paket değişimi |
"Legacy" bir yaş değil, bir durumdur: değiştirmesi riskli ve pahalı olan sistem. Teşhis yapılmadan seçilen yöntem, yanlış soruna doğru cevap verir.
Beş yaklaşım
Yaklaşım | Ne yapılır | Risk | Süre | Ne zaman |
|---|---|---|---|---|
Rehost / replatform | Kod aynı; konteyner, güncel JDK, yönetilen veritabanı | Düşük | Haftalar–aylar | Platform riski ana sorunsa; her yolun ilk adımı |
Yerinde refactor | Testler eklenir, modüller ayrıştırılır, kod temizlenir | Düşük–orta | Sürekli | Kod tabanı kurtarılabilir durumdaysa |
Strangler fig | Yetenekler tek tek yeni sisteme taşınır; eski sistem küçülerek emekliye ayrılır | Orta, adım başına düşük | 6–24 ay, her ay değer üretir | Büyük, canlı, kritik sistemlerde varsayılan yol |
Yeniden yazım (big bang) | Yeni sistem sıfırdan; bir gün geçiş | Yüksek | 12–36 ay, değer sonda | Küçük sistem, ölü platform, net şartname |
Paket / SaaS ile değiştirme | Özel sistem yerine hazır ürün | Orta | 6–18 ay | Süreç standart, farklılaşma yoksa (bkz. özel yazılım mı hazır paket mi) |
Yeniden yazım neden genelde yanlış?
Özellik eşitliği tuzağı: Eski sistemde on beş yılda birikmiş binlerce iş kuralı vardır ve çoğu yazılı değildir. "Aynısını yapan" yeni sistem, canlıya alındığı gün eksik çıkar.
Değer sonda gelir: İki yıl boyunca iş hiçbir şey almaz; bu arada eski sisteme eklenen her özellik yeni sisteme de eklenmelidir — iki hedef birden hareket eder.
İkinci sistem etkisi: "Bu sefer her şeyi doğru yapalım" hırsı, yeni sistemi ilkinden karmaşık yapar.
Tek günlük geçiş: Geri dönüşü zor, riski en yüksek an; veri göçü, eğitim ve entegrasyonlar aynı gece.
Yeniden yazım doğru olduğunda: sistem küçüktür (birkaç ay), platform gerçekten ölmüştür (kaynak kod yok, çalıştırılamıyor) ya da iş süreci zaten değişiyordur ve eski davranış korunmayacaktır.
Strangler fig: adım adım
Desen adını, ev sahibi ağacın etrafında büyüyüp onu zamanla saran incir türünden alır: yeni sistem eskisinin etrafında büyür, yetenekleri tek tek devralır, eski sistem sonunda boşalır. Kesintisiz, geri alınabilir ve her adımda değer üreten tek yol budur.
Adım 0: Eski sistem istemci ──► [eski sistem] ──► [eski DB]
Adım 1: Geçit öne konur istemci ──► [geçit] ──► [eski sistem] ──► [eski DB]
Adım 2: İlk yetenek taşınır istemci ──► [geçit] ─┬─► [eski sistem] ──► [eski DB]
└─► [yeni: fiyatlandırma] ──► (eski DB / kendi DB'si)
Adım N: Eski sistem boşalır istemci ──► [geçit] ──► [yeni modüller] ──► [yeni DB]Geçidi öne koyun. Tüm trafik bir API geçidinden ya da ters vekilden geçer; yönlendirme kuralı yol, kiracı ya da özellik bayrağı bazlıdır. Bu adım eski sistemi değiştirmez ve tek başına geri alınabilir.
Karakterizasyon testleri yazın. Eski sistemin gerçek girdi-çıktılarını kaydedin (altın kayıtlar): "bu 500 sipariş için fiyatlandırma bu sonuçları veriyor". Yeni modül aynı testlerden geçmelidir. Şartnamenin olmadığı yerde davranışın kendisi şartnamedir.
Dikişi seçin. İlk taşınacak yetenek: iş değeri yüksek, bağımlılığı düşük, sınırı net (fiyatlandırma, bildirim, raporlama, yeni bir kanal). En zor modülle başlamayın; ilk döngü ekibin yöntemi öğrenmesi içindir.
Yeni modülü kurun ve yönlendirin. Önce gölge modda (her iki sistem çalışır, sonuçlar karşılaştırılır, yalnızca eski cevap döner), sonra kademeli trafik (%5 → %50 → %100), geri alma tek bayrak.
Eskiyi emekliye ayırın. Taşınan yeteneğin kodu eski sistemden silinir; silinmeyen kod "yedek" değil, iki kat bakımdır.
Tekrarlayın. Her döngü 4–8 hafta; her döngünün sonunda üretimde çalışan yeni bir parça.
# Spring Cloud Gateway: fiyatlandırma yeni modüle, geri kalan eski sisteme
spring:
cloud:
gateway:
routes:
- id: fiyatlandirma-yeni
uri: http://fiyatlandirma-servisi
predicates:
- Path=/api/fiyat/**
- Header=X-Canary, true # önce iç kullanıcılar; bayrak kalkınca herkes
- id: eski-sistem
uri: http://legacy-app
predicates:
- Path=/**// Karakterizasyon testi: eski sistemin kaydedilmiş sonuçları yeni modülün sözleşmesidir
@ParameterizedTest
@MethodSource("altinKayitlar") // 500 gerçek sipariş + eski sistemin verdiği fiyatlar
void yeniFiyatlandirmaEskiyleAyniSonucuVerir(SiparisOrnegi ornek) {
FiyatSonucu yeni = fiyatlandirma.hesapla(ornek.girdi());
assertThat(yeni).usingRecursiveComparison().isEqualTo(ornek.eskiSonuc());
}Veri katmanı: en zor kısım
Kodu taşımak kolay, veriyi ayırmak zordur; çoğu strangler projesi burada tıkanır. Üç aşamalı yol:
Paylaşılan veritabanı (geçici): Yeni modül eski tabloları okur ve yazar. Hızlı başlangıç, ama şema eski sisteme bağlı kalır. Kural: yeni modül eski şemaya kendi anti-corruption katmanıyla erişir; entity'lerini eski tablolara doğrudan bağlamaz.
Sahiplik devri: Taşınan yeteneğin tablolarının tek yazarı yeni modül olur; eski sistem yalnızca okur (ya da bir görünüm üzerinden erişir). "Bir tablonun tek sahibi" ilkesi.
Ayrı veritabanı ve senkronizasyon: Yeni modül kendi şemasına geçer; eski sistemin hâlâ ihtiyaç duyduğu veri, değişiklik yakalama (CDC, örneğin Debezium) ya da olaylarla eski şemaya yansıtılır. Çift yazma (iki veritabanına aynı anda yazmak) tutarsızlık üretir; kaçının.
Veri göçü büyük patlama yerine yetenek bazında ve prova edilerek yapılır; her taşınan yetenek kendi verisini götürür.
Yönetişim: nasıl ölçülür, ne zaman durulur?
Metrikler: Yeni sistemde işlenen trafik yüzdesi, değişiklik teslim süresi (fikirden üretime), üretim olayı sayısı, eski sistemde kalan kod satırı. Sunum değil, pano.
Zaman kutusu ve çıkış kriteri: Her döngü için tarih ve "bitti" tanımı; iki döngü üst üste hedefi kaçıran program yeniden planlanır, sessizce uzamaz.
Eski sisteme değişiklik politikası: Yeni özellik yalnızca yeni modüle; eski sisteme yalnızca hata düzeltme ve mevzuat. Bu kural olmadan hedef sürekli kaçar.
İş katılımı: Her dikişte iş sahibi kabul testinin parçasıdır; gizli kurallar en çok bu görüşmelerde ortaya çıkar.
Sahada sık yapılan hatalar
Her şeyi modernize etmek. Değişmeyen ve çalışan modül (yıllık bordro hesabı) olduğu gibi kalabilir; modernize edilmesi gereken, iş değişikliği talep eden bölümlerdir.
Testsiz taşımak. Karakterizasyon testi olmadan "aynı davranış" iddiası doğrulanamaz; hatalar canlıda müşteriden öğrenilir.
Geçit olmadan başlamak. İstemciler doğrudan eski sisteme bağlıysa yönlendirme yapılamaz; her geçiş bir istemci dağıtımı ister.
Veriyi sona bırakmak. "Kodu taşıyalım, veriye sonra bakarız" — sonra hiç gelmez, paylaşılan veritabanı kalıcı olur.
Eski kodu silmemek. İki sistemin de bakımı sürer; strangler'ın amacı eskinin küçülmesidir.
Sık sorulan sorular
Strangler fig modüler monolit ile uyumlu mu?
Evet ve çoğu zaman en iyi hedef budur: yeni yetenekler ayrı servisler yerine iyi sınırlı modüller olarak tek bir yeni uygulamada toplanır; dağıtık sistem karmaşıklığı olmadan modernizasyon. Sınırlar sonradan servise dönüştürülebilir.
Eski sistemin kaynak kodu yoksa?
Geçit ve karakterizasyon testleri yine mümkündür: davranış dıştan (API, ekran, veritabanı çıktıları) kaydedilir. Kod olmadığı için yerinde refactor seçeneği düşer; strangler fig ya da paket değişimi kalır.
Ne kadar sürer?
Orta boy bir kurumsal sistemde 12–24 ay; ama ilk üretim değeri ilk 6–8 haftada gelir ve program her an durdurulabilir — o güne kadar taşınanlar üretimde kalır. Yeniden yazımda bu iki özellik de yoktur.
Sonuç
Modernizasyon bir proje değil, bir programdır: doğru teşhis, platform riskini önce kapatan replatform, sonra geçit ve karakterizasyon testleriyle desteklenen strangler fig döngüleri, yetenek bazında veri sahipliği devri ve eski kodun gerçekten silinmesi. Yeniden yazım istisnadır; kesintisiz ve geri alınabilir geçiş kuraldır.
Mevcut sisteminizin modernizasyon teşhisi ve strangler fig yol haritası için yazılım tasarımı ve mimari ile bakım ve destek hizmetlerimize göz atabilirsiniz. Keşif görüşmesi ücretsizdir.