Init Fonksiyonları Neden Tehlikeli Olabilir: Initialization Order Sorunları

Anket

Init fonksiyonlarında sıralama hatası yaşadın mı?

0 oy

Init fonksiyonları yazılımın omurgasıdır, ama çoğu geliştirici bunları bir başlangıç noktası olarak görüp, gerçek risklerini gözden kaçırır.

Sorun şu: bir init fonksiyonunun çalıştığı sıra, çoğu zaman belirli değildir ya da başka bir modülün init'inin ne zaman biteceğine bağlıdır. Go'da, Python'da, hatta C++'ta bu durum ortaya çıkar. Global değişkenlerin başlatılması, veritabanı bağlantıları, konfigürasyon yüklenmesi, bunların hepsi zincirleme bağımlılıklar yaratır.

Python'da global state başlatırken bir modülü import ettiğinde, o modülün init kodu hemen çalışır. Eğer o init başka bir modülü import ederse ve o da başka birini ederse, kontrol kaybedersin. Bir yerde bir hata olursa, stack trace seni doğru yere götürmez; başlatma sırasının karmaşıklığında kaybolursun.

Go'da init fonksiyonları dosya adına göre alfabetik sırayla çalışır. Bu deterministik ama tuzaklı. İki init'in aynı paket içinde çalıştığını düşün, ikinci init'in birinciye bağlı olduğunu unutursan, dosya adını değiştirdiğinde kod çöker. Kodu başka bir takıma taşıdığında, hatta başka bir işletim sisteminde derlerken sıra değişebilir.

Reklam · TEST
AdSense Test ReklamıYazı arası (gönderi içi) · Yazı arası

Race condition da gizli tehlike. Eğer init fonksiyonları paralel çalışırsa (veya başlatma sırasında goroutine başlatılırsa), iki init aynı global kaynağa dokunabilir. Bir test ortamında nadir görülen, üretimde sürpriz yapan hatalar bundan doğar.

En sinsi kısım hata ayıklama. Init hatası sırasında program başlamaz; log'a bile yazamayabilir. Eğer init'te bir dosya açmaya çalışırsan ve dosya yoksa, process'in neden başlamadığını anlamak saatleri alabilir. Ek olarak, unit test'ler init'i çalıştırır, bu da test'lerin birbiriyle etkileşim kurmasına neden olur.

Ne yapmalı? Önce, global state'i minimize et. Init'te yalnızca kesinlikle gerekli olanı başlat. Bağımlılıkları açık kıl; bir init başka bir paket/modülün başlatılmasına ihtiyaç duyuyorsa, bunu kod içinde (init'ten sonra) yap, init'in kendisinde değil. Hata işlemeyi cidiye al, init'te bir şey başarısız olursa, anlamlı bir hata mesajı ver ve process'i düzgün kapat.

Son olarak: init'in ne zaman çalıştığını test et. Başlatma sırasını simüle eden testler yaz. Eğer init'in başka bir init'e bağlı olması gerekiyorsa, bunu açık bir fonksiyon çağrısıyla yap, init zincirinin gizli sırasına güvenme. Bu disiplin başlangıçta ekstra çalışma gibi görünse de, üretimde çöken bir sistemde harcayacağın zamanın çok altında kalır.

Reklam · TEST
AdSense Test ReklamıGönderi altı · Görüntülü
konu hakkında tepkinizi verebilirsiniz