Kita semua tahu bahwa angka ajaib (nilai kode keras) dapat mendatangkan malapetaka dalam program Anda, terutama ketika saatnya untuk memodifikasi bagian kode yang tidak memiliki komentar, tetapi di mana Anda menggambar garis?
Misalnya, jika Anda memiliki fungsi yang menghitung jumlah detik antara dua hari, apakah Anda menggantinya
seconds = num_days * 24 * 60 * 60
dengan
seconds = num_days * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE
Pada titik apa Anda memutuskan bahwa itu benar-benar jelas apa artinya nilai yang dikodekan dan biarkan saja?
refactoring
coding-standards
maintainability
oosterwal
sumber
sumber
seconds = CALC_SECONDS(num_days);
TimeSpan.FromDays(numDays).Seconds;
HOURS_PER_DAY will never need to be altered
), Anda tidak akan pernah mengkode perangkat lunak yang digunakan di Mars. : PJawaban:
Ada dua alasan untuk menggunakan konstanta simbolik alih-alih literal angka:
Untuk menyederhanakan perawatan jika angka ajaib berubah. Ini tidak berlaku untuk contoh Anda. Sangat tidak mungkin jumlah detik dalam satu jam, atau jumlah jam dalam sehari akan berubah.
Untuk meningkatkan readibility. Ungkapan "24 * 60 * 60" cukup jelas bagi hampir semua orang. "SECONDS_PER_DAY" juga, tetapi jika Anda mencari bug, Anda mungkin harus memeriksa bahwa SECONDS_PER_DAY didefinisikan dengan benar. Ada nilai singkatnya.
Untuk angka ajaib yang muncul tepat sekali, dan tidak tergantung pada sisa program, memutuskan apakah akan membuat simbol untuk angka itu adalah masalah selera. Jika ada keraguan, silakan dan buat simbol.
Jangan lakukan ini:
sumber
publid final int FOUR = 3;
public static int THREE = 3;
... note - nofinal
!Saya akan menjaga aturan tidak pernah memiliki angka ajaib.
Sementara
Sangat mudah dibaca sebagian besar waktu, setelah dikodekan selama 10 jam sehari selama tiga atau empat minggu dalam mode crunch
jauh lebih mudah dibaca.
Saran FrustratedWithFormsDesigner lebih baik:
atau bahkan lebih baik
Hal-hal berhenti menjadi jelas ketika Anda sangat lelah. Kode bertahan .
sumber
Waktu untuk mengatakan tidak hampir selalu. Saat-saat di mana saya merasa lebih mudah untuk hanya menggunakan nomor kode keras di tempat-tempat seperti tata letak UI - menciptakan konstanta untuk penentuan posisi setiap kontrol pada formulir menjadi sangat cubmersone dan melelahkan dan jika kode itu biasanya ditangani oleh perancang UI itu tidak masalah. ... kecuali UI ditata secara dinamis, atau menggunakan posisi relatif untuk beberapa jangkar atau ditulis dengan tangan. Dalam hal ini, saya akan mengatakan lebih baik untuk mendefinisikan beberapa konstanta yang bermakna untuk tata letak. Dan jika Anda memerlukan faktor fudge di sini atau di sana untuk menyelaraskan / memposisikan sesuatu "tepat", itu juga harus didefinisikan.
Tetapi dalam contoh Anda, saya pikir mengganti
24 * 60 * 60
denganDAYS_TO_SECONDS_FACTOR
lebih baik.Saya mengakui bahwa nilai-nilai hard-coded juga OK ketika konteks dan penggunaannya benar-benar jelas. Namun, ini adalah panggilan penilaian ...
Contoh:
Seperti yang ditunjukkan @rmx, menggunakan 0 atau 1 untuk memeriksa apakah daftar kosong, atau mungkin dalam batas loop adalah contoh kasus di mana tujuan konstanta sangat jelas.
sumber
0
atau1
kurasa.if(someList.Count != 0) ...
lebih baik daripadaif(someList.Count != MinListCount) ...
. Tidak selalu, tetapi secara umum.Berhentilah saat Anda tidak dapat menjabarkan arti atau tujuan nomor tersebut.
jauh lebih mudah dibaca daripada hanya menggunakan angka. (Meskipun bisa dibuat lebih mudah dibaca dengan memiliki
SECONDS_PER_DAY
konstanta tunggal , tetapi ini adalah masalah yang sepenuhnya terpisah.)Asumsikan bahwa pengembang yang melihat kode dapat melihat apa yang dilakukannya. Tetapi jangan berasumsi bahwa mereka juga tahu mengapa. Jika konstanta Anda membantu memahami alasannya, lakukanlah. Jika tidak, jangan.
Jika Anda berakhir dengan konstanta terlalu banyak, seperti yang disarankan oleh satu jawaban, pertimbangkan untuk menggunakan file konfigurasi eksternal, karena memiliki puluhan konstanta dalam file tidak benar-benar meningkatkan keterbacaan.
sumber
Saya mungkin akan mengatakan "tidak" untuk hal-hal seperti:
Dan pasti akan mengatakan "tidak" untuk:
sumber
Salah satu contoh terbaik yang saya temukan untuk mempromosikan penggunaan konstanta untuk hal yang jelas seperti
HOURS_PER_DAY
:Kami menghitung berapa lama barang-barang itu duduk dalam antrian pekerjaan seseorang. Persyaratannya didefinisikan secara longgar dan pemrogramnya berkode keras
24
di sejumlah tempat. Akhirnya kami menyadari bahwa itu tidak adil untuk menghukum pengguna karena duduk pada masalah selama 24 jam ketika benar-benar hanya bekerja selama 8 jam sehari. Ketika tugas datang untuk memperbaikinya DAN melihat laporan lain yang mungkin memiliki masalah yang sama, cukup sulit untuk melakukan grep / mencari kode selama 24 akan lebih mudah untuk melakukan grep / mencariHOURS_PER_DAY
sumber
Saya pikir selama jumlahnya benar-benar konstan dan tidak memiliki kemungkinan untuk berubah, itu bisa diterima. Jadi dalam kasus Anda,
seconds = num_days * 24 * 60 * 60
tidak masalah (dengan asumsi tentu saja Anda tidak melakukan sesuatu yang konyol seperti melakukan perhitungan semacam ini dalam satu lingkaran) dan bisa dibilang lebih baik untuk dibaca daripadaseconds = num_days * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE
.Itu ketika Anda melakukan hal-hal seperti ini yang buruk:
lineOffset += 24; // 24 lines to a page
Bahkan jika Anda tidak dapat lagi memasukkan baris pada halaman atau bahkan jika Anda tidak memiliki niat untuk mengubahnya, gunakan variabel konstan sebagai gantinya, karena suatu hari itu akan kembali menghantui Anda. Pada akhirnya, intinya adalah keterbacaan, tidak menyimpan 2 siklus perhitungan pada CPU. Ini bukan lagi tahun 1978 ketika byte berharga diperas untuk semua nilainya.
sumber
Baik-baik saja. Ini bukan angka ajaib karena mereka tidak akan pernah berubah.
Angka apa pun yang dapat secara wajar berubah atau tidak memiliki makna yang jelas harus dimasukkan ke dalam variabel. Yang berarti hampir semuanya.
sumber
seconds = num_days * 86400
masih bisa diterima? Jika nilai seperti itu digunakan beberapa kali dalam banyak file berbeda, bagaimana Anda memverifikasi bahwa seseorang tidak sengaja mengetikseconds = num_days * 84600
di satu atau dua tempat?Saya akan menghindari membuat konstanta (nilai ajaib) untuk mengkonversi nilai dari satu unit ke unit lainnya. Dalam kasus konversi saya lebih suka nama metode berbicara. Dalam contoh ini, ini akan menjadi misalnya
DayToSeconds(num_days)
internal metode tidak perlu nilai-nilai ajaib karena, arti "24" dan "60" jelas.Dalam hal ini saya tidak akan pernah menggunakan detik / menit / jam. Saya hanya akan menggunakan TimeSpan / DateTime.
sumber
Gunakan konteks sebagai parameter untuk memutuskan
Misalnya, Anda memiliki fungsi yang disebut "calculSecondsBetween: aDay dan: anotherDay", Anda tidak perlu melakukan banyak penjabaran tentang apa yang dilakukan angka-angka itu, karena nama fungsi cukup representatif.
Dan pertanyaan lain adalah, manakah kemungkinan untuk menghitungnya dengan cara yang berbeda? Kadang-kadang ada banyak cara untuk melakukan hal yang sama, jadi untuk memandu programmer masa depan dan menunjukkan kepada mereka metode apa yang Anda gunakan, mendefinisikan konstanta dapat membantu mengetahuinya.
sumber