Jawaban singkat: baca Penanganan Kesalahan Sensible 1 , Penanganan Kesalahan Sensible 2 , dan Penanganan Kesalahan Sensible 3 oleh Niklas Frykholm. Sebenarnya, baca semua artikel di blog itu, selagi Anda melakukannya. Tidak akan mengatakan saya setuju dengan segalanya, tetapi sebagian besar adalah emas.
Jangan gunakan pengecualian. Ada banyak alasan. Saya akan daftar yang utama.
Mereka memang bisa lebih lambat, meskipun itu diminimalkan sedikit pada kompiler baru. Beberapa kompiler mendukung "pengecualian overhead nol" untuk jalur kode yang tidak benar-benar memicu pengecualian (meskipun itu sedikit bohong, karena masih ada data tambahan yang memerlukan penanganan pengecualian, kembung ukuran executable / dll Anda). Hasil akhirnya adalah ya, menggunakan pengecualian lebih lambat, dan dalam setiap jalur kode kritis kinerja , Anda harus benar-benar menghindarinya. Bergantung pada kompiler Anda, mengaktifkannya sama sekali dapat menambah overhead. Mereka selalu selalu mengasapi ukuran kode, agak signifikan dalam banyak kasus, yang dapat sangat mempengaruhi kinerja perangkat keras saat ini.
Pengecualian membuat kode jauh lebih rapuh. Ada grafik terkenal (yang sayangnya saya tidak dapat menemukan sekarang) yang pada dasarnya hanya menunjukkan pada grafik kesulitan menulis kode pengecualian-aman vs pengecualian-kode tidak aman, dan yang pertama adalah bar yang jauh lebih besar. Hanya ada banyak gotcha kecil dengan pengecualian, dan banyak banyak cara untuk menulis kode yang terlihat pengecualian aman tetapi sebenarnya tidak. Bahkan seluruh komite C ++ 11 melakukan kesalahan dalam hal ini dan lupa untuk menambahkan fungsi pembantu penting untuk menggunakan std :: unique_ptr dengan benar, dan bahkan dengan fungsi-fungsi pembantu itu, dibutuhkan lebih banyak pengetikan untuk menggunakannya daripada tidak dan sebagian besar programmer tidak akan Bahkan tidak menyadari apa yang salah jika mereka tidak melakukannya.
Lebih khusus untuk industri gim, kompiler / runtime yang disediakan vendor beberapa konsol secara langsung tidak mendukung pengecualian sepenuhnya, atau bahkan tidak mendukungnya sama sekali. Jika kode Anda menggunakan pengecualian, mungkin Anda masih di hari ini dan usia harus menulis ulang bagian dari kode Anda untuk port ke platform baru. (Tidak yakin apakah itu berubah dalam 7 tahun sejak konsol tersebut dirilis; kami hanya tidak menggunakan pengecualian, bahkan menonaktifkannya di pengaturan kompiler, jadi saya tidak tahu bahwa siapa pun yang saya ajak bicara bahkan telah memeriksa baru-baru ini.)
Garis pemikiran umum cukup jelas: gunakan pengecualian untuk keadaan luar biasa . Gunakan ketika program Anda masuk ke "Saya tidak tahu apa yang harus dilakukan, mungkin semoga orang lain melakukannya, jadi saya akan melemparkan pengecualian dan melihat apa yang terjadi." Gunakan ketika tidak ada pilihan lain yang masuk akal. Gunakan saat Anda tidak peduli jika Anda secara tidak sengaja membocorkan sedikit memori atau gagal membersihkan sumber daya karena Anda mengacaukan penggunaan smart handle yang tepat. Dalam semua kasus lain, jangan gunakan itu.
Mengenai kode seperti contoh Anda, Anda memiliki beberapa cara lain untuk memperbaiki masalah. Salah satu yang lebih kuat - meskipun tidak selalu paling ideal dalam contoh sederhana Anda - adalah condong ke arah tipe kesalahan monadik. Yaitu, createText () dapat mengembalikan tipe pegangan kustom daripada bilangan bulat. Jenis pegangan ini memiliki pengakses untuk memperbarui atau mengendalikan teks. Jika gagang dimasukkan ke dalam status kesalahan (karena createText () gagal) maka panggilan lebih lanjut ke gagang hanya gagal diam-diam. Anda juga dapat meminta gagang untuk melihat apakah ada kesalahan, dan jika demikian, apa kesalahan terakhir itu. Pendekatan ini memiliki lebih banyak overhead daripada opsi lain, tetapi cukup solid. Gunakan dalam kasus ketika Anda perlu melakukan serangkaian operasi panjang dalam beberapa konteks di mana setiap operasi tunggal dapat gagal dalam produksi, tetapi di mana Anda tidak / tidak bisa / tidak akan menang '
Alternatif untuk mengimplementasikan penanganan kesalahan monadik adalah, daripada menggunakan objek pegangan kustom, membuat metode pada objek konteks dengan anggun menangani id pegangan tidak valid. Misalnya, jika createText () mengembalikan -1 ketika gagal, maka panggilan lain ke m_statistics yang mengambil salah satu dari pegangan itu harus keluar dengan anggun jika -1 dilewatkan.
Anda juga dapat menempatkan pencetakan kesalahan di dalam fungsi yang sebenarnya gagal. Dalam contoh Anda, createText () kemungkinan memiliki lebih banyak informasi tentang apa yang salah, sehingga ia dapat membuang kesalahan yang lebih bermakna ke log. Ada sedikit manfaat dalam hal ini untuk mendorong kesalahan penanganan / pencetakan ke penelepon. Lakukan itu ketika penelepon harus menyesuaikan penanganan (atau gunakan injeksi ketergantungan). Perhatikan bahwa memiliki konsol dalam gim yang dapat muncul setiap kali kesalahan dicatat adalah ide yang bagus dan juga membantu di sini.
Opsi terbaik (sudah disajikan dalam seri artikel terkait di atas) untuk panggilan yang Anda tidak harapkan gagal di lingkungan waras - seperti tindakan sederhana membuat gumpalan teks untuk sistem statistik - adalah hanya memiliki fungsi yang gagal (createText dalam contoh Anda) batalkan. Anda dapat yakin bahwa createText () tidak akan gagal dalam produksi kecuali ada sesuatu yang benar-benar dihapus (misalnya, pengguna menghapus file data font, atau karena alasan tertentu hanya memiliki 256MB memori, dll). Dalam banyak kasus ini, bahkan tidak ada hal yang baik untuk dilakukan ketika kegagalan terjadi. Kehabisan memori? Anda bahkan mungkin tidak dapat membuat alokasi yang diperlukan untuk membuat panel GUI yang bagus untuk menunjukkan kepada pengguna kesalahan OOM. Font yang hilang? Membuatnya sulit untuk menampilkan kesalahan kepada pengguna. Apapun yang salah,
Hanya menabrak sama sekali baik-baik saja selama Anda (a) mencatat kesalahan ke file log dan (b) hanya melakukannya pada kesalahan yang tidak disebabkan oleh tindakan pengguna biasa.
Saya tidak akan mengatakan hal yang sama untuk banyak aplikasi server, di mana ketersediaan sangat penting dan pemantauan anjing penjaga tidak cukup, tetapi itu sangat berbeda dari pengembangan klien game . Saya juga akan sangat menjauhkan Anda dari penggunaan C / C ++ di sana karena fasilitas penanganan pengecualian dari bahasa lain cenderung tidak menggigit seperti C ++ karena mereka dikelola lingkungan dan tidak memiliki semua masalah keamanan pengecualian yang dimiliki C ++. Masalah kinerja apa pun juga dikurangi karena server cenderung lebih fokus pada paralelisme dan throughput daripada jaminan latensi minimum seperti klien game. Bahkan server game aksi untuk penembak dan sejenisnya dapat berfungsi dengan cukup baik ketika ditulis dalam C #, misalnya, karena mereka jarang mendorong perangkat keras ke batasnya seperti yang cenderung dilakukan klien FPS.