Apa itu angka ajaib, dan mengapa angka itu buruk? [Tutup]

514

Apa itu angka ajaib?

Kenapa harus dihindari?

Apakah ada kasus yang sesuai?

Adam Davis
sumber
2
Anda akan menghindari angka ajaib karena orang lain melihat kode Anda mungkin tidak mengerti mengapa Anda melakukan apa yang Anda lakukan ... misalnya const myNum = 22; const number = myNum / 11;saat ini 11 orang saya mungkin orang atau botol bir atau sesuatu jadi saya akan mengubah 11 ke konstanta seperti penduduk.
JuicY_Burrito
Menggunakan angka ajaib dalam atribut tidak dapat dihindari, jadi saya kira ini tepat.
donatasj87

Jawaban:

575

Nomor ajaib adalah penggunaan langsung nomor dalam kode.

Misalnya, jika Anda memiliki (di Jawa):

public class Foo {
    public void setPassword(String password) {
         // don't do this
         if (password.length() > 7) {
              throw new InvalidArgumentException("password");
         }
    }
}

Ini harus di refactored untuk:

public class Foo {
    public static final int MAX_PASSWORD_SIZE = 7;

    public void setPassword(String password) {
         if (password.length() > MAX_PASSWORD_SIZE) {
              throw new InvalidArgumentException("password");
         }
    }
}

Ini meningkatkan keterbacaan kode dan lebih mudah untuk mempertahankannya. Bayangkan kasus di mana saya mengatur ukuran bidang kata sandi di GUI. Jika saya menggunakan angka ajaib, setiap kali ukuran max berubah, saya harus mengubah di dua lokasi kode. Jika saya lupa satu, ini akan menyebabkan inkonsistensi.

JDK penuh dengan contoh-contoh seperti di Integer, Characterdan di Mathkelas.

PS: Alat analisis statis seperti FindBugs dan PMD mendeteksi penggunaan angka ajaib dalam kode Anda dan menyarankan refactoring.

Marcio Aguiar
sumber
175
0 dan 1 adalah pengecualian untuk aturan ini.
Jonathan Parker
24
@ Kirill: Jika Anda mengharapkan definisi "Seratus Persen" berubah, maka ya. Pendekatan yang lebih baik adalah dengan memiliki variabel dari apa itu untuk apa yang diwakilinya, yaitu, final public static MAX_DOWNLOAD_PERCENTAGE = 100. Meskipun itu tidak masuk akal, karena "100 persen" didefinisikan dengan sangat baik. Di sisi lain, fakta bahwa Kata Sandi dapat maksimum 7 karakter tidak didefinisikan secara global dan sebenarnya berbeda, sehingga merupakan kandidat untuk suatu variabel.
Michael Stum
40
@ Jonathan Parker, kecuali ketika mereka tidak ( TRUE/ FALSE)
Brendan Long
82
Hanya karena angka ajaib tidak akan pernah berubah bukan berarti angka itu tidak boleh diganti dengan konstanta. Kode saya penuh dengan konstanta global seperti HzPerMHz dan msecPerSecond. Ini tidak akan pernah berubah, tetapi mereka membuat maknanya lebih jelas, dan memberikan perlindungan terhadap kesalahan ketik.
Jeanne Pindar
43
@ MarcusJ Anda tidak bisa salah lagi. Ini bukan masalah pendapat, tetapi pengalaman yang diperoleh dengan susah payah, oleh banyak programmer. Saya tidak bisa memberi tahu Anda berapa kali, selama 40 tahun pemrograman, bahwa saya telah mengutuk programmer sebelumnya yang tidak mendefinisikan konstanta, jadi saya hanya menemukan penggunaan langsung angka, yang perlu dipahami selama pemeliharaan kode , dimakamkan di suatu tempat dalam banyak kode, yang artinya akan dibuat jelas dengan mendefinisikan konstanta seperti itu. Setiap programmer senior lainnya juga akan memiliki banyak cerita horor di sepanjang baris ini.
ToolmakerSteve
146

Angka ajaib adalah nilai hard-kode yang dapat berubah pada tahap selanjutnya, tetapi karena itu bisa sulit untuk diperbarui.

Misalnya, katakanlah Anda memiliki Halaman yang menampilkan 50 Pesanan terakhir di Halaman Ikhtisar "Pesanan Anda". 50 adalah Angka Ajaib di sini, karena itu tidak ditetapkan melalui standar atau konvensi, itu nomor yang Anda buat untuk alasan yang diuraikan dalam spesifikasi.

Sekarang, yang Anda lakukan adalah memiliki 50 di tempat yang berbeda - skrip SQL Anda ( SELECT TOP 50 * FROM orders), Situs Web Anda (Pesanan 50 Terakhir Anda), login pesanan Anda ( for (i = 0; i < 50; i++)) dan mungkin banyak tempat lain.

Sekarang, apa yang terjadi ketika seseorang memutuskan untuk mengubah 50 ke 25? atau 75? atau 153? Anda sekarang harus mengganti 50 di semua tempat, dan kemungkinan besar Anda akan melewatkannya. Find / Replace mungkin tidak berfungsi, karena 50 dapat digunakan untuk hal-hal lain, dan mengganti secara acak 50 dengan 25 dapat memiliki beberapa efek samping buruk lainnya (yaitu Session.Timeout = 50panggilan Anda , yang juga diatur ke 25 dan pengguna mulai melaporkan timeout yang terlalu sering).

Juga, kodenya bisa sulit dipahami, yaitu " if a < 50 then bla" - jika Anda menemukan bahwa di tengah fungsi yang rumit, pengembang lain yang tidak terbiasa dengan kode mungkin bertanya pada diri sendiri "WTF is 50 ???"

Itulah mengapa yang terbaik adalah memiliki angka ambigu dan sewenang-wenang di tepat 1 tempat - " const int NumOrdersToDisplay = 50", karena itu membuat kode lebih mudah dibaca (" if a < NumOrdersToDisplay", itu juga berarti Anda hanya perlu mengubahnya di 1 tempat yang terdefinisi dengan baik.

Tempat-tempat di mana Angka Ajaib sesuai adalah segala sesuatu yang didefinisikan melalui standar, yaitu SmtpClient.DefaultPort = 25atau TCPPacketSize = whatever(tidak yakin apakah itu standar). Juga, semua yang hanya didefinisikan dalam 1 fungsi mungkin dapat diterima, tetapi itu tergantung pada Konteks.

Michael Stum
sumber
18
Bahkan jika itu tidak dapat diubah, itu masih ide yang buruk karena tidak jelas apa yang terjadi.
Loren Pechtel
11
Tidak selalu tidak jelas. SmtpClient.DefaultPort = 25mungkin jelas er daripada SmtpClient.DefaultPort = DEFAULT_SMTP_PORT.
user253751
4
@immibis Saya kira itu dengan asumsi bahwa sama sekali tidak ada kode lain yang menggunakan konsep DEFAULT_SMTP_PORT. Jika port SMTP default untuk aplikasi itu diubah, maka itu perlu diperbarui di banyak tempat yang menyebabkan kemungkinan inkonsistensi.
Russ Bradberry
3
Menemukan semua penggunaan juga lebih sulit - Anda harus mencari di 25seluruh aplikasi dan memastikan Anda hanya mengubah kemunculan 25yang untuk SMTP Port, bukan 25 yang misalnya lebar kolom tabel atau angka catatan untuk ditampilkan di halaman.
Michael Stum
2
Dalam contoh itu, saya mengharapkan kode untuk menggunakan SmtpClient.DefaultPort, bukan 25. Jadi, Anda hanya perlu mengubahnya di satu tempat. Dan nomor port cenderung tetap sama, itu bukan angka ajaib acak, tetapi nomor yang ditetapkan oleh IANA.
njsg
34

Sudahkah Anda melihat entri Wikipedia untuk nomor ajaib?

Ini masuk ke sedikit detail tentang semua cara referensi nomor ajaib dibuat. Berikut adalah kutipan tentang angka ajaib sebagai praktik pemrograman yang buruk

Istilah angka ajaib juga merujuk pada praktik pemrograman yang buruk dengan menggunakan angka secara langsung dalam kode sumber tanpa penjelasan. Dalam kebanyakan kasus ini membuat program lebih sulit untuk dibaca, dimengerti, dan dipelihara. Meskipun sebagian besar panduan membuat pengecualian untuk angka nol dan satu, merupakan ide bagus untuk mendefinisikan semua angka lain dalam kode sebagai konstanta bernama.

somas1
sumber
8
Contoh bagus RTFW :)
Eva
Saya akan mengatakan jawabannya jauh dari lengkap.
Skeeve
25

Magic Number Vs. Konstan Simbolik: Kapan harus mengganti?

Sihir: Semantik tidak dikenal

Simbolik Konstan -> Menyediakan semantik yang benar dan konteks yang benar untuk digunakan

Semantik: Arti atau tujuan suatu hal.

"Buat konstanta, beri nama sesuai artinya, dan ganti angkanya." - Martin Fowler

Pertama, angka ajaib bukan hanya angka. Nilai dasar apa pun bisa "ajaib". Nilai dasar adalah entitas manifes seperti integer, real, double, float, tanggal, string, boolean, karakter, dan sebagainya. Masalahnya bukan tipe data, tetapi aspek "ajaib" dari nilai seperti yang muncul dalam teks kode kami.

Apa yang kita maksud dengan "sihir"? Tepatnya: Dengan "sihir", kami bermaksud menunjukkan semantik (makna atau tujuan) nilai dalam konteks kode kami; bahwa itu tidak diketahui, tidak diketahui, tidak jelas, atau membingungkan. Ini adalah gagasan "sihir". Nilai dasar bukanlah sihir ketika makna semantiknya atau tujuan keberadaannya ada dengan cepat dan mudah diketahui, jelas, dan dipahami (tidak membingungkan) dari konteks sekeliling tanpa kata-kata penolong khusus (misalnya konstanta simbolis).

Oleh karena itu, kami mengidentifikasi angka ajaib dengan mengukur kemampuan pembaca kode untuk mengetahui, menjelaskan, dan memahami makna dan tujuan dari nilai dasar dari konteks sekitarnya. Semakin sedikit diketahui, kurang jelas, dan semakin bingung pembaca, semakin "ajaib" nilai dasarnya.

Definisi yang bermanfaat

  • bingung: menyebabkan (seseorang) menjadi bingung atau bingung.
  • bingung: menyebabkan (seseorang) menjadi bingung dan bingung.
  • bingung: benar-benar bingung; sangat bingung.
  • bingung: benar-benar bingung atau bingung.
  • bingung: tidak bisa mengerti; bingung.
  • memahami: memahami makna yang dimaksudkan (kata-kata, bahasa, atau pembicara).
  • makna: apa yang dimaksud dengan kata, teks, konsep, atau tindakan.
  • dimaksud: bermaksud untuk menyampaikan, menunjukkan, atau merujuk (hal atau gagasan tertentu); menandakan.
  • menandakan: menjadi indikasi.
  • indikasi: tanda atau informasi yang menunjukkan sesuatu.
  • menunjukkan: tunjukkan; menunjukkan.
  • tanda: objek, kualitas, atau peristiwa yang kehadiran atau kemunculannya menunjukkan kemungkinan kehadiran atau kemunculan sesuatu yang lain.

Dasar-dasar

Kami memiliki dua skenario untuk nilai-nilai dasar sihir kami. Hanya yang kedua yang sangat penting bagi programmer dan kode:

  1. Satu-satunya nilai dasar (misalnya angka) yang artinya tidak diketahui, tidak diketahui, tidak jelas, atau membingungkan.
  2. Nilai dasar (misalnya angka) dalam konteks, tetapi artinya tetap tidak diketahui, tidak diketahui, tidak jelas, atau membingungkan.

Ketergantungan menyeluruh dari "sihir" adalah bagaimana nilai dasar tunggal (mis. Angka) tidak memiliki semantik yang dikenal (seperti Pi), tetapi memiliki semantik yang dikenal secara lokal (misalnya program Anda), yang tidak sepenuhnya jelas dari konteksnya atau dapat disalahgunakan dalam konteks yang baik atau buruk.

Semantik dari sebagian besar bahasa pemrograman tidak akan memungkinkan kita untuk menggunakan nilai-nilai dasar tunggal, kecuali (mungkin) sebagai data (yaitu tabel data). Ketika kita menemukan "angka ajaib", kita biasanya melakukannya dalam konteks. Karena itu, jawabannya

"Apakah saya mengganti angka ajaib ini dengan konstanta simbolis?"

adalah:

"Seberapa cepat Anda dapat menilai dan memahami makna semantik dari angka (tujuannya untuk berada di sana) dalam konteksnya?"

Jenis Sihir, tetapi tidak cukup

Dengan pemikiran ini, kita dapat dengan cepat melihat bagaimana angka seperti Pi (3.14159) bukan "angka ajaib" ketika ditempatkan dalam konteks yang tepat (misalnya 2 x 3,14159 x jari-jari atau 2 * Pi * r). Di sini, angka 3.14159 diakui secara mental Pi tanpa pengenal simbolis konstan.

Namun, kami biasanya mengganti 3.14159 dengan pengenal konstanta simbolis seperti Pi karena panjang dan kerumitan jumlahnya. Aspek panjang dan kompleksitas Pi (ditambah dengan kebutuhan akan keakuratan) biasanya berarti pengenal simbolik atau konstanta kurang rentan terhadap kesalahan. Pengakuan "Pi" sebagai nama hanyalah bonus yang mudah, tetapi bukan alasan utama untuk memiliki konstanta.

Sementara itu: Kembali di Peternakan

Mengesampingkan konstanta umum seperti Pi, mari kita fokus terutama pada angka-angka dengan makna khusus, tetapi makna-makna itu dibatasi pada semesta sistem perangkat lunak kita. Angka seperti itu mungkin "2" (sebagai nilai integer dasar).

Jika saya menggunakan angka 2 dengan sendirinya, pertanyaan pertama saya mungkin: Apa artinya "2"? Arti "2" dengan sendirinya tidak diketahui dan tidak diketahui tanpa konteks, meninggalkan penggunaannya tidak jelas dan membingungkan. Meskipun hanya memiliki "2" dalam perangkat lunak kami tidak akan terjadi karena semantik bahasa, kami ingin melihat bahwa "2" dengan sendirinya tidak membawa semantik khusus atau tujuan yang jelas sendirian.

Mari kita letakkan satu-satunya "2" dalam konteks:, di padding := 2mana konteksnya adalah "GUI Container". Dalam konteks ini makna 2 (sebagai piksel atau unit grafis lainnya) menawarkan kepada kita tebakan semantiknya (makna dan tujuan). Kita mungkin berhenti di sini dan mengatakan bahwa 2 tidak apa-apa dalam konteks ini dan tidak ada hal lain yang perlu kita ketahui. Namun, mungkin di dunia perangkat lunak kami ini bukan keseluruhan cerita. Ada lebih dari itu, tetapi "padding = 2" sebagai konteks tidak dapat mengungkapkannya.

Lebih jauh kita berpura-pura bahwa 2 sebagai bantalan piksel dalam program kami adalah variasi "default_padding" di seluruh sistem kami. Karena itu, menulis instruksi padding = 2tidak cukup baik. Gagasan "default" tidak terungkap. Hanya ketika saya menulis: padding = default_paddingsebagai konteks dan kemudian di tempat lain: default_padding = 2saya sepenuhnya menyadari makna yang lebih baik dan lebih lengkap (semantik dan tujuan) dari 2 dalam sistem kami.

Contoh di atas cukup bagus karena "2" dengan sendirinya bisa apa saja. Hanya ketika kita membatasi rentang dan domain pemahaman pada "program saya" di mana 2 adalah bagian default_paddingGUI UX dari "program saya", akhirnya kita memahami "2" dalam konteks yang tepat. Di sini "2" adalah angka "ajaib", yang difaktorkan ke konstanta simbolis default_paddingdalam konteks GUI UX dari "program saya" untuk membuatnya digunakan dengan default_paddingcepat dipahami dalam konteks yang lebih besar dari kode penutup.

Dengan demikian, setiap nilai dasar, yang maknanya (semantik dan tujuan) tidak dapat cukup dan cepat dipahami adalah kandidat yang baik untuk konstanta simbolis di tempat nilai dasar (misalnya angka ajaib).

Melangkah Lebih Lanjut

Angka dalam skala mungkin memiliki semantik juga. Sebagai contoh, berpura-pura kita membuat game D & D, di mana kita memiliki gagasan tentang monster. Objek monster kami memiliki fitur yang disebut life_force, yang merupakan bilangan bulat. Angka-angka memiliki makna yang tidak dapat diketahui atau jelas tanpa kata-kata untuk memasok makna. Jadi, kita mulai dengan mengatakan secara sewenang-wenang:

  • full_life_force: INTEGER = 10 - Sangat hidup (dan tidak terluka)
  • minimum_life_force: INTEGER = 1 - Nyaris tidak hidup (sangat terluka)
  • mati: INTEGER = 0 - Mati
  • undead: INTEGER = -1 - Min undead (hampir mati)
  • zombie: INTEGER = -10 - Max undead (sangat undead)

Dari konstanta simbolis di atas, kita mulai mendapatkan gambaran mental tentang semangat, kematian, dan "undeadness" (dan kemungkinan konsekuensi atau konsekuensi) untuk monster kita dalam permainan D & D kita. Tanpa kata-kata ini (konstanta simbolik), kita hanya memiliki angka mulai dari -10 .. 10. Hanya rentang tanpa kata-kata membuat kita berada di tempat yang kemungkinan besar kebingungan dan berpotensi dengan kesalahan dalam permainan kita jika bagian-bagian yang berbeda dari permainan memiliki ketergantungan pada apa arti kisaran angka itu untuk berbagai operasi seperti attack_elvesatau seek_magic_healing_potion.

Oleh karena itu, ketika mencari dan mempertimbangkan penggantian "angka ajaib" kami ingin mengajukan pertanyaan yang sangat terarah tentang angka-angka dalam konteks perangkat lunak kami dan bahkan bagaimana angka-angka berinteraksi secara semantik satu sama lain.

Kesimpulan

Mari kita tinjau pertanyaan apa yang harus kita tanyakan:

Anda mungkin memiliki nomor ajaib jika ...

  1. Bisakah nilai dasar memiliki makna atau tujuan khusus di alam semesta perangkat lunak Anda?
  2. Dapatkah makna atau tujuan khusus tersebut kemungkinan tidak diketahui, tidak diketahui, tidak jelas, atau membingungkan, bahkan dalam konteks yang tepat?
  3. Bisakah nilai dasar yang tepat digunakan secara tidak benar dengan konsekuensi buruk dalam konteks yang salah?
  4. Dapatkah nilai dasar yang tidak tepat digunakan dengan benar dengan konsekuensi buruk dalam konteks yang benar?
  5. Apakah nilai dasar memiliki hubungan semantik atau tujuan dengan nilai-nilai dasar lainnya dalam konteks tertentu?
  6. Dapatkah nilai dasar ada di lebih dari satu tempat dalam kode kita dengan semantik yang berbeda di masing-masing, sehingga menyebabkan pembaca kita kebingungan?

Periksa nilai-nilai dasar konstan konstan yang ada dalam teks kode Anda. Ajukan setiap pertanyaan dengan perlahan dan penuh pertimbangan tentang setiap contoh nilai seperti itu. Pertimbangkan kekuatan jawaban Anda. Sering kali, jawabannya bukan hitam dan putih, tetapi memiliki nuansa makna dan tujuan yang disalahpahami, kecepatan belajar, dan kecepatan pemahaman. Ada juga kebutuhan untuk melihat bagaimana terhubung ke mesin perangkat lunak di sekitarnya.

Pada akhirnya, jawaban untuk penggantian adalah menjawab ukuran (dalam pikiran Anda) dari kekuatan atau kelemahan pembaca untuk membuat koneksi (mis. "Dapatkan"). Semakin cepat mereka memahami makna dan tujuan, semakin sedikit "keajaiban" yang Anda miliki.

KESIMPULAN: Ganti nilai-nilai dasar dengan konstanta simbolik hanya ketika sihir cukup besar untuk menyebabkan sulit untuk mendeteksi bug yang timbul dari kebingungan.

Larry
sumber
1
Terima kasih. Bagaimana alat analisis statis rekan saya terus menginstal terus mengeluh tentang angka ajaib - tapi bagaimana alat seharusnya memahami semantik? Hasilnya adalah SEMUA nilai dasar diganti dengan konstanta simbolik. Karena saya setuju dengan kesimpulan Anda, saya menemukan ini kurang ideal.
Chomeh
17

Nomor ajaib adalah urutan karakter di awal format file, atau pertukaran protokol. Nomor ini berfungsi sebagai cek kewarasan.

Contoh: Buka file GIF, Anda akan melihat di awal: GIF89. "GIF89" menjadi angka ajaib.

Program lain dapat membaca beberapa karakter pertama file dan mengidentifikasi GIF dengan benar.

Bahayanya adalah bahwa data biner acak dapat berisi karakter yang sama ini. Tetapi sangat tidak mungkin.

Sedangkan untuk pertukaran protokol, Anda dapat menggunakannya untuk mengidentifikasi dengan cepat bahwa 'pesan' saat ini yang dikirimkan kepada Anda rusak atau tidak valid.

Angka ajaib masih berguna.

Brian R. Bondy
sumber
13
Saya kira itu bukan angka ajaib yang dia maksud
Marcio Aguiar
4
Mungkin Anda harus menghapus tag "format file" dan "jaringan" yang Anda tambahkan karena dia jelas tidak berbicara tentang angka-angka ajaib semacam itu.
Landon
9
Masih sangat berguna untuk mengetahui bahwa angka ajaib dapat merujuk lebih dari sekadar masalah kode. -Adam
Adam Davis
3
Jika subjek membaca: "Apa itu angka ajaib dalam hal kode sumber" maka tag tidak boleh ada di sana. Tetapi dia tidak merinci hal ini. Jadi memiliki informasi tambahan saya itu baik. Saya pikir Kyle, Landon dan Marcio salah.
Brian R. Bondy
4
Juga tidak ada cara untuk menentukan mana yang dia cari. Karena saya adalah posting pertama saya tidak bisa menebak yang mana yang dia cari.
Brian R. Bondy
12

Dalam pemrograman, "angka ajaib" adalah nilai yang harus diberi nama simbolis, tetapi dimasukkan ke dalam kode sebagai literal, biasanya di lebih dari satu tempat.

Itu buruk karena alasan yang sama SPOT (Single Point of Truth) baik: Jika Anda ingin mengubah konstanta ini nanti, Anda harus mencari kode Anda untuk menemukan setiap contoh. Ini juga buruk karena mungkin tidak jelas bagi programmer lain apa angka ini mewakili, karenanya "ajaib".

Orang-orang kadang-kadang mengambil penghapusan angka ajaib lebih lanjut, dengan memindahkan konstanta ini ke dalam file terpisah untuk bertindak sebagai konfigurasi. Ini kadang-kadang bermanfaat, tetapi juga bisa menciptakan lebih banyak kompleksitas daripada nilainya.

Nick Retallack
sumber
Bisakah Anda lebih spesifik mengapa menghilangkan nomor maginc TIDAK selalu bagus?
Marcio Aguiar
Dalam rumus matematika seperti e ^ pi + 1 = 0
Jared Updike
5
Marcio: Ketika Anda melakukan hal-hal seperti "const int EIGHT = 8;" dan kemudian persyaratan berubah dan Anda berakhir dengan "const int EIGHT = 9;"
jmucchiello
6
Maaf, tapi itu hanyalah contoh penamaan yang buruk, atau penggunaan basis untuk konstanta.
Kzqai
1
@MarcioAguiar: Pada beberapa platform, ekspresi seperti (foo[i]+foo[i+1]+foo[i+2]+1)/3mungkin dievaluasi lebih cepat daripada loop. Jika seseorang mengganti 3tanpa menulis ulang kode sebagai loop, seseorang yang melihat ITEMS_TO_AVERAGEdidefinisikan sebagai 3angka mereka dapat mengubahnya 5dan memiliki rata-rata kode lebih banyak item. Sebaliknya, seseorang yang melihat ekspresi dengan literal 3akan menyadari bahwa 3mewakili jumlah item yang dirangkum bersama.
supercat
10

Bilangan ajaib juga bisa berupa bilangan dengan semantik khusus yang dikodekan dengan keras. Sebagai contoh, saya pernah melihat sebuah sistem di mana record ID> 0 diperlakukan secara normal, 0 itu sendiri adalah "record baru", -1 adalah "ini adalah root" dan -99 adalah "ini dibuat di root". 0 dan -99 akan menyebabkan WebService menyediakan ID baru.

Apa yang buruk tentang ini adalah bahwa Anda menggunakan kembali ruang (bilangan bulat yang ditandatangani untuk ID rekaman) untuk kemampuan khusus. Mungkin Anda tidak akan pernah ingin membuat catatan dengan ID 0, atau dengan ID negatif, tetapi bahkan jika tidak, setiap orang yang melihat kode atau database mungkin tersandung pada ini dan menjadi bingung pada awalnya. Tak perlu dikatakan bahwa nilai-nilai khusus itu tidak terdokumentasi dengan baik.

Bisa dibilang, 22, 7, -12 dan 620 juga dihitung sebagai angka ajaib. ;-)

Sören Kuklau
sumber
10

Masalah yang belum disebutkan dengan menggunakan angka ajaib ...

Jika Anda memiliki sangat banyak dari mereka, kemungkinannya cukup baik bahwa Anda memiliki dua tujuan berbeda yang Anda gunakan untuk angka ajaib, di mana nilainya sama.

Dan kemudian, tentu saja, Anda perlu mengubah nilainya ... hanya untuk satu tujuan.


sumber
Ini tidak terlihat semua kemungkinan ketika berbicara tentang angka (setidaknya tidak bagi saya), tapi saya menabraknya dengan string dan itu adalah hit: pertama Anda harus membaca banyak kode untuk melihat di mana angka itu digunakan, daripada Anda harus memperhatikan bahwa itu digunakan untuk hal-hal yang berbeda ... bukan hobi favorit saya.
Tomislav Nakic-Alfirevic
4

Saya menganggap ini adalah jawaban atas jawaban saya untuk pertanyaan Anda sebelumnya. Dalam pemrograman, angka ajaib adalah konstanta numerik tertanam yang muncul tanpa penjelasan. Jika itu muncul di dua lokasi yang berbeda, itu dapat menyebabkan keadaan di mana satu contoh diubah dan bukan yang lain. Untuk kedua alasan ini, penting untuk mengisolasi dan menetapkan konstanta numerik di luar tempat mereka digunakan.

Kyle Cronin
sumber
3

Saya selalu menggunakan istilah "angka ajaib" secara berbeda, sebagai nilai yang tidak jelas disimpan dalam struktur data yang dapat diverifikasi sebagai pemeriksaan validitas cepat. Misalnya file gzip berisi 0x1f8b08 sebagai tiga byte pertama, file kelas Java mulai dengan 0xcafebabe, dll.

Anda sering melihat angka ajaib yang tertanam dalam format file, karena file dapat dikirim agak sembarangan dan kehilangan metadata tentang bagaimana mereka dibuat. Namun angka ajaib juga kadang-kadang digunakan untuk struktur data dalam memori, seperti panggilan ioctl ().

Pemeriksaan cepat dari angka ajaib sebelum memproses file atau struktur data memungkinkan seseorang untuk menandai kesalahan lebih awal, daripada schlep sepanjang jalan melalui pemrosesan yang berpotensi panjang untuk mengumumkan bahwa inputnya benar-benar balderdash.

DGentry
sumber
2

Perlu dicatat bahwa kadang-kadang Anda ingin nomor "hard-coded" yang tidak dapat dikonfigurasi dalam kode Anda. Ada beberapa yang terkenal termasuk 0x5F3759DF yang digunakan dalam algoritma root kuadrat terbalik yang dioptimalkan.

Dalam kasus langka di mana saya menemukan kebutuhan untuk menggunakan Angka Ajaib tersebut, saya menetapkannya sebagai const dalam kode saya, dan mendokumentasikan mengapa mereka digunakan, bagaimana mereka bekerja, dan dari mana mereka berasal.

Rob Rolnick
sumber
1
Menurut pendapat saya, bau kode angka ajaib merujuk secara khusus pada konstanta yang tidak dapat dijelaskan . Selama Anda menempatkan mereka dalam konstanta bernama, itu seharusnya tidak menjadi masalah.
Don Kirkby
2

Bagaimana dengan menginisialisasi variabel di bagian atas kelas dengan nilai default? Sebagai contoh:

public class SomeClass {
    private int maxRows = 15000;
    ...
    // Inside another method
    for (int i = 0; i < maxRows; i++) {
        // Do something
    }

    public void setMaxRows(int maxRows) {
        this.maxRows = maxRows;
    }

    public int getMaxRows() {
        return this.maxRows;
    }

Dalam hal ini, 15000 adalah angka ajaib (menurut CheckStyles). Bagi saya, pengaturan nilai default tidak masalah. Saya tidak mau harus melakukan:

private static final int DEFAULT_MAX_ROWS = 15000;
private int maxRows = DEFAULT_MAX_ROWS;

Apakah itu membuatnya lebih sulit dibaca? Saya tidak pernah mempertimbangkan ini sampai saya menginstal CheckStyles.

Ascalonian
sumber
Saya pikir ini akan baik-baik saja jika konstruktor menginisialisasi nilai. Kalau tidak, jika nilai diinisialisasi di luar konstruktor, saya hanya melihatnya sebagai kerumitan dan sebagai sesuatu yang sulit dibaca.
Thomas Eding
Saya pikir static finalkonstanta berlebihan ketika Anda menggunakannya dalam satu metode. Sebuah finalvariabel dideklarasikan di bagian atas metode ini lebih mudah dibaca IMHO.
Eva
0

@ eed3si9n: Saya bahkan menyarankan bahwa '1' adalah angka ajaib. :-)

Prinsip yang terkait dengan angka ajaib adalah bahwa setiap fakta yang ditangani oleh kode Anda harus dinyatakan tepat satu kali. Jika Anda menggunakan angka ajaib dalam kode Anda (seperti contoh panjang kata sandi yang diberikan @marcio, Anda dapat dengan mudah menduplikasi fakta itu, dan ketika Anda memahami fakta itu berubah, Anda mengalami masalah pemeliharaan.

Andrew
sumber
5
Kode TKI harus ditulis seperti ini:factorial n = if n == BASE_CASE then BASE_VALUE else n * factorial (n - RECURSION_INPUT_CHANGE); RECURSION_INPUT_CHANGE = 1; BASE_CASE = 0; BASE_VALUE = 1
Thomas Eding
0

Bagaimana dengan variabel pengembalian?

Saya secara khusus merasa sulit ketika menerapkan prosedur tersimpan .

Bayangkan prosedur tersimpan berikutnya (salah sintaks, saya tahu, hanya untuk menunjukkan contoh):

int procGetIdCompanyByName(string companyName);

Ini mengembalikan ID perusahaan jika ada di tabel tertentu. Jika tidak, ia mengembalikan -1. Entah bagaimana itu angka ajaib. Beberapa rekomendasi yang saya baca sejauh ini mengatakan bahwa saya harus benar-benar merancang sesuatu seperti itu:

int procGetIdCompanyByName(string companyName, bool existsCompany);

Ngomong-ngomong, apa yang harus dikembalikan jika perusahaan tidak ada? Oke: ini akan menetapkan ada perusahaan sebagai salah , tetapi juga akan mengembalikan -1.

Opsi antoher adalah membuat dua fungsi terpisah:

bool procCompanyExists(string companyName);
int procGetIdCompanyByName(string companyName);

Jadi pra-kondisi untuk prosedur tersimpan kedua adalah perusahaan itu ada.

Tetapi saya takut akan konkurensi, karena dalam sistem ini, sebuah perusahaan dapat dibuat oleh pengguna lain.

Intinya adalah: apa pendapat Anda tentang penggunaan "angka ajaib" semacam itu yang relatif dikenal dan aman untuk mengatakan bahwa ada sesuatu yang tidak berhasil atau ada sesuatu yang tidak ada?

Oskytar
sumber
Dalam kasus khusus itu, jika dokumentasi fungsi menyatakan bahwa nilai pengembalian negatif berarti tidak ada perusahaan yang ditemukan, maka tidak ada alasan untuk menggunakan konstanta.
Vincent Fourmond
-1

Keuntungan lain dari mengekstraksi angka ajaib sebagai konstanta memberikan kemungkinan untuk secara jelas mendokumentasikan informasi bisnis.

public class Foo {
    /** 
     * Max age in year to get child rate for airline tickets
     * 
     * The value of the constant is {@value}
     */
    public static final int MAX_AGE_FOR_CHILD_RATE = 2;

    public void computeRate() {
         if (person.getAge() < MAX_AGE_FOR_CHILD_RATE) {
               applyChildRate();
         }
    }
}
jguiraud
sumber