Apa praktik terbaik ketika pengecualian yang tidak ditangani terjadi di aplikasi desktop?
Saya sedang berpikir untuk menunjukkan pesan kepada pengguna, sehingga ia dapat menghubungi dukungan. Saya akan merekomendasikan kepada pengguna untuk me-restart aplikasi, tetapi tidak memaksanya. Mirip dengan apa yang dibahas di sini: ux.stackexchange.com - Apa cara terbaik untuk menangani kesalahan aplikasi yang tidak terduga?
Proyek ini adalah aplikasi .NET WPF, sehingga proposal yang dideskripsikan dapat terlihat seperti ini (Perhatikan bahwa ini adalah contoh yang disederhanakan. Mungkin akan masuk akal untuk menyembunyikan detail pengecualian sampai pengguna mengklik "Tampilkan Detail" dan menyediakan beberapa fungsionalitas untuk mudah melaporkan kesalahan):
public partial class App : Application
{
public App()
{
DispatcherUnhandledException += OnDispatcherUnhandledException;
}
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
LogError(e.Exception);
MessageBoxResult result = MessageBox.Show(
$"Please help us fix it and contact [email protected]. Exception details: {e.Exception}" +
"We recommend to restart the application. " +
"Do you want to stop the application now? (Warning: Unsaved data gets lost).",
"Unexpected error occured.", MessageBoxButton.YesNo);
// Setting 'Handled' to 'true' will prevent the application from terminating.
e.Handled = result == MessageBoxResult.No;
}
private void LogError(Exception ex)
{
// Log to a log file...
}
}
Dalam implementasinya (Perintah ViewModels atau event handler dari peristiwa eksternal) saya kemudian hanya akan menangkap pengecualian eksogen spesifik dan membiarkan semua pengecualian lain (pengecualian berkepala dan tidak dikenal) melambung hingga "Handler resor terakhir" yang dijelaskan di atas. Untuk definisi pengecualian yang dikepalai dan eksogen, lihat: Eric Lippert - pengecualian Vexing
Apakah masuk akal untuk membiarkan pengguna memutuskan apakah aplikasi harus dihentikan? Ketika aplikasi dihentikan, maka Anda pasti tidak memiliki keadaan tidak konsisten ... Di sisi lain pengguna dapat kehilangan data yang belum disimpan atau tidak dapat menghentikan proses eksternal yang dimulai lagi sampai aplikasi dimulai ulang.
Atau keputusan apakah Anda harus menghentikan aplikasi pada pengecualian tidak tertangani tergantung pada jenis aplikasi yang Anda tulis? Apakah itu hanya pertukaran antara "ketahanan" vs "kebenaran" seperti yang dijelaskan dalam Kode Lengkap, Edisi Kedua
Untuk memberi Anda beberapa konteks jenis aplikasi yang sedang kita bicarakan: Aplikasi ini terutama digunakan untuk mengontrol instrumen laboratorium kimia dan menunjukkan hasil yang diukur kepada pengguna. Untuk melakukannya, aplikasi WPF berkomunikasi dengan beberapa layanan (layanan lokal dan jarak jauh). Aplikasi WPF tidak berkomunikasi langsung dengan instrumen.
sumber
Jawaban:
Anda harus mengharapkan program Anda berakhir karena lebih dari sekadar pengecualian yang tidak ditangani, seperti kegagalan daya, atau proses latar belakang berbeda yang membuat seluruh sistem lumpuh. Oleh karena itu saya akan merekomendasikan untuk menghentikan dan me-restart aplikasi, tetapi dengan beberapa langkah untuk mengurangi konsekuensi dari restart seperti itu dan meminimalkan kemungkinan kehilangan data .
Mulailah dengan menganalisis poin-poin berikut:
Berapa banyak data yang benar-benar dapat hilang jika terjadi penghentian program?
Seberapa parah kerugian seperti itu bagi pengguna? Dapatkah data yang hilang direkonstruksi dalam waktu kurang dari 5 menit, atau apakah kita berbicara tentang kehilangan satu hari kerja?
Berapa banyak upaya untuk menerapkan beberapa strategi "cadangan menengah"? Jangan mengesampingkan ini karena "pengguna harus memasukkan alasan perubahan" pada operasi penyimpanan reguler, seperti yang Anda tulis dalam komentar. Lebih baik pikirkan sesuatu seperti file atau status sementara, yang dapat dimuat ulang setelah program macet secara otomatis. Banyak jenis perangkat lunak produktivitas melakukan ini (misalnya MS Office dan LibreOffice keduanya memiliki fitur "penyimpanan otomatis" dan pemulihan kerusakan).
Jika data salah atau rusak, dapatkah pengguna melihat ini dengan mudah (mungkin setelah restart program)? Jika ya, Anda dapat menawarkan opsi untuk membiarkan pengguna menyimpan data (dengan kemungkinan kecil itu rusak), kemudian memaksa restart, muat ulang dan biarkan pengguna memeriksa apakah data terlihat baik-baik saja. Pastikan untuk tidak menimpa versi terakhir yang disimpan secara teratur (alih-alih menulis ke lokasi / file sementara) untuk menghindari kerusakan versi lama.
Jika strategi "intermediate backup" seperti itu merupakan opsi yang masuk akal pada akhirnya tergantung pada aplikasi dan arsitekturnya, dan pada sifat serta struktur data yang terlibat. Tetapi jika pengguna akan kehilangan kurang dari 10 menit kerja, dan crash seperti itu terjadi seminggu sekali atau bahkan lebih jarang, saya mungkin tidak akan berinvestasi terlalu banyak memikirkan hal ini.
sumber
Tergantung pada batas tertentu pada aplikasi yang Anda kembangkan tetapi secara umum, saya akan mengatakan bahwa jika aplikasi Anda menghadapi pengecualian yang tidak tertangani, Anda harus menghentikannya.
Mengapa?
Karena Anda tidak dapat lagi memiliki kepercayaan pada keadaan aplikasi.
Jelas, berikan pesan yang bermanfaat bagi pengguna, tetapi pada akhirnya Anda harus menghentikan aplikasi.
Mengingat konteks Anda, saya pasti ingin aplikasi untuk dihentikan. Anda tidak ingin perangkat lunak yang berjalan di laboratorium menghasilkan output yang korup dan karena Anda tidak berpikir untuk menangani pengecualian, Anda tidak tahu mengapa itu dilemparkan dan apa yang terjadi.
sumber
Menimbang bahwa ini dimaksudkan untuk laboratorium kimia dan aplikasi Anda tidak mengendalikan instrumen secara langsung melainkan melalui layanan lain:
Memaksa penghentian setelah menampilkan pesan. Setelah pengecualian yang tidak ditangani, aplikasi Anda berada dalam kondisi yang tidak diketahui. Itu bisa mengirim perintah yang salah. Ia bahkan bisa memanggil setan hidung . Perintah yang salah berpotensi membuang reagen yang mahal atau membahayakan peralatan atau manusia .
Tetapi Anda dapat melakukan sesuatu yang lain: memulihkan dengan anggun setelah memulai kembali . Saya berasumsi bahwa aplikasi Anda tidak menjatuhkan layanan latar belakang itu sendiri ketika crash. Dalam hal ini Anda dapat dengan mudah memulihkan keadaan dari mereka. Atau, jika Anda memiliki lebih banyak status, pertimbangkan untuk menyimpannya. Dalam penyimpanan yang memiliki ketentuan untuk atomicity dan integritas data (SQLite mungkin?).
Edit:
Seperti yang dinyatakan dalam komentar, proses yang Anda kontrol mungkin memerlukan perubahan cukup cepat sehingga pengguna tidak akan punya waktu untuk bereaksi. Dalam hal ini Anda harus mempertimbangkan untuk memulai kembali aplikasi secara diam-diam sebagai tambahan untuk pemulihan keadaan yang anggun.
sumber
Mencoba menjawab pertanyaan ini secara umum di level teratas program bukan permainan yang cerdas.
Jika ada sesuatu yang menggelegak sepanjang jalan, dan tidak ada dalam arsitektur aplikasi apakah ada yang mempertimbangkan kasus ini, Anda tidak memiliki generalisasi yang dapat Anda buat tentang tindakan apa, atau tidak, aman untuk diambil.
Jadi, tidak, itu jelas bukan desain yang dapat diterima secara umum untuk memungkinkan pengguna untuk memilih apakah aplikasi akan pulih atau tidak, karena aplikasi dan pengembang belum melakukan uji tuntas yang diperlukan untuk mencari tahu apakah itu mungkin atau bahkan bijaksana. .
Namun, jika aplikasi memiliki bagian bernilai tinggi dari logika atau perilaku yang telah direkayasa dengan pemulihan kegagalan semacam ini dalam pikiran, dan dimungkinkan untuk memanfaatkannya dalam hal ini, maka dengan segala cara, lakukanlah - Jika demikian , mungkin dapat diterima untuk meminta pengguna untuk melihat apakah mereka ingin mencoba pemulihan, atau jika mereka hanya ingin menyebutnya berhenti dan mulai lagi dari awal.
Pemulihan semacam ini umumnya tidak diperlukan atau disarankan untuk semua (atau bahkan sebagian besar) program, tetapi, jika Anda bekerja pada suatu program yang memerlukan tingkat integritas operasional seperti ini, itu mungkin merupakan keadaan di mana penyajian semacam ini meminta pengguna akan menjadi hal yang wajar untuk dilakukan.
Dalam leiu dari logika pemulihan kegagalan khusus - Tidak, jangan lakukan ini. Anda benar-benar tidak tahu apa yang akan terjadi, jika Anda melakukannya, Anda akan menangkap pengecualian lebih jauh dan menanganinya.
sumber
Masalah dengan "pengecualian luar biasa", yaitu pengecualian yang belum Anda perkirakan, adalah Anda tidak tahu status program itu. Misalnya, mencoba menyimpan data pengguna sebenarnya dapat menghancurkan lebih banyak data .
Karena itu, Anda harus menghentikan aplikasi.
Ada ide yang sangat menarik yang disebut Crash-only Software oleh George Candea dan Armando Fox . Idenya adalah bahwa jika Anda merancang perangkat lunak Anda sedemikian rupa sehingga satu-satunya cara untuk menutupnya adalah dengan menghancurkannya dan satu-satunya cara untuk memulainya adalah dengan memulihkan dari kerusakan, maka perangkat lunak Anda akan lebih tangguh, dan pemulihan kesalahan jalur kode akan jauh lebih teruji dan dilaksanakan.
Mereka datang dengan ide ini setelah memperhatikan bahwa beberapa sistem mulai lebih cepat setelah crash daripada setelah shutdown tertib.
Contoh yang bagus, meskipun tidak lagi relevan, adalah beberapa versi Firefox yang lebih lama yang tidak hanya mulai lebih cepat saat memulihkan dari kerusakan, tetapi juga memiliki pengalaman startup yang lebih baik seperti itu ! Dalam versi itu, jika Anda mematikan Firefox secara normal, itu akan menutup semua tab yang terbuka dan memulai dengan satu tab kosong. Sedangkan ketika memulihkan dari kerusakan, itu akan mengembalikan tab yang terbuka pada saat kecelakaan. (Dan itulah satu-satunya cara untuk menutup Firefox tanpa kehilangan konteks penelusuran Anda saat ini.) Jadi, apa yang dilakukan orang? Mereka tidak pernah menutup Firefox dan malah selalu
pkill -KILL firefox
mengubahnya.Ada artikel bagus tentang perangkat lunak hanya-crash oleh Valerie Aurora di Linux Weekly News . Komentar juga layak dibaca. Sebagai contoh, seseorang dalam komentar dengan tepat menunjukkan bahwa ide-ide itu tidak baru, dan pada kenyataannya lebih atau kurang setara dengan prinsip-prinsip desain aplikasi berbasis Erlang / OTP. Dan, tentu saja, melihat ini hari ini, 10 tahun setelah Valerie dan 15 tahun setelah artikel asli, kita mungkin memperhatikan bahwa sensasi layanan mikro saat ini adalah menciptakan kembali ide-ide yang sama lagi. Desain pusat data skala Cloud modern juga merupakan contoh pada granularity yang lebih kasar. (Komputer apa pun dapat macet kapan saja tanpa mempengaruhi sistem.)
Namun, tidak cukup hanya membiarkan perangkat lunak Anda rusak. Itu harus dirancang untuk itu. Idealnya, perangkat lunak Anda akan dipecah menjadi komponen kecil dan independen yang masing-masing dapat macet secara independen. Juga, "mekanisme kerusakan" harus di luar komponen yang sedang macet.
sumber
Cara yang tepat untuk menangani sebagian besar pengecualian adalah dengan membatalkan objek apa pun yang mungkin berada dalam kondisi korup, dan melanjutkan eksekusi jika objek yang tidak valid tidak mencegahnya. Misalnya, paradigma aman untuk memperbarui sumber daya adalah:
Jika pengecualian yang tidak terduga terjadi saat memperbarui sumber daya yang dijaga, sumber daya tersebut harus dianggap dalam keadaan korup, dan kunci tidak valid, terlepas dari apakah pengecualian adalah tipe yang seharusnya tidak berbahaya.
Sayangnya, penjaga sumber daya diimplementasikan melalui
IDisposable
/using
akan dilepaskan setiap kali blok yang dijaga keluar, tanpa ada cara untuk mengetahui apakah blok keluar secara normal atau tidak normal. Jadi, meskipun harus ada kriteria yang jelas untuk kapan harus melanjutkan setelah pengecualian, tidak ada cara untuk mengatakan kapan mereka berlaku.sumber
Anda dapat menggunakan pendekatan yang diikuti oleh setiap aplikasi iOS dan MacOS: Pengecualian yang tidak dilakukan segera menghapus aplikasi. Ditambah banyak kesalahan, seperti array di luar batas atau hanya aritmatika overflow dalam aplikasi yang lebih baru melakukan hal yang sama. Tanpa peringatan.
Dalam pengalaman saya, banyak pengguna yang tidak memperhatikan tetapi cukup ketuk ikon aplikasi lagi.
Jelas Anda perlu memastikan bahwa kerusakan seperti itu tidak menyebabkan kehilangan data yang signifikan dan jelas tidak menyebabkan kesalahan yang mahal. Tetapi peringatan “Aplikasi Anda akan macet sekarang. Hubungi dukungan jika itu mengganggu Anda ”tidak membantu siapa pun.
sumber