Setelah membaca "Cara memisahkan kode antarmuka dan kode fungsional (berdasarkan Delphi/VCL)", seseorang menyebutkan sebuah pertanyaan, yaitu bagaimana menangani kesalahan di kelas sisi server.
Dalam struktur berbasis fungsi, kita biasanya menggunakan nilai pengembalian fungsi untuk menunjukkan apakah fungsi berhasil dijalankan dan untuk memberikan informasi seperti jenis kesalahan. Jadi akan ada kode dalam bentuk berikut:
RetVal := SomeFunctionToOpenFile();
jika RetVal = E_SUCCESSED maka
...
lain jika RetVal = E_FILENOTFOUND lalu
...
lain jika RetVal = E_FILEFORMATERR lalu
...
kalau begitu
...
Sangat umum untuk menggunakan metode yang mengembalikan kode kesalahan, namun ada dua masalah dengan menggunakan metode tersebut:
1. Ini menciptakan struktur cabang yang panjang dan rumit (pernyataan if atau case dalam jumlah besar), membuat proses kontrol menjadi rumit.
2. Mungkin ada kesalahan yang belum tertangani (jika pemanggil fungsi tidak menentukan nilai kembalian)
Pengecualian adalah solusi berorientasi objek untuk penanganan kesalahan. Ini dapat melaporkan kesalahan, tetapi yang perlu Anda ketahui adalah bahwa pengecualian tidak dimunculkan karena kesalahan tersebut, tetapi hanya karena kenaikan digunakan.
Dalam Object Pascal, kata cadangan yang dimunculkan digunakan untuk memunculkan pengecualian. Kapan saja (walaupun tidak terjadi kesalahan), raise akan menyebabkan terjadinya pengecualian.
Pengecualian dapat menyebabkan kode segera kembali dari titik di mana pengecualian terjadi, sehingga melindungi kode sensitif di bawah agar tidak dieksekusi. Tidak ada perbedaan antara kembali dari suatu fungsi melalui pengecualian dan kembali dari suatu fungsi secara normal (mengeksekusi hingga akhir fungsi atau mengeksekusi Keluar) untuk fungsi itu sendiri yang memunculkan pengecualian. Perbedaannya adalah di pihak pemanggil, setelah kembali melalui pengecualian, hak eksekusi akan diambil oleh blok try...kecuali pemanggil (jika ada). Jika tidak ada blok coba...kecuali pada pemanggil, pernyataan berikutnya tidak akan terus dieksekusi, tetapi akan kembali ke pemanggil tingkat yang lebih tinggi sampai blok coba...kecuali yang dapat menangani pengecualian ditemukan. Setelah pengecualian ditangani, pernyataan setelah blok coba...kecuali akan terus dieksekusi, dan kontrol tertinggal di lapisan yang menangani pengecualian. Ketika pengendali pengecualian merasa bahwa penanganan pengecualian tidak cukup lengkap, ia memerlukan pemanggil tingkat yang lebih tinggi untuk melanjutkan pemrosesan. Ia dapat melemparkan kembali pengecualian tersebut (menggunakan kenaikan sederhana;) dan mentransfer kontrol ke pemanggil tingkat yang lebih tinggi .
Jika tidak ada preset blok coba...kecuali sama sekali, pengecualian terakhir akan ditangkap oleh blok coba...kecuali terluar dari VCL yang merangkum seluruh program.
Oleh karena itu, tidak akan ada pengecualian yang tidak tertangani, dengan kata lain tidak akan ada kesalahan yang tidak tertangani (walaupun kesalahan dan pengecualian tidak disamakan). Ini juga merupakan keuntungan mekanisme pengecualian dibandingkan penggunaan metode yang mengembalikan kode kesalahan. Selain itu, setelah pengecualian dilempar, arah proses pengendalian sangat jelas dan tidak akan menyebabkan proses kehilangan kendali.
Untuk memberikan contoh cara kerja pengecualian, misalkan kita ingin membuka file dalam format tertentu:
Pertama-tama tentukan dua kelas pengecualian (diwarisi dari Exception)
EFileNotFound = kelas(Pengecualian);
EFileFormatErr = kelas(Pengecualian);
Misalkan ada tombol di Form1, dan menekan tombol tersebut akan membuka file:
Prosedur TForm1.Button1Click(Pengirim: TObject);
mulai
mencoba
UntukMembukaFile();
kecuali
di EFileNotFound lakukan
ShowMessage('Maaf, saya tidak dapat menemukan filenya');
onEFileFormatErr lakukan
ShowMessage('Maaf, file ini bukan yang saya inginkan');
di E: Pengecualian lakukan
ShowMessage(E.Pesan);
akhir;
akhir;
Dan fungsi untuk membuka file :
prosedur KeOpenFile;
varRetVal:Bilangan Bulat;
mulai
//Beberapa kode untuk membuka file
RetVal := -1; //pembukaan gagal
jika RetVal = 0 maka //sukses
KELUAR
lain jika RetVal = -1 maka
Naikkan EFileNotFound.Create('File tidak ditemukan')
lain jika RetVal = -2 maka
Naikkan EFileFormatErr.Create('Kesalahan format file')
lain // kesalahan lainnya
Naikkan Pengecualian.Buat('Kesalahan tidak diketahui');
akhir;
Dalam program ini, TForm1.Button1Click memanggil ToOpenFile dan preset mencoba...kecuali untuk menangani pengecualian yang mungkin diberikan oleh ToOpenFile. Tentu saja, kode penanganan pengecualian TForm1.Button1Click juga dapat disederhanakan:
prosedur TForm1.Button1Click(Pengirim: TObject);
mulai
mencoba
UntukMembukaFile();
kecuali
ShowMessage('Gagal membuka file');
akhir;
akhir;
Penggunaan pengecualian memecahkan masalah penggunaan metode yang mengembalikan kode kesalahan. Tentu saja, penggunaan pengecualian bukannya tanpa biaya. Pengecualian akan menambah beban program, jadi menyalahgunakan pengecualian tidak disarankan. Ada perbedaan besar antara menulis beberapa percobaan...kecuali dan menulis ribuan percobaan...kecuali. Seperti kata-kata Charlie Calverts: "Anda harus menggunakan blok coba...kecuali jika tampaknya berguna. Namun cobalah untuk tidak terlalu bersemangat dengan teknik ini."
Selain itu, Object Pascal memperkenalkan struktur try...finally yang unik. Saya katakan sebelumnya bahwa tidak ada perbedaan antara kembali dari suatu fungsi melalui pengecualian dan kembali dari suatu fungsi secara normal. Oleh karena itu, objek lokal di tumpukan dalam fungsi akan dilepaskan secara otomatis, tetapi objek di tumpukan tidak. Namun, model objek Object Pascal didasarkan pada referensi, yang ada di heap, bukan stack. Oleh karena itu, terkadang kita perlu membersihkan beberapa sumber daya objek lokal sebelum kembali dari suatu fungsi melalui pengecualian. coba...akhirnya menyelesaikan masalah ini.
Saya menulis ulang kode ToOpenFile di atas, kali ini menggunakan beberapa sumber daya selama proses ToOpenFile, dan melepaskan sumber daya ini setelah pengecualian terjadi (atau tidak terjadi) sebelum kembali dari fungsi:
prosedur KeOpenFile;
varRetVal: Bilangan Bulat;
Aliran: TSstream;
mulai
//Beberapa kode untuk membuka file
Aliran := TStream.Buat;
RetVal := -1; //pembukaan gagal
mencoba
jika RetVal = 0 maka //sukses
KELUAR
lain jika RetVal = -1 maka
Naikkan EFileNotFound.Create('File tidak ditemukan')
lain jika RetVal = -2 maka
Naikkan EFileFormatErr.Create('Kesalahan format file')
lain // kesalahan lainnya
Naikkan Pengecualian.Buat('Kesalahan tidak diketahui');
Akhirnya
Streaming.Gratis;
akhir;
akhir;
Melalui kode di atas, kita dapat melihat bahwa meskipun nilai RetVal adalah 0, setelah mengeksekusi Exit, kode di akhirnya akan tetap dieksekusi dan kemudian kembali dari fungsinya. Hal ini memastikan pelepasan sumber daya lokal dengan benar.
Tujuan dan skenario penggunaan coba...kecuali dan coba...akhirnya berbeda, dan banyak pemula yang bingung membedakannya. Berikut ini adalah beberapa pengetahuan pribadi penulis: coba...kecuali umumnya digunakan oleh pemanggil untuk menangkap pengecualian yang diberikan oleh fungsi yang dipanggil dan menanganinya. Dan try...finally umumnya digunakan untuk fungsi yang memunculkan pengecualian untuk melakukan beberapa pekerjaan pembersihan sumber daya.
Pemrograman berorientasi objek menyediakan solusi penanganan kesalahan yang disebut “pengecualian”. Jika digunakan dengan bijak, ini akan bermanfaat bagi pekerjaan kita dan dapat meningkatkan kualitas kode yang kita tulis secara signifikan.
Nicrosoft ([email protected]) 25.7.2001
Sumber asli: Dokumen Sunistudio (http://www.sunistudio.com/asp/sunidoc.asp)