Apakah loop (sementara) benar-benar buruk? [Tutup]

218

Saya sudah pemrograman di Jawa selama beberapa tahun sekarang, tetapi saya baru saja kembali ke sekolah untuk mendapatkan gelar formal. Saya cukup terkejut mengetahui bahwa, pada tugas terakhir saya, saya kehilangan poin karena menggunakan loop seperti di bawah ini.

do{
     //get some input.
     //if the input meets my conditions, break;
     //Otherwise ask again.
} while(true)

Sekarang untuk pengujian saya, saya hanya memindai beberapa input konsol, tetapi saya diberitahu bahwa loop semacam ini tidak dianjurkan karena menggunakan breakmirip dengan goto, kami hanya tidak melakukannya.

Saya mengerti sepenuhnya perangkap gotodan sepupu Java-nya break:label, dan saya memiliki akal sehat untuk tidak menggunakannya. Saya juga menyadari bahwa program yang lebih lengkap akan memberikan cara lain untuk melarikan diri, misalnya untuk mengakhiri saja program tersebut, tetapi itu bukan alasan yang dikutip oleh profesor saya, jadi ...

Ada apa dengan ini do-while(true)?

JHarnach
sumber
23
Tanya guru Anda, hal-hal semacam itu cukup subjektif.
Chris Eberle
18
Saya merasa artikel ini bermanfaat untuk memahami apa yang berbahaya dari goto . Perbandingan dengan breakmungkin bermakna baik, tetapi sebenarnya disalahpahami. Mungkin Anda bisa mendidik profesor Anda tentang ini;) Dalam pengalaman saya, profesor tidak tahu banyak tentang keahlian pemrograman.
Magnus Hoff
100
Satu-satunya hal buruk yang tak terbantahkan tentang hal ini adalah dalam pikiran saya, fakta yang do {} while (true)setara while(true) {}dan yang terakhir sejauh ini merupakan bentuk yang lebih konvensional dan jauh lebih jelas.
Voo
11
Jika ada yang tidak menghargai kekuatan ekspresif sederhana break, mereka harus mencoba pemrograman dalam bahasa tanpa itu. Tidak perlu terlalu banyak loop sebelum Anda menginginkannya!
Steven
16
Saya tidak setuju dengan tag pekerjaan rumah.
aaaa bbbb

Jawaban:

220

Saya tidak akan mengatakan itu buruk - tetapi sama-sama biasanya saya setidaknya akan mencari alternatif.

Dalam situasi di mana ini adalah hal pertama yang saya tulis, saya hampir selalu setidaknya mencoba untuk mengubahnya menjadi sesuatu yang lebih jelas. Kadang-kadang itu tidak dapat membantu (atau alternatifnya adalah memiliki boolvariabel yang tidak melakukan apa pun yang berarti kecuali menunjukkan akhir dari loop, kurang jelas dari sebuah breakpernyataan) tetapi ada baiknya setidaknya mencoba.

Sebagai contoh penggunaan yang lebih jelas breakdaripada bendera, pertimbangkan:

while (true)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        break;
    }
    actOnInput(input);
}

Sekarang mari kita paksa untuk menggunakan bendera:

boolean running = true;
while (running)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        running = false;
    }
    else
    {
        actOnInput(input);
    }
}

Saya melihat yang terakhir sebagai lebih rumit untuk dibaca: ada elseblok tambahan , actOnInputlebih indentasi, dan jika Anda mencoba mencari tahu apa yang terjadi ketika testConditionkembali true, Anda perlu melihat dengan hati-hati melalui sisa blok untuk memeriksa bahwa ada bukan sesuatu setelah itu elseblok yang akan terjadi apakah runningtelah ditetapkan ke falseatau tidak.

The breakpernyataan berkomunikasi maksud lebih jelas, dan memungkinkan sisa blok melanjutkan apa yang perlu dilakukan tanpa khawatir tentang kondisi sebelumnya.

Perhatikan bahwa argumen ini persis sama dengan argumen yang dimiliki orang tentang beberapa pernyataan pengembalian dalam suatu metode. Sebagai contoh, jika saya dapat menentukan hasil metode dalam beberapa baris pertama (misalnya karena beberapa input adalah nol, atau kosong, atau nol) saya merasa lebih jelas untuk mengembalikan jawaban itu secara langsung daripada memiliki variabel untuk menyimpan hasilnya , lalu seluruh blok kode lain, dan akhirnya sebuah returnpernyataan.

Jon Skeet
sumber
3
Saya setuju itu bukan alat pertama yang saya raih, tapi sepertinya untuk mengurus masalah dengan sangat bersih, dan saya suka kode bersih.
JHarnach
3
@ X-Zero: Ya, kadang-kadang. Jika Anda dapat mengubah "istirahat" menjadi "kembali" itu sering kali baik ... meskipun Anda mungkin masih akan berakhir denganwhile (true)
Jon Skeet
21
@trutheality: Saya lebih suka sebagian besar kode saya menjadi tanpa pengindeksan mungkin. Dan kondisi dengan tugas majemuk terasa lebih rumit bagi saya.
Jon Skeet
3
@Vince: Ya, dan itu bagus jika Anda dapat mengekspresikan kondisi dengan mudah di awal loop . Tetapi kadang-kadang Anda tidak bisa - dan itulah situasi yang sedang kita bicarakan. Harap perhatikan beberapa kalimat pertama dari jawaban saya.
Jon Skeet
6
@Ismail: Saya harap tidak. Posting harus dinilai hanya berdasarkan kontennya, bukan pada penulisnya. Heck, saya bahkan akan downvote posting Eric Lippert jika saya merasa itu tidak akurat / tidak membantu. Tapi itu belum terjadi :)
Jon Skeet
100

AFAIK tidak ada, sungguh. Guru hanya alergi goto, karena mereka mendengar di suatu tempat itu sangat buruk. Kalau tidak, Anda hanya akan menulis:

bool guard = true;
do
{
   getInput();
   if (something)
     guard = false;
} while (guard)

Yang merupakan hal yang hampir sama.

Mungkin ini lebih bersih (karena semua info perulangan terdapat di bagian atas blok):

for (bool endLoop = false; !endLoop;)
{

}
El Marcel
sumber
4
Saya suka saran Anda karena kondisi terminating jauh lebih terlihat. Itu berarti ketika membaca kode Anda akan lebih cepat mendapatkan pemahaman tentang apa yang ingin dilakukan. Saya tidak akan pernah menggunakan infinite loop tetapi sering menggunakan dua versi Anda.
Kereta luncur
4
Konsensusnya adalah bahwa sebuah bendera lebih baik daripada merusak sebagian besar karena itu menyatakan niat? Saya bisa melihatnya bermanfaat. Semua jawaban solid, tapi saya akan menandainya sebagai diterima.
JHarnach
20
Kedua hal ini masih mengalami sisa loop yang tercemar (dalam beberapa situasi setidaknya) dengan harus terus ke ujung tubuh loop bahkan jika Anda tahu Anda melanggar . Saya akan memberikan contoh dalam jawaban saya ...
Jon Skeet
8
Saya suka jawaban Jon Skeet lebih baik. Juga, sementara (benar) {} JAUH lebih baik daripada melakukan {} sementara (benar)
aaaa bbbb
1
Saya benci bahwa Dijkstra pernah menulis artikel GoTo itu. Meskipun GoTo tentu saja sering disalahgunakan di masa lalu, bukan berarti Anda tidak boleh menggunakannya. Juga, Exit For, Break, Exit While, Try / Catch semua hanya bentuk khusus dari Goto. Foto seringkali dapat membuat kode lebih mudah dibaca. Dan ya saya sadar bahwa apa pun bisa dilakukan tanpa Goto. Itu tidak berarti seharusnya.
Kibbee
39

Douglas Crockford memiliki komentar tentang bagaimana ia berharap JavaScript mengandung loopstruktur:

loop
{
  ...code...
}

Dan saya tidak berpikir Java akan lebih buruk karena memiliki loopstruktur juga.

Tidak ada yang salah dengan while(true)loop, tapi ada adalah kecenderungan bagi guru untuk mencegah mereka. Dari perspektif pengajaran, sangat mudah untuk membuat siswa membuat loop tanpa akhir dan tidak mengerti mengapa loop tidak pernah lolos.

Tetapi apa yang jarang mereka sebutkan adalah bahwa semua mekanisme perulangan dapat direplikasi dengan while(true)loop.

while( a() )
{
  fn();
}

sama dengan

loop
{
  if ( !a() ) break;
  fn();
}

dan

do
{
  fn();
} while( a() );

sama dengan:

loop
{
  fn();
  if ( !a() ) break;
}

dan

for ( a(); b(); c() )
{
  fn();
}

sama dengan:

a();
loop
{
  if ( !b() ) break;
  fn();
  c();
}

Selama Anda dapat mengatur loop Anda dengan cara yang bekerja membangun yang Anda pilih untuk digunakan tidak penting. Jika kebetulan pas dalam satu forlingkaran, gunakan satu forlingkaran.

Satu bagian terakhir: jaga agar loop Anda tetap sederhana. Jika ada banyak fungsi yang perlu terjadi pada setiap iterasi, letakkan di fungsi. Anda selalu dapat mengoptimalkannya setelah berhasil.

zzzzBov
sumber
2
+1: Ada kerumitan tambahan dengan forloop ketika continuepernyataan dilibatkan, tetapi itu bukan ekstensi utama.
Donal Fellows
Saya biasanya menggunakan for for ketika ada urutan yang ingin saya jalankan, dan beberapa saat ketika ada kondisi yang ingin saya temui. Ini membuat kode imo lebih terbaca.
dascandy
4
Apakah tidak ada yang menulis for (;;) {lagi? (Diucapkan "selamanya"). Ini dulunya sangat populer.
Dawood ibn Kareem
16

Kembali pada tahun 1967, Edgar Dijkstra menulis sebuah artikel di majalah perdagangan tentang mengapa goto harus dihilangkan dari bahasa tingkat tinggi untuk meningkatkan kualitas kode. Paradigma pemrograman keseluruhan yang disebut "pemrograman terstruktur" keluar dari ini, meskipun tentu tidak semua orang setuju bahwa goto secara otomatis berarti kode yang buruk.

Inti dari pemrograman terstruktur pada dasarnya adalah bahwa struktur kode harus menentukan alirannya daripada memiliki gotos atau istirahat atau terus menentukan aliran, sedapat mungkin. Demikian pula, memiliki beberapa titik masuk dan keluar ke loop atau fungsi juga tidak disarankan dalam paradigma itu.

Jelas ini bukan satu-satunya paradigma pemrograman, tetapi seringkali dapat dengan mudah diterapkan pada paradigma lain seperti pemrograman berorientasi objek (ala Java).

Guru-guru Anda mungkin telah diajar, dan sedang berusaha mengajar kelas Anda bahwa kami sebaiknya menghindari "kode spageti" dengan memastikan kode kami terstruktur, dan mengikuti aturan tersirat pemrograman terstruktur.

Sementara tidak ada yang secara inheren "salah" dengan implementasi yang menggunakan break, beberapa menganggapnya lebih mudah untuk membaca kode di mana kondisi untuk loop secara eksplisit ditentukan dalam kondisi while (), dan menghilangkan beberapa kemungkinan menjadi terlalu rumit. Pasti ada jebakan untuk menggunakan kondisi sementara (benar) yang tampaknya sering muncul dalam kode oleh programmer pemula, seperti risiko tidak sengaja membuat loop tak terbatas, atau membuat kode yang sulit dibaca atau membingungkan.

Ironisnya, penanganan pengecualian adalah area di mana penyimpangan dari pemrograman terstruktur pasti akan muncul dan diharapkan saat Anda masuk lebih jauh ke pemrograman di Jawa.

Mungkin juga instruktur Anda mungkin mengharapkan Anda untuk mendemonstrasikan kemampuan Anda untuk menggunakan struktur lingkaran atau sintaksis tertentu yang diajarkan dalam bab atau pelajaran teks Anda, dan sementara kode yang Anda tulis setara secara fungsional, Anda mungkin tidak menunjukkan keterampilan khusus yang seharusnya Anda pelajari dalam pelajaran itu.

Jessica Brown
sumber
2
Ini adalah makalah Edsger Dijkstra . Ini bacaan yang bagus.
Roy Prins
14

Konvensi Java ususal untuk input bacaan adalah:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String strLine;

while ((strLine = br.readLine()) != null) {
  // do something with the line
}

Dan konvensi C ++ biasa untuk membaca input adalah:

#include <iostream>
#include <string>
std::string data;
while(std::readline(std::cin, data)) {
  // do something with the line
}

Dan di C, itu

#include <stdio.h>
char* buffer = NULL;
size_t buffer_size;
size_t size_read;
while( (size_read = getline(&buffer, &buffer_size, stdin)) != -1 ){
  // do something with the line
}
free(buffer);

atau jika Anda yakin tahu berapa lama baris teks terpanjang dalam file Anda, Anda bisa melakukannya

#include <stdio.h>
char buffer[BUF_SIZE];
while (fgets(buffer, BUF_SIZE, stdin)) {
  //do something with the line
}

Jika Anda menguji untuk melihat apakah pengguna Anda memasukkan quitperintah, mudah untuk memperpanjang salah satu dari 3 struktur loop ini. Saya akan melakukannya di Jawa untuk Anda:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;

while ((line = br.readLine()) != null  && !line.equals("quit") ) {
  // do something with the line
}

Jadi, walaupun pasti ada kasus-kasus di mana breakatau gotodibenarkan, jika semua yang Anda lakukan adalah membaca dari file atau konsol baris demi baris, maka Anda seharusnya tidak perlu while (true)loop untuk mencapainya - bahasa pemrograman Anda telah menyediakan Anda dengan idiom yang sesuai untuk menggunakan perintah input sebagai kondisi loop.

Ken Bloom
sumber
Faktanya, jika Anda menggunakan while (true)loop alih-alih salah satu dari loop input konvensional ini, Anda mungkin lupa memeriksa akhir file.
Ken Bloom
3
Anda menyelesaikan ini secara efektif dengan memasukkan bagian pertama dari loop ke whilekondisional. Pada kondisi Java terakhir sudah cukup lumayan, dan jika Anda harus melakukan manipulasi yang luas untuk memutuskan apakah akan melanjutkan atau tidak, mungkin akan cukup lama. Anda bisa membaginya menjadi fungsi terpisah, dan itu mungkin yang terbaik. Tetapi jika Anda menginginkannya dalam satu fungsi, dan ada pekerjaan yang tidak perlu dilakukan sebelum memutuskan apakah akan melanjutkan, while(true)mungkin yang terbaik.
poolie
@poolie: Maka mungkin lebih baik menggunakan perintah read sebagai kondisi loop (yang memeriksa EOF), dan memeriksa kondisi Anda yang lain di dalam loop sebagai pernyataan break.
Ken Bloom
1
Untuk apa nilainya, gets()bukan konvensi umum. Sangat kondusif untuk buffer overflows. fgets(buffer, BUFFER_SIZE, file)jauh lebih seperti praktik standar.
Dave
@ Dave: Sekarang saya sudah mengedit jawaban untuk digunakan fgets.
Ken Bloom
12

Ini bukan hal yang mengerikan, tetapi Anda harus mempertimbangkan pengembang lain saat melakukan pengkodean. Bahkan di sekolah.

Rekan pengembang Anda harus dapat melihat klausa keluar untuk loop Anda, pada deklarasi loop. Kamu tidak melakukan itu. Anda menyembunyikan klausa keluar di tengah-tengah loop, membuat lebih banyak pekerjaan untuk orang lain yang datang dan mencoba memahami kode Anda. Ini adalah alasan yang sama sehingga hal-hal seperti "istirahat" dihindari.

Yang sedang berkata, Anda masih akan melihat hal-hal seperti ini dalam BANYAK kode di dunia nyata.

rfeak
sumber
4
Jika loop dimulai dengan while (true)cukup jelas bahwa akan ada breakatau returndi dalamnya, atau itu akan berjalan selamanya. Menjadi jujur ​​itu penting, tetapi while(true)tidak terlalu buruk dengan sendirinya. Variabel yang memiliki invarian kompleks melintasi iterasi loop akan menjadi contoh dari sesuatu yang menyebabkan lebih banyak kecemasan.
poolie
4
Coba masuk tiga level dalam pencarian dan kemudian keluar. Kode ini akan menjadi jauh lebih buruk jika Anda tidak hanya kembali dari titik itu.
dascandy
11

Ini pistol Anda, peluru dan kaki Anda ...

Itu buruk karena Anda meminta masalah. Bukan Anda atau poster lain di halaman ini yang memiliki contoh loop pendek / sederhana.

Masalahnya akan mulai pada waktu yang sangat acak di masa depan. Mungkin disebabkan oleh programmer lain. Mungkin orang yang menginstal perangkat lunak. Mungkin pengguna akhir.

Mengapa? Saya harus mencari tahu mengapa aplikasi 700K LOC secara bertahap akan mulai membakar 100% dari waktu CPU sampai setiap CPU jenuh. Itu adalah loop while (true) yang menakjubkan. Itu besar dan menjijikkan, tetapi akhirnya menjadi:

x = read_value_from_database()
while (true) 
 if (x == 1)
  ...
  break;
 else if (x ==2)
  ...
  break;
and lots more else if conditions
}

Tidak ada cabang final lain. Jika nilai tidak cocok dengan kondisi if, loop terus berjalan hingga akhir waktu.

Tentu saja, programmer menyalahkan pengguna akhir karena tidak memilih nilai yang diharapkan oleh programmer. (Saya kemudian menghapus semua instance while (true) dalam kode.)

IMHO itu bukan pemrograman defensif yang baik untuk menggunakan konstruksi seperti while (true). Itu akan kembali menghantui Anda.

(Tapi saya ingat profesor menilai jika kita tidak berkomentar setiap baris, bahkan untuk i ++;)

jqa
sumber
3
+1 untuk komentar tentang pemrograman defensif.
JHarnach
3
Dalam contoh Anda, kode itu bodoh bukan karena pilihan sementara (benar) tetapi karena gagasan meletakkan lingkaran di sekitar kode.
Florian F
Memang, apa gunanya loop itu? :)
juzzlin
6

Ini buruk dalam arti bahwa konstruksi pemrograman terstruktur lebih disukai daripada (yang agak tidak terstruktur) istirahat dan melanjutkan pernyataan. Sebagai perbandingan, mereka lebih disukai daripada "kebagian" menurut prinsip ini.

Saya selalu merekomendasikan untuk membuat kode Anda terstruktur mungkin ... meskipun, seperti yang ditunjukkan Jon Skeet, jangan membuatnya lebih terstruktur daripada itu!

Patrick87
sumber
5

Menurut pengalaman saya dalam banyak kasus, loop memiliki kondisi "utama" untuk melanjutkan. Ini adalah kondisi yang harus ditulis ke dalam () operator itu sendiri. Semua kondisi lain yang dapat memutus loop adalah sekunder, tidak begitu penting dll. Mereka dapat ditulis sebagai if() {break}pernyataan tambahan .

while(true) sering membingungkan dan kurang bisa dibaca.

Saya pikir aturan-aturan ini tidak mencakup 100% kasus tetapi mungkin hanya 98%.

AlexR
sumber
Kata baik. Ini seperti menggunakan loop untuk melakukan dengan: while (true) {i ++; ...}. Anda mengubur kondisi loop di dalam loop daripada di 'tanda tangan'.
LegendLength
3

Meskipun tidak selalu merupakan jawaban mengapa tidak menggunakan while (true), saya selalu menemukan komik ini dan menyertai pernyataan penulis penjelasan singkat tentang mengapa melakukan sementara bukan melakukan-saat.

Sehubungan dengan pertanyaan Anda: Tidak ada masalah yang melekat dengannya

while(true) {
   do_stuff();
   if(exit_time) {
      break;
   }
}

... jika Anda tahu apa yang Anda lakukan dan memastikan bahwa exit_timepada titik tertentu akan dievaluasi true.

Guru mencegah Anda menggunakan while(true)karena sampai dan kecuali Anda pada titik yang Anda tahu persis apa yang Anda lakukan, itu adalah cara mudah untuk membuat kesalahan kritis.

Shadur
sumber
Saya pikir pengaturan exit_time = false; while(!exit_time) { execute_stuff(); }dan do { execute_stuff(); } while(! exit_time );keduanya lebih jelas daripada memiliki if( condition ) { break; }di akhir loop dengan a while(true). Istirahat adalah hubung singkat untuk loop - baik-baik saja bila digunakan sebagai hubung singkat di tengah-tengah loop, tetapi Anda hanya harus mengevaluasi suatu kondisi dalam pernyataan sementara vs memiliki istirahat di akhir loop.
dr jimbob
Berkenaan dengan komik itu: sementara do-while tidak bisa melakukan semua itu selagi bisa lakukan, do-while kadang-kadang lebih baik melakukan apa yang do-while bisa lakukan walaupun itu bisa juga dilakukan.
Theraot
3

Anda mungkin hanya menggunakan bendera Boolean untuk menunjukkan kapan harus mengakhiri loop while. Breakdan go toalasan mengapa perangkat lunak sulit dipertahankan - krisis perangkat lunak (tm) - dan harus dihindari, dan bisa juga mudah.

Ini pertanyaan apakah Anda pragmatis atau tidak. Coders pragmatis mungkin hanya menggunakan break dalam situasi sederhana itu.

Tapi itu baik untuk mendapatkan kebiasaan untuk tidak menggunakannya, jika tidak, Anda dapat menggunakannya dari kebiasaan dalam situasi yang tidak cocok, seperti dalam loop bersarang rumit di mana keterbacaan dan pemeliharaan kode Anda menjadi lebih sulit dengan menggunakan break.

Daniel Leschkowski
sumber
8
Karena menjaga bendera boolean mungkin tidak lebih jelas, dan mungkin kurang jelas, menurut pengalaman saya?
Jon Skeet
3
@ Jon Skeet Yah itu pertanyaan tentang pergi dengan kebiasaan baik atau melatih diri sendiri yang buruk dengan menggunakan istirahat. Bangku yang disebut "berlari" tidak jelas bagi Anda? Ini jelas, mudah di-debug, dan seperti yang saya sebutkan sebelumnya habbit yang baik adalah hal yang baik untuk dijaga. Dimana masalahnya?
Daniel Leschkowski
4
Sebuah bool disebut berjalan yang kemudian mengharuskan saya untuk memiliki if (running)dalam loop, indentasi semua sisa kode ketika semua yang saya inginkan adalah untuk keluar loop pasti kurang jelas bagi saya daripada pernyataan break sederhana yang menyatakan persis apa yang saya inginkan lakukan. Anda tampaknya mempertimbangkan menggunakan istirahat sebagai kebiasaan buruk secara aksiomatis - saya tidak menganggapnya sebagai kebiasaan buruk .
Jon Skeet
2
Mengapa Anda memiliki if (running) di dalam loop? Seperti halnya break pada akhir loop Anda memeriksa apakah Anda ingin break dan membalikkan flag alih-alih menggunakan break dan menggunakan flag in while (running) alih-alih while (true). Saya tidak mengerti maksud Anda, serius. Saya setuju bahwa pembuat kode pragmatis mungkin menggunakan break dalam situasi tertentu, tetapi saya benar-benar tidak mendapatkan komentar yang Anda buat di bawah saran saya
Daniel Leschkowski
3
Anda menganggap Anda tidak perlu melakukan apa pun di dalam loop setelah Anda menentukan apakah akan berhenti atau tidak. Misalnya, dalam situasi OP dia perlu meminta lebih banyak input jika dia tidak berhenti.
Jon Skeet
3

Mungkin saya kurang beruntung. Atau mungkin saya hanya kurang pengalaman. Tetapi setiap kali saya ingat berurusan dengan while(true)memiliki breakdi dalam, adalah mungkin untuk meningkatkan kode menerapkan Metode Ekstrak ke -blok sementara , yang membuat while(true)tetapi (secara kebetulan?) Mengubah semua breaks menjadi returns.

Dalam pengalaman saya while(true)tanpa istirahat (yaitu dengan pengembalian atau lemparan) cukup nyaman dan mudah dimengerti.


  void handleInput() {
      while (true) {
          final Input input = getSomeInput();
          if (input == null) {
              throw new BadInputException("can't handle null input");
          }
          if (input.isPoisonPill()) {
              return;
          }
          doSomething(input);
      }
  }
agas
sumber
3

Saya pikir ya itu sangat buruk ... atau setidaknya, bagi banyak pengembang. Ini adalah gejala dari pengembang yang tidak memikirkan kondisi loop mereka. Akibatnya ada kesalahan rawan.

Griff Sob Becker
sumber
2

Tidak ada masalah besar while(true)dengan breakpernyataan, namun beberapa orang mungkin berpikir itu sedikit menurunkan keterbacaan kode. Cobalah untuk memberikan variabel nama yang bermakna, mengevaluasi ekspresi di tempat yang tepat.

Sebagai contoh Anda, tampaknya lebih jelas untuk melakukan sesuatu seperti:

do {
   input = get_input();
   valid = check_input_validity(input);    
} while(! valid)

Ini terutama benar jika loop do while menjadi panjang - Anda tahu persis di mana centang untuk melihat apakah ada iterasi tambahan yang terjadi. Semua variabel / fungsi memiliki nama yang sesuai di tingkat abstraksi. The while(true)pernyataan tidak adalah memberitahu Anda pengolahan yang tidak di tempat yang Anda pikir.

Mungkin Anda ingin output yang berbeda pada kali kedua melalui loop. Sesuatu seperti

input = get_input();
while(input_is_not_valid(input)) {
    disp_msg_invalid_input();
    input = get_input();
}

sepertinya lebih mudah dibaca oleh saya

do {
    input = get_input();
    if (input_is_valid(input)) {
        break;
    }
    disp_msg_invalid_input();
} while(true);

Sekali lagi, dengan contoh sepele keduanya cukup mudah dibaca; tetapi jika loop menjadi sangat besar atau sangat bersarang (yang berarti Anda mungkin seharusnya sudah refactored), gaya pertama mungkin sedikit lebih jelas.

dr jimbob
sumber
1

Saya menggunakan sesuatu yang serupa, tetapi dengan logika yang berlawanan, dalam banyak fungsi saya.

DWORD dwError = ERROR_SUCCESS;

do
{
    if ( (dwError = SomeFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }

    if ( (dwError = SomeOtherFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }
}
while ( 0 );

if ( dwError != ERROR_SUCCESS )
{
    /* resource cleanup */
}
Jim Fell
sumber
1

Ini lebih merupakan hal estetika, lebih mudah untuk membaca kode di mana Anda secara eksplisit tahu mengapa loop akan berhenti tepat di deklarasi loop.

Petey B
sumber
1

Saya akan mengatakan bahwa secara umum alasan itu tidak dianggap ide yang baik adalah bahwa Anda tidak menggunakan konstruk untuk potensi penuh itu. Juga, saya cenderung berpikir bahwa banyak instruktur pemrograman tidak suka ketika siswa mereka datang dengan "bagasi". Maksud saya, saya pikir mereka suka menjadi pengaruh utama pada gaya pemrograman siswa mereka. Jadi mungkin itu hanya kesal dari instruktur.

Paul
sumber
1

Bagi saya, masalahnya adalah keterbacaan.

Pernyataan sementara dengan kondisi sebenarnya tidak memberi tahu Anda tentang loop. Itu membuat pekerjaan memahaminya jauh lebih sulit.

Apa yang akan lebih mudah dipahami dari kedua cuplikan ini?

do {
  // Imagine a nice chunk of code here
} while(true);

do {
  // Imagine a nice chunk of code here
} while(price < priceAllowedForDiscount);
Vince Panuccio
sumber
0

Saya kira menggunakan istirahat untuk guru Anda seperti mematahkan sebatang pohon untuk mendapatkan buah, menggunakan beberapa trik lain (membungkuk cabang) sehingga Anda mendapatkan buah dan cabang masih hidup. :)

Bimal Sharma
sumber
0

1) Tidak ada yang salah dengan a do -while(true)

2) Guru Anda salah.

NSFS !!:

3) Kebanyakan guru adalah guru dan bukan programmer.

Pacerier
sumber
@Connell, tunggu sampai gurumu mendengar itu!
Pacerier
1
Saya belajar sendiri di depan pemrograman. Yang harus saya putuskan adalah guru TI saya di sekolah menengah, yang mengajari kami membuat situs web menggunakan Dreamweaver sedemikian rupa sehingga SEMUA yang merupakan posisi yang benar-benar diposisikan ...
Connell
@Connell posting saya untuk menunjukkan persetujuan Anda
Pacerier
2
"Mereka yang tidak bisa, mengajar." - Itu generalisasi yang cukup besar bukan? Haruskah dokter, insinyur, pilot, dll semua belajar sendiri karena instruktur mereka tidak kompeten menurut Anda?
filip-fku
@ filip-fku wow wow ~ cool it cool it!
Pacerier
0

Mungkin buruk jika loop Anda berjalan di utas latar belakang, jadi ketika Anda menutup aplikasi Anda dengan mengakhiri utas UI, potongan kode itu akan terus dijalankan. Seperti yang sudah dikatakan orang lain, Anda harus selalu menggunakan semacam cek untuk memberikan cara pembatalan.

Dmitry
sumber