Assert sadece testte mi kullanılır?

Data validation için pydantic kullanıyorum. Yapıyı oluşturdum ve bir validator yazdım, kod şu şekilde:

class AC_Base(BaseModel):
    query: str
    service_type: Optional[str] = 1

    @validator('service_type')
    def service_type_validator(cls, v):
        available_service_types = ["1", "2", "3"]
        assert v in available_service_types, 'service_type must be 1, 2 or 3'
        return v

ancak senior bir developer ‘assert’ kullanmama takıldı. assert’ü sadece testlerde kullanmam gerektiğini söyledi. sebebini sordum ‘sen öyle yap’ yanıtı aldım. burada assert kullanmam hatalı mı ya da best practice olmayan bir yöntem mi acaba? yani assert yerineif v not in available_service_types: ... yazmak daha mı mantıklı?

production’da assert kullanılmaması gerekiyormuş.

Is assert only used in testing?
Assert should only be used for testing and debugging — not in production environments. Because assert statements only run when the __debug__ variable is set to True , a Python interpreter can disable them.
1 Beğeni

Takilmasinda sakinca yok, fakat sebebini aciklayamiyorsa cargo cult mensubudur, baska yerden duydugu seyi tekrarliyordur. Senior’lugu sadece isimde olabilir.

Normalde kodun yaptigi varsayimlari belgelemek, dogru olmasini bekledigimiz ama %100 emin olmadigimiz seyleri ozel durumlarda (mesela sistem patladiginda) kontrol etmek icin kullanilir. Surada da bir benzerini yazmisim: Assert deyimi nasıl kullanılır? - aib tarafından #9

Kullanim amaci ve sekli, her alet gibi, kullanana bakar. Mesela release edilecek versiyonlar once assert’ler acik release edilip, bir sure hic bir assertion error olusmuyorsa assert’ler kapali release edilebilir. Veya normalde kapali tutulup sorun cikinca acilabilir (detayli, “trace” log seviyeleri gibi).

Python dokumentasyonu da benzer bir sey soylemis. Ama “production’da kullanmamak” nedir? Onu, yukaridaki ornegi aciklarken yazacagim:

Fonksiyonun nasil kullanildigini goremiyoruz, ama kullanici girdisini dogrulayan bir kod olarak dusunelim. O zaman assertion yanlis hamle. Kullanicinin her zaman dogru degeri girmesini beklemiyoruz; validasyon fonksiyonunun var olma sebebi bu zaten. ValidationError throw etmek veya False veya hata stringi dondurmek gibi, validasyon sistemi tarafindan tanimlanmis bir hareket yapmak lazim.

v’yi kullanan duz bir fonksiyon oldugunu dusunelim. Kullanici burada programci; yanlis deger vermesini bekleyebilir miyiz? Elbette; bu Python. Yine de fonksiyonun normal kullanimi dahilinde beklenen bir durum degil, istisnai bir durum. O zaman TypeError, ValueError, IllegalArgumentException (Java) veya ArgumentException (C#) gibi bir exception throw etmemiz lazim.

Peki nasil bir durumda assertion kullanmak dogru olurdu?
Mesela v’nin 1, 2 veya 3 oldugu kodda baska bir mekanizma tarafindan kontrol ediliyor olsaydi, normal kullanim ve hatta normal yazilim gelistirme surecinde bile baska bir deger beklemezdik. Yine de, baska bir deger oldugunda sacma sapan bir seyler yapacak olsak, veya yapmak uzere oldugumuz seyler kolayca anlasilmayacak, bulunmayacak tuhafliklara yol acacak olsaydi assertion kullanmak isteyebilirdik.

Bakayim, ben nerelerde kullanmisim:

  • Capture edilen USB paketi parse edilirken; header’daki data size’in data’nin size’ina esit olmasi
  • Isik konfigurasyon dosyasinda*; tup ayari tutan array’in boyutu tup sayisina esit, DMX evren numarasi evren sayisindan kucuk, adresi adres menzilinde.
  • Birkac kullanimlik test script’inde; if dev is not None: print(“Unable to find device”) yerine. None’i dogrudan kullaninca cikan hata kod hatasina benziyor; aleti takmayi unuttuysam erken hata versin.
  • USB cihazdan gelen yanita bakarken; “cevap kodu” olarak belledigim 0xcb yerine baska bir sey gelirse. (Iki script ayni anda calisirsa birinin cevabi digerine gidebilir mesela. Veya belki cevap kodu sabit degildir, birkac biti bir ayara baglidir.)

En guzel ornek ilki sanirim.

7 Beğeni

Teşekkür ederim gayet açıklayıcı oldu.

Doğrulama için bir doğrulayıcı fonksiyon yazılmış ama doğrulayamadığı durum yönetilmemiş. Bu durumda doğrulayıcı demek doğru mudur bilemedim.

Hem doğru hem yanlış.

Evet yazılım döngüsü, kodu geliştirmek,kodu test etmek, kodu kullanıcı geri beslemeleri ve çeşitli nedenlerle geliştirmek, hata bildirimlerini dikkate alarak yeniden düzenlemek şeklinde ilerler.

Aslında bu kısmı uzunca anlatırdım ama bu gün o gün değil. Her neyse. Sonuçta bir şekilde kodunuzda kullanım aşamasında da yeniden hatalar çıkabilir ve kodunuzu yeniden yazarsınız.

Burada hedef, kodun kırılamaz olmasıdır. Yani hatalarla başa çıkabilme kabiliyetini artırmaktır. Çünkü hataları her zaman ön görmek mümkün değildir.

Hele ki hata çeşitlerini düşünürsek bütün hataları öngörmek mümkün olmayabilir ama amaç hep hatalara karşı dirençli kod yazmaktır. (Bunu neden yazdığımı sonda açıklarım.)

Şimdi adamın haleti ruhiyesini kestiremiyorum. Adamın canı mı sıkkındı, edinilmiş eski tecrübelerden karşısındaki insanla mesafeyi mi koruyor, bazı zeki insanların iletişim becerileri zayıftır konuşmayı açıklamayı sevmez o tip biri midir, yoksa kulaktan dolma belletilmiş çaresizlik durumundan kendi de bu varsayımı kabul etmiş ve sorgulamamış mıdır bilemedim…

Ama birine bir şeyi yapma dediğimde yapmamasından emin olmak istediğimde kesinlikle nedenini dikkatli ve net bir şekilde açıklarım. Aksi halde murphy kanunları bana o yapma dediğim kişinin yaparak geri gelerek yeni bir sorunu geri bana getirir.

Başta hem evet hem hayır demiştim bu bölümde konuya biraz açıklık getirmeye çalışalım.

Daha önce de söylemiştim tekrarlayayım.

Vaktinde durum muhakemesini yapmayan ileride kriz yönetimi ile uğraşır.

Biz her zaman olası hatalara karşı dirençli bir kod ve program yazmayı hedefliyoruz. Yani kullanıcıdan yada algoritmadan veyahut başka herhangi bir yerden gelen hataya neden olan değişikliklere dirençli bir kod ve bunu sağlamak için de iyi bir hata yönetim mekanizması kurmak hedefimiz.

Burada bir riskten bahsetmiş.

Güzel düşünce. Kullanıcınıza gönderdiğiniz ürünün, çalıştıracağı/koşturacağı konfigürasyon farklı iste hata yönetiminiz asert ile boşa çıkabilir.

Yani yorumlayıcının debug = False yapılması durumunda yada sizin yazdığınız modülü kullanacak asıl programın bunu devre dışı bırakması durumunda sizin kodunuzun hata yönetim kapasitesi devredışı kalmış olacaktır.

Bu risk her zaman göze alınamayabilir. Hele ki bu durumdan kaynaklı bir hatayı kontrol etmek de oldukça zor olacaktır. Ürünü kullanan kullanıcının konfigürasyonuna bakmak gerekir ki, kendi kodunuzun bakımını yapmak mı yoksa kullanıcının sistemine bakıp hata aramak mı dersek daha kolay anlaşılacaktır.

Şimdi hem evet hem hayır dediğim kısmına biraz daha netlik getirmeye çalışalım.

Olmaz diye bir şey yoktur, hangi riski ne seviyede almak istediğinize bağlı, yada özel ihtiyaçlarınıza bağlı.

Hayır kısmı için, göz ucuyla bir ara bakmıştım, şu anki durumu takip etmedim ama kodun debug modunu runtime olarak kontrol edebiliyoruz. (2.x 3.x arasında farklı diye hatırlıyorum.)

Ama en azından debug modunu garanti edecek başlatma scripti ile asıl kodu çalıştırabilirsiniz.

Diğer tarafta yine başta söylediğim, yazılım geliştirme süreci ve durum muhakemesi konusuna dönelim.

Kim bir assertion fail ile sonlanan programdan hoşlanır ki? Neden bu hataları ön görüp, try except blokları ve koşullu kontrollerle denetim altına almaya çalışmayalım.

Tabi şu da aklıma gelmişti assertion fail’ler yönetilebilir mi? Evet bir kaç yerde bunun da dolaylı yöntemlerini gördüm ve fakat hala şu soru kafamda. Bir anda bir hata mesajı ile kapanan programlardan hoşlanıyor muyum?

Hayır. Bu durumda kod geliştirme sürecinizi sürekli kodu ayakta tutmak ve hataları yönetmek üzerine kurmalısınız.

Hata yakaladığınızda sonlandırmak üzerine kurmak mantıklı görünmüyor yine istisnalarını da unutmayalım. Bir döngü içine kapsolmuş bir kodu sistemi kurtarmak için kodu sonlandırmak da gerekebilir.

Terminalde CTR+C ,CTRL+Z yada Windowsta Alt+F4 de hiç karşılaşmadığımız durumlar değil.

2 Beğeni