Pertanyaan OutOfRangeException vs. OutOfBoundsException


PHP mendefinisikan dua SPL pengecualian untuk kunci tidak valid:

OutOfRangeException: Pengecualian dilemparkan ketika indeks ilegal diminta. Ini merupakan kesalahan yang harus dideteksi pada waktu kompilasi.

OutOfBoundsException: Pengecualian dilempar jika nilai bukan kunci yang valid. Ini merupakan kesalahan yang tidak dapat dideteksi pada waktu kompilasi.

Karena PHP bukan bahasa yang dikompilasi, perbedaan antara waktu kompilasi dan waktu berjalan tampaknya aneh dan oleh karena itu saya sulit memahami pengecualian mana yang digunakan saat itu.

Saat ini pemahaman saya adalah bahwa seseorang harus melempar ...
... OutOfRangeException jika kuncinya adalah cacat secara mendasar dan inheren, mis. jika array dilewatkan sebagai kunci.
... OutOfBoundsException jika kunci umumnya baik-baik saja, tetapi tidak dalam beberapa batasan, mis. jika 100 dilewatkan tetapi 50 adalah kunci maksimum.

Apakah pemahaman itu benar?


32
2017-11-19 11:40


asal


Jawaban:


Meskipun PHP tidak memiliki "waktu kompilasi" klasik (atau kompilator yang melakukan banyak pemeriksaan statis dalam hal ini) saya akan memperlakukan "waktu kompilasi" sebagai "hal yang agak statis yang saya lakukan salah saat menulis kode" dan " run time "sebagai" logika, masukan atau validasi saya mati pada beberapa titik ".

Jadi saran saya akan memperlakukannya seperti ini:

"Compile Time" / "OutOfRangeException": Kesalahan selalu dapat diperbaiki dalam kode sumber tanpa atau dengan logika yang sangat sedikit.

Saya selalu mengambil angka dari 1-10 dan Anda memasukkan 11


"Run Time" / "OutOfBoundsException": Kesalahan ini disebabkan oleh penggunaan yang salah saat runtime.

Anda menciptakan saya dan mengatakan kepada saya untuk mengambil nilai dari 1 hingga 5 maka Anda memasukkan 7. Tidak menghitung

atau

Anda meminta indeks yang tidak ada karena Anda tidak meletakkannya di sana seperti seharusnya


Mencicipi:

Saya berharap SplFixedArray akan melempar OutOfBoundsException karena ukurannya bersifat dinamis dan dapat kesempatan saat runtime sementara saya mengharapkan sesuatu seperti Calender::getMonthName untuk melempar dan OutOfRangeException karena jumlah bulan pasti sudah ditetapkan pada waktu "kompilasi / tulis".

Sampel objek array:

Katakanlah $ array adalah objek yang mengimplementasikan ArrayAccess yang dapat Anda lemparkan OutOfBoundsException dalam keadaan seperti ini:

$array['bar'];
$array[7];

Karena nilainya adalah apa yang Anda harapkan untuk ArrayAccess tetapi itu tidak masuk akal dalam kasus SplFixedArray (5). Alternatif akan menjadi DomainException atau mungkin RangeException

Sebuah OutOfRangeException dalam kasus-kasus ini:

$calendar->getMonth(15);

Sebagai meletakkan array atau kelas baru pasti ada beberapa cacat logika yang lebih besar dalam kode yang biasanya hasil dari kesalahan sederhana "oh, saya dimasukkan dalam kesalahan yang salah" oleh seorang programmer. An (mungkin lebih baik) alternatif akan UnexpectedValueException dan tua yang baik InvalidArgumentException.

Untuk kasus seperti:

$array[array()];
$array[new StdClass];

beberapa pengecualian alternatif tampak lebih pas.

Perbandingan dengan dunia Java di mana pengecualian untuk digunakan saat tidak selalu berlaku karena Pengembang Java memiliki masalah tambahan yang harus ditangani.

Pengecualian yang Diperiksa / Tidak Dicentang. Dengan banyak orang yang menyatakan bahwa segala sesuatu yang bukan merupakan pengecualian runtime memiliki penggunaan yang sangat terbatas di Java / tidak boleh digunakan secara internal) nama-nama tersebut telah kehilangan sebagian makna dan maksud aslinya.


25
2017-11-22 15:10



Saya sendiri mengambil ini:

LogicException

digunakan untuk setiap kesalahan pengembang lakukan, mis. kesalahan saat memprogram / merakit aplikasi. Mereka mudah-mudahan akan ditangkap ketika pengembang menjalankan / UnitTests nya (yang kemudian akan menjadi setara dengan Waktu Kompilasi). Pengecualian tersebut seharusnya tidak pernah terjadi di situs produksi karena ada kesalahan dalam perangkat lunak seperti itu.

RuntimeException:

digunakan untuk setiap kesalahan pengguna lakukan atau itu hasil dari data yang tidak valid dimasukkan ke dalam aplikasi pada saat runtime. Ini adalah kesalahan yang mungkin dapat diantisipasi tetapi tidak sepenuhnya dapat dicegah oleh UnitTests, mis. itu bisa terjadi di situs produksi. Pengecualian itu bisa berasal dari kesalahan penggunaan atau kesalahan pemrograman.

OutOfBounds

adalah IMO secara efektif yang didefinisikan oleh Wikipedia sebagai Rentang Array di Kisaran dalam Pemrograman Komputer, yaitu:

Ketika sebuah array diindeks secara numerik, jangkauannya adalah batas atas dan bawah dari array. Tergantung pada lingkungan, peringatan, kesalahan fatal, atau perilaku tak terduga akan terjadi jika program mencoba mengakses elemen larik yang berada di luar jangkauan.

Dengan kata lain, ketika Anda memiliki array dengan indeks [0,1,2] apa pun kecuali [0,1,2] di luar batas. Perhatikan bahwa Bounds juga dapat berlaku untuk tipe data lain juga, mis. mencoba mengakses karakter ke-7 dalam string 5 karakter juga akan OutOfBounds.

OutOfRange:

yang satu ini adalah kue yang sulit. Di C ++ Diluar jangkauan adalah pengecualian umum yang memperluas LogicException (seperti dalam PHP). Saya tidak yakin apakah contoh yang diberikan mudah diterjemahkan ke kode PHP sekalipun atau definisi saya tentang waktu Kompilasi di atas. Terutama karena tidak ada seorang pun yang pertama kali melakukan init a new Vector(10) dan segera mencoba untuk mengaksesnya at(20).

Di Jawa OutOfRange tampaknya merujuk Rentang dalam pengertian matematika

Rentang fungsi adalah kemungkinan nilai y dari fungsi yang dihasilkan ketika kita mengganti semua kemungkinan nilai-x ke dalam fungsi.

Satu referensi Saya bisa menemukan itu memperluas RuntimeException, jadi saya kira mencari bahasa lain tidak akan membantu untuk memecahkan misteri ini. Ada juga yang terbuka laporan bug tentang Pengecualian SPL secara umum, menyatakan itu

  • OutOfRangeException (nilai di luar jangkauan) adalah LogicException, seharusnya: RuntimeException

Tetapi jika ini benar, lalu bagaimana OutOfRange berbeda dari DomainException? Dan jika definisi Anda sendiri benar, maka bagaimana OutOfRange berbeda dari InvalidArgumentException?

Untuk mempersingkat cerita panjang: Saya tidak tahu apa OutOfRangeException seharusnya untuk.


11
2017-11-22 16:46



Jawaban atas pertanyaan Anda juga cukup sulit untuk saya. Namun, berikut beberapa hal yang perlu dipikirkan:

  • Jika array dilewatkan ketika kita mengharapkan kunci array yang valid, kami juga punya InvalidArgumentException karena itu bukan tipe argumen yang tepat.
  • Kami juga bisa melempar a DomainException karena array tidak dalam domain untuk kunci array.
  • Dalam php, Anda umumnya tidak dapat mendeteksi jenis pada waktu kompilasi karena pengikatan statis yang terlambat. Mereka sengaja menunda pengikatan variabel ke runtime.

Bagaimana saya menangani situasi ini:

  • Lempar InvalidArgumentException jika sebuah variabel dilewatkan ke fungsi mana pun argumennya bukan tipe yang benar. Saya masih melakukan ini ketika bekerja dengan array.
  • Lempar InvalidArgumentException jika null disahkan ketika seharusnya tidak. Yang ini benar-benar bisa menjadi banyak hal karena nol tidak diketik. Agar kode kesalahan tetap sederhana, saya tetap menggunakan argumen yang tidak valid.
  • Melemparkan OutOfBoundsException ketika indeks tidak dalam kisaran yang benar, seperti yang Anda sarankan.
  • Melemparkan BadFunctionCallException jika fungsi yang disediakan pengguna sebagai parameter tidak memiliki bentuk yang benar. Jika struktur Anda di dalam array, masuk akal bahwa mereka bisa lewat dalam fungsi untuk memodifikasinya, jadi ini muncul sesekali.

Secara umum, saya dapat menggunakan hanya tiga pengecualian ini untuk mewakili semua kesalahan yang terjadi di luar sumber daya khusus (Jaringan dan koneksi database akan menjadi sumber daya khusus). Yang ketiga tampaknya telah lebih sering muncul, tetapi terutama saya baru saja berurusan dengan dua yang pertama.


4
2017-11-19 17:34



Ini cukup sederhana:

Diluar jangkauan berarti "Kunci yang Anda minta tidak berada dalam indeks satu set didefinisikan dalam kode. "

Di luar batas berarti "Kunci yang Anda minta tidak berada dalam indeks kumpulan didefinisikan oleh konfigurasi yang dimuat. "


3
2017-12-09 22:47



Kebingungan dalam hal ini berasal dari beberapa faktor. Pertama, PHP sebenarnya dikompilasi menjadi bytecode. Ada beberapa lingkungan eksekusi di mana formulir yang dikompilasi ini bertahan dalam bentuk yang relatif permanen di server. Namun, masalah OutOfRangeException / OutOfBoundsException bukan tentang itu, ini tentang kesalahan kategorisasi yang dibuat oleh orang-orang yang mendokumentasikan kelas pengecualian khusus ini.

Karena PHP diketik secara dinamis, seringkali tidak mungkin untuk benar-benar memeriksa rentang dan bahkan mengetik pada waktu kompilasi. Manual menyatakan bahwa OutOfRangeException harus ditingkatkan pada waktu kompilasi dan OutOfBoundsException harus diterapkan pada saat runtime, yang merupakan perbedaan yang keliru untuk dibuat dalam konteks ini.

Kedua entri manual menggunakan bahasa yang tidak jelas tentang arti indeks ilegal, tetapi melihat penggunaan kelas induknya memberikan beberapa petunjuk: LogicExceptions diperluas oleh kelas seperti DomainException, InvalidArgumentException, dan LengthException, sedangkan pengecualian Runtime adalah hal-hal seperti UnexpectedValueException, OverflowException dan UnderflowException. Dari pola ini, seseorang dapat menyimpulkan bahwa OutOfRangeException mungkin harus diterapkan untuk jenis kunci ilegal, dan OutOfBoundsException harus diterapkan ke nilai indeks yang memiliki jenis yang tepat tetapi tidak dalam batas-batas wadahnya.

Ada beberapa diskusi di daftar dev PHP tentang kategorisasi ini menjadi salah, tetapi masalahnya lebih dalam dari itu. Dalam prakteknya, kedua pengecualian hanya dapat dibangkitkan pada saat runtime. Anda dapat menggunakan liku-liku dokumentasi untuk memeras perbedaan antara jenis kunci yang tidak valid dan nilai indeks yang tidak valid, tetapi pada titik ini kita berbicara tentang bug dalam dokumentasi PHP.


1
2017-11-28 23:18



  1. Jika Anda mendapatkan indeks yang tidak terduga. yaitu Anda mengharapkan sebuah stringtetapi berakhir dengan integer atau sebaliknya. Maka Anda harus melempar UnexpectedValueException pengecualian.
  2. Jika Anda mendapatkan jenis indeks yang tepat tetapi tidak ada. Kemudian naikkan warning  (trigger_error) dan lanjutkan. Ini tidak diharapkan untuk menghentikan alur pemrograman.
  3. Jika Anda memiliki objek yang dapat diulang atau seharusnya di-iterasi pada rentang dan mencapai batasnya (yaitu bagian akhir file), maka Anda harus melempar OutOfBoundsException.
  4. Ada yang lain adalah kandidat untuk OutOfRangeException.

Dalam istilah awam. Sebuah OutOfBoundsException adalah sesuatu yang normal. Tidak seserius itu. Ini adalah sesuatu yang sering terjadi dan harus dijaga. dapat digunakan oleh iterator untuk terus membaca data hingga tidak ada lagi yang bisa dibaca. Ini adalah kesalahan logis. Dibuat oleh seseorang yang menggunakan kode bukan oleh seseorang yang menulis kode.

Sebuah OutOfRangeException adalah sesuatu yang serius. Seseorang harus melihat kode sumbernya. Seseorang harus mencari tahu apa yang terjadi. Ini penting. Secara teoretis ini tidak pernah seharusnya terjadi. Hubungi 911. Ini adalah kesalahan waktu kompilasi. Dibuat oleh programmer dummy.

Di luar jangkauan pengecualian ditulis oleh programmer untuk menjaga dari kesalahan oleh programmer lain. Atau mungkin dirimu sendiri di masa depan. Jika Anda merasa hal seperti itu tidak akan pernah terjadi maka gunakan Out Of Range. Gunakan Out of Bounds untuk sesuatu yang mungkin terjadi.


0
2018-01-31 20:22