Jadi setiap angka dalam kode yang kita kirim ke suatu metode sebagai argumen dianggap sebagai Angka Ajaib? Bagi saya, seharusnya tidak. Saya pikir jika beberapa angka katakanlah itu untuk panjang minimum nama pengguna dan kami mulai menggunakan "6" dalam kode ... maka ya kami memiliki masalah pemeliharaan dan di sini "6" adalah angka ajaib .... tetapi jika kita memanggil metode yang salah satu argumennya menerima bilangan bulat misalnya sebagai anggota ke-i koleksi dan kemudian kita meneruskan "0" ke pemanggilan metode itu, dalam hal ini saya tidak melihat "0" sebagai sihir. jumlah. Apa yang kamu pikirkan?
programming-practices
Blake
sumber
sumber
Jawaban:
Jika arti angka itu sangat jelas dalam konteksnya, saya tidak berpikir itu masalah "angka ajaib".
Contoh: Misalkan Anda mencoba untuk mendapatkan substring dari string, dari awal hingga beberapa token dan kode terlihat seperti ini (bahasa imajiner dan perpustakaan):
Dalam konteks ini, arti angka 0 cukup jelas. Saya kira Anda dapat mendefinisikan
START_OF_SUBSTRING
dan menetapkannya ke 0, tetapi dalam kasus ini saya pikir itu akan berlebihan (meskipun itu akan menjadi pendekatan yang benar jika Anda tahu bahwa awal substring Anda mungkin tidak 0, tetapi itu tergantung pada spesifikasi dari situasi Anda).Contoh lain mungkin jika Anda mencoba menentukan apakah suatu bilangan genap atau ganjil. Penulisan:
tidak seaneh:
Menguji angka negatif sebagai
juga terasa aneh bagi saya, saya lebih suka melihat
sumber
360
untuk menandai rotasi penuh dengan pemahaman bahwa kebanyakan orang akan tahu apa artinya (meskipun ini adalah kasus di mana tidak ada ruginya memberikan konstanta)0
dalam konteks contoh substring saya. Dalam hal ini, mungkin ini setidaknya jumlah kerusakan yang mereka dapat menyebabkan. Sudah lama sejak saya melakukan pengkodean yang melakukan perhitungan geometris, tetapi umumnya, nilai 15, 30, 45, 60, 90, 180, 360 adalah konstanta yang diterima. Saya belum pernah melihat orang yang mendefinisikanFIFTEEN_DEGREES
, ...Jelas nol berarti tidak ada. Saya menemukan 0 lebih mudah dipahami daripada variabel bernama "absen".
Jelas 0 adalah posisi awal. Saya akan bingung dengan variabel bernama "firstPosition". Variabel seperti itu akan membuat saya bertanya-tanya apakah posisi awal bisa berubah.
sumber
Saya akan menyarankan tiga faktor utama dalam memutuskan apakah sesuatu harus merupakan deklarasi konstan:
Sesuatu seperti pi mungkin harus ditulis sebagai konstanta bernama, bukan sebagai literal numerik, karena literal numerik cenderung tidak perlu bertele-tele, tidak perlu tidak tepat, atau keduanya. Sesuatu seperti jumlah slot dalam cache kemungkinan harus berupa konstanta bernama (meskipun lihat catatan di bawah) untuk memungkinkan kemungkinan memperluas cache tanpa harus memodifikasi semua kode yang menggunakannya. Hal-hal seperti angka "4", "28", dan "29" dalam pernyataan
if ((year % 4)==0) FebruaryDays = 29; else FebruaryDays = 28;
itu mungkin tidak boleh disebut konstanta, karena ungkapan itu hampir pasti lebih mudah dibaca daripadaif ((year % YearsBetweenLeapYears)==0) FebruaryDays = FebruaryDaysInLeapYear; else FebruaryDays = FebruaryDaysInNonLeapYear;
. Perhatikan bahwa pengelola standar telah mengindikasikan bahwa panjang Februari 2100 di tahun itu tidak akan cocok dengan rumus di atas, halangan untuk menangani tanggal dengan benar (mis. kode tidak akan tersandung oleh integer overflow atau masalah lainnya)Peringatan penting dengan aturan # 2 adalah bahwa dalam beberapa kasus kode dapat mengandalkan angka-angka hard-code dengan cara yang tidak dapat dengan mudah diwakili oleh konstanta bernama. Sebagai contoh, suatu metode yang menghitung produk silang dari dua vektor yang dilewatkan sebagai parameter diskrit hanya akan bermakna ketika digunakan pada vektor tiga dimensi. Jumlah dimensi yang diperlukan bukanlah nilai yang dapat diubah secara bermakna tanpa sepenuhnya menulis ulang rutinitas. Bahkan jika seseorang meramalkan kemungkinan kebutuhan untuk menghitung produk silang dari tiga vektor 4-dimensi, menggunakan konstanta bernama untuk nilai "3" tidak akan banyak membantu membuatnya lebih mudah untuk memenuhi kebutuhan itu.
sumber
Ini, seperti semua prinsip, adalah masalah derajat. Secara umum, jumlah literal dalam kode sumber lebih dicurigai semakin besar. Panjang maksimum seperti 10 atau alamat memori seperti 0x587FB0 jelas merupakan praktik yang buruk - hampir pasti bahwa cepat atau lambat Anda harus mengulangi nilai-nilai ini lebih dari sekali, menciptakan risiko ketidakcocokan dan kesalahan halus yang diperkenalkan di tempat-tempat yang tidak berubah.
0 berada di ujung skala; itu masih mencurigakan tetapi tidak sebanyak. Apakah Anda menggunakan 0 sebagai nilai sentinel? Maka Anda mungkin harus menggunakan konstanta simbolis sebagai gantinya, hanya karena konstanta dapat menjelaskan apa artinya. Apakah ini perjanjian budaya yang sangat mengakar seperti "0 berarti penyelesaian yang sukses"? Itu mungkin baik. Apakah ini berarti "item pertama dalam koleksi"? Itu mungkin tidak berbahaya, tetapi jika ada metode alternatif seperti
first()
saya mungkin lebih suka itu.sumber
Setiap angka yang tidak disebutkan namanya yang tidak segera terlihat dari konteks adalah angka ajaib. Agak konyol untuk mendefinisikan angka-angka yang memiliki makna yang segera jelas dari konteks.
Dalam Django (kerangka web python), saya dapat mendefinisikan beberapa bidang basis data dengan angka mentah seperti:
yang lebih jelas (dan praktik yang disarankan ) daripada mengatakan
karena saya tidak mungkin perlu mengubah panjang (dan selalu dapat dibandingkan dengan
max_length
bidang). Jika saya perlu mengubah panjang bidang setelah awalnya menyebarkan aplikasi, saya harus mengubahnya tepat satu lokasi per bidang dalam kode Django saya, dan kemudian menulis migrasi untuk mengubah skema DB. Jika saya perlu referensimax_length
bidang yang ditentukan dari jenis objek, saya bisa melakukannya secara langsung - jika bidang-bidang itu mendefinisikanPerson
kelas, saya bisa menggunakanPerson._meta.get_field('firstname').max_length
untuk mendapatkanmax_length
sedang digunakan (yang didefinisikan di satu tempat). Fakta bahwa 40 yang sama digunakan untuk banyak bidang tidak relevan karena saya mungkin ingin mengubahnya secara mandiri. Panjang nama depan tidak boleh bergantung pada panjang middlename atau nama belakang; mereka adalah nilai yang terpisah dan dapat berubah secara independen.Seringkali indeks array dapat menggunakan angka yang tidak disebutkan namanya; seperti jika saya memiliki file data CSV yang ingin saya masukkan ke dalam kamus python, dengan elemen pertama di baris sebagai kamus yang
key
akan saya tulis:Tentu saya bisa memberi nama
index_column = 0
dan melakukan sesuatu seperti:atau lebih buruk menentukan
after_index_col = index_col + 1
untuk menyingkirkanindex_col+1
, tetapi itu tidak membuat kode lebih jelas dalam pandangan saya. Juga, jika saya memberiindex_col
nama, saya lebih baik membuat kode bekerja bahkan jika kolomnya tidak 0 (makarow[:index_col] +
bagian itu).sumber
max_lngth=40
vs.max_length=MAX_LENGTH_NAME
adalah contoh klasik dari angka ajaib yang berteriak menjadi simbol. Hari itu akan tiba ketika Anda ingin mendukung 45 nama karakter, dan sekarang setiap penggunaan "40" dicurigai dan harus diperiksa dengan cermat.40
untuk1
. Anda harus memikirkan konteks.