Pada titik mana tabu memiliki loop di dalam loop?

23

Hanya penasaran. Yang paling saya miliki adalah for for loop for for loop, karena setelah membaca ini dari Linus Torvalds:

Tab adalah 8 karakter, dan dengan demikian lekukan juga 8 karakter. Ada gerakan sesat yang mencoba membuat lekukan dalam 4 (atau bahkan 2!) Karakter, dan itu mirip dengan mencoba mendefinisikan nilai PI menjadi 3.

Dasar Pemikiran: Seluruh ide di balik lekukan adalah untuk secara jelas menentukan di mana blok kontrol dimulai dan berakhir. Terutama ketika Anda telah melihat layar selama 20 jam berturut-turut, Anda akan lebih mudah melihat bagaimana lekukan bekerja jika Anda memiliki lekukan besar.

Sekarang, beberapa orang akan mengklaim bahwa memiliki lekukan 8 karakter membuat kode bergerak terlalu jauh ke kanan, dan membuatnya sulit dibaca pada layar terminal 80 karakter. Jawabannya adalah bahwa jika Anda memerlukan lebih dari 3 level indentasi, Anda tetap kacau, dan harus memperbaiki program Anda.

https://www.kernel.org/doc/Documentation/CodingStyle

Saya pikir itu adalah praktik yang tidak dapat diterima bagi saya untuk pergi ke lapisan ketiga perulangan, dan akan merestrukturisasi kode saya (Terutama Qt).

Apakah Linus bercanda?

Apakah ini tergantung pada bahasa atau aplikasi?

Apakah ada beberapa hal yang benar-benar membutuhkan tiga atau lebih tingkat pengulangan?

Akiva
sumber
8
Saya bingung mengapa Anda melompat dari indentasi ke level perulangan? Anda memiliki kutipan besar yang membahas lekukan dan tiba-tiba muncul pertanyaan tentang loop bersarang.
Pieter B
5
Linus mungkin bukan (hanya) bercanda di bagian itu, tetapi perhatikan bahwa ini hanya satu panduan gaya, dan panduan gaya yang sama menekankan bahwa "Gaya pengkodean kernel super sederhana", yaitu lebih dari gaya lainnya.
5
@ Akiva Anda tidak bisa melalui matriks 4 dimensi tanpa memiliki 4 loop bersarang. Saya merasa gila bahwa seseorang akan membatasi jumlah loop bersarang yang dapat Anda miliki. Linus jelas sangat umum dan Anda tidak boleh menganggap semua yang Anda baca sebagai tulisan suci.
Alternatex
9
@Alternatex Bahwa Anda membutuhkan 4 loop tidak berarti mereka harus bersarang secara leksikal . Sangat jelas dari kutipan bahwa kita berbicara tentang bagaimana mengatur kode, bukan tentang eksekusi.
4
@delnan Saya tidak mengatakan 4 loop bersarang secara visual menyenangkan dan saya sadar ada cara lain untuk melakukannya tetapi saya merasa konyol bagaimana OP mengambil kata-kata Linus secara harfiah. Tingkat indentasi ke-4 = ujung dunia. Beri aku istirahat.
Alternatex

Jawaban:

19

Kernel sangat menyukai algoritma sederhana

Sementara berbagai algoritma mungkin memerlukan loop yang sangat bersarang di dalam loop, dalam konteks kernel Linux (di mana kutipan itu dikatakan), Anda biasanya memerlukan respons waktu nyata yang cepat. Dalam konteks itu, deep nesting adalah bau yang dapat mengindikasikan bahwa aliran kode terlalu kompleks untuk domain ini dan mungkin perlu diubah karena karakteristik eksekusi, bukan keterbacaan atau masalah indentasi.

Lebih lanjut, kernel Linux berbeda dari kebanyakan kode aplikasi seperti untuk persyaratan auditabilitas dan pengujian - dan karenanya lebih memilih untuk tidak memiliki algoritma bertingkat 4+ dalam satu fungsi. Harus jelas untuk melihat apa yang masing-masing fragmen kode lakukan dengan tepat dan terperinci, termasuk semua kemungkinan aliran kontrol dan kasus tepi. Kode bersarang sangat menghambat itu.

Peter adalah
sumber
Jadi, apakah Anda berpikir bahwa dengan bahasa tingkat lebih rendah seperti C, loop bersarang pada umumnya becauseproyek yang lebih tabu memanfaatkan bahasa tingkat bawah mendapat manfaat dari gaya pengkodean yang berfokus pada algoritma yang lebih sederhana?
Akiva
4
@ Akiva Saya tidak akan mengikatnya ke bahasa tingkat lebih rendah atau C seperti itu, melainkan ke domain kode. Saya pikir pedoman serupa akan berlaku untuk bahasa apa pun ketika menulis kode yang harus kuat, keamanan fokus dan diaudit dengan mengorbankan hal-hal lain. Misalnya perpustakaan enkripsi yang ditulis dalam Java atau Haskell juga harus ditulis dalam gaya yang membuat hal-hal sesederhana mungkin, membatasi bersarang, dan mencoba memisahkan semuanya menjadi potongan-potongan yang dapat dengan mudah dianalisis dengan semua konsekuensi yang mungkin terjadi.
Peteris
Komentar / jawaban yang sangat mendalam dan bermanfaat. Hanya penasaran; proyek seperti apa yang dilakukan hari ini yang menggunakan bahasa tingkat rendah, tidak akan fokus menjadi kuat, mampu audit, dan aman?
Akiva
7
@ Akiva misalnya, kode pembelajaran mesin di mana Anda mungkin ingin menggunakan C hanya untuk alasan kinerja tetapi tidak terlalu peduli tentang ketahanan atau keamanan karena akan dijalankan secara internal dalam kondisi yang terkendali. Juga, menerapkan fungsionalitas bisnis sederhana pada mikrokontroler tertanam kecil - dalam praktiknya ini sering memiliki bisnis seperti fokus pada fitur dan kecepatan pengembangan dengan mengorbankan kualitas dan keamanan, tetapi menggunakan bahasa tingkat rendah.
Peteris
49

Sampai taraf tertentu, saya berhenti menganggap kutipan ini dengan serius di "Tab adalah 8 karakter" . Inti dari tabulator adalah bahwa mereka bukan jumlah karakter yang tetap (jika ada, tab adalah satu karakter). Apa beban tosh. Demikian pula, saya tidak sepenuhnya yakin bahwa menetapkan aturan "tiga tingkat indentasi" yang keras dan cepat itu waras (sebanyak menetapkan aturan yang keras dan cepat untuk segala sesuatu adalah waras).

Namun, membatasi tingkat Anda dari lekukan adalah secara umum saran yang masuk akal, dan tidak satu yang harus datang sebagai kejutan untuk Anda.

Pada akhirnya, jika program Anda membutuhkan tiga tingkat iterasi, itulah yang dibutuhkan oleh program Anda . Semangat kutipan ini bukan untuk secara ajaib meringankan persyaratan dari proyek Anda, tetapi untuk menghilangkan logika menjadi fungsi dan tipe sehingga kode Anda lebih tegas dan lebih ekspresif.

Ini hanya memberikan umpan balik ke pedoman yang sama yang diberikan di atas mengenai tingkat indentasi. Ini tentang bagaimana Anda menyusun kode dan membuatnya mudah dibaca, dipelihara, dan menyenangkan untuk dimodifikasi selama bertahun-tahun yang akan datang.

Lightness Races dengan Monica
sumber
6
Saya percaya "deklarasi" bahwa tab adalah 8 karakter secara khusus dalam konteks pengembangan kernel. Kutipan ini diambil dari pedoman pengkodean untuk proyek tertentu dan tidak dimaksudkan untuk menjadi pedoman penggunaan umum, dan oleh karena itu diharapkan cukup beralasan.
Lie Ryan
6
@ LieRyan: Maka masih tosh - pedoman pengkodean untuk apa pun tidak ada bisnis yang menentukan seberapa luas saya mengatur tab saya! Tapi saya curiga Linus tahu itu.
Lightness Races with Monica
6
dan tentu saja itu tergantung pada bahasa - di c # adalah umum bahwa Anda membuat indentasi di dalam namespace Anda, di kelas Anda, dan dalam metode Anda .. Anda sudah berada di 3 level indentasi bahkan sebelum Anda berbicara tentang badan pernyataan aliran kontrol menjadi bertakuk.
PeterL
3
@LightnessRacesinOrbit Saya menafsirkan komentar "Tab adalah 8 karakter" untuk tidak berarti bahwa Anda harus secara pribadi melihat tab sebagai lebar 8 di editor Anda, tetapi untuk tujuan aturan lain dalam panduan gaya (seperti "Batas pada panjang garis) adalah 80 kolom dan ini adalah batas yang sangat disukai. ") kita harus memperlakukan tab sebagai 8 kolom, ini juga relevan dengan aturan lain tentang penyelarasan argumen dalam panggilan fungsi. Sekali lagi, saya tidak berpikir maksud dari baris itu memaksa Anda untuk melihat tab seperti itu, saya telah melakukan patching kernel sebelumnya dengan 4 tab lebar dan mengubah kode di akhir.
Vality
4
@underscore_d: Tampaknya saya salah: Outside of comments, documentation and except in Kconfig, spaces are never used for indentation, and the above example is deliberately broken.- 6 paragraf turun dari kutipan di OP.
slebetman
16

Intinya sama dengan konstruksi kontrol aliran apa pun: jika kodenya sulit dipahami, Anda perlu mengubahnya. Jika Anda melakukan manipulasi sederhana dari array multi-dimensi, maka memiliki loop yang bersarang sedalam lima atau enam mungkin tepat, asalkan logika pada loop paling dalam mudah. Namun, jika Anda memproses beberapa logika bisnis yang rumit dan isi loop Anda selusin baris atau lebih, maka Anda mungkin tidak ingin membuat sarang lebih dari satu loop. Anda dapat mencoba menghitung kompleksitas cyclomatic dari kode tersebut, tetapi apa yang sebenarnya terjadi adalah keterbacaan dan pemeliharaan kode tersebut.

TMN
sumber
11
Persis. Terlalu mudah untuk menyarankan bahwa Torvalds adalah loon. (Dia, tentu saja.) Dia mungkin terlalu kaku untuk seleramu, tapi dia menggambarkan masalah perkembangan nyata yang menyebabkan masalah nyata. Anda tidak harus melakukan persis apa yang dikatakannya, tetapi Anda harus memikirkan mengapa ia mengatakannya.
Scant Roger
7
@ ScantRoger Sebenarnya, kutipan-Torvalds hanya terdengar terlalu kaku jika Anda tidak memiliki selera humor. Seingat saya, sebelumnya dalam dokumen yang sama, ia menyarankan untuk mencetak salinan pedoman gaya pengkodean GNU, hanya untuk membakarnya dalam semacam upacara. Anda tidak akan menganggapnya serius, bukan? Dalam kutipan ini, poin utamanya adalah mendefinisikan lekukan untuk kernel linux menjadi delapan ruang, tidak lebih, dan tidak kurang, itulah yang ia tegaskan. Kalimat terakhir hanya untuk menggarisbawahi hal itu, bukan untuk mengatakan bahwa Anda tidak boleh menggunakan lebih banyak tingkat indentasi - tidak ada kekakuan yang tersirat.
cmaster
1
@ cmaster Terima kasih untuk konteksnya, langsung! Untuk menjawab pertanyaan Anda, saya tidak menganggap serius apa pun. ;)
Scant Roger
2
@ cmaster dan kemudian orang membaca tanggapannya ke github menarik permintaan dan panjang baris pesan komit. Dia benar-benar gila.
Gusdor
3
Membakar secara resmi pedoman pengkodean GNU mungkin sebenarnya tidak perlu, tetapi sepenuhnya dalam rangka kapan saja.
dmckee
13

Apakah Linus bercanda?

Sepotong ditulis dalam gaya bermain yang menunjukkan bahwa penulis akrab dengan cara pengkodean gaya dibahas di antara praktisi serius: Kita semua memiliki preferensi kita, dan kita membela mereka dengan berani, tetapi dengan lidah setidaknya sebagian di pipi. Kami sangat memahami bahwa sebagian besar hanya masalah selera pribadi. Dia mengatakan, dalam banyak kata, "Coding style is very personal, and I won't _force_ my views on anybody"- setidaknya di luar kode yang dia pertahankan secara pribadi. Tetapi konsistensi gaya dalam proyek yang diberikan adalah ide yang sangat bagus. Saya lebih suka kode ke gaya saya tidak suka daripada berurusan dengan banyak gaya dalam fungsi yang diberikan.

Berikut adalah contoh penulisan yang jelas-jelas lucu:

However, there is one special case, namely functions: they have the
opening brace at the beginning of the next line, thus:

int function(int x)
{
    body of function
}

Heretic people all over the world have claimed that this inconsistency
is ...  well ...  inconsistent, but all right-thinking people know that
(a) K&R are _right_ and (b) K&R are right.  Besides, functions are
special anyway (you can't nest them in C).

Main-main (1).

Ini bisa dibilang saran yang baik untuk mencoba menjaga indentasi agar tidak lepas kendali, meskipun maksimum tiga level mungkin hiperbolik. Saya tidak akan memahami sumber kernel dan menghitung urutan empat karakter tab, tetapi saya berani bertaruh Anda bisa menemukan setidaknya satu yang ditulis Torvalds.

Di sisi lain, jika seseorang dapat menulis kernel Linux tanpa sering melebihi tiga level indentasi, batas tiga level mungkin merupakan latihan yang patut dicoba untuk sementara waktu dalam kode Anda sendiri, hanya untuk melihat ke mana ia membawa Anda. Ini tidak seperti perubahan jenis kelamin, Anda tahu. Itu bukan komitmen seumur hidup.

Jika Anda bertemu seseorang di Internet yang berpikir ia memahami pemrograman jauh lebih baik daripada Torvalds (2), Anda tahu orang seperti apa yang suka berbicara banyak di Internet.

Di sisi lain, ia secara pidana salah tentang tab delapan-ruang. Itu adalah keributan dari seorang pria yang harus disimpan dalam pengekangan dan diberi makan melalui slot. Empat ruang jelas benar.

(1) Tetapi perhatikan bagaimana ia secara keliru menempatkan ruang di depan elips, dan dua ruang setelahnya, dan dua ruang setelah berhenti penuh. SALAH SALAH SALAH. Dan kemudian dia memiliki keberanian berani untuk menghukum para bidat. Bidat itu adalah kamu, Torvalds! ITU ADALAH KAMU!

(2) Jika Anda ingin berbicara tentang " memahami cara merancang sistem kontrol sumber ", mungkin ada ruang untuk perdebatan.

Catatan: Rekan pengguna terkasih yang telah berulang kali mengirimkan hasil edit yang sama: Pemformatan dalam materi yang dikutip disimpan persis seperti yang dimaksudkan penulis. Itu karena itu dari esai tentang pemformatan teks lebar tetap, ditulis dalam teks lebar tetap, oleh seseorang yang telah memberikan pemformatan teks lebar tetap pemikiran yang adil. Format adalah bagian sadar dan sengaja dari maksud penulis, dan itu relevan dengan subjek.

Selain itu, saya merujuk kembali ke format itu di teks saya sendiri. Jika Anda menghapus pra-pemformatan, catatan kaki saya (1) menjadi omong kosong. Jika pra-format dihapus, maka seharusnya teks di catatan kaki saya (1) merujuk pada pasangan spasi setelah berhenti penuh di akhir kalimat. Saya dapat melihat alasan untuk menghapus catatan kaki itu, karena itu menjadi kurang lucu daripada ketika saya menulisnya. Tetapi untuk menghapus format tanpa menghapus catatan kaki tidak membantu.

Ed Plunkett
sumber
3
Jawaban yang luar biasa. Salah satu kasus yang layak mendapat +2 ... (Catatan: Tidak ada spasi yang salah .di komentar ini ;-))
cmaster
2
Paragraf intro Linus yang Anda tunjukkan sangat penting jadi terima kasih telah melakukannya! Saya pikir kalimat pertama juga sangat penting untuk konteks, khususnya preferred coding styledan jugabut this is what goes for anything that I have to be able to maintain
Chris Haas
9

Linus memiliki gaya berbicara yang sangat blak-blakan, dan selera humor yang kering, tetapi dia tidak bercanda dalam hal ini. Ada situasi di mana suatu algoritma perlu bersarang lebih dalam dari dua level, tetapi Anda dapat melakukannya dengan menggunakan cara lain selain mengindentasi kode Anda. Panduan gaya kernel Linux sangat memilih metode-metode lain ini, karena sulitnya mempertahankan loop yang bersarang secara mendalam, dan itulah yang dikatakan Linus di sini.

Untuk beberapa contoh metode alternatif, Anda dapat menggunakan rekursi, memisahkan loop internal menjadi fungsinya sendiri, atau membuat struktur data menengah.

Bersarang berlebihan adalah salah satu kasus yang lebih mudah ditulis, tetapi sulit dibaca. Mengatur kedalaman tab yang besar adalah cara Linus membuatnya lebih mengganggu untuk menulis juga.

Karl Bielefeldt
sumber
3

Ada banyak pertanyaan di mana saran berbeda untuk seseorang yang mengajukan pertanyaan daripada seseorang yang tidak bertanya. Jika Anda bertanya "Jika saya pernah memiliki loop yang bersarang lebih dari dua level" maka untuk Anda, orang yang menanyakan pertanyaan itu, jawabannya adalah TIDAK. Jika Anda bertanya, maka jangan lakukan itu. Jika Anda memiliki cukup pengalaman yang tidak perlu Anda tanyakan, maka Anda tahu apa jawaban yang benar dalam setiap kasus. Dan jangan berdebat jika Anda tidak setuju dengan jawabannya, karena jawabannya bukan untuk Anda.

gnasher729
sumber
1

Ini akan tampak seperti kasus buku teks dari ekor yang mengibas-ngibaskan anjing.

Jika Anda memiliki tampilan 80 karakter maka tentu saja Anda akan mencoba dan membuat kode sesuai yang Anda bisa, bahkan jika itu tidak menghasilkan struktur terbaik untuk kode .

Menangani sisa poin Anda di kepala:

Saya pikir itu adalah praktik yang tidak dapat diterima.

Saya pikir Anda terlalu banyak membaca ini. Tahan dorongan untuk menganggap segala sesuatu yang Anda baca sebagai Injil tanpa memahami konteksnya dengan tepat.

Apakah dia bercanda?

Sulit untuk memastikan konteksnya, tetapi lihat poin asli saya di atas.

Apakah ini tergantung pada bahasa atau aplikasi?

Sangat banyak sehingga. Ambil bahasa mainframe / midrange mana pun di mana Anda cenderung membuat kode pada terminal (atau terminal emulator).

Apakah ada beberapa hal yang benar-benar membutuhkan tiga atau lebih tingkat pengulangan?

Ya, ini sangat umum dalam beberapa algoritma brute force. Lihat Masalah 31 tentang Euler Proyek. Ini adalah contoh klasik dari masalah yang bisa diselesaikan dengan kekerasan menggunakan sejumlah loop (8 tepatnya).

Robbie Dee
sumber
1
Sepertinya Masalah 31 tidak memerlukan bruteforce dan dapat diselesaikan menggunakan algoritma pemrograman dinamis (edit: yang berarti struktur kode Anda bukan yang terbaik jika Anda menggunakan algoritma bruteforce). Juga, poin Linus adalah bahwa jika kode Anda memerlukan banyak tingkat indentasi, kemungkinan bukan struktur terbaik untuk kode tersebut.
Vincent Savard
2
@VincentSavard Tidak pernah mengatakan itu membutuhkan kekerasan. Tidak setuju dengan poin ke-2 Anda - terkadang ini adalah pendekatan yang paling jelas dan paling ringkas, belum lagi yang paling efisien dalam beberapa kasus.
Robbie Dee
1
Dengan masalah seperti itu saya biasanya tidak membuat loop. Saya pikir saya punya satu kasus dengan 20 loop bersarang, benar-benar sepele untuk ditulis, dan tidak ada lekukan sehingga Anda dapat melihat loop hampir identik.
gnasher729
1
@RobbieDee: Maksud saya adalah bahwa contoh Anda masalah yang diselesaikan oleh banyak loop adalah bahwa algoritma Anda tidak seefisien solusi pemrograman dinamis, yang tidak memerlukan banyak tingkat indentasi. Dengan demikian, seperti yang dikatakan Linus, level indentasi Anda dapat dihilangkan dengan menggunakan solusi yang lebih baik. Anda juga salah mengerti poin kedua saya karena saya setuju dengan apa yang Anda katakan. Terkadang , ini solusi terbaik. Terkadang tidak sering, dan tidak mungkin.
Vincent Savard
1
Kutipan Linus cukup eksplisit mengatakan bahwa jika beberapa kode memerlukan sesuatu seperti bruteforcing Soal-31, maka Anda tetap kacau - itu tidak akan cepat atau sederhana, dan operasi kernel harus cepat dan sederhana. Termasuk semua algoritma O (n ^ 4) dalam kernel adalah risiko yang signifikan terhadap kinerja atau penolakan layanan, jadi dalam konteks ini rekomendasinya hanya memperingatkan bahwa ini adalah tanda kode yang mungkin secara fundamental tidak sesuai dan diinginkan di Linux.
Peteris
0

Apakah Linus bercanda?

Tidak, itu adalah pedoman resmi.

Apakah ini tergantung pada bahasa atau aplikasi?

Pedoman pengkodean umumnya tergantung pada bahasa dan aplikasi, namun kode yang sangat bersarang selalu membebani pembaca.

Masalah dengan kode bersarang adalah bahwa secara umum meningkatkan kompleksitas siklomatik: yaitu, semakin banyak kode bersarang, semakin banyak jalur eksekusi potensial yang ada dalam fungsi. Ledakan kombinatorial dari jalur eksekusi potensial membuatnya sulit untuk beralasan tentang kode, dan karenanya harus dihindari secara umum.

Jadi mengapa 3? Pedoman pengkodean subyektif sulit untuk ditegakkan dan tidak mungkin untuk ditegakkan secara otomatis. Menyiapkan pedoman pengkodean obyektif pada tingkat lekukan maksimum membutuhkan persetujuan angka: di kernel Linux mereka memilih 3.

Ini sewenang-wenang, dan tampaknya cukup untuk mereka.

Apakah ada beberapa hal yang benar-benar membutuhkan tiga atau lebih tingkat pengulangan?

Algoritma-bijaksana, mungkin, namun dalam bahasa yang cukup ekspresif Anda selalu dapat memperbaiki kode menjadi potongan yang lebih kecil (baik dengan fungsi atau penutupan).

Anda jelas dapat menulis kode yang dikaburkan dengan sedikit bersarang dan banyak fungsi kecil saling memanggil tanpa pernah mengeja kontrak mereka ...

... namun, fungsi kecil dengan kontrak yang jelas jauh lebih mudah untuk diaudit daripada fungsi besar dengan kontrak yang jelas pada umumnya.

Matthieu M.
sumber
2
Walaupun ini mungkin panduan resmi, ini sepele untuk menemukan tempat di kode kernel di mana panduan tidak diberlakukan.
MikeB
1
@ MikeB: Semua alasan lagi untuk menegakkan pedoman secara otomatis ...
Matthieu M.
1
@ MatthieuM. Apakah Anda yakin memahami perbedaan antara pedoman dan persyaratan wajib? Sebagai "pedoman umum" (pedoman jika Anda suka), pedoman lebih seperti rekomendasi dan tidak ditegakkan.
Brendan