Bugün yine kendi kendime "Neden böyle çalışıyor?" diye sorduğum bir gün. Projede refactoring yapıyordum, her şey güzel gidiyordu. Ta ki, iki yıl önce yazılmış, "çalışıyor, elleme" denilen bir modüle gelene kadar.
Kutsal Kod Parçasına Dokunmak
Modül, bir veri işleme akışının tam ortasındaydı. İsmi data_sanitizer.py'dı. İçine baktığımda, sanki bir zaman kapsülü buldum. Requests kütüphanesinin eski bir versiyonuna bağımlı, try-except blokları içinde yakalanmış ve loglanmamış onlarca hata, ve en kötüsü... global değişkenlerle kontrol edilen bir durum makinesi.
Herkes bu dosyadan korkuyordu. "Çalışıyor ya, dokunma bozarsın" lafı, adeta bir tabu haline gelmişti.
Meğer Neler Barındırıyormuş
Merakıma yenik düşüp test yazmaya karar verdim. Basit bir unit test ile farklı edge case'leri besledim. İlk testte, özel karakterler içeren bir string girdiğimde, modül sessizce None döndü ve ana akış hiçbir hata almadan devam etti! Sonuç? Veritabanına boş kayıt gitti.
Daha derine indim. Meğerse o "sihirli" fonksiyon, belirli bir network timeout'unun altında çalışırsa, cache'lenmiş (ve güncelliği 1 yıl önce geçmiş) bir dosyadan veri okuyordu. Yani sistem yavaşladığında, aslında 1 yıllık eski kur verilerini işliyorduk! StackOverflow'da bile böyle kreatif bir bug bulamazsınız.
Temizliğe Giriştim ve...
Kodu parçalara ayırmaya, her bir işlevi küçük, test edilebilir fonksiyonlara bölmeye başladım. Global state'i kaldırdım, dependency'leri enjekte ettim. İlk başta, tabii ki her şey kırıldı. Eski kod, onu saran diğer parçalarla öyle iç içe geçmişti ki, ayrıştırmak ameliyat gibiydi.
Ama sonunda... Tertemiz bir modül ortaya çıktı. Hata durumları net, loglar anlamlı, performans 3 kat arttı. Ve en önemlisi, artık ne yaptığını biliyoruz.
İşin acı komik tarafı: O "dokunulmaz" kod, yıllardır sessiz sedasız hatalı sonuçlar üretiyor ve kimse fark etmemişti çünkü "çalışıyor" gibi görünüyordu.
Siz de projelerinizde böyle kutsal, kimsenin dokunmaya cesaret edemediği kara kutular var mı? Onları temizlemek için nasıl bir strateji izliyorsunuz? Yoksa "Çalışıyorsa dokunma" felsefesine sadık mısınız?
Modül, bir veri işleme akışının tam ortasındaydı. İsmi data_sanitizer.py'dı. İçine baktığımda, sanki bir zaman kapsülü buldum. Requests kütüphanesinin eski bir versiyonuna bağımlı, try-except blokları içinde yakalanmış ve loglanmamış onlarca hata, ve en kötüsü... global değişkenlerle kontrol edilen bir durum makinesi.
Python:
if global_config.get('clean'):
# 150 satırlık kimsenin anlamadığı sihir
result = do_the_magic(data)
Herkes bu dosyadan korkuyordu. "Çalışıyor ya, dokunma bozarsın" lafı, adeta bir tabu haline gelmişti.
Merakıma yenik düşüp test yazmaya karar verdim. Basit bir unit test ile farklı edge case'leri besledim. İlk testte, özel karakterler içeren bir string girdiğimde, modül sessizce None döndü ve ana akış hiçbir hata almadan devam etti! Sonuç? Veritabanına boş kayıt gitti.
Daha derine indim. Meğerse o "sihirli" fonksiyon, belirli bir network timeout'unun altında çalışırsa, cache'lenmiş (ve güncelliği 1 yıl önce geçmiş) bir dosyadan veri okuyordu. Yani sistem yavaşladığında, aslında 1 yıllık eski kur verilerini işliyorduk! StackOverflow'da bile böyle kreatif bir bug bulamazsınız.
Kodu parçalara ayırmaya, her bir işlevi küçük, test edilebilir fonksiyonlara bölmeye başladım. Global state'i kaldırdım, dependency'leri enjekte ettim. İlk başta, tabii ki her şey kırıldı. Eski kod, onu saran diğer parçalarla öyle iç içe geçmişti ki, ayrıştırmak ameliyat gibiydi.
Ama sonunda... Tertemiz bir modül ortaya çıktı. Hata durumları net, loglar anlamlı, performans 3 kat arttı. Ve en önemlisi, artık ne yaptığını biliyoruz.
İşin acı komik tarafı: O "dokunulmaz" kod, yıllardır sessiz sedasız hatalı sonuçlar üretiyor ve kimse fark etmemişti çünkü "çalışıyor" gibi görünüyordu.
Siz de projelerinizde böyle kutsal, kimsenin dokunmaya cesaret edemediği kara kutular var mı? Onları temizlemek için nasıl bir strateji izliyorsunuz? Yoksa "Çalışıyorsa dokunma" felsefesine sadık mısınız?