Sürekli Kırılan Kod Tabanı
Bir sorunumuz vardı. Ana müşteri projemiz — yaklaşık 50.000 satır JavaScript'ten oluşan bir React SPA — giderek kırılganlaşıyordu. Her sprint regresyon getiriyordu. Burada yeniden adlandırılmış bir prop, orada değişmiş bir API yanıtı ve bir anda üç sayfa çökmüş oluyordu.
Ekip, geliştirmekten çok hata ayıklamakla zaman harcıyordu. Bir şeylerin değişmesi gerekiyordu.
Neden TypeScript? (Ve Neden Tereddüt Ettik)
Dürüst olayım: Başta şüpheciydim. TypeScript iş yükü gibi geliyordu. Daha fazla dosya, daha fazla sözdizimi, daha fazla araç yapılandırması. Küçük ekibimiz yavaşlamayı göze alamazdı.
Ama art arda üçüncü sprint'te tip kaynaklı bir bug için hotfix gönderdiğimizde, taşımamanın maliyeti ortaya çıktı. TypeScript'ten kaçınarak zaman kazanmıyorduk — onu en kötü şekilde harcıyorduk: önlenebilir buglar üzerinde.
Migrasyon Stratejimiz: Big Bang Yok
Bir keresinde tam yeniden yazım denedik. Farklı bir projede. Başarısız oldu. Üç haftalık çalışma çöpe gitti.
Bu sefer kademeli gittik:
Faz 1 — Altyapı (1. Hafta)
strict: false ve allowJs: true ile tsconfig.json ekledik. Giriş noktasını yeniden adlandırdık. Bu kadar. Uygulama hâlâ çalışıyordu.
Faz 2 — Ortak Tipler (2-3. Hafta)
Bir /types dizini oluşturduk. API yanıt tipleri ile başladık — en yüksek değerli, en düşük riskli hedef.
Faz 3 — Bileşen Bileşen (Süregelen) Biri bir dosyaya her dokunduğunda, onu dönüştürdü. Özel "migrasyon sprint'leri" yok. Normal iş akışının bir parçası olarak organik şekilde gerçekleşti.
Sürprizler (İyi ve Kötü)
Beklenenden iyi gidenler
Onboarding hızı ikiye katlandı. Yeni geliştiriciler artık "Bu prop ne yapıyor?" diye sormayı bıraktı. Herhangi bir değişkenin üzerine gelip tipini görebiliyorlardı.
Refactoring korkusuz hale geldi. TypeScript'ten önce bir prop'u yeniden adlandırmak, tüm kod tabanını grep ile taramak ve hiçbir şeyi kaçırmadığını ummak demekti. Artık derleyici değişmesi gereken her yeri söylüyor.
API uyumsuzlukları build zamanında yakalandı. Çalışma zamanı doğrulaması için zod şemaları, derleme zamanı güvenliği için TypeScript arayüzleri kullanıyoruz.
Beklenenden zor olanlar
Üçüncü parti tiplendirmeler. Bazı kütüphanelerin eski veya eksik tip tanımları vardı.
Ekip desteği. Herkes hevesli değildi. Bir kıdemli geliştirici TypeScript'in "kılık değiştirmiş Java" olduğunu düşünüyordu.
Generic tipler. Paylaşılan bileşen kütüphanemizin generic'lere ihtiyacı vardı — Table<T>, Select<TOption> — ve bunları doğru tiplemek gerçekten zordu.
6 Ay Sonraki Rakamlar
- Tip hatalarından kaynaklanan üretim bugları: 12/ay → 0-1/ay
- Ortalama PR inceleme süresi: 45 dk → 25 dk
- Yeni geliştirici onboarding süresi: 5 gün → 2-3 gün
- Geliştirici memnuniyeti: 6,2'den 8,4/10'a yükseldi
Migrasyon %90 kapsama ulaşmak için yaklaşık 4 ay sürdü. Şu an %98'deyiz.
Neyi Farklı Yapardım
strict: true ile başlamak. strict: false ile başladık ama sonra ikinci bir geçiş yapmak zorunda kaldık.
Ortak tiplere daha erken yatırım yapmak. En büyük kazanımlarımız tek bir doğruluk kaynağından geldi.
Test dosyalarını en sona bırakmamak. Test dosyalarını sona bıraktık, bu da testlerimizin kapsam konusunda yalan söylediği anlamına geliyordu.
Değer mi?
Birden fazla geliştiricisi olan ve 6 aydan uzun ömrü olacak her proje için — kesinlikle. TypeScript tüm bugları engellemez ama bütün bir kategoriyi ortadan kaldırır.
Migrasyon maliyetimiz 4 ay boyunca hızımızın yaklaşık %15'iydi. Getirisi kalıcı ve birikmeli.