Apa yang mendefinisikan kode yang kuat?

42

Profesor saya terus merujuk pada contoh Java ini ketika ia berbicara tentang kode "kuat":

if (var == true) {
    ...
} else if (var == false) {
    ...
} else {
    ...
}

Dia mengklaim bahwa "kode yang kuat" berarti bahwa program Anda memperhitungkan semua kemungkinan, dan bahwa tidak ada yang namanya kesalahan - semua situasi ditangani oleh kode dan menghasilkan keadaan yang valid, karenanya "lain".

Namun saya ragu. Jika variabel adalah boolean, apa gunanya memeriksa keadaan ketiga ketika keadaan ketiga secara logis tidak mungkin?

"Tidak memiliki kesalahan" tampaknya konyol juga; bahkan aplikasi Google menunjukkan kesalahan secara langsung kepada pengguna alih-alih menelannya diam-diam atau entah bagaimana menganggapnya sebagai keadaan yang valid. Dan itu bagus - saya suka tahu kapan ada masalah. Dan sepertinya klaim untuk mengatakan aplikasi tidak akan pernah memiliki kesalahan.

Jadi apa definisi sebenarnya dari "kode kuat"?

Lotus Notes
sumber
4
Ini hanya akan digunakan dalam bahasa yang tidak diketik dengan kuat. Dalam bahasa yang sangat diketik, variabel tipe boolean (bukan bilangan bulat yang menyamar sebagai boolean), hanya bisa benar atau salah, tidak ada opsi ketiga ...
Marjan Venema
23
tanyakan kepadanya bagaimana Anda menguji cakupan pada case ke-3, karena kode yang kuat pasti harus memerlukan pengujian, dan jika Anda tidak berhasil menguji case ke-3, Anda tidak akan dapat menemukan bug yang mungkin bersembunyi di sana.
gbjbaanb
2
@Marjan - dalam bahasa yang tidak diketik dengan sangat baik, orang mungkin akan menulis: if (var) {} else {}
kevin cline
2
Saya tidak tahu bahasa apa pun di mana x dan! X bisa benar. Perhatikan bahwa saya tidak menyarankan "jika (x == true) ..."; Saya benci perbandingan seperti itu.
kevin cline

Jawaban:

33

apa gunanya memeriksa keadaan ketiga ketika keadaan ketiga secara logis tidak mungkin?

Bagaimana dengan Boolean?yang memungkinkan NULLnegara yang tidak benar atau salah. Sekarang apa yang harus dilakukan oleh perangkat lunak? Beberapa perangkat lunak harus sangat tahan terhadap kecelakaan seperti alat pacu jantung. Pernah melihat seseorang menambahkan kolom ke database yang merupakan Booleandan menginisialisasi data saat ini untuk NULLawalnya? Saya tahu saya telah melihatnya.

Berikut adalah beberapa tautan yang membahas apa artinya menjadi kuat dalam hal perangkat lunak:

Jika Anda berpikir ada satu yang secara universal menyetujui definisi "kuat" di sini, semoga sukses. Mungkin ada beberapa sinonim seperti bom-bukti atau idiot-proof. Programer Lakban akan menjadi contoh seseorang yang biasanya menulis kode yang kuat setidaknya dalam pemahaman saya tentang persyaratan.

JB King
sumber
13
Jika ini adalah boolean nullable baik Java dan c # akan melempar, maka null harus diperiksa terlebih dahulu.
Esben Skov Pedersen
Tampaknya tidak ada definisi yang disepakati secara universal tentang apa itu kucing atau anjing.
Tulains Córdova
11

Demi diskusi saya, Bool dapat memiliki 2 status, Benar atau Salah. Yang lainnya adalah ketidaksesuaian dengan spesifikasi pemrograman langugae. Jika rantai alat Anda tidak sesuai dengan spesifikasinya, Anda disembunyikan apa pun yang Anda lakukan. Jika seorang pengembang membuat jenis Bool yang memiliki lebih dari 2 negara, itu adalah hal terakhir yang akan dia lakukan pada basis kode saya.

Opsi A.

if (var == true) {
    ...
} else if (var == false) {
    ...
} else {
    ...
}

Opsi B

if (var == true) {
    ...
} else {
    ...
}

Saya menegaskan Opsi B lebih kuat .....

Setiap twit dapat memberitahu Anda untuk menangani kesalahan yang tidak terduga. Mereka biasanya mudah dideteksi setelah Anda memikirkannya. Contoh yang diberikan oleh profesor Anda bukanlah sesuatu yang bisa terjadi, jadi ini adalah contoh yang sangat buruk.

A tidak mungkin untuk diuji tanpa memanfaatkan uji yang berbelit-belit. Jika Anda tidak dapat membuatnya, bagaimana Anda akan mengujinya? Jika Anda belum menguji kode, bagaimana Anda tahu kode itu berfungsi? Jika Anda tidak tahu itu berfungsi, maka Anda tidak sedang menulis perangkat lunak yang tangguh. Saya pikir mereka masih menyebutnya Catch22 (Film Hebat, tonton kapan-kapan).

Opsi B mudah untuk diuji.

Masalah berikutnya, tanyakan pada Anda, profesor, pertanyaan ini, "Apa yang Anda ingin saya lakukan jika Boolean itu Benar atau Salah?" Itu harus mengarah pada diskusi yang sangat menarik .....

Sebagian besar kasus, dump inti tepat, paling buruk itu mengganggu pengguna atau menghabiskan banyak uang. Bagaimana jika, katakanlah, modulnya adalah sistem perhitungan masuk kembali real-time antar-jemput Antariksa? Jawaban apa pun, betapapun tidak akuratnya, tidak bisa lebih buruk daripada batal, yang akan membunuh pengguna. Jadi apa yang harus dilakukan, jika Anda tahu jawabannya mungkin salah, pilih 50/50, atau batalkan dan lakukan untuk kegagalan 100%. Jika saya seorang anggota kru, saya akan mengambil 50/50.

Opsi A membunuh saya. Opsi B memberi saya kesempatan untuk bertahan hidup.

Tapi tunggu - ini adalah simulasi masuknya kembali pesawat ulang-alik - lalu apa? Batalkan sehingga Anda tahu tentang itu. Kedengarannya seperti ide yang bagus? - BUKAN - karena Anda perlu menguji dengan kode yang Anda rencanakan untuk dikirim.

Opsi A lebih baik untuk simulasi, tetapi tidak dapat digunakan. Tidak berguna Opsi B adalah kode yang digunakan sehingga simulasi melakukan hal yang sama dengan sistem hidup.

Katakanlah ini adalah masalah yang valid. Solusi yang lebih baik adalah dengan mengisolasi penanganan kesalahan dari logika aplikasi.

if (var != true || var != false) {
    errorReport("Hell just froze over, var must be true or false")
}
......
if (var == true){
 .... 
} else {
 .... 
}

Bacaan lebih lanjut - Mesin Therac-25 Xray, Ariane 5 Rocket failure, dan lain-lain (Tautan memiliki banyak tautan rusak tetapi cukup info yang Google akan bantu)

mattnz
sumber
1
".. kesalahan yang tidak terduga. Mereka biasanya mudah dideteksi setelah Anda memikirkannya" - tetapi ketika Anda memikirkannya, mereka tidak lagi tak terduga.
gbjbaanb
7
Ada beberapa pertanyaan tentang apakah kode Anda if (var != true || var != false) {seharusnya merupakan &&gantinya.
1
Saya dapat dengan mudah memikirkan bool yang tidak benar atau salah, tetapi masih tak terduga. Jika Anda mengatakan bool tidak bisa apa-apa lagi, jika saya memeriksa apakah huruf adalah karakter digit dan kemudian mengubahnya menjadi nilai integernya, saya dapat dengan mudah menganggap bahwa nilai integer kurang dari 0 atau lebih besar dari 9, tetapi masih tak terduga.
gnasher729
1
Null Booleans didukung di Java dan C #, dan memiliki aplikasi dunia nyata. Pertimbangkan database yang berisi daftar orang. Setelah beberapa saat Anda memutuskan Anda membutuhkan bidang gender (isMale). Null berarti "tidak pernah ditanya jadi tidak tahu"; benar berarti laki-laki dan palsu berarti perempuan. (Oke, trans-gender dihilangkan karena kesederhanaan ...).
kiwiron
@kiwiron: Apakah solusi yang lebih baik tidak menggunakan tipe enumerasi, "Pria", "Wanita", "Tidak Bertanya". Pencacahan lebih baik - dapat diperpanjang ketika kebutuhan muncul (misalnya Aseksual Anda, Hermafrodit, "Menolak untuk Menjawab" muncul di benak).
mattnz
9

Sebenarnya kode Anda tidak lebih kuat tetapi KURANG kuat. Final elsehanyalah kode mati yang tidak dapat Anda uji.

Dalam perangkat lunak penting seperti dalam wahana antariksa, kode mati dan kode yang lebih umum yang tidak diuji dilarang: Jika sinar kosmik menghasilkan satu peristiwa yang mengganggu yang pada gilirannya membuat kode mati Anda diaktifkan, semuanya mungkin terjadi. Jika SEU mengaktifkan sebagian kode yang kuat, perilaku (tak terduga) tetap terkendali.

mouviciel
sumber
Saya tidak mendapatkannya di wahana antariksa dilarang kode mati? yaitu Anda tidak dapat menulis yang terakhir? karena kamu tidak bisa mengujinya kamu tidak bisa memasukkannya? tetapi kemudian apa artinya "Jika SEU mengaktifkan sebagian kode yang kuat, perilaku (tak terduga) tetap terkendali."
Lusuh
5
Ya, dalam ruang, cakupan pengujian perangkat lunak kritis harus 100% dan sebagai akibatnya kode yang tidak terjangkau (alias kode mati) dilarang.
mouviciel
7

Saya pikir profesor mungkin membingungkan "kesalahan" dan "bug". Kode yang kuat tentunya memiliki sedikit / tidak ada bug. Kode yang kuat mungkin, dan dalam lingkungan yang tidak bersahabat, harus, memiliki manajemen kesalahan yang baik (baik itu penanganan pengecualian atau tes status pengembalian yang ketat).

Saya setuju bahwa contoh kode profesor itu konyol, tetapi tidak sebodoh saya.

// Assign 3 to x
var x = 3;
x = 3;   // again, just for sure
while (x < 3 or x > 3) { x = 3; }  // being robust
if (x != 3) { ... }  // this got to be an error!
David Andersson
sumber
1
Yang terakhir jika dipicu pasti, itu tidak akan membutuhkan banyak usaha. Setiap programmer C yang berpengalaman telah melihat nilai yang tiba-tiba berubah. Tentu saja secara logis, dalam lingkungan single-threaded yang terkendali, ini seharusnya tidak pernah terjadi. Dalam kehidupan nyata, kode di dalam if pada akhirnya akan terjadi. Jika tidak ada yang berguna yang bisa Anda lakukan di dalam itu, maka jangan kode itu! (Saya memiliki pengalaman lucu selama pengembangan perangkat lunak tertentu di mana saya mengajukan perkecualian dengan kata-kata kutukan seandainya terjadi sesuatu yang mustahil ... tebak apa yang terjadi?).
Alex
2
Kisah nyata:boolean x = something(); if (x) { x = True // make sure it's really true, ... }
Andres F.
6

Tidak ada definisi yang disepakati tentang Kode Kuat , karena untuk banyak hal dalam pemrograman itu lebih atau kurang subyektif ...

Contoh yang diberikan profesor Anda bergantung pada bahasanya:

  • Di Haskell, a Booleanbisa berupa Trueatau False, tidak ada opsi ketiga
  • Dalam C ++, sebuah boolbisa true, falseatau (sayangnya) datang dari beberapa pemain yang meragukan bahwa memasukkannya ke dalam kasus yang tidak diketahui ... ini harus tidak terjadi, tapi mungkin, sebagai akibat dari kesalahan sebelumnya.

Namun, apa yang disarankan oleh dosen Anda mengaburkan kode dengan memperkenalkan logika asing untuk peristiwa yang tidak boleh terjadi di tengah program inti, jadi saya akan mengarahkan Anda, sebaliknya, ke arah Pemrograman Defensif .

Dalam hal universitas, Anda bahkan dapat menambahnya dengan mengadopsi strategi Desain Dengan Kontrak:

  • Menetapkan invarian untuk kelas (mis., sizeAdalah jumlah item dalam datadaftar)
  • Menetapkan pra-kondisi dan pasca-kondisi untuk setiap fungsi (mis., Fungsi ini hanya dapat dipanggil dengan akurang dari 10)
  • Uji masing-masing pada titik masuk dan keluar dari masing-masing fungsi Anda

Contoh:

class List:
  def __init__(self, items):
    self.__size = len(items)
    self.__data = items

  def __invariant(self):
    assert self.__size == len(self.__data)

  def size(self):
    self.__invariant()

    return self.__size

  def at(self, index):
    """index should be in [0,size)"""
    self.__invariant()
    assert index >= 0 and index < self.__size

    return self.__data[index]

  def pushback(self, item):
    """the subsequent list is one item longer
       the item can be retrieved by self.at(self.size()-1)"""
    self.__invariant()

    self.__data.append(item)
    self.__size += 1

    self.__invariant()
    assert self.at(self.size()-1) == item
Matthieu M.
sumber
Tetapi profesor secara khusus mengatakan bahwa itu adalah Jawa, dan secara khusus TIDAK mengatakan apa jenis var. Jika itu Boolean, itu bisa benar, salah, atau nol. Jika sesuatu yang lain, itu bisa tidak sama dengan benar dan tidak sama dengan salah. Ya, tumpang tindih antara kuat, defensif, dan paranoid.
Andy Canfield
2
Dalam C, C ++ dan Objective-C, bool dapat memiliki nilai tak tentu, seperti jenis lainnya, tetapi tugas apa pun akan mengaturnya menjadi benar atau salah dan tidak ada yang lain. Sebagai contoh: bool b = 0; b ++; b ++; akan mengatur b menjadi true.
gnasher729
2

Pendekatan profesor Anda benar-benar salah arah.

Suatu fungsi, atau hanya sedikit kode, harus memiliki spesifikasi yang mengatakan apa yang dilakukannya, yang harus mencakup setiap input yang mungkin. Dan kode harus ditulis sehingga perilakunya dijamin sesuai dengan spesifikasi. Pada contoh, saya akan menulis spek yang cukup sederhana seperti ini:

Spec: If var is false then the function does "this", otherwise it does "that". 

Kemudian Anda menulis fungsinya:

if (var == false) dothis; else dothat; 

dan kode memenuhi spesifikasi. Jadi, profesor Anda berkata: Bagaimana jika var == 42? Lihatlah spec: Dikatakan fungsi harus melakukan "itu". Lihatlah kodenya: Fungsi melakukan "itu". Fungsi memenuhi spesifikasi.

Di mana kode profesor Anda membuat hal-hal yang sama sekali tidak aman adalah kenyataan bahwa dengan pendekatannya, ketika var tidak benar atau salah, ia akan mengeksekusi kode yang belum pernah dipanggil sebelumnya dan yang sama sekali belum diuji, dengan hasil yang sama sekali tidak dapat diprediksi.

gnasher729
sumber
1

Saya setuju dengan pernyataan @ gnasher729: Pendekatan profesor Anda benar-benar salah arah.

Robust berarti tahan terhadap kerusakan / kegagalan karena membuat beberapa asumsi dan dipisahkan: itu mandiri, mandiri, dan portabel. Ini juga mencakup kemampuan beradaptasi terhadap perubahan persyaratan. Singkatnya, kode Anda tahan lama .

Ini biasanya diterjemahkan ke dalam fungsi pendek yang mendapatkan data mereka dari parameter yang dilewatkan oleh pemanggil, dan penggunaan antarmuka publik untuk konsumen - metode abstrak, pembungkus, tipuan, antarmuka gaya COM, dll - daripada fungsi yang mengandung kode implementasi konkret.

Vektor
sumber
0

Robust code hanyalah kode yang menangani kegagalan dengan baik. Tidak lebih, tidak kurang.

Dari kegagalan, ada banyak jenis: kode salah, kode tidak lengkap, nilai tak terduga, status tak terduga, pengecualian, sumber daya habis, .... Robust code menangani ini dengan baik.

Sparky
sumber
0

Saya akan mempertimbangkan kode yang Anda berikan sebagai contoh pemrograman defensif (setidaknya saat saya menggunakan istilah ini). Bagian dari pemrograman defensif adalah membuat pilihan yang meminimalkan asumsi yang dibuat tentang perilaku seluruh sistem. Misalnya, mana yang lebih baik:

for (int i = 0; i != sequence.length(); ++i) {
    // do something with sequence[i]
}

Atau:

for (int i = 0; i < sequence.length(); ++i) {
    // do something with sequence[i]
}

(Jika Anda mengalami kesulitan melihat perbedaannya, periksa tes loop: penggunaan pertama !=, penggunaan kedua <).

Sekarang, dalam sebagian besar keadaan, kedua loop akan berperilaku dengan cara yang persis sama. Namun, yang pertama (membandingkan dengan !=) membuat asumsi yang iakan bertambah hanya satu kali per iterasi. Jika melompati nilai sequence.length()maka loop dapat terus melampaui batas urutan dan menyebabkan kesalahan.

Karena itu Anda dapat membuat argumen bahwa implementasi kedua lebih kuat: itu tidak bergantung pada asumsi tentang apakah loop body berubah i(catatan: sebenarnya itu masih membuat asumsi yang itidak pernah negatif).

Untuk memberikan motivasi mengapa Anda mungkin tidak ingin membuat asumsi itu, bayangkan bahwa loop memindai string, melakukan beberapa pemrosesan teks. Anda menulis loop dan semuanya baik-baik saja. Sekarang persyaratan Anda berubah dan Anda memutuskan untuk mendukung karakter pelolosan dalam string teks, sehingga Anda mengubah badan loop sedemikian sehingga jika mendeteksi karakter pelolosan (katakanlah, garis miring terbalik), itu kenaikan iuntuk melewati karakter segera setelah melarikan diri. Sekarang loop pertama memiliki bug karena jika karakter terakhir dari teks adalah garis miring terbalik, tubuh loop akan bertambah idan loop akan terus berlanjut di luar akhir urutan.

John Bartholomew
sumber
-1

Saya pribadi menggambarkan kode sebagai 'kuat' yang memiliki atribut penting ini:

  1. Jika ibu saya duduk di depannya dan bekerja dengannya, dia tidak dapat merusak sistem

Sekarang, yang saya maksudkan adalah membuat sistem menjadi tidak stabil, atau menyebabkan pengecualian UNHANDLED . Anda tahu, terkadang untuk konsep yang sederhana, Anda dapat membuat definisi dan penjelasan yang kompleks. Tapi saya lebih suka definisi sederhana. Pengguna cukup pandai menemukan aplikasi yang kuat. Jika pengguna aplikasi Anda mengirimi Anda banyak permintaan tentang bug, tentang kehilangan status, tentang alur kerja yang tidak intuitif, dll., Maka ada yang salah dengan pemrograman Anda.

Saeed Neamati
sumber