Menguji nilai batas bawah dan atas dengan Python

Sep 19 2020

Fungsi kode

Kode berikut menguji apakah nilai yang ditentukan pengguna untuk batas bawah dan atas pada dua properti:

  1. Batas bawah lebih kecil dari batas atas.
  2. Nilainya lebih besar dari 0 (positif).

Sejak pertama kali memeriksa apakah batas bawah lebih kecil dari batas atas, itu secara implisit memverifikasi batas atas lebih besar dari 0, jika menguji apakah batas bawah lebih besar dari 0. Oleh karena itu, pertimbangan saya adalah: Saya dapat membuat kode lebih banyak kompak dengan menghilangkan centang untuk "adalah batas atas lebih besar dari 0".

Kode

# Object getting labels
class Get_labels:
    def __init__(self,lower_bound,upper_bound,configuration_name):
        self.lower_bound = lower_bound
        self.upper_bound = upper_bound
        self.configuration_name = configuration_name
        self.check_threshold_validity()
          
                            
    # Verifies if the chosen thresholds are valid values.
    def check_threshold_validity(self):
        if self.lower_bound>=self.upper_bound:
            raise Exception(f'Sorry, the lower threshold={self.lower_bound} should be smaller than the upper bound={self.upper_bound} for configuration={self.configuration_name}')
        
        # checks if lower bound (and implicitly upper bound) are above zero
        if self.lower_bound<=0:
            raise Exception(f'Sorry, the lower threshold={self.lower_bound} should be larger than 0 for configuration={self.configuration_name}')
        
if __name__ == '__main__':
    get_labels = Get_labels(-1,25,"first")

Pilihan desain

Namun, jika kode diubah, mungkin tidak terlihat jelas batas atas juga perlu diperiksa karena dilakukan secara implisit. Itu mungkin mengakibatkan kasus tepi dengan batas atas di bawah nol tidak tertangkap setelah modifikasi. Oleh karena itu untuk mencegah skenario ini, saya dapat menerapkan uji dua unit yang memeriksa apakah ada kesalahan yang muncul untuk:

  1. Negatif batas bawah, batas atas negatif
  2. Batas bawah nol, batas atas negatif
  3. Batas bawah positif, batas atas negatif

Pertanyaan

Apakah disarankan untuk menyertakan pemeriksaan eksplisit dalam kode utama, meskipun itu diuji dalam pengujian unit?

Jawaban

9 FMc Sep 19 2020 at 00:38

Kecuali dalam keadaan yang tidak biasa, kelas adalah benda atau entitas - karenanya disebut objek - sedangkan fungsi atau metode adalah tindakan atau operasi. Anda ingin memberi nama yang sesuai. Untuk alasan itu, Get_labelsmenurutku sebagai kelas bernama aneh. Berdasarkan apa yang Anda tunjukkan kepada kami, saya mungkin menyarankan nama Boundssebagai alternatif. Manfaat sampingan dari nama itu adalah memungkinkan Anda mempersingkat nama atribut tanpa kehilangan makna.

Bagi saya, metode terpisah untuk memeriksa validitas dasar batas-batas tampaknya terlalu rekayasa - kecuali logika pemeriksaan menjadi jauh lebih kompleks atau kecuali akan digunakan di tempat lain dalam kode. Jadi saya hanya akan melakukan validasi sederhana __init__()dalam kasus ini.

Hindari godaan untuk menggunakan pesan cerewet atau bertele-tele dalam kode Anda. Ini tidak akan membantu Anda atau pengguna Anda dalam jangka panjang - setidaknya itulah pengalaman saya. Jaga agar semuanya tetap langsung dan ringkas dengan ketat. Faktanya, sering kali bermanfaat untuk menjaga pesan tetap sangat teknis daripada alami dalam orientasi gaya mereka. Yang saya maksud dengan hal itu adalah daripada mendeskripsikan masalah seperti yang mungkin dilakukan seseorang secara lisan kepada manusia ("Batas bawah, yaitu 1000, harus kurang dari batas atas, yaitu 125"), Anda sering kali lebih baik menggambarkannya masalah dalam rumus, skema, seperti komputer. Antara lain, pendekatan tersebut memungkinkan Anda untuk mengadopsi format konvensional untuk semua pesan kesalahan dalam aplikasi. Format pesan kesalahan yang ditunjukkan dalam penulisan ulang di bawah ini secara umum dapat dijelaskan sebagai PROBLEM: SELF. Pendekatan yang konsisten membuatnya lebih mudah untuk menulis kode validasi sejak awal dan menjaganya dari waktu ke waktu. Konsistensi juga menyampaikan profesionalisme kepada pengguna.

Sejalan dengan itu, Anda sering kali dapat menyederhanakan pembuatan pesan validasi tersebut dengan terlebih dahulu menentukan __repr__()kelas Anda, seperti yang diilustrasikan di bawah ini.

Untuk validasi yang Anda miliki sejauh ini, ValueErrora lebih cocok daripada membesarkan seorang jenderal Exception. Selain itu, Anda dapat mempertimbangkan untuk memeriksa jenis kesalahan lainnya: misalnya, apakah batas dibatasi hanya untuk bilangan bulat?

Jika Anda benar-benar memeriksanya, angkat a TypeError.

Akhirnya, poin halus gaya dan diakui subjektif. Di bawah ini adalah jejak tumpukan dari kode Anda seperti yang tertulis. Kami melihat pesan verbose dua kali, pertama sebagai f-string, dan kemudian dengan parameter yang diisi. Apa yang salah dengan itu? Tidak ada yang serius, tapi berat, membosankan, bahkan kurang elegan. Minimal, dapat dikatakan bahwa pengulangan pesan verbose agak mengganggu pengguna, memberikan tambahan beban visual atau kognitif pada pengguna untuk mencari tahu apa yang terjadi. Bandingkan itu dengan jejak tumpukan dari kode yang direvisi.

# ORIGINAL.

Traceback (most recent call last):
  File "bounds.py", line 19, in <module>
    get_labels = Get_labels(-1,25,"first")
  File "bounds.py", line 7, in __init__
    self.check_threshold_validity()
  File "bounds.py", line 17, in check_threshold_validity
    raise Exception(f'Sorry, the lower threshold={self.lower_bound} should be larger than 0 for configuration={self.configuration_name}')
Exception: Sorry, the lower threshold=-1 should be larger than 0 for configuration=first

# REVISED.

Traceback (most recent call last):
  File "bounds.py", line 72, in <module>
    b1 = Bounds(1000, 125, 'first')
  File "bounds.py", line 67, in __init__
    raise Exception(msg)
Exception: Upper bound must be greater than lower: Bounds(1000, 125, first)

Kode dengan beberapa kemungkinan pengeditan untuk Anda pertimbangkan:

class Bounds:

    def __init__(self, lower, upper, name):
        self.lower = lower
        self.upper = upper
        self.name = name

        if lower <= 0 or upper <= 0:
            msg = f'Bounds must be positive: {self}'
            raise ValueError(msg)

        if upper <= lower:
            msg = f'Upper bound must be greater than lower: {self}'
            raise ValueError(msg)

    def __repr__(self):
        return f'Bounds({self.lower}, {self.upper}, {self.name!r})'