Tentang mengetik bebek :
Mengetik bebek dibantu oleh biasanya tidak menguji untuk jenis argumen dalam metode dan fungsi badan, mengandalkan dokumentasi, kode yang jelas dan pengujian untuk memastikan penggunaan yang benar.
Tentang validasi argumen (EAFP: Lebih mudah untuk meminta maaf daripada izin). Contoh yang diadaptasi dari sini :
... dianggap lebih pythonic untuk dilakukan:
def my_method(self, key):
try:
value = self.a_dict[member]
except TypeError:
# do something else
Ini berarti bahwa orang lain yang menggunakan kode Anda tidak harus menggunakan kamus atau subkelas nyata - mereka dapat menggunakan objek apa pun yang mengimplementasikan antarmuka pemetaan.
Sayangnya dalam praktiknya tidak sesederhana itu. Bagaimana jika anggota dalam contoh di atas mungkin bilangan bulat? Integer tidak dapat diubah - jadi sangat masuk akal untuk menggunakannya sebagai kunci kamus. Namun mereka juga digunakan untuk mengindeks objek jenis urutan. Jika anggota kebetulan merupakan bilangan bulat maka contoh dua bisa membiarkan daftar dan string serta kamus.
Tentang pemrograman asertif :
Pernyataan adalah cara sistematis untuk memeriksa bahwa keadaan internal suatu program adalah seperti yang diharapkan oleh programmer, dengan tujuan menangkap bug. Secara khusus, mereka bagus untuk menangkap asumsi palsu yang dibuat saat menulis kode, atau penyalahgunaan antarmuka oleh programmer lain. Selain itu, mereka dapat bertindak sebagai dokumentasi in-line sampai batas tertentu, dengan membuat asumsi programmer jelas. ("Eksplisit lebih baik daripada implisit.")
Konsep-konsep yang disebutkan kadang-kadang bertentangan, jadi saya mengandalkan faktor-faktor berikut ketika memilih jika saya tidak melakukan validasi data sama sekali, melakukan validasi yang kuat atau menggunakan pernyataan:
Validasi yang kuat. Dengan validasi yang kuat maksud saya meningkatkan Pengecualian khusus (
ApiError
misalnya). Jika fungsi / metode saya adalah bagian dari API publik, lebih baik memvalidasi argumen untuk menampilkan pesan kesalahan yang baik tentang tipe yang tidak terduga. Dengan memeriksa tipe yang saya maksud bukan hanya menggunakanisinstance
, tetapi juga jika objek yang lewat mendukung antarmuka yang diperlukan (duck typing). Sementara saya mendokumentasikan API dan menentukan jenis yang diharapkan dan pengguna mungkin ingin menggunakan fungsi saya dengan cara yang tidak terduga, saya merasa lebih aman ketika saya memeriksa asumsi. Saya biasanya menggunakanisinstance
dan jika nanti saya ingin mendukung jenis atau bebek lain, saya mengubah logika validasi.Pemrograman asertif. Jika kode saya baru, saya menggunakan banyak pernyataan. Apa saran Anda tentang ini? Apakah nanti Anda menghapus pernyataan dari kode?
Jika fungsi / metode saya bukan bagian dari API, tetapi meneruskan beberapa argumennya ke kode lain yang tidak ditulis, dipelajari atau diuji oleh saya, saya melakukan banyak penegasan sesuai dengan antarmuka yang dipanggil. Logika saya di balik ini - lebih baik gagal dalam kode saya, kemudian di suatu tempat 10 tingkat lebih dalam di stacktrace dengan kesalahan yang tidak dapat dimengerti yang memaksa untuk banyak debug dan kemudian menambahkan pernyataan ke kode saya.
Komentar dan saran kapan harus menggunakan atau tidak menggunakan validasi tipe / nilai, tegaskan? Maaf karena bukan rumusan pertanyaan terbaik.
Sebagai contoh, pertimbangkan fungsi berikut, di mana Customer
model deklaratif SQLAlchemy:
def add_customer(self, customer):
"""Save new customer into the database.
@param customer: Customer instance, whose id is None
@return: merged into global session customer
"""
# no validation here at all
# let's hope SQLAlchemy session will break if `customer` is not a model instance
customer = self.session.add(customer)
self.session.commit()
return customer
Jadi, ada beberapa cara untuk menangani validasi:
def add_customer(self, customer):
# this is an API method, so let's validate the input
if not isinstance(customer, Customer):
raise ApiError('Invalid type')
if customer.id is not None:
raise ApiError('id should be None')
customer = self.session.add(customer)
self.session.commit()
return customer
atau
def add_customer(self, customer):
# this is an internal method, but i want to be sure
# that it's a customer model instance
assert isinstance(customer, Customer), 'Achtung!'
assert customer.id is None
customer = self.session.add(customer)
self.session.commit()
return customer
Kapan dan mengapa Anda menggunakan masing-masing ini dalam konteks pengetikan bebek, pengecekan tipe, validasi data?