Mengapa itu dianggap praktik yang buruk untuk menghilangkan kawat gigi keriting? [Tutup]


177

Mengapa semua orang memberi tahu saya menulis kode seperti ini adalah praktik yang buruk?

if (foo)
    Bar();

//or

for(int i = 0 i < count; i++)
    Bar(i);

Argumen terbesar saya untuk menghilangkan kurung kurawal adalah kadang-kadang bisa dua kali lebih banyak garis dengan mereka. Sebagai contoh, berikut adalah beberapa kode untuk melukis efek cahaya untuk label dalam C #.

using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor)))
{
    for (int x = 0; x <= GlowAmount; x++)
    {
        for (int y = 0; y <= GlowAmount; y++)
        {
            g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));
        }
     }
 }
 //versus
using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor)))
    for (int x = 0; x <= GlowAmount; x++)
        for (int y = 0; y <= GlowAmount; y++)
            g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));

Anda juga bisa mendapatkan manfaat tambahan dari merantai usingsbersama tanpa harus melakukan indentasi jutaan kali.

using (Graphics g = Graphics.FromImage(bmp))
{
    using (Brush brush = new SolidBrush(backgroundColor))
    {
        using (Pen pen = new Pen(Color.FromArgb(penColor)))
        {
            //do lots of work
        }
    }
 }
//versus
using (Graphics g = Graphics.FromImage(bmp))
using (Brush brush = new SolidBrush(backgroundColor))
using (Pen pen = new Pen(Color.FromArgb(penColor)))
{
    //do lots of work
}

Argumen yang paling umum untuk kurung kurawal berkisar pada pemrograman maintance, dan masalah yang akan terjadi dengan memasukkan kode antara pernyataan asli jika pernyataan dan hasil yang dimaksudkan:

if (foo)
    Bar();
    Biz();

Pertanyaan:

  1. Apakah salah jika ingin menggunakan sintaks yang lebih ringkas yang ditawarkan bahasa? Orang-orang yang mendesain bahasa ini cerdas, saya tidak bisa membayangkan mereka akan menempatkan fitur yang selalu buruk untuk digunakan.
  2. Haruskah kita atau tidakkah kita menulis kode sehingga penyebut umum terendah dapat memahami dan tidak memiliki masalah untuk mengatasinya?
  3. Apakah ada argumen lain yang saya lewatkan?

6
Saya setuju denganmu. Hilangkan mereka. Titik.
Andrei Rînea

67
SIAPA YANG PEDULI BAGAIMANA BANYAK GARIS SESUATU ITU ADA DI 2010. Monitor lebar dan murah dan beresolusi tinggi! Monitor saya 2048 X 1152 dan saya punya DUA! Keterbacaan jauh lebih penting daripada menyimpan 2 garis vertikal saat Anda dapat dengan mudah memperkenalkan kesalahan halus yang sulit ditemukan.

51
Monitor lebar dan murah, tetapi tidak tinggi dan murah. Ruang vertikal lebih langka daripada ruang horizontal.
Adam Says - Pasang kembali Monica

32
@AdamRuth Putar mereka ke samping :)
Zachary Yates

16
Jadi Anda tidak mengacau seperti Apple dengan bug SSL yang ditemukan pada Februari 2014, LOL.
learnvst

Jawaban:


183

Sebenarnya, satu-satunya waktu yang benar-benar menggigit saya adalah ketika saya sedang debug, dan berkomentar di bar ():

if(foo)
  // bar();
doSomethingElse();

Selain itu, saya cenderung menggunakan:

if(foo) bar();

Yang menangani kasus di atas.

EDIT Terima kasih telah menjelaskan pertanyaan, saya setuju, kita tidak boleh menulis kode ke penyebut umum terendah.


31
Tentu saja itu kasar, tapi saya pikir masalah terbesar bagi pengelola adalah mereka akan menambah baris kedua, dan tidak menyadari itu bukan bagian dari pernyataan bersyarat meskipun itu BENAR-BENAR kelihatannya seharusnya.
danieltalsky

23
Saya tidak suka gaya one liner karena saya selalu mencari loop body di bawah ini.
Nosredna

18
Saya menemukan gaya one-liner lebih menjengkelkan daripada membantu karena (terutama di sarang yang dalam - ugh) pernyataan itu dapat dengan mudah dibaca dan kebingungan dapat terjadi. Saya hampir secara eksklusif menggunakan pernyataan-tunggal seperti pernyataan untuk validasi input (yaitu pengembalian awal) atau kontrol lingkaran (misalnya mengabaikan nama file yang tidak relevan dalam berjalan filesystem), meskipun, di mana baris kosong membantu pengaturannya dari kode utama.
Alan Plum

1
Gaya satu garis juga menyembunyikan bilah () dari cakupan tes. Itu akan terlihat tertutup bahkan jika foo selalu salah.
Bohumil Janda

1
Ini adalah cara lain untuk mengatakan, "seandainya sumbernya menyertakan kurung kurawal, saya tidak akan membuang waktu saat debugging." - menambahkan kawat gigi itu sederhana, dan menghindari meninggalkan jebakan untuk orang berikutnya. Satu-satunya argumen yang menentang adalah "keterbacaan," yang cukup renggang, mengingat bahwa ini adalah kasus di mana sesuatu secara implisit terjadi jika Anda menghilangkannya.
Andrew Theken

156

Kecepatan membaca ...

Selain dari apa yang telah disebutkan. Pada titik ini, saya sudah dikondisikan untuk menguraikan pernyataan dengan kawat gigi dan ruang putih. Jadi saya membaca:

if (condition)
{
    DoSomething();
}

DoSomethingElse();

Sedikit lebih cepat daripada yang saya baca:

if (condition) DoSomething();

DoSomethingElse();

Saya membacanya sedikit lebih lambat jika terlihat seperti ini:

if (condition) DoSomething();
DoSomethingElse();

Saya membaca ini secara signifikan lebih lambat dari sebelumnya:

if (condition) 
    DoSomething();
DoSomethingElse();

karena saya tidak bisa tidak membacanya lagi untuk berjaga-jaga dan bertanya-tanya apakah penulis bermaksud:

if (condition)
{
    DoSomething();
    DoSomethingElse();
}

Sudah dibahas secara umum, tetapi ketika datang untuk membaca di bawah ini, saya akan melihat ini cukup lama untuk memastikan apa yang penulis maksudkan. Saya bahkan dapat memburu penulis asli untuk mengkonfirmasi.

if (condition) 
    DoSomething();
    DoSomethingElse();

29
Masalahnya terpecahkan ketika, dalam sampel ke-4 Anda, Anda hanya meletakkan baris kosong setelah jika pernyataan untuk memisahkannya dari DoSomethingElse () Itulah yang saya lakukan dan keterbacaan secara praktis sama dengan sampel 1 (jika tidak lebih baik ;-P) Hal lain adalah bahwa menempatkan baris dalam kelompok 2 atau 3 secara signifikan membantu kemudahan, Anda hanya memindai kode lebih cepat.
Piotr Owsiak

6
Mungkin itu karena saya sudah terbiasa dengan Python, tetapi menempatkan kurung kurawal pertama pada baris yang sama dengan pernyataan if memungkinkan saya untuk membaca + memahaminya bahkan lebih cepat.
Ponkadoodle

16
Masalah dengan gaya tanpa gelang itu membuat Anda menyia-nyiakan konsentrasi Anda yang berharga untuk memikirkan apakah balok memiliki kawat gigi daripada hal-hal yang lebih penting. Ini saja merupakan alasan yang cukup baik untuk menggunakan konvensi paling sederhana yang mungkin, yaitu kawat gigi selalu.
Nate CK

2
Kawat gigi secara eksplisit bersifat alami. Saya akan tetap dengan itu, terima kasih.
TheOptimusPrimus

2
Dalam kasus terakhir, memburu penulis asli dan memukulnya ...;)
Per Lundberg

55

Jika kecil, tulis seperti ini:

if(foo()) bar();

Jika cukup lama untuk dibagi menjadi dua garis, gunakan kawat gigi.


ya, itulah yang saya lakukan juga. Ini memaksa Anda untuk menambahkan kawat gigi jika Anda menambahkan baris lain, dan cukup jelas untuk melihat bahwa bar () sebenarnya adalah bagian dari if, jadi hal-hal buruk akan terjadi jika Anda hanya berkomentar saja.
jalf

10
Tapi tidak terlalu ramah debugger. Bagaimana Anda mengatur breakpoint pada bagian "bar"?
Nemanja Trifunovic

9
@Nemanja: Cukup letakkan kursor Anda di bar (); dan tekan F9. Baik VS2005 dan VS2008 menangani breakpoint intra-line, jika keduanya terpisah "pernyataan".
GalacticCowboy

4
GalanticCowboy: Ada lebih banyak lingkungan daripada yang Anda tahu. :-)

20
Tentu, tetapi karena konteksnya adalah C #, yang seharusnya mencakup sebagian besar pengguna ...
GalacticCowboy

47

Dulu saya juga berpikir lebih baik menggunakan kawat gigi saat dibutuhkan. Tetapi tidak lagi, alasan utama, ketika Anda memiliki banyak kode, itu membuatnya lebih mudah dibaca dan Anda dapat menguraikan kode lebih cepat ketika Anda memiliki gaya menguatkan yang konsisten.

Alasan bagus lainnya untuk selalu menggunakan kawat gigi, selain seseorang menambahkan pernyataan kedua ke if, adalah sesuatu seperti ini bisa terjadi:

if(a)
   if(b)
     c();
else
   d();

Apakah Anda memperhatikan bahwa klausa lain sebenarnya adalah "jika (b)"? Anda mungkin melakukannya, tetapi apakah Anda memercayai siapa pun untuk terbiasa dengan gotcha ini?

Jadi, jika hanya untuk konsistensi dan karena Anda tidak pernah tahu hal-hal tak terduga apa yang mungkin terjadi ketika orang lain (selalu orang lain yang bodoh) mengubah kode, saya selalu memasang kawat gigi, karena itu membuat kode sumber lebih mudah dibaca, lebih cepat diurai oleh otakmu. Hanya untuk pernyataan if yang paling sederhana, seperti jika di mana delegasi dibuat atau seperti switch, di mana Anda tahu klausa tidak akan pernah diperpanjang, saya akan meninggalkan kawat gigi.


12
Ini adalah salah satu dari dua kasus di mana saya menggunakan kawat gigi. Kalau tidak, tidak.
Andrei Rînea

3
Ini seharusnya dituliskan seolah-olah (a && b) ... pertama-tama adalah metode.
alexander.biskop

8
@ alexander.biskop: Tentunya tidak, karena itu memberi orang lain makna yang berbeda ( !a || !b) dibandingkan dengan dengan ( !a) atau tanpa ( a && !b) menambahkan kawat gigi.
Ben Voigt

1
@ Ben Voigt: Benar! Jatuh untuk itu ;-) Setengah tahun dan dua upvotes kemudian, seseorang menyadari pernyataan yang saya buat salah ... Kira saya tidak cukup memperhatikan detail, terutama karena niat di balik komentar saya berbeda daripada menunjukkan. transformasi yang benar secara teknis dari jika-klausa. Yang saya maksudkan adalah bahwa nested inline jika-pernyataan umumnya mengurangi keterbacaan (dan terutama penelusuran aliran kontrol) secara signifikan dan karenanya harus digabungkan menjadi satu pernyataan (atau dielakkan sama sekali). Cheers
alexander.biskop

3
@ alexander.biskop: Pada saat yang sama, debugging lebih mudah dengan masing-masing bersarang dengan kondisi yang lebih sederhana, karena Anda dapat memilih satu langkah ke masing-masing.
Ben Voigt


35

Garis itu murah. Kekuatan prosesor itu murah. Waktu pengembang sangat mahal.

Sebagai aturan umum, kecuali saya mengembangkan beberapa aplikasi kritis sumber daya / kecepatan, saya akan selalu berbuat salah di sisi penulisan kode yang

(a) Mudah bagi pengembang lain untuk mengikuti apa yang saya lakukan

(B) Komentar bagian tertentu dari kode yang mungkin membutuhkannya

(c) Mudah di-debug jika terjadi kesalahan

(D) Mudah untuk memodifikasi jika perlu di masa depan (yaitu menambah / menghapus kode)

Kecepatan atau keanggunan akademik dari kode adalah faktor sekunder dari faktor-faktor ini dari perspektif Bisnis. Ini bukan untuk mengatakan saya mulai menulis kode yang kikuk atau jelek, tapi ini adalah urutan prioritas SAYA.

Dengan menghilangkan kurung kurawal dalam banyak hal, bagi saya itu membuat (b), (c) dan (d) lebih sulit (perhatikan bukan tidak mungkin). Saya akan mengatakan bahwa menggunakan kurung kurawal atau tidak tidak berpengaruh pada (a).


9
Pernyataan terakhir Anda tentang (a) adalah pendapat bahwa sejumlah besar dev, termasuk poster lain di sini, akan berdebat.
Kelly S. French

34

Saya lebih suka kejelasan yang ditawarkan kurung kurawal. Anda tahu persis apa yang dimaksud dan tidak perlu menebak jika seseorang hanya melakukan kesalahan dan meninggalkannya (dan memperkenalkan bug). Satu-satunya waktu saya menghilangkannya adalah ketika saya meletakkan if dan action pada baris yang sama. Saya juga tidak sering melakukannya. Saya sebenarnya lebih suka spasi putih yang diperkenalkan dengan menempatkan kurung kurawal pada jalurnya sendiri, meskipun dari bertahun-tahun pemrograman K&R C, mengakhiri garis dengan kurawal adalah praktik yang harus saya atasi jika IDE tidak menerapkannya untuk saya.

if (condition) action();  // ok by me

if (condition) // normal/standard for me
{
   action();
}

23

Saya pikir ini masalah pedoman untuk proyek yang sedang Anda kerjakan dan selera pribadi.

Saya biasanya menghilangkannya ketika tidak diperlukan, kecuali beberapa kasus seperti berikut:

if (something)
    just one statement; // i find this ugly
else
{
    // many
    // lines
    // of code
}

saya lebih memilih

if (something)
{
    just one statement; // looks better:)
}
else
{
    // many
    // lines
    // of code
}

15

Salah satu contoh di mana ini dapat menggigit Anda adalah kembali di masa lalu makro C / C ++. Saya tahu ini adalah pertanyaan C #, tetapi sering kali pengkodean standar terbawa tanpa alasan mengapa standar itu dibuat.

Jika Anda tidak terlalu berhati-hati saat membuat makro, Anda dapat menyebabkan masalah dengan pernyataan if yang tidak menggunakan {}.

#define BADLY_MADE_MACRO(x) function1(x); function2(x);

if (myCondition) BADLY_MADE_MACRO(myValue)

Sekarang, jangan salah paham, saya tidak mengatakan bahwa Anda harus selalu melakukan {} hanya untuk menghindari masalah ini di C / C ++, tapi saya harus berurusan dengan beberapa bug yang sangat aneh karena ini.


2
andai saja semua kode menyatakan dirinya sebagai ... sigh
Nathan Strong

15

Dulu saya berpikir dengan cara yang sama.

Sampai suatu hari (mengapa selalu ada "satu hari" yang mengubah hidup Anda selamanya?) Kami menghabiskan 24 - 36 jam berturut-turut tanpa tidur men-debug kode produksi hanya untuk mengetahui bahwa seseorang tidak memasang kawat gigi yang dikombinasikan dengan perubahan pencarian / ganti .

Sesuatu seperti ini.

 if( debugEnabled ) 
      println( "About to save 1 day of work to some very important place.");
 saveDayData();

Apa yang terjadi kemudian adalah

 if( debugEnabled ) 
 //     println( "About to save 1 day of work to some very important place.");
 saveDayData();

Ternyata sistem tersebut menghasilkan 500 mb log setiap hari dan kami diminta untuk menghentikannya. Bendera debug tidak cukup sehingga pencarian dan ganti println dilakukan.

Masih ketika aplikasi pergi ke produksi bendera debug dimatikan dan "saveDayData" yang penting tidak pernah dipanggil.

EDIT

Sekarang satu-satunya tempat di mana saya tidak menggunakan kawat gigi adalah jika saya mencoba membangun.

if( object != null ) try { 
     object.close();
} catch( .....

Setelah menonton seorang pengembang superstar melakukan itu.


3
Saya tidak mengerti. Anda memiliki variabel yang mengontrol debugging (debugEnabled) dan Anda masih menggunakan komentar untuk menonaktifkan debugging ??? Mengapa Anda tidak mengatur debugEnabled ke false?
Igor Popov

Ini bukan skenario yang sebenarnya, tetapi Anda membuat poin yang bagus. Hal-hal bodoh (seperti tidak mengatur debug ke false) memang membuat bug yang halus dan bodoh yang lebih sulit ditemukan daripada bug yang "jelas". Tidak menggunakan kawat gigi tidak banyak membantu dalam kasus ini.
OscarRyz

1
@ Goror Bagaimana kalau mereka hanya ingin menghapus satu baris logging tidak semua baris logging?
gman

14

Terus terang saya melihatnya sebagai:

Pemrogram yang baik memprogram pertahanan, Pemrogram jahat tidak.

Karena ada beberapa contoh di atas dan pengalaman saya sendiri yang serupa dengan bug yang terkait dengan lupa kawat gigi maka saya belajar cara yang sulit untuk SELALU PUT BRACES.

Yang lainnya adalah memilih gaya pribadi daripada keselamatan dan itu jelas pemrograman yang buruk.

Joel bahkan menyebutkan ini di Making Wrong Code Look Wrong

Setelah Anda mendapatkan sedikit bug karena kawat gigi yang hilang, Anda mengetahui bahwa kawat gigi yang hilang terlihat salah karena Anda tahu itu adalah tempat yang potensial untuk bug lain terjadi.


Jika kawat gigi terbuka ditempatkan pada jalur sendiri, maka di mana pun tempat dua atau lebih garis berlekuk tanpa pasangan kawat gigi akan terlihat salah, seperti halnya pasangan kawat gigi yang tidak cocok. Penggunaan tersebut akan dikenakan biaya baris kosong dalam kasus di mana ifpernyataan mengontrol blok, tetapi menghindari perlunya blok dalam kasus di mana ifpernyataan mengontrol tindakan tunggal daripada blok.
supercat

14

Saya cukup senang untuk:

foreach (Foo f in foos)
  foreach (Bar b in bars)
    if (f.Equals(b))
      return true;

return false;

Secara pribadi, saya tidak mengerti mengapa

foreach (Foo f in foos)
{
  foreach (Bar b in bars)
  {
    if (f.Equals(b))
    {
      return true;
    }
  }
}

return false;

lebih mudah dibaca.

Ya, baris gratis, tetapi mengapa saya harus menggulir halaman dan halaman kode ketika ukurannya bisa setengah?

Jika ada perbedaan dalam keterbacaan atau pemeliharaan maka, tentu saja, pasang kawat gigi di ... tetapi dalam kasus ini saya tidak melihat alasan untuk itu.

Juga, saya akan selalu meletakkan kawat gigi untuk bersarang jika di mana saya bersarang di tempat lain

if (condition1)
  if (condition2)
    doSomething();
  else (condition2)
    doSomethingElse();

vs.

if (condition1)
  if (condition2)
    doSomething();
else (condition2)
  doSomethingElse();

sangat membingungkan, jadi saya selalu menuliskannya sebagai:

if (condition1)
{
  if (condition2)
    doSomething();
  else (condition2)
    doSomethingElse();
}

Kapan pun memungkinkan, saya menggunakan operator ternary, tetapi saya tidak pernah membuat sarangnya .


baru saja melihat ini hampir terjadi dalam kode saya :) pikir saya akan melihat-lihat, dan lihatlah ... itu sudah di luar sana :)
Noctis

10

Saya setuju bahwa "jika Anda cukup pintar untuk membuat seseorang membayar Anda untuk menulis kode, Anda harus cukup pintar untuk tidak hanya bergantung pada lekukan untuk melihat aliran kode."

Namun ... kesalahan bisa dibuat, dan yang ini sulit untuk di-debug ... terutama jika Anda datang melihat kode orang lain.


10

Filosofi saya adalah jika membuat kode lebih mudah dibaca, mengapa tidak melakukannya?

Jelas Anda harus menggambar garis di suatu tempat, seperti menemukan media yang bahagia antara nama variabel yang singkat dan deskriptif. Tetapi kurung benar-benar menghindari kesalahan dan meningkatkan keterbacaan kode.

Anda dapat berargumen bahwa orang yang cukup pintar untuk menjadi pembuat kode akan cukup pintar untuk menghindari bug yang memunculkan pernyataan tanpa bracket. Tetapi bisakah Anda dengan jujur ​​mengatakan Anda tidak pernah tersandung oleh sesuatu yang sederhana seperti kesalahan ejaan? Minutia seperti ini bisa luar biasa ketika melihat proyek-proyek besar.


7
Tentu ini sangat subyektif. Meninggalkannya kadang meningkatkan keterbacaan.
Brian Knoblauch

Benar, jika saya pernah meninggalkan tanda kurung, saya menjaga satu baris, seperti yang telah disebutkan. Saya sudah terlalu sering digigit tetapi multi-baris pernyataan bracketless. Bahkan jika Anda tahu untuk mewaspadai hal itu, kadang-kadang masih bisa Anda dapatkan.
James McMahon

10

Selalu ada pengecualian, tapi saya akan membantah menghilangkan kawat gigi hanya jika ada di salah satu bentuk:

if(x == y)
   for(/* loop */)
   {
      //200 lines
   }

//rampion's example:
for(/* loop */)
{
   for(/* loop */)
      for(/* loop */)
      {
         //several lines
      }
}

Kalau tidak, saya tidak punya masalah dengan itu.


4
Contoh buruk. Dalam kedua kasus tersebut, saya akan memfaktorkan bahwa 200 baris untuk loop ke metode sendiri, atau lebih disukai beberapa metode.
Adam Jaskiewicz

2
Benar, tetapi itu TIDAK terjadi. Plus, setiap kali satu blok lebih panjang dari layar pembaca tinggi, Anda akan mengalami masalah ini. Dan Anda tidak dapat mengontrol ketinggian layar pembaca kode Anda. Mereka mungkin hanya melihat beberapa garis di setiap sisi.
rampion

2
Itu memang terjadi. Itu tidak berarti itu harus terjadi.
Adam Jaskiewicz

3
@AdamJaskiewicz Benar. Itu memang terjadi. Kami harus berpikir tentang apa yang tidak terjadi, bukan apa yang seharusnya terjadi. Jika kita dapat membatasi diri pada apa yang seharusnya terjadi, kita tidak perlu khawatir tentang bug.
Beska

10

Saya kadang-kadang menggunakan kode paling bawah (banyak menggunakan pernyataan), tetapi selain itu saya selalu memasukkan kurung. Saya hanya menemukan itu membuat kode lebih jelas. Jelas sekali dari lebih dari sekadar indentasi bahwa pernyataan adalah bagian dari blok (dan karenanya mungkin bagian dari if, dll).

Saya telah melihat

if (...)
    foo();
    bar();

bug menggigit saya (atau lebih tepatnya "saya dan kolega" - saya tidak benar-benar memperkenalkan bug) sekali . Ini terlepas dari kenyataan bahwa standar pengkodean kami pada waktu itu merekomendasikan penggunaan kawat gigi di mana-mana. Secara mengejutkan saya butuh waktu lama untuk menemukan - karena Anda melihat apa yang ingin Anda lihat. (Ini sekitar 10 tahun yang lalu. Mungkin saya akan menemukannya lebih cepat sekarang.)

Tentu saja jika Anda menggunakan "penjepit di ujung garis" itu mengurangi garis tambahan yang terjadi, tetapi saya pribadi tidak menyukai gaya itu. (Saya menggunakannya di tempat kerja, dan menganggapnya kurang menyenangkan daripada yang saya harapkan, tetapi masih sedikit tidak menyenangkan.)


Saya selalu berpendapat bahwa konsistensi lebih penting daripada gaya yang sebenarnya, mengapa kita harus membuat pengecualian hanya dalam kasus usings?
Bob

@ Bob: Poin bagus, dan saya hanya melakukannya sesekali. Saya tidak akan seperti berpura-pura bahwa saya memiliki alasan yang sebenarnya di sini :) Sebenarnya, ada alasan yang masuk akal - bersarang yang usings (dan hanya usings) seperti yang cukup jelas, dan Anda masih berakhir dengan sebuah blok. Saya tidak bisa langsung melihat bahaya.
Jon Skeet

Itu tidak berarti bahwa tidak ada bahaya, tentu saja.
Jon Skeet

1
Solusi terbaik untuk bug ini: Gunakan Python. (Bercanda, tentu saja.)
Joel Wietelmann

10

Saya terkesan dan rendah hati bahwa rekan-rekan saya di bidang pemrograman komputer (Anda banyak) tidak gentar dengan prospek bug potensial ketika Anda melewatkan kawat gigi pada blok baris tunggal.

Saya kira itu berarti saya tidak pintar. Saya telah membuat kesalahan sekitar ini beberapa kali. Saya telah membantah kesalahan orang lain dalam hal ini. Saya telah menonton perangkat lunak kapal dengan bug karena ini (RDP ke mesin yang menjalankan VS2002 dan font jendela arloji Anda akan miring).

Jika saya melihat semua kesalahan yang saya buat yang bisa dihindari dengan perubahan gaya pengkodean, daftarnya sangat panjang. Jika saya tidak mengubah pendekatan saya dalam setiap kasus ini, saya mungkin tidak akan pernah berhasil sebagai programmer. Sekali lagi, saya kira saya tidak pintar. Untuk mengimbangi, saya telah menjadi pengguna yang kuat kawat gigi pada blok baris tunggal untuk waktu yang lama.

Yang mengatakan, beberapa hal telah berubah di dunia yang membuat "kamu harus menggunakan kawat gigi pada blok tunggal" aturan hari ini kurang relevan daripada ketika Musa membawanya ke kita:

  • Beberapa bahasa populer membuat masalah hilang dengan membuat komputer membaca lekukan, seperti yang dilakukan oleh programmer (misalnya Python).

  • Editor saya secara otomatis memformat untuk saya, sehingga kemungkinan saya menyesatkan oleh indentasi jauh berkurang.

  • TDD berarti bahwa jika saya memperkenalkan bug karena saya bingung oleh blok satu baris, saya jauh lebih mungkin untuk menemukan bug dengan cepat.

  • Refactoring dan pengekspresian bahasa berarti bahwa blok saya jauh lebih pendek, dan blok satu garis terjadi lebih sering daripada biasanya. Hipotetis, dengan aplikasi ExtractMethod yang kejam, saya mungkin hanya punya satu baris blok di seluruh program saya. (Aku ingin tahu seperti apa itu nantinya?)

Faktanya, ada manfaat berbeda yang bisa didapat dari refactoring tanpa ampun & menghilangkan kawat gigi pada blok satu baris: ketika Anda melihat kawat gigi, sedikit alarm dapat berbunyi di kepala Anda yang mengatakan "kompleksitas di sini! Waspadalah!". Bayangkan jika ini adalah norma:

if (condition) Foo();   // normal, everyday code

if (condition) 
{
    // something non-trivial hapening; pay attention!
    Foo();
    Bar();
}

Saya membuka diri pada gagasan untuk mengubah konvensi pengkodean saya menjadi sesuatu seperti "blok baris tunggal mungkin tidak pernah memiliki kawat gigi" atau "jika Anda dapat meletakkan blok pada baris yang sama dengan kondisi, dan semuanya cocok dalam 80 karakter, hilangkan kawat gigi ". Kita lihat saja nanti.


Sebagai mantan programmer Java, saya harus sepenuhnya setuju dengan pemformatan otomatis menjadi jawaban nyata untuk masalah ini. Anda bahkan tidak perlu meminta penyunting Anda menambahkan kawat gigi secara otomatis - indentasi otomatis saja dapat membantu menghindari banyak ambiguitas. Tentu saja sekarang saya telah beralih ke Python, saya sudah terbiasa memformat kode saya dengan benar.
Alan Plum

Saya merasakan hal yang sama tentang kawat gigi. Ini semua tentang kerumitannya. Idealnya kita hanya memiliki satu blok garis. Itulah yang saya sebut keterbacaan, bukan kawat gigi yang tidak perlu.
Igor Popov

9

Dari tiga konvensi:

if(addCurleyBraces()) bugFreeSofware.hooray();

dan:

if(addCurleyBraces())
    bugFreeSofware.hooray();

dan (yang mewakili gaya lekukan apa pun menggunakan brace pembuka dan penutup):

if(addCurleyBraces()) {
    bugFreeSofware.hooray();
}

Saya lebih suka yang terakhir sebagai:

  • Saya merasa lebih mudah membaca jika semua pernyataan if ditulis dengan cara yang seragam.
  • Mungkin membuat perangkat lunak sedikit lebih kuat dan bebas bug. Namun semua editor teks modern dan maju IDE memiliki fitur indentasi otomatis yang bagus yang saya pikir semua orang harus menggunakannya selama itu tidak mengacaukan pemformatan komentar atau bertentangan dengan standar tim (dalam banyak kasus dimungkinkan untuk membuat skema pemformatan kustom dan bagikan dengan tim). Maksud saya di sini adalah bahwa jika lekukan dilakukan dengan benar risiko pengenalan bug berkurang sedikit.
  • Saya lebih suka ekspresi dan pernyataan boolean dieksekusi pada baris yang berbeda. Saya ingin dapat menandai baris untuk keperluan debugging. Bahkan jika saya menggunakan IDE di mana saya dapat menandai pernyataan dan melangkah ke sana, ini adalah operasi interaktif dan saya mungkin lupa di mana saya mulai men-debug atau setidaknya itu akan membawa saya sedikit lebih banyak waktu untuk menelusuri kode beberapa kali (karena saya harus menandai posisi secara manual setiap kali selama debugging).

8

Argumen utama Anda yang menentang penggunaan kawat gigi adalah bahwa mereka menggunakan garis tambahan dan mereka membutuhkan indentasi tambahan.

Baris (hampir) gratis, meminimalkan jumlah baris dalam kode Anda seharusnya tidak menjadi tujuan.

Dan indentasi tidak tergantung pada penggunaan brace. Dalam contoh 'menggunakan' cascading Anda, saya masih berpikir Anda harus membuat indentasi bahkan ketika Anda menghilangkan kawat gigi.


8

Saya sangat percaya dalam menulis kode yang rapi dan ringkas, tetapi saya akan selalu menggunakan kurung kurawal. Saya menemukan bahwa mereka adalah cara yang mudah untuk dengan cepat melihat ruang lingkup di mana baris kode tertentu ada. Tidak ada ambiguitas, itu hanya secara eksplisit ditetapkan di depan Anda.

Beberapa orang mungkin mengatakan itu adalah kasus preferensi, tetapi saya menemukan aliran logis dari suatu program jauh lebih mudah untuk diikuti jika itu konsisten secara internal, dan saya tidak percaya bahwa itu konsisten untuk menulis satu pernyataan IF seperti ini;

if(x < y)
    x = y;
else
    y = x;

Dan yang lain seperti ini;

if(x < y)
{
    x = y;
    x++;
}
else
{
    y = x;
    y++;
}

Saya lebih suka hanya memilih satu gaya umum dan tetap menggunakannya :)


7

Salah satu masalah utama adalah ketika Anda memiliki wilayah one-liners dan non-one liner, bersama dengan pemisahan dari statment kontrol ( for,if , apa yang harus Anda) dan akhir pernyataan tersebut.

Sebagai contoh:

for (...)
{
  for (...)
    for (...) 
    {
      // a couple pages of code
    }
  // which for block is ending here?  A good text editor will tell you, 
  // but it's not obvious when you're reading the code
}

4
Mengapa Anda masih memiliki beberapa halaman kode untuk loop Anda?
Adam Jaskiewicz

b / c Saya gumpalan tidak sensitif, dan saya terobsesi untuk menyingkirkan "biaya" panggilan fungsi. :)
rampion

4
Beberapa halaman kode harus berada dalam fungsi yang terpisah, biasanya.
Jonathan Leffler

1
permisi, maksudku aku memainkan peran gumpalan. Namun, saya berpendapat bahwa masalah yang sama dapat terjadi untuk wilayah yang lebih pendek, jika dilihat melalui viewport kecil. Dan itu di luar kendali coder.
rampion

7

Saya dulunya adalah pendukung besar "kurung kurawal adalah suatu KEHARUSAN!", Tetapi sejak mengadopsi pengujian unit, saya menemukan bahwa pengujian unit saya melindungi pernyataan tanpa gelang dari skenario seperti:

if (foo)
    snafu();
    bar();

Dengan tes unit yang baik, saya dapat dengan yakin menghilangkan kurung kurawal untuk pernyataan sederhana untuk meningkatkan keterbacaan (ya, itu bisa subjektif).

Atau, untuk sesuatu seperti di atas, saya mungkin akan menunjukkan bahwa:

if (foo) snafu();

Dengan begitu, pengembang yang perlu menambahkan bilah () ke kondisi, akan lebih cenderung mengenali kurangnya kurung kurawal, dan menambahkannya.


2
Anda berkata "Saya tidak membutuhkannya" lalu memberikan alasan untuk menggunakannya: keterbacaan!
tvanfosson

4
Saya tidak akan bergantung pada Tes Unit untuk menemukan itu. LINT mungkin, Unit test no!
Kristen

2
@ Kristen - Gagasan unit test adalah untuk menegaskan perilaku metode ini. Jika perilaku berubah (seperti dijelaskan di atas) tes unit akan gagal. Saya tidak melihat masalah dalam hal itu.
Liggy

Tetapi mengapa mengandalkan Unit Test untuk mengambil jelas-jelas jelas yang harus diperbaiki sebelum pergi ke UT?
Andrew

7

Gunakan penilaian pribadi.

if (foo)
  bar();

baik-baik saja dengan sendirinya. Kecuali jika Anda benar-benar khawatir tentang orang bodoh memasukkan sesuatu seperti ini nanti:

if (foo)
  bar();
  baz();

Jika Anda tidak khawatir dengan orang bodoh, Anda baik-baik saja (saya tidak - jika mereka tidak bisa mendapatkan sintaksis kode dasar dengan benar, ini adalah masalah mereka yang paling kecil)>

Sebagai gantinya, itu jauh lebih mudah dibaca.

Sisa waktu:

if (foo) {
  bar();
  baz();
}

Yang telah menjadi favorit saya selama saya bisa ingat. Selain itu:

if (foo) {
  bar();
  baz();
} else {
  qux();
}

Bekerja untukku.

Ruang vertikal dengan sendirinya tidak terlalu relevan, keterbacaan adalah. Brace pembuka pada baris dengan sendirinya hanya menghentikan percakapan untuk elemen sintaksis, sampai mata Anda bergerak ke bawah ke baris berikutnya. Bukan yang aku suka.


Satu-satunya waktu saya lebih suka gaya pertama adalah ketika saya harus segera kembali atau melemparkan kesalahan jika ada sesuatu yang salah. Seperti if (parameter == null) return null;.
nawfal

7

Oke, ini pertanyaan lama yang sudah dijawab sampai mati. Saya punya sesuatu untuk ditambahkan.

Pertama saya hanya harus mengatakan GUNAKAN BRASES. Mereka hanya dapat membantu keterbacaan, dan keterbacaan (untuk diri sendiri dan orang lain!) Harus sangat tinggi pada daftar prioritas Anda kecuali Anda menulis perakitan. Kode yang tidak dapat dibaca selalu, selalu mengarah ke bug. Jika Anda menemukan bahwa kawat gigi membuat kode Anda menghabiskan terlalu banyak ruang, metode Anda mungkin terlalu lama. Sebagian besar atau semua metode apa pun harus masuk dalam satu ketinggian layar jika Anda melakukannya dengan benar, dan Find (F3) adalah teman Anda.

Sekarang untuk tambahan saya: Ada masalah dengan ini:

if (foo) bar();

Coba atur breakpoint yang hanya akan mengenai jika bar () akan dijalankan. Anda dapat melakukan ini di C # dengan meletakkan kursor pada bagian kedua dari kode, tetapi itu tidak jelas dan sedikit menyusahkan. Di C ++ Anda tidak bisa melakukannya sama sekali. Salah satu pengembang paling senior kami yang bekerja pada kode C ++ bersikeras untuk melanggar pernyataan 'jika' menjadi dua baris karena alasan ini. Dan saya setuju dengannya.

Jadi lakukan ini:

if (foo)
{
    bar(); //It is easy to put a breakpoint here, and that is useful.
}

2
Klik kanan pada bar dan pilih Sisipkan Breakpoint ... Tidak sulit sama sekali. Ketahui alat Anda.
Bob

Mengklik kanan bilah indikator tidak menghasilkan apa-apa; maksud Anda klik kanan teks? Lagi pula, jika Anda hanya ingin titik istirahat dipukul ketika pernyataan "jika" benar, dan "bar ()" berada di barisnya sendiri, Anda dapat meletakkan kursor di mana saja di baris itu dan tekan F9, atau klik kiri tombol margin indikator. Namun, jika semua kode berada pada satu baris, Anda harus memposisikan kursor pada "bar ()" atau klik kanan tepat di sana sebelum menekan F9, dan mengklik margin indikator tidak akan berfungsi (tempat breakpoint pada ' jika'). Ini bukan "sulit," tetapi membutuhkan konsentrasi lebih sedikit ketika kode berada pada dua baris.
batu

Oh, ha ha, klik kanan pada "bar ()." Anda memang bermaksud teks. Kena kau. Tentu, atau cukup tekan F9 ...
stone

>> Anda harus memposisikan kursor pada "bar ()" atau klik kanan di sana sebelum menekan F9, (maksud saya posisikan kursor tepat di sana sebelum menekan F9 atau mengklik kanan)
batu

7

untuk menjaga agar kode dengan kawat gigi tidak memakan banyak ruang, saya menggunakan teknik yang direkomendasikan dalam buku, Lengkap :

if (...) {
    foo();
    bar();
}
else {
    ...
}

Saya tidak mengerti mengapa itu downmodded menghemat satu baris untuk setiap pasangan braket saya menggunakannya sepanjang waktu
Eric

2
Ini lebih dikenal sebagai gaya K&R. Berdasarkan buku Bahasa Pemrograman C oleh Kernighan dan Ritchie: en.wikipedia.org/wiki/The_C_Programming_Language_(book) . Dan itu seharusnya tidak membuat Anda dimodelkan.
jmucchiello

Terima kasih! Saya pikir itu hanya selera pribadi. Saya dulu menganggap sintaks ini mengganggu diri saya sendiri, tetapi saya mengadopsinya setelah membaca Kode Lengkap, dan sangat menikmatinya sekarang.
Nathan Prather

Saya membaca semua jawaban di atas, berpikir, "Mengapa belum ada yang menyarankan ini?" Itu membuat bracket penutupan sejajar dengan blok yang ditutup, yaitu "jika" atau "sementara", dll, bukan "{" yang tidak berarti. +1.
nickf

Jika kawat gigi terbuka selalu ditempatkan pada garis sendiri, maka ifyang diikuti oleh garis indentasi tunggal dapat secara visual diakui sebagai mengendalikan pernyataan tunggal tanpa perlu kawat gigi apa pun. Gaya open-brace-by-sendirinya dengan demikian menghemat ruang putih dalam situasi di mana ifpernyataan mengontrol sesuatu yang secara semantik merupakan tindakan tunggal (berbeda dari urutan langkah yang kebetulan hanya berisi satu langkah tunggal). Sebagai contoh, if (someCondition)/ `lempar SomeException (...)` baru.
supercat

6

Katakanlah Anda memiliki beberapa kode:

if (foo)
    bar();

dan kemudian orang lain datang dan menambahkan:

if (foo)
    snafu();
    bar();

Menurut cara ini ditulis, bar (); sekarang dijalankan tanpa syarat. Dengan memasukkan kurung kurawal, Anda mencegah kesalahan tak disengaja semacam ini. Kode harus ditulis sedemikian rupa untuk membuat kesalahan seperti itu sulit atau tidak mungkin dilakukan. Jika saya melakukan review kode dan melihat kawat gigi yang hilang, terutama tersebar di beberapa baris, saya akan membuat cacat. Dalam kasus di mana itu dibenarkan, tetap di satu baris sehingga kemungkinan membuat kesalahan seperti itu dijaga agar tetap minimum.


Poin itu sudah dibuat dalam pertanyaan.
Mike Scott

Sebenarnya tidak cukup. Ya, dia menyebutkan potensi bug semacam ini, tetapi saya berbicara tentang membuat kode Anda anti-bug dan menghapus potensi kesalahan sebagai bagian dari praktik terbaik.
Elie

Apakah benar ada kode bukti bug?
Bob

Tidak, tetapi Anda bisa membuatnya lebih sulit. Baca "Best Kept Secrets of Peer Code Review" oleh Jason Cohen (lihat tautan di samping beberapa halaman di sini) untuk mendapatkan ide yang lebih baik tentang mengapa Anda melakukan ini.
Elie

Siapa Mike Scott ini dan mengapa dia adalah jawaban polisi? Itu selalu membuatku bingung bahwa orang harus menyatakan apa yang jelas. Jadi mengapa Mike tidak terus mengomentari deskripsi tambahan yang pengguna posting tentang masalah ini. Bukankah semua jawaban mengacu pada pertanyaan?
bruceatk

6

Mengurangi garis sebenarnya bukan argumen yang bagus untuk menjatuhkan kawat gigi. Jika metode Anda terlalu besar, itu mungkin harus di refactored menjadi potongan-potongan kecil atau direstrukturisasi. Melakukan itu tidak diragukan lagi akan meningkatkan keterbacaan lebih dari sekadar mengambil kawat gigi.


5

Saya selalu menghilangkannya jika perlu, seperti pada contoh pertama Anda. Bersihkan, kode ringkas yang dapat saya lihat dan pahami dengan melirik lebih mudah untuk mempertahankan, men-debug dan memahami daripada kode yang harus saya gulir dan baca baris demi baris. Saya pikir sebagian besar programmer akan setuju dengan ini.

Sangat mudah untuk keluar dari tangan jika Anda mulai melakukan beberapa sarang, jika / lain klausa dan sebagainya, tapi saya pikir sebagian besar programmer harus bisa mengatakan di mana harus menggambar garis.

Aku melihatnya jenis seperti argumen untuk if ( foo == 0 )vs if ( 0 == foo ). Yang terakhir dapat mencegah bug untuk programmer baru (dan mungkin bahkan kadang-kadang untuk veteran), sedangkan yang pertama lebih mudah untuk dengan cepat membaca dan memahami ketika Anda mempertahankan kode.


4

Sering kali sudah tertanam sebagai standar pengkodean, baik untuk perusahaan atau proyek FOSS.

Pada akhirnya, orang lain perlu mengosongkan kode Anda dan itu adalah waktu yang menguras waktu bagi setiap pengembang untuk mengetahui gaya khusus dari bagian kode yang mereka kerjakan.

Juga, bayangkan bahwa seseorang pergi antara Python dan bahasa Cish lebih dari sekali sehari ... Dalam Python indentasi adalah bagian dari blok symantics bahasa dan akan sangat mudah untuk membuat kesalahan seperti yang Anda kutip.


+1 untuk komentar tentang python. Saya selalu kagum betapa "bodohnya" saya ketika terus beralih antar bahasa.
Kena

3

Kesalahan di sisi yang lebih aman - hanya satu bug lagi yang berpotensi tidak perlu Anda perbaiki.

Saya pribadi merasa lebih aman jika semua balok saya terbungkus keriting. Bahkan untuk one-liners, ini adalah notasi sederhana yang mudah mencegah kesalahan. Itu membuat kode lebih mudah dibaca dalam arti bahwa Anda melihat dengan jelas apa yang ada di blok agar tidak membingungkan tubuh blok dengan pernyataan berikut di luar blok.

Jika saya memiliki satu-liner, saya biasanya memformatnya sebagai berikut:

if( some_condition ) { do_some_operation; }

Jika saluran terlalu rumit maka gunakan yang berikut ini:

if( some_condition )
{
    do_some_operation;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.