Peringatan! C ++ programmer datang ke sini dengan ide-ide yang mungkin berbeda tentang bagaimana penanganan pengecualian harus dilakukan dengan mencoba menjawab pertanyaan yang tentunya tentang bahasa lain!
Diberi ide ini:
Sebagai contoh, bayangkan kita memiliki sumber daya, yang melakukan permintaan HTTP dan mengembalikan data yang diambil. Dan alih-alih kesalahan seperti ServiceTentarUnavailable atau RateLimitExceeded kami hanya akan meningkatkan RetryableError menyarankan konsumen bahwa itu hanya harus mencoba kembali permintaan dan tidak peduli dengan kegagalan spesifik.
... satu hal yang saya sarankan adalah Anda mungkin mencampur-adukkan kekhawatiran melaporkan kesalahan dengan tindakan untuk meresponsnya dengan cara yang dapat menurunkan sifat umum kode Anda atau memerlukan banyak "titik terjemahan" untuk pengecualian .
Misalnya, jika saya memodelkan transaksi yang melibatkan pemuatan file, itu mungkin gagal karena sejumlah alasan. Mungkin memuat file melibatkan memuat plugin yang tidak ada di mesin pengguna. Mungkin file tersebut hanya rusak dan kami mengalami kesalahan dalam menguraikannya.
Apa pun yang terjadi, katakan saja tindakannya adalah melaporkan apa yang terjadi pada pengguna dan memberi tahu dia tentang apa yang ingin dia lakukan ("coba lagi, muat file lain, batalkan").
Pelempar vs Penangkap
Tindakan tersebut berlaku terlepas dari kesalahan apa yang kami temui dalam kasus ini. Itu tidak tertanam ke dalam gagasan umum tentang kesalahan parsing, itu tidak tertanam ke dalam gagasan umum gagal memuat sebuah plugin. Ini tertanam ke dalam gagasan menemukan kesalahan seperti itu selama konteks yang tepat memuat file (kombinasi memuat file dan gagal). Jadi biasanya saya melihatnya, secara kasar, sebagai catcher's
tanggung jawab untuk menentukan arah tindakan dalam menanggapi pengecualian yang dilemparkan (mis: mendorong pengguna dengan opsi), bukan thrower's
.
Dengan kata lain, situs-situs yang throw
pengecualian biasanya tidak memiliki informasi kontekstual semacam ini, terutama jika fungsi-fungsi yang melempar secara umum berlaku. Bahkan dalam konteks yang sama sekali merosot ketika mereka memiliki informasi ini, Anda akhirnya menyudutkan diri Anda dalam hal perilaku pemulihan dengan memasukkannya ke dalam throw
situs. Situs-situs yang catch
umumnya memiliki jumlah informasi terbanyak tersedia untuk menentukan tindakan, dan memberi Anda satu tempat sentral untuk memodifikasi jika tindakan tersebut harus pernah berubah untuk transaksi yang diberikan.
Ketika Anda mulai mencoba untuk melempar pengecualian tidak lagi melaporkan apa yang salah tetapi mencoba menentukan apa yang harus dilakukan, itu mungkin menurunkan sifat umum dan fleksibilitas kode Anda. Kesalahan penguraian seharusnya tidak selalu mengarah ke jenis prompt ini, ini bervariasi berdasarkan konteks di mana pengecualian seperti itu dilemparkan (transaksi di mana ia dilempar).
The Blind Thrower
Secara umum, banyak desain penanganan pengecualian sering berputar di sekitar gagasan pelempar buta. Tidak tahu bagaimana pengecualian akan ditangkap, atau di mana. Hal yang sama berlaku untuk bentuk pemulihan kesalahan yang lebih lama menggunakan propagasi kesalahan manual. Situs yang mengalami kesalahan tidak termasuk tindakan pengguna, mereka hanya menyematkan informasi minimal untuk melaporkan jenis kesalahan apa yang ditemui.
Tanggung jawab terbalik dan menggeneralisasi Penangkap
Memikirkan hal ini lebih hati-hati, saya mencoba membayangkan jenis basis kode di mana ini bisa menjadi godaan. Imajinasi saya (mungkin salah) adalah bahwa tim Anda masih memainkan peran "konsumen" di sini dan menerapkan sebagian besar kode panggilan juga. Mungkin Anda memiliki banyak transaksi yang berbeda (banyak try
blok) yang semuanya dapat mengalami serangkaian kesalahan yang sama, dan semua harus, dari perspektif desain, mengarah ke arah tindakan pemulihan yang seragam.
Mempertimbangkan saran bijak dari Lightness Races in Orbit's
jawaban yang baik (yang saya pikir benar-benar berasal dari pola pikir berorientasi perpustakaan canggih), Anda mungkin masih tergoda untuk melempar pengecualian "apa yang harus dilakukan", hanya lebih dekat ke situs pemulihan transaksi.
Dimungkinkan untuk menemukan perantara, tempat penanganan transaksi umum dari ini di sini yang sebenarnya memusatkan perhatian "apa yang harus dilakukan" tetapi masih dalam konteks penangkapan.
Ini hanya akan berlaku jika Anda dapat merancang semacam fungsi umum yang digunakan oleh semua transaksi luar ini (mis: fungsi yang memasukkan fungsi lain untuk dipanggil atau kelas dasar transaksi abstrak dengan pemodelan perilaku yang dapat ditimpa memodelkan situs transaksi perantara ini yang melakukan penangkapan canggih ).
Namun seseorang dapat bertanggung jawab untuk memusatkan tindakan pengguna dalam menanggapi berbagai kemungkinan kesalahan, dan masih dalam konteks menangkap daripada melempar. Contoh sederhana (pseudocode Python-ish, dan saya bukan pengembang Python yang berpengalaman sedikit pun sehingga mungkin ada cara yang lebih idiomatis tentang hal ini):
def general_catcher(task):
try:
task()
except SomeError1:
# do some uniformly-designed recovery stuff here
except SomeError2:
# do some other uniformly-designed recovery stuff here
...
[Semoga dengan nama yang lebih baik dari general_catcher
]. Dalam contoh ini, Anda bisa meneruskan fungsi yang berisi tugas apa yang harus dilakukan tetapi masih mendapat manfaat dari perilaku tangkapan umum / terpadu untuk semua jenis pengecualian yang Anda minati, dan terus memperluas atau memodifikasi bagian "apa yang harus dilakukan" Anda suka dari lokasi pusat ini dan masih dalam catch
konteks di mana ini biasanya didorong. Yang terbaik dari semuanya, kita dapat menjaga situs-situs pelemparan agar tidak menganggap diri mereka sendiri sebagai "apa yang harus dilakukan" (mempertahankan gagasan "pelempar buta").
Jika Anda tidak menemukan satu pun dari saran ini di sini yang membantu dan ada godaan yang kuat untuk melempar pengecualian "apa yang harus dilakukan", terutama perlu diketahui bahwa ini sangat anti-idiomatik, dan berpotensi menghambat pola pikir umum.