Apakah lebih masuk akal untuk mencatat pengecualian di catch-all atau di kelas pengecualian dasar?

15

Saya sedang dalam proses refactoring aplikasi web yang cukup besar. Salah satu masalah utama adalah penanganan kesalahan yang tidak konsisten dan saya mencoba untuk membuat strategi yang masuk akal. Saya telah membuat penangan kesalahan khusus, melalui set_error_handler yang pada dasarnya mengubah kesalahan PHP di ErrorExceptions dan kelas pengecualian basis kustom, yang secara langsung diwarisi dari Pengecualian .

Pada produksi saya menggunakan pengecualian umum catch-all, melalui set_exception_handler , dan saya akan menambahkan pengecualian logging * ke dalam campuran. Dilema saya adalah di mana harus melakukan logging yang sebenarnya, di kelas pengecualian dasar atau di catch-all.

Saya telah memikirkan beberapa alasan untuk mencatatnya di catch-all:

  • Ada beberapa pengecualian dalam kode yang perlu dikonversi ke beberapa anak yang sesuai dari kelas pengecualian dasar. Sampai itu terjadi, tidak semua pengecualian akan dicatat.
  • Entah bagaimana rasanya lebih alami untuk melakukannya di catch-all, kelas pengecualian dasar seharusnya tidak melakukan lebih dari itu. (Mungkin itu hal tanggung jawab prinsip tunggal, tapi itu bisa saja perasaan yang salah arah)

dan satu alasan untuk masuk ke kelas pengecualian dasar:

  • Saat ini tangkapan-semua hanya digunakan pada produksi. Akan mudah untuk memperkenalkannya di lingkungan kami yang lain (pengembangan, pengujian) tetapi itu akan membutuhkan beberapa penyesuaian, karena kesalahan ditangani secara berbeda per lingkungan, seperti pada produksi mereka diterjemahkan ke 404/503 halaman kesalahan.

Apakah ada praktik yang dapat diterima di mana harus memasukkan pengecualian?

* Logging akan melibatkan penulisan ke file teks pada awalnya, dan mungkin berevolusi untuk mengirim surat untuk jenis pengecualian tertentu.


Beberapa klarifikasi, dipicu oleh jawaban @ unholysampler :

Saya menghadapi basis kode sloc 2 * 10 ^ 6, dengan banyak hal pihak ketiga yang tidak dapat saya kendalikan, dan beberapa kode saya memang memiliki kendali atas pengecualian pra-tanggal dalam PHP. Dan ada juga beberapa kode baru-baru ini jelek, kita pulih dari tekanan panjang yang panjang di mana kita benar-benar harus berhenti berpikir dan hanya meretas.

Kami secara aktif refactoring untuk mengatasi semua ketidakkonsistenan dan memperkenalkan pendekatan penanganan kesalahan yang masuk akal, tetapi itu akan memakan waktu. Saya lebih tertarik pada apa yang harus dilakukan sampai saya mencapai titik di mana kesalahan ditangani dengan tepat. Saya mungkin akan mengajukan pertanyaan lain tentang strategi pengecualian yang masuk akal di beberapa titik.

Motivasi utama di balik pencatatan adalah mendapatkan email di ponsel saya setiap kali terjadi sesuatu yang buruk pada produksi. Saya tidak peduli jika kesedihan data menjadi besar, jika mereka melakukannya saya akan memiliki pekerjaan cron menghapus yang lama setiap saat.

yannis
sumber

Jawaban:

11

Singkatnya, satu-satunya waktu Anda harus mencatat keberadaan pengecualian adalah ketika Anda menanganinya.

Ketika Anda melempar pengecualian, itu karena kode Anda telah mencapai keadaan di mana ia tidak dapat melanjutkan dengan benar. Dengan melemparkan pengecualian, Anda mewakili pesan tertentu ke program Anda tentang kesalahan yang terjadi. Anda seharusnya tidak menangkap pengecualian sampai Anda berada pada titik di mana ia dapat ditangani dengan benar.

Kode yang Anda tulis sebagai bagian dari aplikasi utama Anda harus mengetahui jenis-jenis pengecualian yang dapat dilempar dan kapan mereka dilempar. Jika Anda tidak dapat melakukan sesuatu yang produktif dengan pengecualian, jangan tangkap. Jangan mencatat pengecualian sampai sedang ditangani. Hanya kode penanganan yang tahu apa arti pengecualian dalam konteks aliran program dan bagaimana meresponsnya. Menulis pesan log di sini mungkin masuk akal di sini. Jika Anda menggunakan kerangka kerja logging, Anda dapat mengatur level log untuk pesan dan berpotensi menyaringnya. Ini berfungsi baik untuk pengecualian yang dapat terjadi, tetapi tidak kritis dan dapat dipulihkan dari bersih.

Pengecualian Anda, semua, adalah upaya terakhir Anda untuk menjaga agar kode Anda tidak mengalami kematian yang buruk. Jika sejauh ini, Anda mencatat semua informasi status dan kesalahan yang Anda bisa. Kemudian Anda melakukan yang terbaik untuk memberi tahu pengguna bahwa program mogok sebelum semuanya berhenti. Sasaran Anda adalah jangan pernah mengeksekusi kode ini.

Menanamkan masuk ke kelas dasar tidak mengikuti pedoman di atas. Kelas dasar tidak tahu apa-apa tentang status kode. (Memiliki jejak stack tidak dihitung karena Anda tidak akan menulis kode yang membuat keputusan berdasarkan penguraiannya.) Kelas dasar tidak dapat melakukan apa pun untuk menunjukkan tingkat keparahan atau bagaimana pengecualian dapat ditangani. Anda tidak ingin data dump dan stack stack besar setiap kali ada pengecualian sederhana yang dapat Anda tangani dan pulihkan dari bersih.

unholysampler
sumber
Saya telah menambahkan beberapa klarifikasi tentang pertanyaan yang ditanyakan oleh jawaban Anda. Dari apa yang saya kumpulkan, di sisi praktis dari pertanyaan yang Anda usulkan untuk masuk semua?
yannis
1
@YannisRizos: Ya, Anda harus menerapkan catch-all sebagai langkah pertama Anda. Apa yang saya katakan tentang tangkapan-semua lebih untuk memastikan bahwa Anda tidak menggunakannya sebagai bagian normal dari aliran kode Anda. Menerapkan penangan pengecualian yang tidak tertangani adalah penting karena memungkinkan Anda untuk mendapatkan banyak informasi setiap kali kode Anda melakukan sesuatu yang buruk.
unholysampler
Apakah tidak ada kerangka kerja logging yang dapat dengan mudah menangani konsep "Inilah banyak hal yang harus dicatat kecuali ia digantikan"? Setiap lapisan yang melihat pengecualian dapat menggantikan data dari sebelumnya, kecuali bahwa jika pengecualian baru dilemparkan selama tumpukan dibuka, laporan log terakhir tidak akan digantikan dan dengan demikian akan direkam. Apakah tidak ada kerangka kerja yang mendukung pola seperti itu?
supercat
3

Jika bahasa / runtime Anda tidak mudah membiarkan Anda menentukan sumber pengecualian, ada alasan untuk mencatatnya saat melempar. C ++ dan beberapa mesin JS tidak mengekspos file + line atau memanggil stack pengecualian pada saat Anda menangkapnya / tetapi informasi ini tersedia pada saat Anda membuat pengecualian.

Solusi kami adalah menyediakan mekanisme yang menggunakan konfigurasi runtime untuk mengaktifkan pencatatan jenis pengecualian bersama dengan tumpukan murah ketika mencoba mendiagnosis masalah ini.

JBRWilkinson
sumber
+1 Itu jelas merupakan kasus yang bagus untuk login saat melempar ... PHP memang menyediakan jejak stack penuh saat tangkapan, jadi saya mungkin akan pergi ke arah lain ...
yannis