Mengapa penanganan pengecualian buruk?

90

Bahasa Go Google tidak memiliki pengecualian sebagai pilihan desain, dan ketenaran Linus dari Linux menyebut pengecualian sebagai omong kosong. Mengapa?

joemoe
sumber
2
Pencipta ZeroMQ menulis tentang bagaimana menurutnya itu adalah kesalahan untuk menulisnya dalam C ++ (kebanyakan karena penanganan kesalahan) 250bpm.com/blog:4
serbaut
Go mungkin tidak memiliki pengecualian, tetapi memiliki "kepanikan" yang dapat Anda "pulihkan" (sementara pernyataan yang ditangguhkan masih dijalankan) dan yang menyediakan aliran kontrol non-lokal ...
Kerrek SB
Berikut artikel yang bagus lighterra.com/papers/exceptionsharmful (Penanganan Pengecualian Dianggap Berbahaya)
masterxilo
Afaics, pengecualian dapat disimulasikan di Go dengan boilerplate yang signifikan , meskipun poin ini mungkin lebih berarti untuk transpiling dari syntax sugar daripada untuk menulis boilerplate secara manual.
Shelby Moore III

Jawaban:

83

Pengecualian membuatnya sangat mudah untuk menulis kode di mana pengecualian yang dilemparkan akan merusak invarian dan membiarkan objek dalam keadaan tidak konsisten. Mereka pada dasarnya memaksa Anda untuk mengingat bahwa hampir setiap pernyataan yang Anda buat berpotensi melempar, dan menanganinya dengan benar. Melakukannya bisa jadi rumit dan kontra-intuitif.

Pertimbangkan sesuatu seperti ini sebagai contoh sederhana:

class Frobber
{
    int m_NumberOfFrobs;
    FrobManager m_FrobManager;

public:
    void Frob()
    {
        m_NumberOfFrobs++;

        m_FrobManager.HandleFrob(new FrobObject());
    }
};

Dengan asumsi FrobManagerakan deleteyang FrobObject, penampilan OK ini, kan? Atau mungkin tidak ... Bayangkan jika salah satu FrobManager::HandleFrob()atau operator newmelempar pengecualian. Dalam contoh ini, kenaikan m_NumberOfFrobstidak dapat diputar kembali. Jadi, siapa pun yang menggunakan contoh Frobberini akan memiliki objek yang mungkin rusak.

Contoh ini mungkin tampak bodoh (oke, saya harus sedikit meregangkan diri untuk membuatnya :-)), tetapi, kesimpulannya adalah jika seorang programmer tidak terus-menerus memikirkan pengecualian, dan memastikan bahwa setiap permutasi status digulung kembali setiap kali ada lemparan, Anda mendapat masalah dengan cara ini.

Sebagai contoh, Anda dapat menganggapnya seperti Anda memikirkan mutex. Di dalam bagian kritis, Anda mengandalkan beberapa pernyataan untuk memastikan bahwa struktur data tidak rusak dan utas lain tidak dapat melihat nilai antara Anda. Jika salah satu dari pernyataan itu tidak berjalan secara acak, Anda berakhir di dunia yang menyakitkan. Sekarang singkirkan kunci dan konkurensi, dan pikirkan tentang setiap metode seperti itu. Pikirkan setiap metode sebagai transaksi permutasi pada status objek, jika Anda mau. Pada awal pemanggilan metode Anda, objek harus dalam keadaan bersih, dan pada akhirnya juga harus ada keadaan bersih. Di antara, variabel foomungkin tidak konsisten denganbar, tetapi kode Anda pada akhirnya akan memperbaikinya. Yang dimaksud pengecualian adalah bahwa salah satu pernyataan Anda dapat mengganggu Anda kapan saja. Tanggung jawab ada pada Anda dalam setiap metode untuk melakukannya dengan benar dan memutar kembali ketika itu terjadi, atau memesan operasi Anda sehingga lemparan tidak memengaruhi status objek. Jika Anda salah (dan mudah membuat kesalahan seperti ini), penelepon akhirnya melihat nilai tengah Anda.

Metode seperti RAII, yang sering disebut oleh programmer C ++ sebagai solusi pamungkas untuk masalah ini, sangat membantu untuk melindungi dari hal ini. Tapi itu bukan peluru perak. Ini akan memastikan Anda melepaskan sumber daya dalam sekejap, tetapi tidak membebaskan Anda dari keharusan memikirkan kerusakan status objek dan pemanggil melihat nilai perantara. Jadi, bagi banyak orang, lebih mudah mengatakannya, berdasarkan gaya pengkodean, tanpa pengecualian . Jika Anda membatasi jenis kode yang Anda tulis, lebih sulit untuk memperkenalkan bug ini. Jika tidak, cukup mudah untuk membuat kesalahan.

Seluruh buku telah ditulis tentang pengecualian kode aman dalam C ++. Banyak ahli yang salah. Jika memang serumit itu dan memiliki begitu banyak nuansa, mungkin itu pertanda baik bahwa Anda perlu mengabaikan fitur itu. :-)

asveikau
sumber
9
Jawaban yang menarik, namun tidak mencerminkan apa pun dalam pengalaman pemrograman saya. Jadi saya kira itu khusus budaya (mungkin lebih merupakan masalah di Java atau C ++ daripada, katakanlah, Python) atau khusus domain.
ddaa
42
Pengecualian yang ditulis dalam bahasa terkelola menggunakan pola coba-tangkap-akhirnya tidak boleh meninggalkan status tidak valid jika ditulis dengan benar; karena blok terakhir dijamin akan dieksekusi, objek dapat dibatalkan alokasinya di sana. Sisanya harus ditangani oleh variabel yang keluar dari ruang lingkup dan pengumpulan sampah.
Robert Harvey
7
@ddaa Masalahnya pasti mungkin terjadi dengan Python. Hasilnya biasanya bug yang sulit direproduksi. Mungkin Anda sangat teliti, atau beruntung. Tapi kemudian, Anda benar bahwa ini lebih merupakan masalah di C ++, di mana bug paling umum dari EH yang buruk adalah kebocoran memori. Saya mencoba menekankan bahwa kebocoran bukanlah masalah yang paling serius. @Robert GC akan mengurangi kebocoran memori, tetapi saya tidak yakin kode yang dikelola akan membebaskan Anda dari kesalahan programmer. Terutama jika seseorang tidak memperhatikan keamanan pengecualian karena menurut mereka itu bukan masalah dalam bahasa mereka, itu bukan pertanda bagus.
asveikau
4
@lzprgmr pasti ada: pengecualian memungkinkan Anda untuk menangani diff. jenis kesalahan di diff. tempat dalam kode. Berurusan dengan kesalahan koneksi mungkin memerlukan koneksi ulang, tetapi tidak di tengah-tengah fungsi yang sangat bertingkat. Anda ingin menyampaikannya ke manajer koneksi atau sesuatu. Kemudian berurusan dengan nilai kembali memaksa Anda untuk memeriksa kesalahan pada setiap panggilan tunggal, dan menggelembung itu secara manual (dalam kasus kesalahan reset koneksi misalnya). Juga, kembali nilai-nilai menumpuk dalam panggilan bersarang: func3 dapat kembali -1, func2 panggilan func3, pengembalian -2 pada kesalahan nya, -1 untuk func3 ini, dll ..
abourget
4
Saya memberikan suara ke bawah, tetapi saya membalikkannya karena ini adalah alasan mengapa pengecualian dipandang rendah. Namun menurut saya, hampir semua metode atau potongan kode bisa gagal. Anda tidak dapat menangani setiap kondisi kesalahan dengan memasukkan nilai kembalian untuknya. Anda akan kehilangan informasi tentang kesalahan tersebut. Berpikir bahwa Anda dapat menjaga semuanya tetap tersinkronisasi dengan baik dengan memeriksa setiap pernyataan dan melakukan pembersihan mengarah ke kode yang sangat berbelit-belit - menangkap kesalahan pada beberapa pernyataan dan membersihkan satu atau dua sumber daya yang tidak digabungkan jauh lebih bersih.
Maarten Bodewes
50

Alasan Go tidak memiliki pengecualian dijelaskan di FAQ desain bahasa Go:

Pengecualian adalah cerita yang serupa. Sejumlah desain untuk pengecualian telah diusulkan tetapi masing-masing menambahkan kompleksitas yang signifikan pada bahasa dan waktu proses. Pada dasarnya, pengecualian mencakup fungsi dan bahkan mungkin goroutine; mereka memiliki implikasi yang luas. Ada juga kekhawatiran tentang pengaruhnya terhadap perpustakaan. Mereka, menurut definisi, luar biasa namun memiliki pengalaman dengan bahasa lain yang mendukungnya menunjukkan bahwa mereka memiliki efek yang besar pada spesifikasi pustaka dan antarmuka. Alangkah baiknya menemukan desain yang memungkinkan mereka menjadi benar-benar luar biasa tanpa mendorong kesalahan umum untuk berubah menjadi aliran kontrol khusus yang mengharuskan setiap programmer untuk mengimbanginya.

Seperti obat generik, pengecualian tetap menjadi masalah terbuka.

Dengan kata lain, mereka belum menemukan cara untuk mendukung pengecualian di Go dengan cara yang menurut mereka memuaskan. Mereka tidak mengatakan bahwa Pengecualian buruk per se ;

UPDATE - Mei 2012

Para desainer Go kini telah turun dari pagar. FAQ mereka sekarang mengatakan ini:

Kami percaya bahwa pengecualian penggandengan ke struktur kontrol, seperti dalam idiom coba-tangkap-akhirnya, menghasilkan kode yang berbelit-belit. Ini juga cenderung mendorong pemrogram untuk memberi label terlalu banyak kesalahan biasa, seperti gagal membuka file, sebagai pengecualian.

Go mengambil pendekatan berbeda. Untuk penanganan kesalahan biasa, pengembalian multi-nilai Go memudahkan untuk melaporkan kesalahan tanpa membebani nilai pengembalian. Jenis kesalahan kanonis, ditambah dengan fitur Go lainnya, membuat penanganan kesalahan menyenangkan tetapi sangat berbeda dari yang ada di bahasa lain.

Go juga memiliki beberapa fungsi bawaan untuk memberi sinyal dan memulihkan dari kondisi yang benar-benar luar biasa. Mekanisme pemulihan dijalankan hanya sebagai bagian dari status fungsi yang dihancurkan setelah terjadi kesalahan, yang cukup untuk menangani bencana tetapi tidak memerlukan struktur kontrol tambahan dan, jika digunakan dengan baik, dapat menghasilkan kode penanganan kesalahan yang bersih.

Lihat artikel Tunda, Panik, dan Pulihkan untuk detailnya.

Jadi jawaban singkatnya adalah mereka dapat melakukannya secara berbeda menggunakan pengembalian multi-nilai. (Dan mereka memiliki bentuk penanganan pengecualian.)


... dan ketenaran Linus dari Linux menyebut pengecualian sebagai omong kosong.

Jika Anda ingin tahu mengapa Linus menganggap pengecualian itu omong kosong, hal terbaik adalah mencari tulisannya tentang topik tersebut. Satu-satunya hal yang saya lacak sejauh ini adalah kutipan ini yang disematkan di beberapa email di C ++ :

"Keseluruhan penanganan pengecualian C ++ pada dasarnya rusak. Ini terutama rusak untuk kernel."

Anda akan melihat bahwa dia berbicara tentang pengecualian C ++ secara khusus, dan bukan pengecualian secara umum. (Dan C ++ pengecualian yang tampaknya memiliki beberapa masalah yang membuat mereka sulit untuk menggunakan dengan benar.)

Kesimpulan saya adalah bahwa Linus tidak menyebut pengecualian (secara umum) sebagai "omong kosong" sama sekali!

Stephen C
sumber
30
Saya benci jika mereka menyembunyikan informasi dengan memasukkannya ke FAQ. :)
brian d foy
7
Perhatikan bahwa Linus memulai email itu dengan "C ++ adalah bahasa yang mengerikan." dan terus mengoceh tentang betapa dia membenci C ++ dan orang-orang yang memilih untuk memprogramnya. Karena itu menurut saya pendapatnya tentang pengecualian C ++ dapat dianggap dapat diandalkan mengingat pendapatnya yang agak bias terhadap C ++.
Pharap
1
@ Hi-Angel - Seperti teks yang saya kutip mengatakan: "Untuk penanganan kesalahan biasa, kembalian multi-nilai Go membuatnya mudah untuk melaporkan kesalahan tanpa membebani nilai kembalian." . Begitulah hubungannya. Bagaimanapun, saya mengutip alasan para desainer Go. Jika Anda ingin berdebat, berdebat dengan >> mereka <<.
Stephen C
1
@ Hi-Angel - Saya tidak menulis paragraf itu. Saya hanya mengutipnya. Jika Anda memiliki masalah dengan mereka, Anda mungkin harus membahasnya dengan penulis. Secara teori saya bisa saja memberikan tutorial tentang bahasa Go sebagai konteks. Namun sejujurnya, orang yang tidak memahami terminologi Go dapat mengunjungi situs web Go untuk mencari tahu apa artinya semua itu.
Stephen C
1
".. menghasilkan kode yang berbelit-belit" Dahulu kala saya telah menulis program C dengan banyak operasi string. Setiap metode adalah alokasi memori dan kemudian memeriksa apakah alokasi berhasil. Tampaknya sebagian besar kode hanya memeriksa alokasi. Bukankah itu berbelit-belit? C ++ dengan pengecualian adalah penyelamatan besar bagi saya.
robsosno
29

Pengecualian memang tidak buruk, tetapi jika Anda tahu itu akan sering terjadi, hal itu bisa mahal dalam hal kinerja.

Aturan praktisnya adalah bahwa pengecualian harus menandai kondisi luar biasa, dan Anda tidak boleh menggunakannya untuk mengontrol aliran program.

Robert Harvey
sumber
9
@Robert: "Anda tidak boleh menggunakannya untuk mengontrol aliran program", saya tidak memikirkannya seperti ini, perspektif baru untuk saya: P +1
okw
2
Itu juga sangat tergantung pada bahasanya. Sulit untuk menghindari pengecualian jika Anda memprogram di Java misalnya.
Charles Salvia
2
@Charles: Saya pikir intinya adalah bahwa pengecualian sesuai dalam situasi yang menunjukkan bug, sistem yang salah konfigurasi, atau masukan yang tidak wajar. Kebanyakan pengecualian perpustakaan Java dapat dihindari dalam kode "alur kerja normal".
Artelius
6
mereka tidak perlu mengeluarkan banyak biaya. misalnya, Anda dapat menerapkan "coba" yang tidak memerlukan waktu eksekusi, dan "melempar" mencari penangan pengecualian dalam tabel berdasarkan alamat pemanggil yang dilihatnya di tumpukan ... Saya akan mengatakan bahwa alasan terbesar untuk tidak pengecualian penggunaan sama sekali tidak terkait dengan kinerja.
asveikau
Diulangi; pertanyaannya dengan jelas mengisyaratkan penggunaan pengecualian secara umum, atau tidak menggunakan pengecualian sama sekali (itu omong kosong atau bahkan tidak ada dalam bahasa tersebut). Jawaban Anda hanya menunjukkan mengapa pengecualian berdampak buruk bagi performa saat digunakan untuk alur kontrol program.
Maarten Bodewes
26

Saya tidak setuju dengan "hanya memberikan pengecualian dalam situasi yang luar biasa." Meskipun secara umum benar, ini menyesatkan. Pengecualian untuk kondisi kesalahan (kegagalan eksekusi).

Terlepas dari bahasa yang Anda gunakan, ambil salinan Panduan Desain Framework : Konvensi, Idiom, dan Pola untuk Perpustakaan .NET yang Dapat Digunakan Kembali (Edisi ke-2). Bab tentang pengecualian melempar tanpa rekan. Beberapa kutipan dari edisi pertama (yang ke-2 di tempat kerja saya):

  • JANGAN mengembalikan kode kesalahan.
  • Kode kesalahan dapat dengan mudah diabaikan, dan seringkali begitu.
  • Pengecualian adalah cara utama melaporkan kesalahan dalam kerangka kerja.
  • Aturan praktis yang baik adalah jika suatu metode tidak melakukan apa yang disarankan namanya, metode tersebut harus dianggap sebagai kegagalan tingkat metode, yang mengakibatkan pengecualian.
  • JANGAN gunakan pengecualian untuk aliran kontrol normal, jika memungkinkan.

Ada halaman catatan tentang manfaat pengecualian (konsistensi API, pilihan lokasi kode penanganan kesalahan, peningkatan ketahanan, dll.) Ada bagian tentang kinerja yang mencakup beberapa pola (Penguji-Pelaku, Coba-Parse).

Pengecualian dan penanganan pengecualian tidak buruk. Seperti fitur lainnya, fitur tersebut dapat disalahgunakan.

TrueWill
sumber
4
Saya harus tidak setuju dengan itu. Saya tidak menentang pengecualian, dan buku itu harus dimiliki, namun itu bias terhadap pengembangan .NET, dan C #.
3
Saya tahu ini kuno, hanya ingin berkomentar bahwa sepertinya akan ada ketidaksepakatan gaya umum antara tipe .NET dan tipe * nix. Semua pustaka yang saya gunakan sebagai pengembang Linux menggunakan kode pengembalian, dan panduan gaya * nix yang pernah saya baca (seperti perusahaan saya dan Google misalnya) cukup mengatakan "kami tidak melakukan pengecualian". Anggap saja itu menarik.
jarvisteve
1
Kerangka kerja harus memperlakukan pengecualian secara berbeda dari aplikasi pengguna akhir. Kerangka tidak memiliki cara untuk menangani kesalahan selain memberikan pengecualian, aplikasi konsumen melakukannya.
0x6C38
11

Dari perspektif golang, saya rasa tidak memiliki penanganan pengecualian membuat proses kompilasi tetap sederhana dan aman.

Dari perspektif Linus, saya memahami bahwa kode kernel SEMUA tentang kasus sudut. Jadi masuk akal untuk menolak pengecualian.

Pengecualian masuk akal dalam kode adalah tidak masalah untuk menjatuhkan tugas saat ini ke lantai, dan di mana kode kasus umum lebih penting daripada penanganan kesalahan. Tetapi mereka membutuhkan pembuatan kode dari kompiler.

Misalnya, mereka baik-baik saja di sebagian besar kode tingkat tinggi yang menghadap pengguna, seperti kode aplikasi web dan desktop.

ddaa
sumber
Tetapi apa yang benar untuk kode kernel juga berlaku untuk proses server asli yang berjalan lama.
Lothar
11

Pengecualian di dalam dan dari dirinya sendiri tidaklah "buruk", cara penanganan pengecualian yang terkadang cenderung buruk. Ada beberapa pedoman yang dapat diterapkan saat menangani pengecualian untuk membantu meringankan beberapa masalah ini. Beberapa di antaranya termasuk (tetapi pasti tidak terbatas pada):

  1. Jangan gunakan pengecualian untuk mengontrol aliran program - yaitu, jangan mengandalkan pernyataan "menangkap" untuk mengubah aliran logika. Hal ini tidak hanya cenderung menyembunyikan berbagai detail seputar logika, tetapi juga dapat menyebabkan kinerja yang buruk.
  2. Jangan melempar pengecualian dari dalam suatu fungsi saat "status" yang dikembalikan akan lebih masuk akal - hanya lemparkan pengecualian dalam situasi luar biasa. Membuat pengecualian adalah operasi yang mahal dan padat kinerja. Misalnya, jika Anda memanggil metode untuk membuka file dan file itu tidak ada, lemparkan pengecualian "FileNotFound". Jika Anda memanggil metode yang menentukan apakah akun pelanggan ada, kembalikan nilai boolean, jangan kembalikan pengecualian "CustomerNotFound".
  3. Saat menentukan apakah akan menangani pengecualian atau tidak, jangan gunakan klausa "coba ... menangkap" kecuali Anda dapat melakukan sesuatu yang berguna dengan pengecualian tersebut. Jika Anda tidak dapat menangani pengecualian, Anda harus membiarkannya menggelembung tumpukan panggilan. Jika tidak, pengecualian mungkin akan "ditelan" oleh pawang dan detailnya akan hilang (kecuali Anda mengembalikan pengecualian).
Jeff Bramwell
sumber
2
Mengembalikan status adalah hal yang sulit. Saya telah melihat terlalu banyak kode yang memiliki metode GetCustomer yang mengembalikan entitas Pelanggan saat berhasil atau nol saat gagal. Dalam banyak kasus kode panggilan tidak pernah memeriksa hasilnya, tetapi langsung mengakses Pelanggan. Ini bekerja sebagian besar waktu ...
TrueWill
3
Namun jika GetCustomer melontarkan pengecualian dan bukan menampilkan null, kode klien masih perlu menangani pengecualian tersebut. Entah itu dengan memeriksa nol atau dengan menangani pengecualian, tanggung jawab terletak pada kode klien - jika kode tidak melakukan hal-hal dengan benar, maka cepat atau lambat sesuatu akan meledak.
Chris
1
@TrueWill Bahasa yang mendukung template / generik memecahkan masalah ini dengan mengembalikan an, Option<T>bukan nullsaat ini. Baru saja diperkenalkan di Java 8 misalnya, mengambil petunjuk dari Guava (dan lainnya).
Maarten Bodewes
@limbahh Suka mungkin monad. Itu cara yang baik untuk pergi jika bahasa Anda mendukungnya dan menawarkan pencocokan pola.
TrueWill
@owlstead Sekali lagi, apa yang dikatakan Chris masih berlaku untuk itu - pengguna harus ingat untuk memanggil fungsi .orElse (defaultObject), atau idiom mana pun yang diputuskan oleh bahasa yang bersangkutan. Pada akhirnya, pada akhirnya pemrogramlah yang menjadi masalah, bukan metode penanganan kesalahan.
Pharap
9

Argumen umumnya adalah bahwa tidak ada cara untuk mengetahui pengecualian apa yang akan keluar dari potongan kode tertentu (bergantung pada bahasa) dan bahwa mereka terlalu mirip gotos, sehingga sulit untuk melacak eksekusi secara mental.

http://www.joelonsoftware.com/items/2003/10/13.html

Jelas tidak ada konsensus tentang masalah ini. Saya akan mengatakan bahwa dari sudut pandang programmer C hard-core seperti Linus, pengecualian jelas merupakan ide yang buruk. Seorang programmer Java yang khas berada dalam situasi yang sangat berbeda.

Tim Sylvester
sumber
1
Kode C memiliki semacam pengecualian, hanya dengan cara yang berbeda. Anda perlu menggabungkan setiap panggilan ke fungsi non-sepele jika yang membuat penggunaan bahasa itu memusingkan!
RCIX
1
Ada juga setjmp/ longjmpbarang, yang sangat buruk.
Tim Sylvester
9
Apakah Anda benar-benar ingin menerima nasihat dari seseorang yang menghargai programmer Duct Tape dan yang tidak percaya bahwa pengujian unit diperlukan? joelonsoftware.com/items/2009/09/23.html
TrueWill
4
Ini adalah kesalahan klasik (atau curang) dalam diskusi di mana argumen tentang subjek diganti dengan referensi kepribadian. Itu biasanya merupakan tanda diskusi yang merosot.
Petr Gladkikh
1
@PetrGladkikh Diskusi dimulai dengan OP mengacu pada pendapat Linus ... bahwa kecurangan dikenal sebagai kekeliruan banding ke otoritas. Diskusi hanya bisa menanjak dari sana, dan tidak ada "curang" untuk menjawab pertanyaan mengapa Linus tidak menyukai pengecualian dengan mengacu pada kepribadiannya.
Jim Balter
7

Pengecualian tidak buruk. Mereka cocok dengan model RAII C ++, yang merupakan hal paling elegan tentang C ++. Jika Anda sudah memiliki banyak kode yang tidak terkecuali aman, maka kode itu buruk dalam konteks itu. Jika Anda menulis perangkat lunak tingkat rendah, seperti OS linux, maka itu buruk. Jika Anda suka mengotori kode Anda dengan sekumpulan pemeriksaan kesalahan, maka itu tidak membantu. Jika Anda tidak memiliki rencana untuk kontrol sumber daya saat pengecualian dilempar (yang disediakan oleh destruktor C ++) maka itu buruk.

paul
sumber
7
RAII berguna bahkan tanpa pengecualian.
Markus Tebusan
4
namun, pengecualian tidak berguna tanpa RAII (atau pengelolaan sumber daya otomatis lainnya).
Greg Rogers
+1 untuk menunjukkan situasi di mana pengecualian tidak sesuai dan pengecualian itu tidak buruk secara inheren.
Pharap
4

Kasus penggunaan yang bagus untuk pengecualian adalah ....

Katakanlah Anda sedang mengerjakan sebuah proyek dan setiap pengontrol (sekitar 20 pengontrol utama yang berbeda) memperluas pengontrol superclass tunggal dengan metode tindakan. Kemudian setiap pengontrol melakukan banyak hal yang berbeda satu sama lain memanggil objek B, C, D dalam satu kasus dan F, G, D dalam kasus lain. Pengecualian datang untuk menyelamatkan di sini dalam banyak kasus di mana ada banyak kode kembali dan SETIAP pengontrol menanganinya secara berbeda. Saya memukul semua kode itu, melemparkan pengecualian yang tepat dari "D", menangkapnya dalam metode aksi pengontrol superclass dan sekarang semua pengontrol kami konsisten. Sebelumnya D mengembalikan null untuk MULTIPLE kasus kesalahan berbeda yang ingin kami beri tahu pengguna akhir tetapi tidak bisa dan saya tidak melakukannya

ya, kita harus mengkhawatirkan setiap level dan pembersihan / kebocoran resource, tetapi secara umum tidak ada pengontrol kami yang memiliki resource untuk dibersihkan setelahnya.

Alhamdulillah kami memiliki pengecualian atau saya akan mengalami refactor besar dan membuang terlalu banyak waktu untuk sesuatu yang seharusnya menjadi masalah pemrograman sederhana.

Dean Hiller
sumber
1
+1 Mudah salah satu argumen terbaik untuk menggunakan pengecualian yang telah saya baca. Bisa saja menggunakan contoh yang lebih rinci (yaitu diagram UML, beberapa pseudocode atau beberapa kode aktual) tetapi poin tentang membuat subclass bekerja secara konsisten adalah bagus. Selain itu, fakta bahwa bukti Anda bersifat anekdot menunjukkan bahwa pengecualian berguna dalam situasi nyata, dan kegunaan adalah tujuan utama fitur bahasa apa pun.
Pharap
hanya sebagai tambahan, jika Anda berada dalam scala, Anda dapat mengembalikan Try [ResponseType] yang mewakili pengecualian atau respons aktual. Anda kemudian dapat mengikuti pola yang sama dengan yang saya hindari di atas tanpa pengecualian aktual selain yang dicoba. Maka itu seperti setiap metode yang Anda miliki mengembalikan 1 + n jenis respons yang menurut saya diperlukan. Namun kami dalam scala mengembalikan Future [respon] yang bekerja seperti Try tetapi dapat membantu dengan pemrograman yang lebih asinkron.
Dean Hiller
2

Secara teoritis mereka sangat buruk. Dalam dunia matematika yang sempurna, Anda tidak bisa mendapatkan situasi pengecualian. Lihatlah bahasa fungsional, mereka tidak memiliki efek samping, jadi mereka hampir tidak memiliki sumber untuk situasi yang tidak terkecuali.

Tapi, kenyataannya adalah cerita lain. Kami selalu menghadapi situasi yang "tidak terduga". Inilah mengapa kami membutuhkan pengecualian.

Saya pikir kita dapat menganggap pengecualian sebagai gula sintaks untuk ExceptionSituationObserver. Anda baru saja mendapatkan pemberitahuan tentang pengecualian. Tidak ada lagi.

Dengan Go, saya pikir mereka akan memperkenalkan sesuatu yang akan menghadapi situasi "tak terduga". Saya dapat menebak bahwa mereka akan mencoba membuatnya terdengar kurang destruktif sebagai pengecualian dan lebih sebagai logika aplikasi. Tapi ini hanya tebakanku.

Mike Chaliy
sumber
2
"Lihatlah bahasa fungsional, mereka tidak memiliki efek samping, jadi mereka hampir tidak memiliki sumber untuk situasi yang tidak terkecuali." Itu adalah pernyataan yang terlalu berlebihan.
Stephen C
3
Apa 5/0 dalam matematika? Arcsin (200)? Akar (-1)? Matematika memiliki banyak situasi luar biasa.
Robert Fraser
3
Ini bukan situasi eksekusi ... hanya tidak ada artinya ... dan karena itu bisa diimplementasikan sebagai pengecualian ... tapi juga bisa diimplementasikan sebagai vialation dari prasyarat .. jadi tergantung pada implementasi teknis.
Mike Chaliy
3
@MikeChaliy - Maaf, tapi itu hanya menyesatkan. Anda dapat menerapkan alasan semacam itu untuk mengatakan bahwa TIDAK ADA situasi pengecualian dalam segala hal, PERNAH. Pada kenyataannya, ekspresi matematika yang tidak memiliki arti (atau yang tidak memiliki nilai pasti) adalah luar biasa. Ini tidak berarti bahwa mereka perlu ditangani dengan membuang dan menangkap pengecualian ... tetapi jika Anda tidak melakukannya, Anda memerlukan nilai khusus (seperti Inf dan Nan) atau operasi yang mengembalikan banyak nilai. Singkatnya, kasus ini membutuhkan beberapa jenis perlakuan khusus.
Stephen C
1
Komputer adalah mesin negara. Bukan dunia matematika yang sempurna.
Arunav Sanyal
1

Paradigma penanganan-pengecualian dari C ++, yang menjadi dasar parsial untuk Java, dan pada gilirannya .net, memperkenalkan beberapa konsep yang baik, tetapi juga memiliki beberapa keterbatasan yang parah. Salah satu tujuan desain utama dari penanganan pengecualian adalah mengizinkan metode untuk memastikan bahwa metode tersebut akan memenuhi kondisi pascanya atau melontarkan pengecualian, dan juga memastikan bahwa pembersihan apa pun yang perlu dilakukan sebelum metode dapat keluar, akan terjadi. Sayangnya, paradigma penanganan pengecualian C ++, Java, dan .net semuanya gagal memberikan cara yang baik untuk menangani situasi di mana faktor-faktor tak terduga mencegah pembersihan yang diharapkan dilakukan. Ini pada gilirannya berarti bahwa seseorang harus mengambil risiko membuat semuanya berhenti menderu jika sesuatu yang tidak terduga terjadi (pendekatan C ++ untuk menangani pengecualian terjadi selama pelepasan tumpukan),

Meskipun penanganan pengecualian secara umum akan baik, bukan tidak masuk akal untuk menganggap paradigma penanganan pengecualian yang tidak dapat diterima yang gagal memberikan cara yang baik untuk menangani masalah yang terjadi saat membersihkan masalah lain. Itu tidak berarti bahwa kerangka kerja tidak dapat dirancang dengan paradigma penanganan pengecualian yang dapat memastikan perilaku yang masuk akal bahkan dalam skenario banyak kegagalan, tetapi belum ada bahasa atau kerangka kerja teratas yang dapat melakukannya.

supercat
sumber
1

Saya belum membaca semua jawaban lainnya, jadi masalah ini telah disebutkan, tetapi satu kritik adalah bahwa mereka menyebabkan program terputus dalam rantai panjang, sehingga sulit untuk melacak kesalahan saat men-debug kode. Misalnya, jika Foo () memanggil Bar () yang memanggil Wah () yang memanggil ToString () lalu secara tidak sengaja mendorong data yang salah ke ToString () berakhir seperti kesalahan di Foo (), fungsi yang hampir tidak berhubungan sama sekali.

kingfrito_5005
sumber
0
  • Pengecualian tidak ditangani umumnya buruk.
  • Pengecualian yang ditangani dengan buruk itu buruk (tentu saja).
  • 'Kebaikan / keburukan' penanganan eksepsi bergantung pada konteks / ruang lingkup dan kesesuaiannya, dan bukan untuk kepentingan melakukannya.
baik w
sumber
0

Oke, jawaban yang membosankan di sini. Saya kira itu benar-benar tergantung pada bahasanya. Jika pengecualian dapat meninggalkan sumber daya yang dialokasikan, mereka harus dihindari. Dalam bahasa skrip, mereka hanya meninggalkan atau melompati bagian dari aliran aplikasi. Itu sendiri tidak disukai, namun menghindari kesalahan yang hampir fatal dengan pengecualian adalah ide yang dapat diterima.

Untuk pemberian sinyal kesalahan, saya biasanya lebih menyukai sinyal kesalahan. Semua bergantung pada API, kasus penggunaan, dan tingkat keparahan, atau jika logging sudah cukup. Juga saya mencoba untuk mendefinisikan ulang perilaku dan throw Phonebooks()sebaliknya. Idenya adalah bahwa "Pengecualian" sering kali menemui jalan buntu, tetapi "Buku Telepon" berisi informasi bermanfaat tentang pemulihan kesalahan atau rute eksekusi alternatif. (Belum menemukan kasus penggunaan yang baik, tapi teruslah mencoba.)

mario
sumber
0

Bagi saya masalahnya sangat sederhana. Banyak programmer menggunakan penangan pengecualian secara tidak tepat. Lebih banyak sumber daya bahasa lebih baik. Mampu menangani pengecualian itu baik. Salah satu contoh penggunaan yang buruk adalah nilai bilangan bulat yang harus tidak diverifikasi, atau masukan lain yang mungkin membagi dan tidak diperiksa untuk pembagian nol ... penanganan pengecualian mungkin cara mudah untuk menghindari lebih banyak pekerjaan dan pemikiran keras, programmer mungkin ingin melakukan pintasan kotor dan menerapkan penanganan pengecualian ... Pernyataan: "kode profesional TIDAK PERNAH gagal" mungkin merupakan ilusi, jika beberapa masalah yang diproses oleh algoritme tidak pasti oleh sifatnya sendiri. Mungkin dalam situasi yang tidak diketahui secara alami baik ikut bermain pengendali pengecualian. Praktik pemrograman yang baik adalah bahan perdebatan.

iuri
sumber
Masalahnya bukanlah (atau tidak seharusnya) apakah kode dapat gagal - masalah yang lebih besar adalah sejauh mana, jika kode tersebut gagal, seseorang peduli dengan detailnya. Jika seseorang mencoba memuat dokumen dan salah satu metode "baca data" gagal, sering kali orang tidak terlalu peduli yang mana, karena efeknya tetap sama: dokumen tidak dapat dimuat. Secara konseptual, penanganan pengecualian seharusnya bagus untuk itu. Masalahnya adalah bahwa paradigma penanganan pengecualian dari .NET dan Java tidak memberikan cara yang baik untuk membedakan pengecualian "membosankan" yang harus disatukan, dari yang tidak seharusnya.
supercat