goto
hampir secara universal putus asa. Apakah menggunakan pernyataan ini bermanfaat?
goto
programming-practices
Casebash
sumber
sumber
goto
adalah apa yang cpu akhirnya lakukan, tetapi tidak bekerja dengan baik dengan apa yang manusia perlu pahami dan abstrak karena tidak ada tanda pada ujung target. Bandingkan dengan IntercalCOMEFROM
.goto
tidak diperlukan. Ini hanyalah cara paling rasional untuk mengimplementasikannya dalam bahasa imperatif, karena ini adalah hal yang paling dekat dengan semantik transisi negara. Dan tujuannya bisa sangat jauh dari sumbernya, tidak akan menghalangi keterbacaan. Contoh favorit saya dari kode semacam itu adalah implementasi game DE Adventure dari Knuth.Jawaban:
Ini telah dibahas beberapa kali di Stack Overflow, dan Chris Gillum merangkum kemungkinan penggunaan
goto
:Saya berpendapat, seperti banyak orang lain akan berpendapat, bahwa dalam semua kasus ini, penggunaan
goto
digunakan sebagai sarana untuk keluar dari sudut satu kode ke diri sendiri, dan umumnya merupakan gejala kode yang bisa dire-refored.sumber
finally
blok dalam bahasa modern, dan yang kedua diselesaikan dengan labelbreak
s. Namun, jika Anda terjebak dengan C,goto
cukup satu-satunya cara untuk menyelesaikan masalah ini dengan elegan.finally
hanya valid dalam kondisi tersebut. Ada situasi yang sangat jarang namun valid di mana goto adalah cara untuk pergi.break 3
ataubreak myLabel
dangoto myLabel
. Oh itu benar hanya kata kunci. Jika Anda menggunakanbreak
,continue
atau kata kunci serupa yang Anda gunakan menggunakangoto
(Jika Anda menggunakanfor, while, foreach, do/loop
Anda menggunakan goto bersyarat.)Konstruksi aliran kontrol level yang lebih tinggi cenderung sesuai dengan konsep dalam domain masalah. If / else adalah keputusan berdasarkan beberapa kondisi. Loop mengatakan untuk melakukan beberapa tindakan berulang kali. Bahkan pernyataan break mengatakan "kami melakukan ini berulang kali, tapi sekarang kami harus berhenti".
Pernyataan goto, di sisi lain, cenderung sesuai dengan konsep dalam program yang sedang berjalan, bukan dalam domain masalah. Dikatakan untuk melanjutkan eksekusi pada titik tertentu dalam program . Seseorang yang membaca kode harus menyimpulkan apa artinya sehubungan dengan domain masalah.
Tentu saja semua konstruksi tingkat yang lebih tinggi dapat didefinisikan dalam hal gotos dan cabang kondisional sederhana. Itu tidak berarti bahwa mereka hanya goto yang menyamar. Pikirkan mereka sebagai goto yang dibatasi - dan pembatasanlah yang membuatnya bermanfaat. Pernyataan break diimplementasikan sebagai lompatan ke ujung loop tertutup, tetapi lebih baik dianggap beroperasi pada loop secara keseluruhan.
Semua yang lain dianggap sama, kode yang strukturnya mencerminkan bahwa dari domain masalah cenderung lebih mudah dibaca dan dipelihara.
Tidak ada kasus di mana pernyataan goto mutlak diperlukan (ada teorema untuk efek itu), tetapi ada kasus di mana itu bisa menjadi solusi yang paling buruk. Kasing tersebut bervariasi dari satu bahasa ke bahasa lain, tergantung pada tingkat konstruksi apa yang didukung oleh bahasa tersebut.
Di C, misalnya, saya percaya ada tiga skenario dasar di mana goto sesuai.
Di sisi lain, mesin negara hingga eksplisit juga dapat diimplementasikan dengan pernyataan switch di dalam loop. Ini memiliki keuntungan bahwa setiap negara mulai di tempat yang sama dalam kode, yang dapat berguna untuk debugging, misalnya.
Penggunaan utama goto dalam bahasa modern yang cukup (yang mendukung jika / else dan loop) adalah untuk mensimulasikan konstruksi aliran kontrol yang hilang dari bahasa.
sumber
goto
. SSSM sering merupakan struktur yang baik untuk digunakan, karena mereka memisahkan negara SM dari konstruk eksekusi, tetapi mereka tidak benar-benar menghilangkan "gotos".Tentunya itu tergantung pada bahasa pemrogramannya. Alasan utama
goto
telah menjadi kontroversial adalah karena efek buruknya yang muncul ketika kompiler memungkinkan Anda menggunakannya terlalu bebas. Masalah dapat timbul, misalnya, jika memungkinkan Anda menggunakangoto
sedemikian rupa sehingga Anda sekarang dapat mengakses variabel yang tidak diinisialisasi, atau lebih buruk, untuk melompat ke metode lain dan mengacaukan dengan tumpukan panggilan. Seharusnya menjadi tanggung jawab kompiler untuk melarang aliran kontrol yang tidak masuk akal.Java telah berusaha untuk "memecahkan" masalah ini dengan menolak
goto
sepenuhnya. Namun, Java memungkinkan Anda menggunakanreturn
di dalamfinally
blok dan dengan demikian menyebabkan pengecualian tertelan secara tidak sengaja. Masalah yang sama masih ada: kompiler tidak melakukan tugasnya. Menghapusgoto
dari bahasa belum memperbaikinya.Dalam C #,
goto
seamanbreak
,continue
,try/catch/finally
danreturn
. Itu tidak membiarkan Anda menggunakan variabel yang tidak diinisialisasi, itu tidak membiarkan Anda melompat keluar dari blok akhirnya, dll. Kompiler akan mengeluh. Ini karena itu memecahkan masalah nyata , yang seperti saya katakan aliran kontrol tidak masuk akal.goto
tidak secara ajaib membatalkan analisis penugasan tertentu dan pengecekan wajar lainnya.sumber
goto
tidak jahat? Jika demikian, itu adalah kasus untuk setiap bahasa modern yang digunakan secara rutin dengan sebuahgoto
konstruk, tidak hanya C # ...Iya nih. Ketika loop Anda bersarang dalam beberapa level,
goto
adalah satu - satunya cara untuk melepaskan loop dalam secara elegan. Opsi lainnya adalah mengatur bendera dan keluar dari setiap loop jika bendera itu memenuhi syarat. Ini benar-benar jelek, dan sangat rentan kesalahan. Dalam kasus ini,goto
lebih baik.Tentu saja,
break
pernyataan berlabel Java melakukan hal yang sama, tetapi tanpa memungkinkan Anda untuk melompat ke titik sembarang dalam kode, yang menyelesaikan masalah dengan rapi tanpa membiarkan hal-hal yang membuatgoto
kejahatan.sumber
Do
loop. Mengapa? Karena saya dapat mengubah satu loop yang membutuhkan terobosan dalam menjadiDo
loop dan ketikExit Do
dan tidak adaGoTo
. Loop bersarang terjadi sepanjang waktu. Melanggar tumpukan terjadi beberapa% dari waktu.Keputusasaan yang paling besar datang dari semacam "agama" yang telah diciptakan oleh Dewa Djikstra yang memaksa pada awal tahun 60an tentang kekuatannya yang membabi buta untuk:
Ini tidak ada hubungannya dengan
goto
pernyataan bahasa modern, yang keberadaannya semata-mata karena mendukung penciptaan struktur kode selain dari bahasa yang disediakan.Khususnya, titik utama pertama di atas diizinkan dan yang kedua dibersihkan (jika Anda
goto
keluar dari blok tumpukan dilepaskan dengan benar dan semua penghancur yang tepat dipanggil)Anda dapat merujuk jawaban ini untuk mengetahui bagaimana bahkan kode yang tidak menggunakan goto dapat dibaca. Masalahnya bukan goto itu sendiri, tetapi penggunaannya yang buruk.
Saya dapat menulis seluruh program tanpa menggunakan
if
, hanyafor
. Tentu saja, itu tidak akan mudah dibaca, terlihat canggung dan tidak perlu rumit.Tapi masalahnya bukan
for
. Ini aku.Hal suka
break
,continue
,throw
,bool needed=true; while(needed) {...}
, dll mencatat lebih dari masqueradegoto
untuk melarikan diri jauh dari pedang dari fanatik Djikstrarian, bahwa -50 tahun setelah penemuan laguages- modern yang masih ingin tawanan mereka. Mereka lupa apa yang dibicarakan Djikstra, mereka hanya ingat judul catatannya (GOTO dianggap berbahaya, dan itu bahkan bukan judulnya sendiri: itu diubah oleh editor) dan menyalahkan dan bash, bash dan menyalahkan setiap konstruksi yang memiliki 4 surat ditempatkan secara berurutan.Ini tahun 2011: saatnya untuk memahami bahwa
goto
tidak perlu berurusan denganGOTO
pernyataan yang Djikstra tuntut.sumber
break n
tidak tersedia di C ++, karenanyagoto escape
, bahkan jikaescape
tidak diharuskan untuk keluar dari loop n-ple.Goto aneh di sini atau di sana, selama itu lokal untuk suatu fungsi, jarang secara signifikan merusak keterbacaan. Seringkali manfaat dengan menarik perhatian pada fakta bahwa ada sesuatu yang tidak biasa terjadi dalam kode ini yang memerlukan penggunaan struktur kontrol yang agak tidak biasa.
Jika goto (lokal) secara signifikan merusak keterbacaan, maka itu biasanya merupakan tanda bahwa fungsi yang mengandung goto menjadi terlalu kompleks.
Goto terakhir yang saya masukkan ke dalam sepotong kode C adalah membangun sepasang loop yang saling terkait. Ini tidak sesuai dengan definisi normal penggunaan goto "dapat diterima", tetapi fungsi tersebut berakhir secara signifikan lebih kecil dan lebih jelas. Untuk menghindari kebotakan akan membutuhkan pelanggaran DRY yang sangat berantakan.
sumber
Saya pikir seluruh masalah ini adalah kasus menggonggong pohon yang salah.
GOTO seperti itu tampaknya tidak bermasalah bagi saya, tetapi itu lebih sering merupakan gejala dari dosa yang sebenarnya: kode spaghetti.
Jika GOTO menyebabkan persimpangan besar garis kontrol aliran maka itu buruk, titik. Jika tidak ada garis kontrol aliran, itu tidak berbahaya. Di zona abu-abu di antara kami memiliki hal-hal seperti bailout lingkaran, masih ada beberapa bahasa yang belum menambahkan konstruksi yang mencakup semua kasus abu-abu yang sah.
Satu-satunya kasus saya menemukan diri saya benar-benar menggunakannya dalam beberapa tahun adalah kasus loop di mana titik keputusan berada di tengah-tengah loop. Anda memiliki kode duplikat, bendera, atau GOTO. Saya menemukan solusi GOTO yang terbaik dari ketiganya. Tidak ada persimpangan jalur kontrol aliran di sini, tidak berbahaya.
sumber
goto
s yang melompat ke dalam loop (jika bahasa memungkinkan ini; karena kasus lain, melompat keluar dari loop di tengah, biasanya sepele tanpagoto
).goto
berteriak ALIRAN PENGENDALIAN DI SINI TIDAK SESUAI DENGAN POLA PEMROGRAMAN TERSTRUKTUR NORMAL . Karena aliran kontrol yang sesuai dengan pola pemrograman terstruktur lebih mudah untuk dipikirkan daripada yang tidak, orang harus berusaha menggunakan pola tersebut jika memungkinkan; jika kode cocok dengan pola seperti itu, orang tidak boleh berteriak bahwa itu tidak. Di sisi lain, dalam kasus-kasus di mana kode benar-benar tidak cocok dengan pola-pola seperti itu, berteriak tentang itu mungkin lebih baik daripada berpura-pura kode cocok ketika sebenarnya tidak.Ya, goto dapat digunakan untuk memberi manfaat pada pengalaman pengembang: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
Namun, seperti halnya alat yang ampuh (pointer, multiple inheritance, dll.), Seseorang harus disiplin menggunakannya. Contoh yang disediakan dalam tautan menggunakan PHP, yang membatasi penggunaan konstruksi goto ke fungsi / metode yang sama dan menonaktifkan kemampuan untuk melompat ke blok kontrol baru (misalnya, loop, pernyataan switch, dll.)
sumber
Tergantung pada bahasanya. Ini masih banyak digunakan dalam pemrograman Cobol, misalnya. Saya juga bekerja pada perangkat Barionet 50, yang bahasa pemrograman firmware-nya adalah dialek BASIC awal yang tentu saja mengharuskan Anda untuk menggunakan Goto.
sumber
Saya akan mengatakan tidak. Jika Anda merasa perlu menggunakan GOTO, saya berani bertaruh bahwa ada kebutuhan untuk mendesain ulang kode.
sumber
goto
mungkin berguna saat memindahkan kode assembler lawas ke C. Pada contoh pertama, konversi instruksi-demi-instruksi ke C, menggunakangoto
sebagai pengganti untukbranch
instruksi assembler , dapat memungkinkan porting yang sangat cepat.sumber
Saya berpendapat tidak. Mereka harus selalu diganti dengan alat yang lebih spesifik untuk masalah goto sedang digunakan untuk menyelesaikan (kecuali itu tidak tersedia dalam bahasa Anda). Sebagai contoh, break statemen dan pengecualian memecahkan masalah yang sebelumnya diselesaikan dengan kebohongan loop melarikan diri dan penanganan kesalahan.
sumber
goto
biasanya tidak ada bahasa tersebut.goto
hal yang paling dekat dengan semantik domain yang sangat bermasalah, yang lain akan menjadi hack kotor.