Saya telah menulis sebuah struct yang mewakili koordinat lintang / bujur. Nilai mereka berkisar dari -180 hingga 180 untuk longtitude dan 90 hingga -90 untuk lattitudes.
Jika pengguna struct itu memberi saya nilai di luar rentang itu, saya punya 2 opsi:
- Lempar pengecualian (arg diluar jangkauan)
- Konversikan nilainya menjadi kendala
Karena koordinat -185 memiliki makna (sangat mudah dapat dikonversi ke +175 karena itu adalah koordinat kutub), saya dapat menerimanya dan mengubahnya.
Apakah lebih baik untuk melemparkan pengecualian untuk memberi tahu pengguna bahwa kodenya telah memberi saya nilai yang seharusnya tidak dimiliki?
Sunting: Juga saya tahu perbedaan antara lat / lng dan koordinat, tapi saya ingin menyederhanakan itu untuk diskusi yang lebih mudah - itu bukan ide yang paling cerdas
c#
exceptions
validation
K. Gkinis
sumber
sumber
Jawaban:
Jika inti dari pertanyaan Anda adalah ini ...
... maka jawaban umum saya adalah "tolak", karena ini akan membantu menarik perhatian ke bug potensial dalam kode klien yang sebenarnya menyebabkan nilai yang tidak valid muncul di program dan mencapai konstruktor Anda. Menarik perhatian pada bug pada umumnya adalah properti yang diinginkan di sebagian besar sistem, setidaknya selama pengembangan (kecuali itu adalah properti yang diinginkan sistem Anda untuk diatasi jika terjadi kesalahan).
Pertanyaannya adalah apakah Anda benar-benar menghadapi kasus itu .
Jika struktur data Anda dimaksudkan untuk memodelkan koordinat kutub secara umum, maka terima nilainya karena sudut di luar rentang -180 dan +180 tidak benar-benar tidak valid. Mereka benar-benar valid dan kebetulan selalu memiliki yang setara yang berada dalam kisaran -180 dan +180 (dan jika Anda ingin mengonversinya untuk menargetkan rentang itu, jangan ragu - kode klien biasanya tidak perlu peduli) .
Jika struktur data Anda secara eksplisit memodelkan koordinat Web Mercator (sesuai dengan pertanyaan dalam bentuk awalnya), maka yang terbaik adalah mengikuti ketentuan yang disebutkan dalam spesifikasi (yang saya tidak tahu, jadi saya tidak akan mengatakan apa-apa tentang itu) . Jika spesifikasi benda yang Anda modelkan mengatakan bahwa beberapa nilai tidak valid, tolaklah. Jika dikatakan bahwa mereka dapat diartikan sebagai sesuatu yang masuk akal (dan dengan demikian mereka benar-benar valid), terimalah.
The Mekanisme yang Anda gunakan untuk sinyal apakah nilai-nilai yang diterima atau tidak tergantung pada fitur bahasa Anda, filsafat umum dan persyaratan kinerja Anda. Jadi, Anda bisa melempar pengecualian (dalam konstruktor) atau mengembalikan versi nullable dari struct Anda (melalui metode statis yang memanggil konstruktor pribadi) atau mengembalikan boolean dan meneruskan struct Anda ke pemanggil sebagai
out
parameter (lagi melalui sebuah metode statis yang memanggil konstruktor pribadi), dan sebagainya.sumber
Itu sangat tergantung. Tetapi Anda harus memutuskan untuk melakukan sesuatu dan mendokumentasikannya .
Satu-satunya hal yang pasti salah untuk kode Anda lakukan adalah lupa untuk mempertimbangkan bahwa input pengguna mungkin di luar kisaran yang diharapkan, dan menulis kode yang secara tidak sengaja memiliki beberapa perilaku. Karena beberapa orang akan membuat asumsi yang salah tentang bagaimana kode Anda berperilaku dan itu akan menyebabkan bug, sementara yang lain akan berakhir tergantung pada perilaku kode Anda secara tidak sengaja memiliki (bahkan jika perilaku itu benar-benar gila) dan sehingga Anda akan menyebabkan lebih banyak bug saat nanti Anda memperbaiki masalahnya.
Dalam hal ini saya bisa melihat argumennya. Jika seseorang bepergian +10 derajat dari 175 derajat, mereka akan berakhir di -175. Jika Anda selalu menormalkan input pengguna dan memperlakukan 185 sebagai setara dengan -175 maka kode klien tidak dapat melakukan hal yang salah ketika menambahkan 10 derajat; selalu memiliki efek yang tepat. Jika Anda memperlakukan 185 sebagai kesalahan yang Anda paksa setiap kasus di mana kode klien menambahkan derajat relatif untuk dimasukkan ke dalam logika normalisasi (atau setidaknya ingat untuk memanggil prosedur normalisasi Anda), Anda sebenarnya akan menyebabkanbug (meskipun mudah-mudahan mudah untuk menangkap yang akan cepat tergencet). Tetapi jika angka bujur dimasukkan oleh pengguna, ditulis secara harfiah dalam program, atau dihitung melalui beberapa prosedur yang dimaksudkan untuk selalu berada di [-180, 180), maka nilai di luar rentang tersebut sangat mungkin mengindikasikan kesalahan, jadi "sangat membantu "Mengubahnya bisa menyembunyikan masalah.
Cita-cita saya dalam hal ini mungkin akan mendefinisikan jenis yang mewakili domain yang benar. Gunakan tipe abstrak (jangan biarkan kode klien mengakses angka mentah di dalamnya), dan berikan pabrik normalisasi dan validasi (sehingga klien dapat melakukan tradeoff). Tetapi apa pun nilai dari jenis ini dibuat, 185 harus tidak dapat dibedakan dari -175 ketika dilihat melalui API publik Anda (tidak masalah apakah itu dikonversi pada konstruksi atau Anda memberikan kesetaraan, pengakses, dan operasi lain yang entah bagaimana mengabaikan perbedaannya) .
sumber
Jika tidak terlalu penting bagi Anda untuk memilih satu solusi, Anda bisa membiarkan pengguna yang memutuskan.
Mengingat struct Anda adalah objek nilai hanya baca dan dibuat oleh metode / konstruktor, Anda bisa memberikan dua kelebihan berdasarkan pilihan yang dimiliki pengguna:
Juga tidak pernah membiarkan pengguna memiliki struct yang tidak valid untuk meneruskan ke metode Anda yang lain, lakukan dengan benar saat membuat.
Sunting: berdasarkan komentar, saya asumsikan Anda menggunakan c #.
sumber
catch
pengecualian Anda. Seperti yang dikatakan orang lain, itu memungkinkan klien untuk membatasi diri jika diinginkan. Anda tidak benar-benar menghindari apa pun.Itu tergantung apakah input langsung dari pengguna melalui beberapa UI, atau dari sistem.
Input melalui UI
Ini adalah pertanyaan pengalaman pengguna bagaimana menangani input yang tidak valid. Saya tidak tahu tentang kasus spesifik Anda, tetapi secara umum ada beberapa opsi:
Pilihannya tergantung pada harapan pengguna Anda dan seberapa penting data tersebut. Misalnya Google secara otomatis memperbaiki ejaan dalam kueri, tetapi ini berisiko rendah karena perubahan yang tidak membantu bukanlah masalah dan mudah diperbaiki (dan bahkan kemudian diperjelas pada halaman hasil bahwa kueri diubah). Di sisi lain, jika Anda memasukkan koordinat untuk rudal nuklir, Anda mungkin menginginkan validasi input yang lebih kaku dan tidak ada perbaikan diam untuk data yang tidak valid. Jadi tidak ada jawaban universal.
Yang paling penting, Anda harus mempertimbangkan apakah mengoreksi input bahkan memiliki manfaat bagi pengguna. Mengapa pengguna memasukkan data yang tidak valid? Sangat mudah untuk melihat bagaimana seseorang mungkin membuat kesalahan ejaan, tetapi mengapa ada orang yang memasukkan garis bujur -185? Jika pengguna benar-benar berarti +175 mereka mungkin akan mengetik +175. Saya pikir kemungkinan besar bahwa garis bujur yang tidak valid hanyalah kesalahan pengetikan, dan pengguna bermaksud -85 atau yang lainnya. Dalam hal ini, konversi secara diam-diam itu buruk dan tidak membantu . Pendekatan yang paling ramah pengguna untuk aplikasi Anda mungkin adalah untuk memperingatkan pengguna untuk nilai yang tidak valid, dan minta pengguna untuk memperbaikinya sendiri.
Input melalui API
Jika input dari sistem atau subsistem lain, tidak ada pertanyaan. Anda harus melempar pengecualian. Anda seharusnya tidak pernah diam mengonversi input yang tidak valid dari sistem lain, karena mungkin menutupi kesalahan di tempat lain dalam sistem. Jika input "dikoreksi" itu harus terjadi di lapisan UI, tidak lebih dalam ke sistem.
sumber
Anda harus melempar pengecualian.
Pada contoh yang Anda berikan, mengirim 185 dan mengonversinya menjadi -175, maka mungkin berguna dalam beberapa kasus untuk menyediakan fungsionalitas itu. Tetapi bagaimana jika penelepon mengirim 1 juta? Apakah mereka benar-benar bermaksud untuk mengubahnya? Tampaknya lebih mungkin itu adalah kesalahan. Jadi, jika Anda perlu melemparkan pengecualian untuk 1.000.000 tetapi tidak untuk 185, maka Anda harus membuat keputusan tentang ambang batas sewenang-wenang untuk melempar pengecualian. Ambang itu akan membuat Anda tersandung suatu saat karena beberapa aplikasi panggilan mengirim nilai di sekitar ambang tersebut.
Lebih baik membuang pengecualian untuk nilai di luar rentang.
sumber
Opsi paling nyaman bagi pengembang adalah dukungan kompilasi waktu kesalahan di platform, untuk nilai di luar jangkauan. Dalam hal ini, rentang juga harus menjadi bagian dari tanda tangan metode, seperti jenis parameternya. Dengan cara yang sama pengguna API Anda tidak dapat meneruskan sebuah String jika tanda tangan metode Anda didefinisikan untuk mengambil bilangan bulat , pengguna seharusnya tidak dapat memberikan nilai tanpa memeriksa apakah nilainya berada dalam kisaran yang diberikan dalam tanda tangan metode. Jika tidak dicentang, ia harus mendapatkan kesalahan waktu kompilasi dan dengan demikian, kesalahan runtime dapat dihindari.
Namun saat ini, sangat sedikit kompiler / platform yang mendukung jenis pemeriksaan waktu kompilasi ini. Jadi, itu sakit kepala pengembang. Tetapi idealnya, metode Anda harus membuang pengecualian yang berarti untuk nilai yang tidak didukung dan mendokumentasikannya dengan jelas.
BTW, saya sangat suka model kesalahan yang diusulkan oleh Joe Duffy di sini .
sumber
Defaultnya adalah melempar pengecualian. Anda juga dapat mengizinkan opsi seperti
strict=false
dan melakukan pemaksaan berdasarkan pada flag, di mana tentu sajastrict=true
default. Ini cukup umum:DateFormat
mendukung ringan .sumber
strict=false
?Bagi saya praktik terbaik adalah tidak pernah mengubah input pengguna. Pendekatan yang biasanya saya lakukan adalah memisahkan validasi dari eksekusi.
sumber