Saya membaca beberapa catatan kuliah dosen C ++ saya dan dia menulis yang berikut:
- Gunakan Indentasi // OK
- Jangan pernah mengandalkan prioritas operator - Selalu gunakan tanda kurung // OK
- Selalu gunakan blok {} - bahkan untuk satu baris // tidak OK , kenapa ???
- Objek Const di sisi kiri perbandingan // OK
- Gunakan unsigned untuk variabel yang>> 0 // trik yang bagus
- Setel Pointer ke NULL setelah penghapusan - Proteksi penghapusan ganda // tidak buruk
Teknik ke-3 tidak jelas bagi saya: apa yang akan saya dapatkan dengan menempatkan satu baris dalam { ... }
?
Misalnya, ambil kode aneh ini:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}
dan ganti dengan:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
Apa manfaat menggunakan versi 1?
for (unsigned i = 100; i >= 0; --i)
.(i % 2 == 0)
bertentangan (2). Anda mengandalkan prioritas operator, dan artinya tentu saja((i % 2) == 0)
bukan(i % (2 == 0))
. Saya akan mengklasifikasikan aturan 2 sebagai "sentimen yang valid tetapi 'selalu' salah".Jawaban:
Mari kita coba juga memodifikasi
i
ketika kita menambahj
:Oh tidak! Berasal dari Python, ini terlihat ok, tetapi kenyataannya tidak, karena ini setara dengan:
Tentu saja, ini adalah kesalahan konyol, tetapi yang bahkan bisa dilakukan oleh programmer berpengalaman.
Alasan lain yang sangat bagus ditunjukkan dalam jawaban ta.speot.is .
Yang ketiga yang bisa saya pikirkan adalah bersarang
if
:Sekarang, anggap Anda sekarang ingin
doSomethingElse()
ketikacond1
tidak terpenuhi (fitur baru). Begitu:yang jelas salah, karena
else
bergaul dengan batinif
.Sunting: Karena ini mendapat perhatian, saya akan mengklarifikasi pandangan saya. Pertanyaan yang saya jawab adalah:
Yang telah saya jelaskan. Ada beberapa manfaatnya. Tapi, IMO, aturan "selalu" tidak selalu berlaku. Jadi saya tidak sepenuhnya mendukung
Saya tidak mengatakan selalu menggunakan
{}
blok. Jika itu kondisi & perilaku yang cukup sederhana, jangan. Jika Anda mencurigai seseorang akan datang kemudian & mengubah kode Anda untuk menambah fungsionalitas, lakukan.sumber
i++
sebelumnyaj++
, maka kedua variabel akan tetap berada di ruang lingkup ketika mereka digunakan.i++;
cara yang segera menunjukkan bahwa itu bukan bagian dari loop. (Di masa lalu, ini mungkin argumen yang masuk akal, dan saya telah melihat masalah seperti itu. Sekitar 20 tahun yang lalu. Tidak sejak itu.)Sangat mudah untuk secara tidak sengaja mengubah aliran kontrol dengan komentar jika Anda tidak menggunakan
{
dan}
. Sebagai contoh:Jika Anda berkomentar
do_something_else()
dengan komentar satu baris, Anda akan berakhir dengan ini:Itu mengkompilasi, tetapi
must_always_do_this()
tidak selalu disebut.Kami memiliki masalah ini di basis kode kami, tempat seseorang masuk untuk menonaktifkan beberapa fungsi dengan sangat cepat sebelum dirilis. Untungnya kami menangkapnya dalam ulasan kode.
sumber
must_always_do_this();
akan dieksekusi jika Anda berkomentar // do_something_else ();if(debug) \n //print(info);
. Pada dasarnya mengeluarkan seluruh perpustakaan.Fortunately we caught it in code review.
Aduh! Kedengarannya salah.Fortunately we caught it in unit tests.
akan jauh lebih baik!Saya memiliki keraguan terhadap kompetensi dosen. Mempertimbangkan poinnya:
(b*b) - ((4*a)*c)
? Beberapa prioritas sudah jelas (atau seharusnya), dan kurung tambahan hanya menambah kebingungan. (Di sisi lain, Anda _harus_ menggunakan tanda kurung dalam kasus yang kurang jelas, bahkan jika Anda tahu bahwa mereka tidak diperlukan.){
tidak terlalu terlihat, jadi sebaiknya Anda menganggapnya selalu ada. Namun, pada bagian kedua, saya (dan sebagian besar orang yang bekerja sama dengan saya) tidak memiliki masalah dengan menghilangkan kawat gigi untuk satu pernyataan. (Asalkan, tentu saja, bahwa lekukan itu sistematis dan Anda menggunakan gaya ini secara konsisten. (Dan banyak programmer yang sangat bagus, menulis kode yang sangat mudah dibaca, menghilangkan kawat gigi bahkan ketika memformat cara pertama.)if ( NULL == ptr )
itu cukup jelek untuk menghalangi keterbacaan. Tulis perbandingan secara intuitif. (Yang dalam banyak kasus menghasilkan konstanta di sebelah kanan.) 4 Nya adalah nasihat yang buruk; apa pun yang membuat kode itu tidak alami membuatnya kurang mudah dibaca.int
dicadangkan untuk kasus khusus. Untuk programmer C dan C ++ yang berpengalaman, gunakanunsigned
operator sinyal bit. C ++ tidak memiliki tipe kardinal nyata (atau tipe subrange efektif lainnya);unsigned
tidak berfungsi untuk nilai numerik, karena aturan promosi. Nilai numerik yang tidak memungkinkan operasi aritmatika masuk akal, seperti nomor seri, mungkin bisa terjadiunsigned
. Saya membantahnya, karena mengirimkan pesan yang salah: operasi bitwise juga tidak masuk akal. Aturan dasarnya adalah tipe integral adalahint
_unless_, ada alasan signifikan untuk menggunakan tipe lain.delete this;
seringkali merupakan kasus yang paling sering (dan Anda tidak dapat mengaturthis
keNULL
), dan sebaliknya, sebagiandelete
besar dalam destruktor, sehingga Anda tidak dapat mengakses pointer nanti. Dan mengaturnya agarNULL
tidak melakukan apa-apa tentang pointer lain yang beredar. Mengatur pointer secara sistematis untukNULL
memberikan rasa aman palsu, dan tidak benar-benar membelikan Anda apa pun.Lihatlah kode di salah satu referensi umum. Stroustrup melanggar setiap aturan yang Anda berikan kecuali yang pertama, misalnya.
Saya sarankan Anda mencari dosen lain. Orang yang benar-benar tahu apa yang dia bicarakan.
sumber
delete this
, apakah ini lebih umum daripada yang saya lihat? Saya tidak cenderung berpikir menetapkan pointer ke NULL setelah digunakan adalah hal yang buruk untuk dilakukan selain YMMV. Mungkin hanya saya, tetapi sebagian besar pedomannya tidak terlalu buruk.if (ptr = NULL)
kecuali Anda menuliskannya sebagaiif ((ptr = NULL))
. Harus setuju dengan James Kanze bahwa keburukan memiliki yangNULL
pertama membuatnya menjadi TIDAK yang pasti bagi saya.unsigned
mengindikasikan aspirasi pada bagian programmer bahwa variabel hanya mewakili angka positif. Pencampuran dengan nomor yang ditandatangani biasanya akan menyebabkan peringatan kompiler yang mungkin apa yang diinginkan dosen.size_t
siapa saja?Semua jawaban lain mempertahankan aturan dosen Anda 3.
Izinkan saya mengatakan bahwa saya setuju dengan Anda: aturannya berlebihan dan saya tidak akan menyarankannya. Memang benar bahwa secara teoritis mencegah kesalahan jika Anda selalu menambahkan kurung keriting. Di sisi lain, saya tidak pernah mengalami masalah ini dalam kehidupan nyata : bertentangan dengan apa yang dinyatakan oleh jawaban lain, saya tidak pernah lupa menambahkan tanda kurung keriting begitu diperlukan. Jika Anda menggunakan indentasi yang tepat, segera menjadi jelas bahwa Anda perlu menambahkan kurung keriting sekali lebih dari satu pernyataan yang indentasi.
Jawaban oleh "Komponen 10" sebenarnya menyoroti satu-satunya kasus yang mungkin di mana ini benar-benar dapat menyebabkan kesalahan. Tetapi di sisi lain, mengganti kode melalui ekspresi reguler selalu membutuhkan perhatian besar.
Sekarang mari kita lihat sisi lain dari medali: adakah kerugian untuk selalu menggunakan kurung keriting? Jawaban lain cukup mengabaikan hal ini. Tapi ada adalah kerugian: tidak memakan banyak ruang layar vertikal, dan ini pada gilirannya dapat membuat kode Anda terbaca karena itu berarti Anda harus gulir lebih dari yang diperlukan.
Pertimbangkan fungsi dengan banyak klausa penjaga di awal (dan ya, berikut ini adalah kode C ++ yang buruk tetapi dalam bahasa lain ini akan menjadi situasi yang cukup umum):
Ini adalah kode yang mengerikan, dan saya sangat berpendapat bahwa yang berikut ini jauh lebih mudah dibaca:
Demikian pula, loop bersarang pendek manfaat dari menghilangkan kurung keriting:
Dibandingkan dengan:
Kode pertama adalah ringkas; kode kedua membengkak.
Dan ya, ini dapat dikurangi sampai batas tertentu dengan menempatkan brace pembuka pada baris sebelumnya. Tapi itu masih kurang dibaca daripada kode tanpa tanda kurung keriting.
Singkatnya: jangan menulis kode yang tidak perlu yang memakan ruang layar.
sumber
if (a == nullptr) { throw null_ptr_error("a"); }
sebagai satu baris.Basis kode yang saya kerjakan tersebar dengan kode oleh orang-orang dengan keengganan patologis terhadap kawat gigi, dan bagi orang-orang yang datang kemudian, itu benar-benar dapat membuat perbedaan untuk pemeliharaan.
Contoh bermasalah yang paling sering saya temui adalah ini:
Jadi ketika saya datang dan ingin menambahkan pernyataan saat itu, saya dapat dengan mudah berakhir dengan ini jika saya tidak hati-hati:
Mengingat bahwa diperlukan ~ 1 detik untuk menambahkan kawat gigi dan dapat menghemat setidaknya beberapa menit debugging yang membingungkan, mengapa Anda tidak akan menggunakan opsi ambiguitas yang dikurangi? Sepertinya ekonomi palsu bagi saya.
sumber
if(really long...editor){ do_foo;}
membantu Anda menghindari kasus ini? Sepertinya masalahnya masih akan sama. Secara pribadi saya lebih suka menghindari kawat gigi ketika tidak perlu, namun itu tidak ada hubungannya dengan waktu yang dibutuhkan untuk menulisnya tetapi mengurangi keterbacaan karena dua baris tambahan dalam kode2c saya:
Jelas sekali
Saya tidak akan menggunakan kata "tidak pernah dan" selalu ", tetapi secara umum saya melihat aturan ini berguna. Dalam beberapa bahasa (Lisp, Smalltalk) ini bukan masalah.
Saya tidak pernah melakukan itu dan tidak pernah memiliki masalah tunggal, tetapi saya bisa melihat bagaimana itu bisa baik bagi siswa, khususnya. jika mereka mempelajari Python sebelumnya.
Kondisi yoda? Tidak, kumohon. Itu menyakitkan keterbacaan. Cukup gunakan level peringatan maksimum ketika Anda mengkompilasi kode Anda.
BAIK. Cukup lucu, saya pernah mendengar Stroustrup tidak setuju.
Saran yang buruk! Tidak pernah memiliki pointer yang menunjuk ke objek yang dihapus atau tidak ada.
sumber
unsigned
rusak", salah satu masalahnya adalah ketika C ++ membandingkan jenis yang ditandatangani dan tidak ditandatangani yang berukuran sama, itu dikonversi ke yang tidak ditandatangani sebelum melakukan perbandingan. Yang menghasilkan perubahan nilai. Mengubah ke yang sudah ditandatangani tidak selalu jauh lebih baik; perbandingan harus benar-benar terjadi "seolah-olah" kedua nilai dikonversi ke tipe yang lebih besar yang dapat mewakili semua nilai dalam kedua jenis.unsigned
. Saya yakin dia tidak memiliki masalah denganexp(double)
mengembalikan nilai lebih dariMAX_INT
:-). Tetapi sekali lagi, masalah sebenarnya adalah konversi implisit.int i = exp( 1e6 );
benar-benar valid C ++. Stroustrup sebenarnya mengusulkan penghentian konversi implisit lossy pada satu titik, tetapi komite tidak tertarik. (Sebuah pertanyaan menarik: apakahunsigned
->int
dianggap lossy. Saya akan mempertimbangkan keduanyaunsigned
->int
danint
->unsigned
lossy. Yang mana akan membuatunsigned
OKitu lebih intuitif dan mudah dimengerti. Itu membuat maksudnya jelas.
Dan itu memastikan bahwa kode tidak rusak ketika pengguna baru mungkin secara tidak sadar melewatkannya
{
,}
sambil menambahkan pernyataan kode baru.sumber
Makes the intent clear
+1, ini mungkin alasan paling ringkas dan akurat.Untuk menambah saran yang sangat masuk akal di atas, satu contoh yang saya temui saat refactoring beberapa kode di mana ini menjadi kritis adalah sebagai berikut: Saya mengubah basis kode yang sangat besar untuk beralih dari satu API ke yang lain. API pertama memiliki panggilan untuk menetapkan Id Perusahaan sebagai berikut:
sedangkan penggantian membutuhkan dua panggilan:
Saya mulai mengubah ini menggunakan ekspresi reguler yang sangat sukses. Kami juga melewati kode melalui astyle , yang membuatnya sangat mudah dibaca. Kemudian, sebagian dari proses peninjauan, saya menemukan bahwa dalam beberapa kondisi bersyarat itu mengubah ini:
Untuk ini:
yang jelas bukan apa yang dibutuhkan. Saya harus kembali ke awal melakukan ini lagi dengan memperlakukan penggantian sebagai sepenuhnya dalam satu blok dan kemudian secara manual mengubah apa pun yang akhirnya tampak konyol (setidaknya itu tidak akan salah.)
Saya perhatikan bahwa astyle sekarang memiliki opsi
--add-brackets
yang memungkinkan Anda untuk menambahkan tanda kurung di mana tidak ada tanda kurung dan saya sangat merekomendasikan ini jika Anda pernah berada di posisi yang sama dengan saya.sumber
#define FOO() func1(); \ func2();
(dengan linebreak setelah garis miring terbalik), hal yang sama berlaku untuk pencarian dan penggantian. Yang mengatakan, saya telah melihat "selalu menggunakan kawat gigi" maju sebagai aturan gaya justru karena itu menyelamatkan Anda dari membungkus semua makro multi-pernyataan Andado .. while(0)
. Tapi saya tidak setuju.inline
), maka Anda mungkin harus bertujuan agar mereka bekerja sebanyak mungkin fungsi, menggunakando { ... } while(0)
trik jika perlu (dan banyak tanda kurung tambahan. Tapi itu masih tidak akan tidak akan menghentikan Anda dari menggunakan kawat gigi di mana-mana, jika itu adalah gaya rumah (FWIW: Saya telah bekerja di tempat-tempat dengan gaya rumah yang berbeda-beda, mencakup semua gaya yang dibahas di sini. Saya tidak pernah menemukan ada yang menjadi masalah serius.)Saya menggunakan di
{}
mana - mana kecuali beberapa kasus yang jelas. Satu baris adalah salah satu kasus:Mungkin menyakitkan Anda ketika Anda menambahkan beberapa metode sebelum kembali. Lekukan menunjukkan bahwa pengembalian sedang dieksekusi ketika kondisi terpenuhi, tetapi itu akan selalu kembali.
Contoh lain dalam C # dengan menggunakan statment
yang setara dengan
sumber
using
pernyataan dan Anda tidak perlu :)using
).Contoh paling relevan yang dapat saya pikirkan:
Dengan yang mana
if
akanelse
dipasangkan? Lekukan menyiratkan bahwa bagian luarif
mendapatkanelse
, tetapi itu tidak benar-benar bagaimana kompiler akan melihatnya; bagian dalamif
akan mendapatkan bagian luarelse
, dan bagian luarif
tidak. Anda harus tahu itu (atau melihatnya berperilaku seperti itu dalam mode debugging) untuk mencari tahu dengan memeriksa mengapa kode ini mungkin gagal sesuai harapan Anda. Semakin membingungkan jika Anda tahu Python; dalam hal ini Anda tahu bahwa lekukan mendefinisikan blok kode, jadi Anda akan mengharapkannya untuk mengevaluasi sesuai dengan lekukan. C #, bagaimanapun, tidak memberikan flip terbang tentang spasi.Sekarang, yang mengatakan, saya tidak terlalu setuju dengan aturan "selalu gunakan tanda kurung" di wajahnya. Itu membuat kode sangat vertikal berisik, mengurangi kemampuan untuk membacanya dengan cepat. Jika pernyataannya adalah:
... maka harus ditulis seperti ini. Pernyataan "selalu menggunakan tanda kurung" terdengar seperti "selalu mengelilingi operasi matematika dengan tanda kurung". Itu akan mengubah pernyataan yang sangat sederhana
a * b + c / d
menjadi((a * b) + (c / d))
, memperkenalkan kemungkinan kehilangan orang dekat (kutukan banyak pengkode), dan untuk apa? Urutan operasi dikenal dan ditegakkan dengan baik, sehingga tanda kurung berlebihan. Anda hanya menggunakan tanda kurung untuk menjalankan urutan operasi yang berbeda dari yang biasanya diterapkan:a * (b+c) / d
misalnya. Kawat gigi blok serupa; menggunakannya untuk menentukan apa yang ingin Anda lakukan dalam kasus di mana ia berbeda dari default, dan tidak "jelas" (subyektif, tetapi biasanya cukup masuk akal).sumber
else
dengan yang pertama,if
bukan yang kedua. Silakan hapus downvote.Melihat melalui jawaban tidak ada yang secara eksplisit menyatakan jenis praktik yang saya biasakan, menceritakan kisah kode Anda:
Menjadi:
Menempatkan
j++
di baris yang sama dengan jika harus memberi sinyal kepada orang lain, "Saya hanya ingin blok ini terus bertambahj
" . Dari coursethis hanya bermanfaat jika garis adalah sebagai sederhana mungkin, karena menempatkan breakpoint di sini, seperti peri menyebutkan, tidak akan menjadi sangat berguna.Sebenarnya saya baru saja menjalankan bagian dari Twitter Storm API yang memiliki 'semacam' kode ini di java, di sini adalah potongan kode dari kode eksekusi, di halaman 43 dari tayangan slide ini :
Blok loop for memiliki dua hal di dalamnya, jadi saya tidak akan inline kode itu. Yaitu tidak pernah :
Ini mengerikan dan saya bahkan tidak tahu apakah itu berfungsi (sebagaimana dimaksud); jangan lakukan ini . Baris dan kawat gigi baru membantu membedakan bagian kode yang terpisah tetapi terkait, dengan cara yang sama seperti koma atau semi-kolon dalam prosa. Blok di atas sama buruknya dengan kalimat yang sangat panjang dengan beberapa klausa dan beberapa pernyataan lain yang tidak pernah putus atau jeda untuk membedakan bagian yang terpisah.
Jika Anda benar-benar ingin mengirim telegraf ke orang lain, itu hanya pekerjaan satu jalur saja menggunakan operator atau
?:
formulir ternary :Tapi ini sedang dalam kode-golf, dan saya pikir ini bukan latihan yang bagus (Tidak jelas bagi saya apakah saya harus meletakkan j ++ di satu sisi
:
atau tidak). NB Saya belum menjalankan operator ternary di C ++ sebelumnya, saya tidak tahu apakah ini berfungsi, tetapi memang ada .Pendeknya:
Bayangkan bagaimana pembaca Anda (yaitu orang yang mempertahankan kode) menafsirkan cerita Anda (kode) Buat sejelas mungkin bagi mereka. Jika Anda tahu kode pemula / siswa mempertahankan ini, mungkin bahkan meninggalkan sebanyak
{}
mungkin, supaya mereka tidak bingung.sumber
for
loop Anda pada satu baris, mengapa ini tidak berhasil? Ini bekerja karena alasan yang sama bahwa Anda dapat menghilangkan kawat gigi; baris baru tidak signifikan dalam C ++. (3) Contoh operator kondisional Anda, selain mengerikan, tidak valid C ++.Karena ketika Anda memiliki dua pernyataan tanpa
{}
, mudah untuk melewatkan masalah. Anggap kode itu seperti ini.Terlihat baik. Masalahnya sangat mudah untuk dilewatkan, terutama ketika fungsi yang mengandung kode jauh lebih besar. Masalahnya adalah yang
goto fail
dijalankan tanpa syarat. Anda dapat dengan mudah membayangkan betapa frustrasinya ini (membuat Anda bertanya mengapa yang terakhirhash_update
selalu gagal, setelah semuanyahash_update
berfungsi dengan baik).Namun, itu tidak berarti saya menambahkan di
{}
mana-mana (menurut saya, melihat di{}
mana - mana itu mengganggu). Meskipun dapat menyebabkan masalah, itu tidak pernah terjadi pada proyek saya sendiri, karena gaya pengkodean pribadi saya melarang persyaratan tanpa{}
ketika mereka tidak berada pada baris yang sama (ya, saya setuju bahwa gaya pengkodean saya tidak konvensional, tapi saya suka, dan saya gunakan gaya kode proyek saat berkontribusi ke proyek lain). Ini membuat kode berikut baik-baik saja.Tapi bukan yang berikut.
sumber
Itu membuat kode Anda lebih mudah dibaca dengan mendefinisikan dengan jelas ruang lingkup loop dan blok bersyarat Anda. Ini juga menyelamatkan Anda dari kesalahan yang tidak disengaja.
sumber
wrt 6: Lebih aman karena menghapus pointer nol adalah larangan. Jadi, jika Anda secara tidak sengaja melewati jalur itu dua kali, Anda tidak akan menyebabkan korupsi memori menjadi membebaskan memori yang bebas atau telah dialokasikan untuk sesuatu yang lain.
Ini adalah sebagian besar masalah dengan objek ruang lingkup file statis dan lajang yang tidak memiliki masa hidup yang sangat jelas dan telah diketahui dapat diciptakan kembali setelah mereka dihancurkan.
Dalam kebanyakan kasus, Anda dapat menghindari kebutuhan ini dengan menggunakan auto_ptrs
sumber
NULL
setelah menghapusnya. JikaNULL
ada nilai yang benar untuk pointer dalam keadaan seperti itu; misalnya pointer menunjuk ke nilai cache, danNULL
menunjukkan cache yang tidak valid. Tetapi ketika Anda melihat seseorang menetapkan pengaturan sebuah penunjukNULL
sebagai baris terakhir dalam destruktor, Anda bertanya-tanya apakah dia tahu C ++.)Saya suka jawaban Luchian yang diterima, sebenarnya saya belajar dengan cara yang sulit bahwa dia benar, jadi saya selalu menggunakan kawat gigi, bahkan untuk blok baris tunggal. Namun, secara pribadi saya membuat pengecualian saat menulis filter, seperti Anda dalam contoh Anda. Ini:
terlihat berantakan bagiku. Ini memisahkan for for dan pernyataan if menjadi tindakan yang terpisah, ketika maksud Anda sebenarnya adalah tindakan tunggal: untuk menghitung semua bilangan bulat yang dapat dibagi dengan 2. Dalam bahasa yang lebih ekspresif, ini dapat dituliskan seperti:
Dalam bahasa yang tidak memiliki penutupan, filter tidak dapat diekspresikan dalam satu pernyataan, tetapi harus berupa for for diikuti oleh pernyataan if. Namun, itu masih satu tindakan dalam pikiran programmer, dan saya percaya itu harus tercermin dalam kode, seperti:
sumber
for (int i = 0; i < 100; i += 2);
, demi melanjutkan argumen tentang indentasi ;-) Mungkin ada bunfight terpisah yang bisa kita miliki, bagaimana "terbaik" untuk mengekspresikan logika "untuk masing-masingi
dalam rentang tertentu dengan properti tertentu" di C ++ tanpa loop, menggunakan beberapa kombinasi mimpi buruk dari algoritma standar,filter_iterator
dan / ataucounting_iterator
.i
dalam kisaran tertentu dengan properti tertentu". Hanya saja biasanya pada SO, orang-orang sangat cepat mengabaikan pertanyaan yang sebenarnya dalam mendukung pendekatan yang sama sekali berbeda dengan contoh yang diberikan. Tapi indentasi itu penting , jadi kita tidak ;-)Salah satu opsi untuk membantu mencegah kesalahan yang telah dijelaskan di atas adalah untuk menjelaskan apa yang Anda inginkan terjadi ketika Anda tidak menggunakan kawat gigi. Itu membuatnya lebih sulit untuk tidak melihat kesalahan ketika Anda mencoba mengubah kode.
sumber
else
tidak terkait denganif
.Jika Anda seorang kompiler, itu tidak ada bedanya. Keduanya sama.
Tetapi untuk programmer, yang pertama lebih jelas, mudah dibaca dan lebih rentan kesalahan.
sumber
{
di jalurnya sendiri, toh.Contoh lain dari menambahkan kurung kurawal. Pernah saya mencari bug dan menemukan kode seperti itu:
Jika Anda membaca metode baris demi baris, Anda akan melihat bahwa ada kondisi dalam metode yang kembali jika itu tidak benar. Tetapi sebenarnya ini terlihat seperti 100 penangan event sederhana lainnya yang menetapkan beberapa variabel berdasarkan beberapa kondisi. Dan suatu hari Fast Coder masuk dan menambahkan pernyataan pengaturan variabel tambahan di akhir metode:
Akibatnya, SetAnotherVariableUnconditionnaly dieksekusi ketika SomeConditionIsMet (), tetapi orang cepat tidak menyadarinya karena semua garis hampir sama ukurannya dan bahkan ketika kondisi pengembaliannya indentasi secara vertikal, itu tidak terlalu terlihat.
Jika pengembalian bersyarat diformat seperti ini:
itu jauh terlihat dan Fast Coder akan menemukannya dalam sekejap.
sumber
return
pernyataan yang disorot sintaksis dalam tubuh fungsi sebelum menambahkan sesuatu ke dalamnya, Anda tidak boleh membiarkan fast coder mendekati kode Anda. Anda tidak akan menghentikan orang seperti itu untuk mengganggu kode Anda dengan memasukkan kawat gigi.Saya menganggap yang pertama menjadi jelas kemudian kedua. Ini memberi perasaan menutup instruksi, dengan sedikit kode baik-baik saja ketika kode menjadi kompleks
{...}
banyak membantu bahkan jika ituendif
ataubegin...end
sumber
Yang terbaik adalah mengatur pointer ke NULL ketika Anda selesai menggunakannya.
Berikut ini contohnya:
Kelas A melakukan hal berikut:
Kelas B melakukan hal berikut
Pada titik ini baik Kelas A dan Kelas B memiliki pointer yang menunjuk ke blok memori yang sama, sejauh Kelas A yang bersangkutan blok memori ini tidak ada karena sudah selesai dengan itu.
Pertimbangkan masalah berikut:
Bagaimana jika ada kesalahan logika di Kelas A yang membuatnya menulis ke memori yang sekarang menjadi milik Kelas B?
Dalam contoh khusus ini, Anda tidak akan mendapatkan kesalahan pengecualian akses yang buruk karena alamat memori legal, sementara itu kelas A sekarang secara efektif merusak data kelas B.
Kelas B pada akhirnya bisa crash jika menemui nilai yang tidak terduga dan ketika itu crash, kemungkinan besar, Anda akan menghabiskan waktu yang cukup lama berburu bug ini di kelas B saat masalahnya ada di kelas A.
Jika Anda telah mengatur pointer memori yang dihapus ke NULL, Anda akan mendapatkan kesalahan pengecualian segera setelah kesalahan logika di Kelas A mencoba menulis ke pointer NULL.
Jika Anda khawatir tentang kesalahan logika dengan penghapusan ganda ketika pointer NULL untuk kedua kalinya, kemudian tambahkan menegaskan untuk ini.
Juga: Jika Anda akan memilih, harap jelaskan.
sumber
Selalu memiliki kurung kurawal adalah aturan yang sangat sederhana dan kuat. Namun kode tersebut mungkin terlihat tidak bagus ketika ada banyak kawat gigi. Jika aturan memungkinkan untuk menghilangkan kurung kurawal maka harus ada aturan gaya yang lebih rinci dan alat yang lebih canggih. Kalau tidak, itu dapat dengan mudah mengakibatkan kode kacau dan membingungkan (tidak elegan). Oleh karena itu mencari aturan gaya tunggal yang terpisah dari panduan gaya lainnya dan alat yang digunakan kemungkinan tidak membuahkan hasil. Saya hanya akan membawa beberapa detail penting tentang aturan # 3 yang bahkan belum disebutkan dalam jawaban lain.
Detail menarik pertama adalah bahwa sebagian besar pendukung aturan itu setuju untuk melanggarnya
else
. Dengan kata lain mereka tidak menuntut kode yang ditinjau:Sebaliknya, jika mereka melihatnya mereka bahkan mungkin menyarankan untuk menulisnya seperti itu:
Itu secara teknis melanggar aturan itu karena tidak ada tanda kurung antara
else
danif
. Dualitas aturan tersebut muncul ketika mencoba menerapkannya ke basis kode secara otomatis dengan alat yang tidak ada artinya. Memang, mengapa harus berdebat, biarkan saja alat untuk menerapkan gaya secara otomatis.Detail kedua (yang juga sering dilupakan oleh pendukung aturan itu) adalah bahwa kesalahan yang mungkin terjadi tidak pernah hanya karena pelanggaran aturan # 3 itu. Sebenarnya itu hampir selalu melibatkan pelanggaran aturan # 1 juga (yang tidak ada yang membantah). Sekali lagi dari sudut pandang alat otomatis, tidak sulit untuk membuat alat yang langsung mengeluh ketika aturan # 1 dilanggar dan sebagian besar kesalahan dapat ditangkap tepat waktu.
Detail ketiga (yang sering dilupakan oleh penentang aturan itu) adalah sifat pernyataan kosong yang membingungkan yang diwakili oleh satu titik koma. Sebagian besar pengembang dengan beberapa pengalaman menjadi bingung cepat atau lambat oleh satu titik koma yang salah tempat atau dengan pernyataan kosong yang ditulis menggunakan titik koma tunggal. Dua kawat gigi keriting bukannya titik koma tunggal secara visual lebih mudah dikenali.
sumber
Saya harus mengakui bahwa tidak selalu digunakan
{}
untuk satu baris, tetapi ini adalah praktik yang baik.Katakanlah Anda menulis kode tanpa tanda kurung yang terlihat seperti ini:
untuk (int i = 0; i <100; ++ i) untuk (int j = 0; j <100; ++ j) DoSingleStuff ();
Dan setelah beberapa waktu Anda ingin menambahkan dalam
j
lingkaran beberapa hal lain dan Anda hanya melakukannya dengan menyelaraskan dan lupa untuk menambahkan tanda kurung.Kesepakatan memori lebih cepat. Katakanlah Anda memiliki ruang lingkup besar dan membuat array besar di dalamnya (tanpa
new
begitu mereka berada di tumpukan). Array tersebut dikeluarkan dari memori setelah Anda meninggalkan ruang lingkup. Tetapi ada kemungkinan bahwa Anda menggunakan array itu di satu tempat dan akan berada di tumpukan untuk sementara waktu dan menjadi semacam sampah. Karena stack memiliki ukuran terbatas dan sangat kecil, maka dimungkinkan untuk melebihi ukuran stack. Jadi dalam beberapa kasus lebih baik menulis{}
untuk mencegah hal itu. CATATAN ini bukan untuk jalur tunggal tetapi untuk situasi seperti ini:if (...) {// SomeStuff ... {// kita tidak punya if, while, etc. // SomeOtherStuff} // SomeMoreStuff}
Cara ketiga untuk menggunakannya mirip dengan yang kedua. Hanya saja tidak membuat stack cleaner tetapi untuk membuka beberapa fungsi. Jika Anda menggunakan
mutex
fungsi yang panjang biasanya lebih baik mengunci dan membuka kunci sebelum mengakses data dan setelah selesai membaca / menulis itu. CATATAN cara ini digunakan jika Anda memiliki beberapa milik Anda sendiriclass
ataustruct
denganconstructor
dandestructor
untuk mengunci memori.Apa yang lebih:
if (...) if (...) SomeStuff (); lain SomeOtherStuff (); // pergi ke yang kedua jika, tetapi alligment menunjukkan itu pada yang pertama ...
Semua Dalam Semua, saya tidak bisa mengatakan, apa cara terbaik untuk selalu menggunakan
{}
untuk satu baris tetapi tidak ada yang buruk untuk melakukan itu.EDIT PENTING Jika Anda menulis kompilasi kode kurung untuk satu baris tidak melakukan apa-apa, tetapi jika kode Anda akan ditafsirkan itu memperlambat kode untuk sangat sedikit. Sangat sedikit.
sumber
Ada sejumlah cara yang memungkinkan untuk menulis pernyataan kontrol; kombinasi tertentu dari mereka dapat hidup berdampingan tanpa mengganggu keterbacaan, tetapi kombinasi lainnya akan menyebabkan masalah. Gaya
akan hidup berdampingan dengan nyaman dengan beberapa cara lain menulis pernyataan kontrol, tetapi tidak begitu baik dengan yang lain. Jika pernyataan yang dikontrol multi-garis ditulis sebagai:
maka akan jelas secara visual
if
pernyataan mana yang mengendalikan satu baris dan mana yang mengendalikan banyak baris. Namun, jikaif
pernyataan multi-baris ditulis sebagai:maka kemungkinan seseorang mencoba untuk memperluas
if
konstruksi pernyataan tunggal tanpa menambahkan kawat gigi yang diperlukan mungkin jauh lebih tinggi.Pernyataan baris-pernyataan-ke-berikutnya
if
juga mungkin bermasalah jika basis kode menggunakan signifikan formulirPreferensi saya sendiri adalah bahwa memiliki pernyataan pada jalurnya sendiri umumnya meningkatkan keterbacaan kecuali dalam kasus di mana ada banyak
if
pernyataan dengan blok kontrol yang sama, misalnyadalam hal ini saya biasanya akan mendahului dan mengikuti kelompok
if
pernyataan seperti itu dengan garis kosong untuk memisahkan mereka secara visual dari kode lain. Memiliki serangkaian pernyataan yang semuanya dimulai denganif
lekukan yang sama kemudian akan memberikan indikasi visual yang jelas bahwa ada sesuatu yang tidak biasa.sumber