Saya sering menemukan bug yang disebabkan oleh penggunaan ELSE
konstruk. Contoh utama adalah sesuatu di sepanjang baris:
If (passwordCheck() == false){
displayMessage();
}else{
letThemIn();
}
Bagi saya ini menjerit masalah keamanan. Saya tahu bahwa passwordCheck kemungkinan besar adalah boolean, tetapi saya tidak akan menempatkan keamanan aplikasi saya di atasnya. Apa yang akan terjadi jika string, int dll?
Saya biasanya mencoba menghindari penggunaan ELSE
, dan sebagai gantinya memilih dua pernyataan IF yang sepenuhnya terpisah untuk menguji apa yang saya harapkan. Hal lain yang diabaikan atau ditangani secara khusus.
Tentunya ini adalah cara yang lebih baik untuk mencegah bug / masalah keamanan memasuki aplikasi Anda.
bagaimana kalian melakukannya?
self-improvement
programming-practices
security
billy.bob
sumber
sumber
I know that passwordCheck is likely to be a boolean...
Apa maksudmu? Dalam bahasa yang diketik dengan kuat.passwordCheck
akan menjadi apa pun yang Anda inginkan.else
pernyataan ...passwordCheck()
mungkin karena tidak menjadi boolean (yang mungkin menjadi perhatian wajar), dan kemudian Anda menyalahkannyaelse
? Saya tidak melihat masalah apaelse
penyebabnya.Jawaban:
The
else
blok harus selalu terdiri dari apa yang Anda inginkan perilaku default untuk menjadi.Tidak perlu menghindarinya, hanya berhati-hatilah untuk menggunakannya dengan tepat.
Dalam contoh Anda, status defaultnya adalah tidak mengizinkan akses. Sedikit refactoring memberi Anda:
yaitu jika pemeriksaan kata sandi berfungsi, biarkan masuk, jika tidak selalu berlaku untuk menampilkan beberapa pesan kesalahan.
Tentu saja Anda dapat menambahkan cek tambahan untuk logika Anda dengan menggunakan pernyataan yang tidak
else if
sepenuhnya terpisahif
.sumber
passwordCheck
bisa apa saja, fenull
, yang akan membuatpasswordCheck == false
untukfalse
dan akan pengguna memungkinkan untuk masuk karena kesalahan internal.if
memerlukan abool
, variabel harus ditetapkan secara pasti, semua jalur harus mengembalikan nilai, dll., Saya tidak bisa memikirkan alasan apa pun urutanif
danelse
akan penting selain keterbacaan. Artinya,if(a){b();}{c();}
harus setara denganif(!a){c();{b();}
. Di JavaScript, di sisi lain, Anda harus menyadari itupasswordCheck
bisa terjadiundefined
, dll.Tidak, tidak ada yang salah dengan itu
ELSE
.ELSE
bukan yang baruGOTO
. Bahkan, menggunakan duaIF
s bukannyaELSE
dapat menyebabkan beberapa masalah.Contoh satu:
Anda melihat copy-paste? Itu hanya menunggu hari ketika Anda mengubah satu dan melupakan yang lain.
Contoh dua:
Seperti yang Anda lihat,
IF
item kedua juga akan dieksekusi untuk item pertama, karena kondisinya sudah berubah. Dalam program dunia nyata, bug semacam itu lebih sulit dikenali.sumber
if
pernyataan dan pembalik ekspresi boolean hanya untuk menghindarielse
- sekarang yang merupakan pemrograman yang buruk! Anda tidak hanya menduplikasi kode ( pemrograman buruk ), Anda juga memperlambat kinerja (jika pemeriksaannya sangat rumit, Anda sekarang melakukannya dua kali - ba-- uh, well, Anda tahu apa yang mereka katakan tentang optimasi prematur saat ini ... pemrograman tidak begitu baik !).Selalu ada ELSE. Jika kamu menulis
Anda benar-benar menulis
Apa pun yang Anda masukkan dalam jalur ELSE adalah tanggung jawab Anda.
sumber
Saya pribadi cenderung menghindari
else
sebanyak yang saya bisa, tetapi ini bukan untuk masalah keamanan apa pun .Saat membaca kode, pernyataan bersarang membuat Anda lebih sulit untuk mengikuti logika, karena Anda perlu mengingat serangkaian kondisi yang akan mengarah ke sana. Untuk alasan ini, saya penggemar berat dari awal keluar:
Ini juga berlaku untuk
for
danwhile
loop di mana saya akan menggunakancontinue
danbreak
setiap kali itu menghindari tingkat lekukan.Chris Lattner mengatakan itu lebih baik daripada yang saya lakukan dalam Standar Pengkodean LLVM .
sumber
*writes an answer*
Kemudian ganti saja,
sumber
If ((passwordCheck == true) == true)
? :-)Seperti Matthieu M., saya lebih suka keluar awal untuk blok lain yang sangat bersarang ... Ini menggambarkan pemrograman defensif dengan baik (jika kondisi buruk, tidak ada gunanya untuk melanjutkan). Banyak orang akan tidak setuju dengan kami, lebih memilih titik keluar yang unik; itu bukan inti dari perdebatan (saya pikir).
Sekarang, saya tentu menggunakan
else
ketika itu masuk akal, terutama untuk alternatif yang sederhana dan pendek. Seperti yang dikatakan, menduplikasi tes adalah buang-buang waktu (programmer dan CPU), sumber kebingungan dan, kemudian, bug (ketika satu diubah, bukan yang lain).Kadang-kadang, saya menambahkan komentar pada
else
bagian itu, mengingatkan apa kondisinya (terutama jikaif
bagian itu panjang, misalnya dalam kode warisan) atau apa alternatifnya.Perhatikan bahwa beberapa pendukung ekstrem pemrograman fungsional mengusulkan untuk menyingkirkan seluruhnya
if
, demi pencocokan pola ... Agak terlalu ekstrem untuk selera saya. :-)sumber
Tidak ada yang salah dengan menggunakan ELSE. Namun itu dapat menyebabkan kode yang terlalu rumit yang sulit dibaca dan dipahami. Ini mungkin menunjukkan desain yang buruk. Ini tentu menunjukkan kasus penggunaan tambahan yang perlu diuji.
Cobalah untuk menghapus ELSE jika Anda bisa - tetapi jangan paranoid tentang hal itu. Steve McConnell menyebut kode garis lurus ini dalam Kode Lengkap. Yaitu ada jalur yang jelas sederhana melalui kode Anda.
Pendekatan untuk mencoba masalah khusus Anda:
Secara umum - berikut ini dapat membantu mengurangi ELSE dalam kode Anda:
sumber
Anggapan Anda tentang kode yang menjadi kebocoran keamanan mungkin atau mungkin tidak benar tergantung pada bahasa yang Anda gunakan. Dalam kode C itu bisa menjadi masalah (terutama karena dalam C a boolean hanyalah sebuah int yang bukan nol atau nol) - tetapi dalam bahasa yang diketik paling kuat (yaitu pengecekan tipe runtime) jika
passwordCheck
variabel dideklarasikan sebagai boolean, tidak ada cara untuk menetapkan sesuatu yang lain untuk itu. Faktanya, segala sesuatu dalamif
predikat harus diselesaikan ke boolean, apakah Anda menggunakan operator boolean atau hanya menggunakan nilai. Jika Anda berhasil membuat jenis objek lain terikat kepasswordCheck
runtime akan membuang beberapa jenis pengecualian pemain ilegal.Sederhana jika / jika konstruksi lebih mudah dibaca daripada jika / jika konstruksi - dan kurang rentan terhadap masalah yang tidak disengaja jika seseorang mencoba untuk membalikkan konstruksi. Mari kita ambil contoh yang sama sebentar:
Arti dari klausa yang saling eksklusif yang ingin Anda jalankan di atas hilang. Itulah yang konstruksi if / else sampaikan. Dua cabang eksekusi yang saling eksklusif, di mana salah satunya akan selalu berjalan. Ini adalah bagian penting dari keamanan - memastikan tidak ada cara untuk
letThemIn
setelah Anda menelepondenyAccess
.Untuk tujuan kejelasan kode, dan untuk tujuan memastikan bagian kritis paling terlindungi, mereka harus berada di dalam klausa utama (
if
bagian). Perilaku default yang tidak patuh harus dalam klausa alternatif (else
bagian). Sebagai contoh:CATATAN: dalam bekerja dengan bahasa yang berbeda, saya telah mengembangkan habbit pengkodean yang membantu menghindari pertanyaan "bagaimana jika itu sebuah string?" Pada dasarnya, ini adalah untuk menempatkan konstanta pertama dalam ekspresi boolean. Misalnya, alih-alih memeriksa,
passwordCheck == false
saya memeriksafalse == passwordCheck
. Ini juga menghindari masalah penugasan tak disengaja yang mungkin terjadi di C ++. Menggunakan pendekatan ini, kompiler akan mengeluh jika saya mengetik=
bukan==
. Dalam bahasa seperti Java dan C #, kompiler akan memperlakukan tugas dalam klausa if sebagai kesalahan, tetapi C ++ akan menerimanya dengan senang hati. Itu sebabnya saya juga cenderung melakukan pemeriksaan nol dengan yangnull
pertama.Jika Anda secara rutin mengubah bahasa, menempatkan konstanta terlebih dahulu sangat membantu. Namun, di tim saya itu berlawanan dengan standar pengkodean dan kompiler menangkap masalah itu pula. Ini bisa menjadi kebiasaan yang sulit untuk dilanggar.
sumber
Mengatakan bahwa menggunakan
else
saat pemrograman buruk adalah seperti mengatakan bahwa menggunakanotherwise
saat berbicara itu buruk.Tentu, keduanya dapat digunakan dengan cara yang buruk, tetapi itu tidak berarti mereka harus dihindari hanya karena Anda membuat kesalahan yang kebetulan termasuk mereka. Saya tidak akan terkejut jika banyak bug bergantung pada
default
kasus yang hilang dalam sebuahswitch
pernyataan.sumber
Anggap
Else
sebagai daftar putih aliran aplikasi Anda. Anda memeriksa kondisi yang HARUS memungkinkan aliran aplikasi untuk melanjutkan, dan jika ini tidak terpenuhi, maka AndaElse
dieksekusi untuk menyelesaikan masalah, menghentikan eksekusi aplikasi, atau yang serupa.Else
itu sendiri tidak buruk, tetapi jika Anda menggunakannya dengan buruk, Anda dapat melihat efek yang tidak diinginkan.Juga, sehubungan dengan pernyataan Anda tentang
"Saya tahu kata sandi yang mungkin menjadi boolean, tetapi saya tidak akan menempatkan keamanan aplikasi saya di atasnya."
Untuk metode yang Anda kembangkan, SELALU mengembalikan satu tipe data. Meskipun PHP Core dipenuhi dengan kode yang mengembalikan dua atau lebih tipe data, ini adalah praktik yang buruk karena membuat dugaan panggilan fungsi. Jika Anda harus mengembalikan lebih dari satu tipe data, pertimbangkan untuk melempar pengecualian (saya menemukan ini sering menjadi alasan saya ingin mengembalikan tipe data lain - ada yang tidak beres, sangat salah), atau pertimbangkan untuk menyusun kembali kode Anda sehingga Anda dapat mengembalikan hanya satu tipe data.
sumber
Pertama-tama. LOL! TIDAK ADA ALASAN untuk menghindari yang lain, sama sekali. Ini BUKAN praktik yang buruk dengan cara apapun, bentuk atau bentuk.
Jika ada kode harus
Tidak ada dua seandainya ada dan tidak ada yang lain. Ini adalah apa yang saya lakukan di semua aplikasi saya kecuali satu di mana saya melemparkan pengecualian. Pengecualian tertangkap dalam fungsi saya yang memeriksa url untuk halaman yang tepat untuk ditampilkan (atau sebagai alternatif saya dapat menempatkan catch / check di fungsi kesalahan asp.net). Mencetak halaman umum yang mengatakan tidak mengotorisasi atau pesan apa pun yang saya gunakan dalam pengecualian (saya selalu memeriksa jenis pengecualian dan mengatur kode status http).
-Edit- seperti yang ditunjukkan pada contoh ammoQ dua jika tidak masuk akal. Sungguh yang lain sama baiknya atau lebih baik daripada jika. Jika ada yang harus dihindari (walaupun saya pribadi tidak. Tapi saya menggunakan kembali dan banyak istirahat) seperti yang dikatakan lebih banyak jalur kode meningkatkan kemungkinan bug. Lihat Kompleksitas Siklomatik
-Edit 2- Jika Anda khawatir tentang penggunaan if / else. Saya juga akan mencatat bahwa preferensi saya adalah meletakkan blok kode terpendek di atas seperti
Sebaliknya
sumber
Saya suka mengatur default sebelum kondisi ketika saya bisa. Saya merasa sedikit lebih mudah membaca dan sedikit lebih eksplisit, tetapi ini hanya preferensi. Saya memiliki kecenderungan untuk mencoba dan menghindari kondisi negatif dalam kode saya. Saya bukan penggemar berat untuk memeriksa! Foo atau false == foo dan saya merasa seperti itu adalah sejenis persyaratan bersyarat negatif.
dari pada ...
Blok kode sebelumnya sepertinya sedikit lebih mudah bagi saya untuk membaca. Tampaknya lebih alami bagi saya untuk memiliki semacam paranoia skeptis tentang kode saya. Pengaturan default terlepas dari kondisi apa pun membuat saya merasa nyaman: P
sumber
Saya berpendapat bahwa menggunakan logika percabangan dalam bentuk apa pun harus dihindari sebanyak mungkin. Meskipun tidak ada yang salah dengan ELSE atau IF, ada banyak cara untuk menulis kode untuk meminimalkan kebutuhan untuk menggunakan logika percabangan apa pun. Saya tidak mengatakan logika percabangan dapat sepenuhnya dihilangkan - itu akan diperlukan di beberapa tempat - tetapi dimungkinkan untuk refactor kode untuk menghilangkan sebagian yang baik dari itu. Dalam kebanyakan kasus ini akan meningkatkan kejelasan dan akurasi kode Anda.
Sebagai salah satu contoh, operator ternary juga biasanya merupakan kandidat yang baik:
Menggunakan pendekatan ternary:
Operator ternary menggeser cabang ke kanan dengan cara yang baik.
sumber