Saat ini saya sedang refactoring subsistem besar dengan arsitektur multi-layered, dan saya berjuang untuk merancang strategi logging kesalahan \ penanganan yang efektif.
Katakanlah arsitektur saya terdiri dari tiga lapisan berikut:
- Antarmuka Umum (Pengontrol MVC)
- Lapisan Domain
- Lapisan Akses Data
Sumber kebingungan saya adalah di mana saya harus mengimplementasikan kesalahan logging \ handling:
Solusi termudah adalah menerapkan penebangan di tingkat atas (yaitu Pengendali Antarmuka Publik \ MVC). Namun ini terasa salah karena itu berarti meluapkan pengecualian melalui lapisan yang berbeda, dan kemudian mencatatnya; daripada mencatat pengecualian pada sumbernya.
Mencatat pengecualian pada sumbernya jelas merupakan solusi terbaik karena saya memiliki informasi paling banyak. Masalah saya dengan hal ini adalah bahwa saya tidak dapat menangkap setiap pengecualian pada sumber tanpa menangkap SEMUA pengecualian, dan pada lapisan antarmuka domain / publik, ini akan mengarah pada menangkap pengecualian yang telah ditangkap, dicatat dan dilemparkan kembali oleh lapisan di bawah .
Strategi lain yang mungkin adalah campuran # 1 dan # 2; di mana saya menangkap pengecualian khusus pada layer mereka kemungkinan besar akan dibuang (IE Catching, logging and re-throwing
SqlExceptions
di Layer Akses Data) dan kemudian mencatat pengecualian yang tidak tertangkap lebih lanjut di level atas. Namun ini juga akan mengharuskan saya untuk menangkap dan me-relog setiap pengecualian di tingkat atas, karena saya tidak dapat membedakan antara kesalahan yang telah dicatat \ ditangani dengan yang tidak.
Sekarang, jelas ini adalah masalah di sebagian besar aplikasi perangkat lunak, jadi harus ada solusi standar untuk masalah ini yang menghasilkan pengecualian yang ditangkap pada sumbernya, dan dicatat sekali; namun saya tidak bisa melihat bagaimana melakukannya sendiri.
Catatan, judul pertanyaan ini sangat mirip dengan ' Pengecualian pencatatan dalam aplikasi multi-tier " ', namun jawaban dalam posting itu kurang detail dan tidak cukup untuk menjawab pertanyaan saya.
sumber
The easiest solution would be to implement the logging at the top level
- melakukan hal ini. Mengecualikan pengecualian pada sumbernya bukan ide yang baik dan setiap aplikasi yang saya temui melakukan hal ini adalah PITA untuk debug. Seharusnya menjadi tanggung jawab penelepon untuk menangani pengecualian.try{ ... } catch(Exception ex) { Log(ex); }
akan menghasilkan pengecualian yang sama dicatat pada setiap layer. (Sepertinya ini agak buruk untuk menangkap setiap pengecualian pada setiap lapisan dalam basis kode.)Jawaban:
Untuk pertanyaan Anda:
Memiliki gelembung pengecualian hingga ke tingkat atas adalah pendekatan yang benar-benar benar dan masuk akal. Tidak satu pun dari metode lapisan yang lebih tinggi mencoba untuk melanjutkan beberapa proses setelah kegagalan, yang biasanya tidak dapat berhasil. Dan pengecualian yang dilengkapi dengan baik berisi semua informasi yang diperlukan untuk logging. Dan tidak melakukan apa-apa tentang pengecualian membantu Anda menjaga kode Anda tetap bersih dan fokus pada tugas utama alih-alih kegagalan.
Itu setengah benar. Ya, sebagian besar informasi bermanfaat tersedia di sana. Tapi saya akan merekomendasikan untuk memasukkan semua ini ke objek pengecualian (jika belum ada di sana) daripada langsung login. Jika Anda masuk pada level rendah, Anda masih perlu membuang pengecualian untuk memberi tahu penelepon Anda bahwa Anda tidak menyelesaikan pekerjaan Anda. Ini berakhir di beberapa log dari acara yang sama.
Pengecualian
Pedoman utama saya adalah menangkap dan mencatat pengecualian di tingkat atas saja. Dan semua lapisan di bawah ini harus memastikan bahwa semua informasi kegagalan yang diperlukan akan dipindahkan ke tingkat atas. Dalam aplikasi proses tunggal misalnya di Jawa, ini sebagian besar berarti tidak mencoba / menangkap atau masuk sama sekali di luar tingkat atas.
Terkadang, Anda ingin beberapa informasi konteks termasuk dalam log pengecualian yang tidak tersedia dalam pengecualian asli, misalnya pernyataan SQL dan parameter yang dieksekusi ketika pengecualian dilemparkan. Kemudian Anda dapat menangkap pengecualian asli dan melemparkan kembali yang baru, berisi yang asli ditambah konteksnya.
Tentu saja, kehidupan nyata terkadang mengganggu:
Di Jawa, terkadang Anda harus menangkap pengecualian dan membungkusnya menjadi jenis pengecualian yang berbeda hanya untuk mematuhi beberapa tanda tangan metode tetap. Tetapi jika Anda melempar kembali pengecualian, pastikan yang dilempar kembali berisi semua informasi yang diperlukan untuk masuk nanti.
Jika Anda melewati batas antar-proses, seringkali Anda secara teknis tidak dapat mentransfer objek pengecualian lengkap termasuk jejak stack. Dan tentu saja koneksi mungkin hilang. Jadi, inilah titik di mana suatu layanan harus mencatat pengecualian dan kemudian mencoba yang terbaik untuk mengirimkan sebanyak mungkin informasi kegagalan ke klien. Layanan harus memastikan klien mendapat pemberitahuan kegagalan, baik dengan menerima respons kegagalan atau dengan menjalankan timeout jika terjadi koneksi yang terputus. Ini biasanya akan menyebabkan kegagalan yang sama untuk dicatat dua kali, sekali di dalam layanan (dengan lebih detail) dan sekali di tingkat teratas klien.
Penebangan
Saya menambahkan beberapa kalimat tentang login secara umum, tidak hanya pengecualian-logging.
Selain situasi luar biasa, Anda ingin kegiatan penting aplikasi Anda dicatat dalam log juga. Jadi, gunakan kerangka kerja logging.
Berhati-hatilah dengan level log (membaca log di mana informasi debug dan kesalahan serius tidak ditandai dengan yang berbeda karena itu menyebalkan!). Level log yang umum adalah:
Dalam produksi, atur level log ke INFO. Hasilnya harus bermanfaat bagi administrator sistem sehingga ia tahu apa yang terjadi. Harapkan dia menelepon Anda untuk meminta bantuan atau memperbaiki bug untuk setiap KESALAHAN dalam log dan setengah dari PERINGATAN.
Aktifkan level DEBUG hanya selama sesi debug nyata.
Kelompokkan entri log ke dalam kategori yang sesuai (misalnya dengan nama kelas yang sepenuhnya memenuhi syarat dari kode yang menghasilkan entri), memungkinkan Anda untuk mengaktifkan log debug untuk bagian-bagian tertentu dari program Anda.
sumber
Saya menguatkan diri untuk downvotes, tapi saya akan mengambil risiko dan mengatakan saya tidak yakin saya bisa setuju dengan ini.
Mengecewakan pengecualian, apalagi mencatatnya lagi, adalah upaya ekstra dengan sedikit manfaat. Tangkap pengecualian di sumber (ya, termudah), catat, tapi jangan melemparkan kembali pengecualian, cukup laporkan "kesalahan" ke pemanggil. "-1", null, string kosong, beberapa enum, apa pun. Penelepon hanya perlu tahu bahwa panggilan itu gagal, hampir tidak pernah detail yang mengerikan. Dan itu akan ada di log Anda, bukan? Dalam kasus yang jarang terjadi bahwa penelepon membutuhkan detail, silakan dan muncul, tetapi tidak sebagai default otomatis tanpa berpikir.
sumber
null
senar kosong? Apakah -1 atau angka negatif apa pun? 2. Jika penelepon tidak peduli (yaitu tidak memeriksa) ini mengarah ke tindak lanjut kesalahan yang tidak terkait dengan penyebab aslinya, misalnya aNullPointerException
. Atau lebih buruk: Perhitungan berlanjut dengan nilai yang salah. 3. Jika penelepon peduli tetapi programmer tidak menganggap metode ini gagal, kompiler tidak mengingatkannya. Pengecualian tidak memiliki masalah ini, baik Anda menangkap atau Anda mengubah kembali.