Pertimbangkan kode berikut:
public void doSomething(int input)
{
while(true)
{
TransformInSomeWay(input);
if(ProcessingComplete(input))
break;
DoSomethingElseTo(input);
}
}
Asumsikan bahwa proses ini melibatkan sejumlah langkah yang terbatas tetapi bergantung pada input; loop dirancang untuk berakhir dengan sendirinya sebagai akibat dari algoritma, dan tidak dirancang untuk berjalan tanpa batas waktu (sampai dibatalkan oleh peristiwa luar). Karena tes untuk melihat apakah loop harus diakhiri berada di tengah serangkaian langkah logis, loop sementara itu sendiri saat ini tidak memeriksa sesuatu yang berarti; Sebaliknya cek dilakukan di tempat "layak" dalam algoritma konseptual.
Saya diberitahu bahwa ini adalah kode yang buruk, karena lebih rentan terhadap bug karena kondisi akhir tidak diperiksa oleh struktur loop. Lebih sulit untuk mengetahui bagaimana Anda keluar dari loop, dan dapat mengundang bug karena kondisi kerusakan mungkin dilewati atau dihilangkan secara tidak sengaja karena perubahan di masa mendatang.
Sekarang, kode dapat disusun sebagai berikut:
public void doSomething(int input)
{
TransformInSomeWay(input);
while(!ProcessingComplete(input))
{
DoSomethingElseTo(input);
TransformInSomeWay(input);
}
}
Namun, ini menggandakan panggilan ke metode dalam kode, melanggar KERING; jika TransformInSomeWay
kemudian diganti dengan metode lain, kedua panggilan harus ditemukan dan diubah (dan fakta bahwa ada dua mungkin kurang jelas dalam potongan kode yang lebih kompleks).
Anda juga bisa menulis seperti:
public void doSomething(int input)
{
var complete = false;
while(!complete)
{
TransformInSomeWay(input);
complete = ProcessingComplete(input);
if(!complete)
{
DoSomethingElseTo(input);
}
}
}
... tetapi Anda sekarang memiliki variabel yang hanya bertujuan untuk mengubah kondisi-memeriksa ke struktur lingkaran, dan juga harus diperiksa beberapa kali untuk memberikan perilaku yang sama dengan logika asli.
Bagi saya, saya katakan bahwa dengan algoritma yang diterapkan kode ini di dunia nyata, kode asli adalah yang paling mudah dibaca. Jika Anda mengalaminya sendiri, ini adalah cara Anda akan memikirkannya, dan itu akan menjadi intuitif bagi orang-orang yang terbiasa dengan algoritma.
Jadi, mana yang "lebih baik"? Apakah lebih baik memberikan tanggung jawab memeriksa kondisi ke loop sementara dengan menyusun logika di sekitar loop? Atau lebih baik untuk menyusun logika dengan cara "alami" seperti yang ditunjukkan oleh persyaratan atau deskripsi konseptual dari algoritma, meskipun itu mungkin berarti melewati kemampuan bawaan loop?
do ... until
membangun juga berguna untuk jenis-jenis loop karena mereka tidak harus "prima."Jawaban:
Tetap dengan solusi pertama Anda. Loop dapat menjadi sangat terlibat dan satu atau lebih istirahat bersih dapat jauh lebih mudah pada Anda, orang lain melihat kode Anda, pengoptimal, dan kinerja program daripada menguraikan pernyataan jika dan variabel tambahan. Pendekatan saya yang biasa adalah mengatur loop dengan sesuatu seperti "while (true)" dan mendapatkan pengkodean terbaik yang saya bisa. Seringkali saya dapat dan kemudian mengganti break dengan kontrol loop standar; kebanyakan loop cukup sederhana. Kondisi akhir harus diperiksa oleh struktur loop untuk alasan yang Anda sebutkan, tetapi tidak dengan biaya menambahkan seluruh variabel baru, menambahkan pernyataan if, dan kode berulang, yang semuanya bahkan lebih rentan terhadap bug.
sumber
Ini hanya masalah yang berarti jika loop body non-sepele. Jika tubuhnya sangat kecil, maka menganalisanya seperti ini sepele, dan tidak masalah sama sekali.
sumber
Saya kesulitan menemukan solusi lain yang lebih baik daripada yang rusak. Yah, saya lebih suka cara Ada yang memungkinkan untuk dilakukan
tetapi solusi break adalah rendering terbersih.
POV saya adalah bahwa ketika ada struktur kontrol yang hilang, solusi terbersih adalah menirunya dengan struktur kontrol lainnya, tidak menggunakan aliran data. (Dan juga, ketika saya memiliki masalah aliran data untuk lebih memilih solusi aliran data murni daripada yang melibatkan struktur kontrol *).
Jangan salah, diskusi tidak akan terjadi jika kesulitannya tidak sama: kondisinya sama dan ada di tempat yang sama.
Yang mana dari
dan
membuat struktur yang dimaksudkan lebih baik? Saya memberikan suara untuk yang pertama, Anda tidak perlu memeriksa bahwa kondisinya cocok. (Tapi lihat lekukan saya).
sumber
sementara (benar) dan istirahat adalah idiom yang umum. Ini adalah cara kanonik untuk menerapkan loop keluar-keluar dalam bahasa mirip-C. Menambahkan variabel untuk menyimpan kondisi keluar dan if () di sekitar paruh kedua loop adalah alternatif yang masuk akal. Beberapa toko mungkin secara resmi melakukan Standarisasi pada satu atau yang lain, tetapi tidak ada yang unggul; mereka setara.
Seorang programmer yang baik yang bekerja dalam bahasa-bahasa ini harus dapat mengetahui apa yang terjadi secara sekilas jika dia melihat salah satunya. Ini mungkin membuat pertanyaan wawancara kecil yang bagus; berikan seseorang dua loop, satu menggunakan setiap idiom, dan tanyakan kepada mereka apa perbedaannya (jawaban yang tepat: "tidak ada", dengan mungkin tambahan "tapi saya biasanya menggunakan satu itu.")
sumber
Alternatif Anda tidak seburuk yang Anda kira. Kode yang baik harus:
Tunjukkan dengan jelas dengan nama variabel yang baik / komentar dalam kondisi apa loop harus diakhiri. (Kondisi melanggar tidak harus disembunyikan)
Tunjukkan dengan jelas apa urutan operasi yang dilakukan. Di sinilah menempatkan operasi ke-3 opsional (
DoSomethingElseTo(input)
) di dalam if adalah ide yang bagus.Yang mengatakan, mudah untuk membiarkan naluri perfeksionis, pemoles kuningan menghabiskan banyak waktu. Saya hanya akan men-tweak jika seperti yang disebutkan di atas; komentar kode dan lanjutkan.
sumber
Orang-orang mengatakan itu adalah praktik yang buruk untuk digunakan
while (true)
, dan seringkali mereka benar. Jikawhile
pernyataan Anda mengandung banyak kode yang rumit dan tidak jelas kapan Anda keluar dari if, maka Anda dibiarkan dengan sulit untuk mempertahankan kode dan bug sederhana dapat menyebabkan loop tak terbatas.Dalam contoh Anda, Anda benar untuk digunakan
while(true)
karena kode Anda jelas dan mudah dipahami. Tidak ada gunanya membuat kode yang tidak efisien dan lebih sulit untuk dibaca, hanya karena beberapa orang menganggap itu selalu praktik yang buruk untuk digunakanwhile(true)
.Saya dihadapkan dengan masalah yang sama:
Menggunakan
do ... while(true)
menghindari yangisset($array][$key]
tidak perlu dipanggil dua kali, kode itu lebih pendek, lebih bersih, dan lebih mudah dibaca. Sama sekali tidak ada risiko bug loop tak terbatas diperkenalkan denganelse break;
di akhir.Sangat baik untuk mengikuti praktik yang baik dan menghindari praktik yang buruk tetapi selalu ada pengecualian dan penting untuk tetap berpikiran terbuka dan menyadari pengecualian itu.
sumber
Jika aliran kontrol tertentu secara alami dinyatakan sebagai pernyataan istirahat, pada dasarnya tidak pernah menjadi pilihan yang lebih baik untuk menggunakan mekanisme kontrol aliran lainnya untuk meniru pernyataan istirahat.
(perhatikan bahwa ini termasuk membuka sebagian loop dan menggeser badan loop ke bawah sehingga loop mulai bertepatan dengan uji kondisional)
Jika Anda dapat mengatur ulang loop Anda sehingga aliran kontrol diekspresikan secara alami dengan memiliki pemeriksaan bersyarat pada awal loop, bagus. Bahkan mungkin layak meluangkan waktu untuk memikirkan apakah itu mungkin. Tapi tidak, jangan mencoba memasukkan pasak persegi ke dalam lubang bundar.
sumber
Anda juga bisa menggunakan ini:
Atau kurang membingungkan:
sumber
Ketika kompleksitas logika menjadi sulit maka menggunakan loop tanpa batas dengan jeda putaran untuk kontrol aliran benar-benar masuk akal. Saya punya proyek dengan beberapa kode yang terlihat seperti berikut. (Perhatikan pengecualian di akhir loop.)
Untuk melakukan logika ini tanpa melanggar loop tanpa batas, saya akan berakhir dengan sesuatu seperti berikut:
Jadi pengecualian sekarang dilemparkan ke dalam metode pembantu. Juga memiliki banyak
if ... else
sarang. Saya tidak puas dengan pendekatan ini. Karena itu saya pikir pola pertama adalah yang terbaik.sumber