Canlı sistemi durdurmadan monorepo'yu beşe bölmek
iBERRY'nin kodu uzun süre iki büyük monorepo'da yaşadı. Ekip büyüdükçe ve servisler farklı hızlarda gelişmeye başladıkça, her değişikliğin bütün depoyu etkilemesi yavaşlatıcı hâle geldi. Hedef, canlı sistemi hiç durdurmadan iki monorepo'yu beş bağımsız repoya ayırmaktı. Bu yazı, işi güvenli kılan sırayı anlatıyor.
1. Önce haritayı çıkarın
Bölmeden önce kimin kimi import ettiğini bilmek gerekir. Her paket ve servis için bağımlılık grafiğini çıkardım: hangi modül hangi modülü, hangi yardımcı kodu, hangi tipleri kullanıyor? Bu harita iki şeyi gösterdi: bazı "ortak" kodların aslında tek bir servise ait olduğunu ve bazı servislerin birbirinin iç detaylarına doğrudan eriştiğini.
2. Sınırları önce kodda çizin
Repoları ayırmadan önce, sınırları aynı repo içinde zorunlu hâle getirdim. Her servis için izin verilen import listesini tanımlayıp CI'da denetledim: izin listesi dışında bir import derlemeyi kırıyordu. Böylece ayrışma, dosyaların taşınmasından önce kodun kendisinde gerçekleşti. Bu tür kararları ve denetimleri ADR yazısında anlattım.
3. Ortak kodu paket yapın
Gerçekten ortak olan kod (tipler, hata kodları, küçük yardımcılar) sürümlü bir pakete dönüştü. Servisler bu paketi dışarıdan bağımlılık olarak kullanmaya başladı; artık ortak kodu değiştirmek, bir sürüm yayımlamak ve servisleri bilinçli olarak güncellemek demekti.
4. Taşı, doğrula, sonra sil
Her servis için sıra aynıydı:
- Yeni repoyu oluştur ve servisi geçmişiyle birlikte taşı.
- Yeni repoda tip denetimi ve derleme temiz geçene kadar düzelt.
- Yeni repodan yayın hattını kur ve servisi oradan yayına al.
- Eski repodaki kopyayı ancak yeni repodan en az bir sorunsuz yayın yapıldıktan sonra sil.
Eski ve yeni kopyanın kısa bir süre yan yana yaşaması, geri dönüşü her an mümkün kıldı. Canlı sistem, yayını yapılan her servisin eski ya da yeni sürümüyle çalışmaya devam edebiliyordu.
5. Sözleşmeler sabit kalsın
Bölme sırasında servisler arası API sözleşmelerine dokunmadım. Yapısal değişiklik ile davranış değişikliğini aynı anda yapmak, bir sorun çıktığında sebebini bulmayı imkânsız hâle getirir. Önce taşıma, sonra iyileştirme.
Bu tür bir işte en değerli araç, her adımın sonunda "hâlâ derleniyor ve tipler tutuyor mu?" sorusuna otomatik cevap veren bir CI hattıdır. Beş reponun her biri, sıfır tip hatası ve temiz derlemeyle teslim edildi; bunu mümkün kılan, doğrulamanın elle değil otomatik yapılmasıydı.
Sonuç
Bölme bir haftalık bir "büyük geçiş" değil, her biri tek başına geri alınabilen küçük adımlar dizisiydi. Aynı yaklaşım, para alanlarını float'tan Decimal'e taşırken de işe yaradı; onu bu yazıda anlattım.