Pada proyek baru-baru ini, saya perlu mengkonversi dari byte ke kilobyte kibibyte . Kode itu cukup mudah:
var kBval = byteVal / 1024;
Setelah menulis itu, saya mendapatkan sisa fungsi bekerja & pindah.
Tetapi kemudian, saya mulai bertanya-tanya apakah saya baru saja memasukkan angka ajaib dalam kode saya. Sebagian dari diriku mengatakan itu baik-baik saja karena jumlahnya adalah konstanta yang tetap dan harus mudah dipahami. Tetapi bagian lain dari diriku berpikir itu akan sangat jelas jika dibungkus dengan konstanta yang didefinisikan seperti BYTES_PER_KBYTE
.
Jadi, apakah bilangan yang dikenal sebagai konstanta benar-benar ajaib atau tidak?
Pertanyaan-pertanyaan Terkait:
Kapan angka merupakan angka ajaib? dan Apakah setiap angka dalam kode dianggap sebagai "angka ajaib"? - mirip, tetapi pertanyaan yang jauh lebih luas dari yang saya tanyakan. Pertanyaan saya terfokus pada angka konstan terkenal yang tidak dibahas dalam pertanyaan itu.
Menghilangkan Angka Ajaib: Kapan waktunya untuk mengatakan "Tidak"? juga terkait, tetapi difokuskan pada refactoring sebagai kebalikan dari apakah angka konstan adalah angka ajaib atau tidak.
sumber
FOUR_HUNDRED_FOUR = 404
,. Saya bekerja pada proyek lain di mana mereka militan tentang menggunakan string konstan daripada literal, sehingga mereka memiliki lusinan baris dalam kode yang tampak seperti,DATABASE = "database"
1024
, karena kalau tidak tim dev Anda akan menghabiskan semua waktu berdebat tentang apakah itu "kilobytes" atau "kibibytes".#define
KIBI
1024,MEBI
seperti 1024 * 1024 ...ZERO=0, ONE=1, TWO=2
dan ketika program porting ke bahasa lain (atau programer tidak mengubah perilaku ketika mengganti bahasa mereka) Anda akan melihatnya di sana juga dan Anda harus berdoa agar tidak ada orang yang mengubahnya keONE=2
...Jawaban:
Tidak semua angka ajaib itu sama.
Saya pikir dalam contoh itu, konstanta itu OK. Masalah dengan angka ajaib adalah ketika angka itu ajaib, yaitu tidak jelas asal usulnya, mengapa nilainya seperti apa adanya, atau apakah nilainya benar atau tidak.
Menyembunyikan 1024 di belakang BYTES_PER_KBYTE juga berarti Anda tidak melihat langsung apakah itu benar atau tidak.
Saya akan mengharapkan siapa pun untuk segera mengetahui mengapa nilainya 1024. Di sisi lain, jika Anda mengubah byte ke megabyte, saya akan mendefinisikan BYTES_PER_MBYTE konstan atau serupa karena konstanta 1.048.576 tidak begitu jelas sehingga 1024 ^ 2, atau bahkan itu benar.
Hal yang sama berlaku untuk nilai-nilai yang ditentukan oleh persyaratan atau standar, yang hanya digunakan di satu tempat. Saya menemukan hanya menempatkan konstanta di tempat dengan komentar ke sumber yang relevan agar lebih mudah ditangani daripada mendefinisikannya di tempat lain dan harus mengejar kedua bagian, misalnya:
Saya menemukan lebih baik daripada
Hanya ketika
SOME_THRESHOLD_VALUE
digunakan di banyak tempat, tradeoff menjadi layak untuk mendefinisikan konstanta, menurut saya.sumber
e^i*pi = -1
jauh lebih eksplisit (lebih baik) daripada2.718^i*3.142 = -1
. Variabel penting dan mereka bukan hanya untuk kode umum. Kode ditulis untuk membaca pertama, kompilasi kedua. Juga, spesifikasi berubah (banyak). Sementara 1024 mungkin tidak harus dalam konfigurasi 3,5 suara seperti seharusnya.1024*1024
tolong!Ada dua pertanyaan yang saya tanyakan dalam hal angka ajaib.
Apakah nomor itu memiliki nama?
Nama berguna karena kita dapat membaca nama dan memahami tujuan nomor di belakangnya. Konstanta penamaan dapat meningkatkan keterbacaan jika nama lebih mudah dipahami daripada nomor yang diganti dan nama konstan adalah singkat.
Jelas, konstanta seperti pi, e, et al. memiliki nama yang bermakna. Nilai seperti 1024 bisa
BYTES_PER_KB
tetapi saya juga berharap bahwa setiap pengembang akan tahu apa artinya 1024. Audiens yang dituju untuk kode sumber adalah pemrogram profesional yang harus memiliki latar belakang untuk mengetahui berbagai kekuatan dua dan mengapa mereka digunakan.Apakah ini digunakan di banyak lokasi?
Sementara nama adalah salah satu kekuatan konstanta, yang lain adalah usabilitas. Jika suatu nilai kemungkinan berubah, itu dapat diubah di satu tempat alih-alih perlu memburunya di beberapa lokasi.
Pertanyaanmu
Dalam hal pertanyaan Anda, saya akan menggunakan nomor apa adanya.
Nama: ada nama untuk nomor itu, tetapi tidak ada yang benar-benar berguna. Ini tidak mewakili konstanta matematika atau nilai yang ditentukan dalam dokumen persyaratan apa pun.
Lokasi: bahkan jika digunakan di banyak lokasi, itu tidak akan pernah berubah, meniadakan manfaat ini.
sumber
Kutipan ini
seperti yang dikatakan oleh Jörg W Mittag menjawab pertanyaan ini dengan cukup baik.
Beberapa angka memang tidak ajaib dalam konteks tertentu. Dalam contoh yang diberikan dalam pertanyaan, satuan ukuran ditentukan oleh nama variabel dan operasi yang terjadi cukup jelas.
Jadi
1024
tidak ajaib karena konteksnya membuatnya sangat jelas bahwa itu adalah nilai yang tepat dan konstan untuk digunakan untuk konversi.Demikian juga contoh:
sama jelas dan tidak ajaib karena diketahui bahwa ada 24 jam dalam sehari.
sumber
24
tetap tidak bisa menggunakannya ! Seperti yang disebutkan Izkata, detik kabisat terasa sakit. Mungkin Anda akan lebih beruntung menggunakan konstanta24
di Mars daripada di Bumi!Poster-poster lain menyebutkan bahwa konversi terjadi 'jelas', tetapi saya tidak setuju. Pertanyaan awal, pada saat ini, termasuk:
Jadi sudah saya tahu penulisnya sedang atau bingung. Halaman Wikipedia menambah kebingungan:
Jadi "Kilobyte" dapat digunakan untuk berarti faktor 1000 dan 1024, dengan satu-satunya perbedaan dalam steno adalah kapitalisasi huruf 'k'. Selain itu, 1024 dapat berarti kilobyte (JEDEC) atau kibibyte (IEC). Mengapa tidak menghancurkan semua kebingungan itu dengan konstanta dengan nama yang bermakna? BTW, utas ini telah sering menggunakan "BYTES_PER_KBYTE", dan itu tidak kalah mendua. KBYTE: apakah itu KIBIBYTE atau KILOBYTE? Saya lebih suka mengabaikan JEDEC dan memiliki
BYTES_PER_KILOBYTE = 1000
danBYTES_PER_KIBIBYTE = 1024
. Tidak ada lagi kebingungan.Alasan mengapa orang-orang seperti saya, dan banyak orang lain di luar sana, memiliki pendapat 'militan' (mengutip komentar di sini) tentang penamaan angka-angka ajaib adalah tentang mendokumentasikan apa yang ingin Anda lakukan, dan menghilangkan ambiguitas. Dan Anda benar-benar memilih unit yang telah menyebabkan banyak kebingungan.
Jika saya melihat:
Maka segera jelas apa yang dimaksudkan penulis lakukan, dan tidak ada ambiguitas. Saya dapat memeriksa konstanta dalam hitungan detik (bahkan jika itu ada di file lain), jadi meskipun itu bukan 'instan', itu cukup dekat untuk instan.
Pada akhirnya, mungkin terlihat jelas ketika Anda menulisnya, tetapi akan menjadi kurang jelas ketika Anda kembali lagi nanti, dan mungkin bahkan lebih tidak jelas ketika orang lain mengeditnya. Dibutuhkan 10 detik untuk membuat konstanta; mungkin butuh setengah jam atau lebih untuk men-debug masalah dengan unit (kode tidak akan melompat keluar pada Anda dan memberi tahu Anda unit salah, Anda harus melakukan matematika sendiri untuk mengetahuinya, dan Anda mungkin akan memburu 10 jalan berbeda sebelum Anda memeriksa unit).
sumber
KB
) secara berbeda tidak akan membantu.Mendefinisikan nama sebagai merujuk pada nilai numerik menunjukkan bahwa setiap kali nilai yang berbeda diperlukan di satu tempat yang menggunakan nama itu, kemungkinan akan dibutuhkan di semua. Ini juga cenderung menyarankan bahwa mengubah nilai numerik yang diberikan pada nama adalah cara yang sah untuk mengubah nilai. Implikasi seperti itu bisa berguna ketika itu benar, dan berbahaya ketika itu salah.
Fakta bahwa dua tempat yang berbeda menggunakan nilai literal tertentu (misalnya 1024) akan lemah menunjukkan bahwa perubahan yang akan mendorong seorang programmer untuk mengubah satu agak mungkin menginspirasi programmer untuk ingin mengubah yang lain, tetapi implikasinya jauh lebih lemah daripada yang akan berlaku jika programmer menetapkan nama ke konstanta seperti itu.
Bahaya besar dengan sesuatu seperti itu
#define BYTES_PER_KBYTE 1024
adalah bahwa hal itu mungkin menyarankan kepada seseorang yang menemukanprintf("File size is %1.1fkB",size*(1.0/BYTES_PER_KBYTE));
bahwa cara aman untuk menggunakan kode ribuan byte adalah dengan mengubah#define
pernyataan. Perubahan seperti itu bisa menjadi bencana, namun, jika misalnya beberapa kode lain yang tidak terkait menerima ukuran objek dalam Kbytes dan menggunakan konstanta itu ketika mengalokasikan buffer untuknya.Mungkin masuk akal untuk menggunakan
#define BYTES_PER_KBYTE_FOR_USAGE_REPORT 1024
dan#define BYTES_PER_KBYTE_REPORTED_BY_FNOBULATOR 1024
, menugaskan nama yang berbeda untuk setiap tujuan yang berbeda dilayani oleh konstanta 1024, tetapi itu akan menghasilkan banyak pengidentifikasi yang didefinisikan dan digunakan tepat sekali. Lebih jauh, dalam banyak kasus, lebih mudah untuk memahami apa arti suatu nilai jika seseorang melihat kode di mana ia digunakan, dan lebih mudah untuk mencari tahu di mana arti kode jika seseorang melihat nilai konstanta yang digunakan di dalamnya. Jika literal numerik hanya digunakan satu kali untuk tujuan tertentu, menulis literal di tempat di mana ia digunakan akan sering menghasilkan kode yang lebih mudah dipahami daripada menetapkan label untuk itu di satu tempat dan menggunakan nilainya di tempat lain.sumber
Saya akan cenderung menggunakan hanya nomor, namun saya pikir satu masalah penting belum diangkat: Jumlah yang sama dapat berarti hal-hal yang berbeda dalam konteks yang berbeda, dan ini dapat mempersulit refactoring.
1024 juga merupakan jumlah KiB per MiB. Misalkan kita menggunakan 1024 untuk juga mewakili perhitungan itu di suatu tempat, atau di banyak tempat, dan sekarang kita perlu mengubahnya untuk menghitung GiB sebagai gantinya. Mengubah konstanta lebih mudah daripada pencarian / penggantian global tempat Anda dapat secara tidak sengaja mengubah yang salah di beberapa tempat, atau melewatkannya di tempat lain.
Atau bahkan bisa berupa topeng bit yang diperkenalkan oleh programmer malas yang perlu diperbarui suatu hari.
Ini sedikit contoh yang dibuat-buat tetapi dalam beberapa basis kode ini dapat menyebabkan masalah ketika refactoring atau memperbarui untuk persyaratan baru. Untuk kasus khusus ini, saya tidak akan menganggap angka polos sebagai bentuk yang benar-benar buruk terutama jika Anda dapat menyertakan perhitungan dalam metode untuk digunakan kembali, saya mungkin akan melakukannya sendiri tetapi menganggap konstanta lebih 'benar'.
Jika Anda menggunakan konstanta bernama, seperti dikatakan supercat, penting untuk mempertimbangkan apakah konteks juga penting, dan jika Anda memerlukan banyak nama.
sumber