Apakah pernah ada ide bagus untuk nilai hardcode ke dalam aplikasi kita?

45

Apakah pernah ada ide bagus untuk nilai hardcode ke dalam aplikasi kita? Atau apakah selalu merupakan hal yang tepat untuk memanggil tipe-tipe nilai ini secara dinamis jika mereka perlu berubah?

Edward
sumber
2
parameter config akan membantu Anda
Gopi
54
Anda tidak pernah tahu kapan nilai pimungkin berubah ...
Gabe
12
Sobat, saya kira orang-orang seperti @gabe adalah alasan ini adalah "Aturan". Jika Anda mengulangi 3,14 di 20 tempat dalam kode Anda dan kemudian menemukan bahwa Anda benar-benar membutuhkan lebih akurat, Anda kacau. Saya tidak menyadari ini tidak jelas.
Bill K
17
Itu agak kasar, @Bill. @ Gabe jelas bercanda, tapi selain itu, pertanyaannya adalah tentang parameter hardcoding vs config, tidak menggunakan angka ajaib konstan dan berulang di banyak tempat.
David Conrad
1
Ya, terkadang hardcoding bisa menjadi ide yang bagus. Lihat artikel Wikipedia tentang anti-pola "Softcoding".
user16764

Jawaban:

64

Ya, tetapi jelaskan .

Melakukan:

  • gunakan konstanta
  • menggunakan nama variabel deskriptif

Jangan:

Jonathan Khoo
sumber
44
Mana yang lebih bersih, diameter = 2 * radiusatau diameter = RADIUS_TO_DIAMETER_FACTOR * radius? Memang ada kasus sudut di mana angka ajaib mungkin solusi yang lebih baik.
Joonas Pulakka
5
Saya tidak bisa cukup setuju dengan jawaban ini. Saya cenderung berpikir pemrograman seperti menjadi seorang novelis. Anda menceritakan kisah Anda melalui kode dan jika orang tidak dapat memahami logika itu membuat kode Anda tidak berharga menurut saya. Itulah sebabnya konvensi penamaan yang dipikirkan dengan baik pada dasarnya untuk keterbacaan. Juga, tidak ada alasan bagus untuk menggunakan angka ajaib. Dengan menggunakan angka ajaib Anda menghapus "mengapa" dari persamaan dan membuatnya lebih sulit untuk dipahami. Misalnya: "diameter = 2 * radius" Untuk apa keduanya? "Diameter = radius RADIUS_TO_DIAMETER_FACTOR *" ini jauh lebih masuk akal.
chrisw
9
diameter = 2 * radius langsung dari matematika sekolah menengah. Alasan untuk tidak menyebut "2" adalah karena memiliki nilai apa pun akan membutuhkan perubahan pada hukum fisika atau matematika, atau keduanya. (Di sisi lain, penamaan Pi, atau konstanta Plancks adalah langkah yang bagus untuk keterbacaan sederhana).
cepat,
8
@Joonas: Pfft. Tentunya maksud Anda diameter = radius << 1? Saya kira itu juga bisa diameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT.
Semut
4
bagaimana kalau beberapadiameter = radius.toDiameter()
Carson Myers
27

Apa yang saya temukan aneh tentang T&J ini sejauh ini adalah bahwa tidak ada yang benar-benar berusaha untuk mendefinisikan dengan jelas "hard-code" atau, yang lebih penting, alternatif.

tl; dr: Ya, itu adalah kadang-kadang ide yang baik untuk nilai hard-code, tetapi tidak ada aturan sederhana untuk saat ; itu tergantung sepenuhnya pada konteks.

Pertanyaannya memang mempersempitnya menjadi nilai - nilai , yang saya maksud dengan angka ajaib , tetapi jawaban untuk apakah itu ide yang baik adalah relatif terhadap apa yang sebenarnya mereka gunakan!

Beberapa contoh nilai "hard-coded" adalah:

  • Nilai konfigurasi

    Saya merasa ngeri setiap kali saya melihat pernyataan seperti command.Timeout = 600. Kenapa 600? Siapa yang memutuskan itu? Apakah ini waktu sebelumnya, dan seseorang menaikkan batas waktu sebagai peretasan alih-alih memperbaiki masalah kinerja yang mendasarinya? Atau itu sebenarnya harapan yang diketahui dan didokumentasikan untuk waktu pemrosesan?

    Ini tidak boleh angka ajaib atau konstanta, mereka harus dieksternalisasi dalam file konfigurasi atau database di suatu tempat dengan nama yang bermakna, karena nilai optimalnya ditentukan sebagian besar atau seluruhnya oleh lingkungan di mana aplikasi berjalan.

  • Rumus matematika

    Rumus biasanya cenderung sangat statis, sehingga sifat dari nilai-nilai konstan di dalamnya tidak terlalu penting. Volume piramida adalah (1/3) b * h. Apakah kita peduli dari mana 1 atau 3 berasal? Tidak juga. Seorang komentator sebelumnya dengan tepat menunjukkan bahwa diameter = radius * 2mungkin lebih baik daripada diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR- tetapi itu adalah dikotomi yang salah.

    Apa yang harus Anda lakukan untuk jenis skenario ini adalah membuat fungsi . Saya tidak perlu tahu bagaimana Anda membuat formula tetapi saya masih perlu tahu untuk apa itu . Jika, alih-alih omong kosong yang ditulis di atas, saya menulis volume = GetVolumeOfPyramid(base, height)kemudian tiba-tiba semuanya menjadi jauh lebih jelas, dan tidak apa-apa memiliki angka ajaib di dalam fungsi ( return base * height / 3) karena jelas bahwa mereka hanya bagian dari rumus.

    Kuncinya di sini tentu saja memiliki fungsi pendek dan sederhana . Ini tidak berfungsi untuk fungsi dengan 10 argumen dan 30 baris perhitungan. Gunakan komposisi fungsi atau konstanta dalam kasus itu.

  • Aturan domain / bisnis

    Yang ini selalu area abu-abu karena tergantung pada apa tepatnya nilainya. Sebagian besar waktu, angka ajaib inilah yang merupakan kandidat untuk berubah menjadi konstanta, karena itu membuat program lebih mudah dipahami tanpa menyulitkan logika program. Pertimbangkan tes if Age < 19vs if Age < LegalDrinkingAge; Anda mungkin dapat mengetahui apa yang terjadi tanpa konstanta, tetapi lebih mudah dengan judul deskriptif.

    Ini juga dapat menjadi kandidat untuk abstraksi fungsi, misalnya function isLegalDrinkingAge(age) { return age >= 19 }. Satu-satunya hal adalah bahwa seringkali logika bisnis Anda jauh lebih berbelit-belit daripada itu, dan mungkin tidak masuk akal untuk mulai menulis lusinan fungsi dengan masing-masing 20-30 parameter. Jika tidak ada abstraksi yang jelas berdasarkan objek dan / atau fungsi maka beralih ke konstanta adalah OK.

    Peringatannya adalah, jika Anda bekerja untuk departemen pajak, menjadi sangat, sangat membebani dan jujur ​​tidak ada gunanya menulis AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR). Anda tidak akan melakukan itu, Anda akan melakukannya AttachForm("B-46")karena setiap pengembang tunggal yang pernah bekerja atau pernah akan bekerja di sana akan tahu bahwa "B-46" adalah kode formulir untuk wajib pajak tunggal yang mengajukan bla bla bla - kode formulir adalah bagian dari domain itu sendiri, mereka tidak pernah berubah, jadi itu bukan angka ajaib.

    Jadi, Anda harus menggunakan konstanta hemat dalam logika bisnis; pada dasarnya Anda harus memahami apakah "angka ajaib" itu sebenarnya angka ajaib atau apakah itu aspek domain yang terkenal. Jika itu domain, maka Anda tidak melakukan soft-code kecuali ada peluang yang benar-benar bagus untuk berubah.

  • Kode kesalahan dan bendera status

    Ini tidak pernah oke untuk hard-code, seperti bajingan miskin yang pernah dipukul dengan Previous action failed due to error code 46dapat memberitahu Anda. Jika bahasa Anda mendukungnya, Anda harus menggunakan jenis enumerasi. Jika tidak, Anda biasanya memiliki seluruh file / modul penuh konstanta yang menentukan nilai yang valid untuk jenis kesalahan tertentu.

    Jangan pernah biarkan saya melihat return 42penangan kesalahan, capiche? Tidak ada alasan.

Saya mungkin meninggalkan beberapa skenario tetapi saya pikir itu mencakup sebagian besar dari mereka.

Jadi, ya, kadang-kadang praktik yang diterima untuk hal-hal kode sulit. Hanya saja, jangan malas tentang itu; itu harus menjadi keputusan sadar daripada kode ceroboh tua yang biasa.

Aaronaught
sumber
Terima kasih atas rinciannya! - kebanyakan orang tidak memikirkan semua opsi yang akan saya tambahkan "Konfigurasi Lingkungan" - Saya pikir ini harus dihindari (bukan hard-coded), karena sebagian besar data harus dimasukkan ke dalam file konfigurasi atau database. Ini mengikuti prinsip "menjaga data dan logika terpisah" yang merupakan andalan MVC atau MVVM. string TestServerVar = "foo"; string ProdServerVal = "bar";
m1m1k
7

Ada berbagai alasan untuk menetapkan pengidentifikasi ke nomor.

  • Jika nomor mungkin berubah, itu harus memiliki pengenal. Jauh lebih mudah untuk menemukan NUMBER_OF_PLANETS daripada mencari setiap instance dari 9 dan mempertimbangkan apakah itu harus diubah menjadi 8. (Perhatikan bahwa string yang dapat dilihat pengguna mungkin harus berubah jika perangkat lunak harus digunakan dalam bahasa yang berbeda, dan itu hal yang sulit untuk diprediksi sebelumnya.)
  • Jika nomor tersebut sulit diketik dengan cara apa pun. Untuk konstanta seperti pi, lebih baik memberikan satu definisi presisi maksimum daripada mengetik ulang di beberapa tempat, mungkin tidak akurat.
  • Jika angkanya terjadi di tempat yang berbeda. Anda tidak harus melihat dua kegunaan 45 dalam fungsi yang berdekatan dan bertanya-tanya apakah mereka memiliki arti yang sama.
  • Jika artinya tidak langsung dikenali. Aman untuk berasumsi bahwa semua orang tahu apa itu 3.14159265 .... Tidak aman untuk mengasumsikan bahwa semua orang akan mengenali konstanta gravitasi, atau bahkan pi / 2. ("Semua orang" di sini tergantung pada sifat perangkat lunak. Pemrogram sistem dapat diharapkan untuk mengetahui representasi oktal dari bit izin Unix atau sejenisnya. Dalam perangkat lunak arsitektur angkatan laut / laut, memeriksa jumlah Froude dari lambung yang diusulkan dan kecepatan untuk lihat apakah 1.1 atau lebih besar mungkin cukup jelas bagi siapa saja yang harus mengerjakannya.)
  • Jika konteksnya tidak dikenali. Semua orang tahu ada 60 menit dalam satu jam, tetapi mengalikan atau membagi dengan 60 mungkin tidak jelas jika tidak ada indikasi langsung bahwa kuantitas adalah nilai waktu atau nilai tarif.

Ini memberi kita kriteria untuk literal hard-coding. Mereka harus tidak berubah, tidak sulit untuk mengetik, terjadi di satu tempat atau konteks saja, dan dengan makna yang dapat dikenali. Tidak ada gunanya mendefinisikan 0 sebagai ARRAY_BEGINNING, misalnya, atau 1 sebagai ARRAY_INCREMENT.

David Thornley
sumber
5

Sebagai tambahan jawaban lainnya. Gunakan konstanta untuk string bila memungkinkan. Tentu saja, Anda tidak mau memilikinya

const string server_var="server_var";

tetapi Anda harus melakukannya

const string MySelectQuery="select * from mytable;";

(dengan asumsi Anda benar-benar memiliki kueri di mana Anda ingin mendapatkan semua hasil dari tabel tertentu, selalu)

Selain itu, gunakan konstanta untuk angka selain 0 (biasanya). Jika Anda memerlukan bitmask izin 255, jangan gunakan

const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.

alih-alih gunakan

const int AllowGlobalRead=255;

Tentu saja, bersama dengan konstanta, tahu kapan harus menggunakan enumerator. Kasing di atas mungkin akan cocok dalam satu.

Earlz
sumber
typedef enum {state_0 = 0, state_1 = 1, state_2 = 2, ...} ... Jangan tertawa, saya sudah melihatnya selesai. Pukul orang itu di sekitar kepala dengan ikan basah!
cepat,
@ cukup baik tentu saja Anda menginginkan sesuatu yang lebih sepertitypedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
Earlz
6
THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS
StuperUser
4
Untuk string, Anda tidak hanya menginginkan konstanta. Anda ingin memasukkan string yang terlihat oleh pengguna ke dalam semacam file sumber daya (detail akan tergantung pada platform Anda) sehingga Anda dapat dengan mudah mengubah bahasa lain.
David Thornley
Anda mungkin juga ingin menempelkan string yang terkait dengan logika bisnis (seperti kueri SQL) dalam file sumber daya dengan beberapa jenis enkripsi atau kebingungan. Itu akan mencegah pengguna "penasaran" dari rekayasa balik logika Anda (atau skema basis data).
TMN
4

Itu tergantung apa yang Anda anggap sebagai hardcoding. Jika Anda mencoba menghindari setiap dan semua hal yang dikodekan dengan keras , Anda berakhir di wilayah softcoding , dan membuat sistem yang hanya bisa dikelola oleh pembuatnya (dan itulah hardcode utama)

Banyak hal yang dikodekan dalam kerangka kerja yang masuk akal dan mereka bekerja. yaitu tidak ada alasan teknis mengapa saya tidak dapat mengubah titik masuk aplikasi C # (static void Main), tetapi hardcoding yang tidak menimbulkan masalah bagi pengguna mana pun (kecuali sesekali pertanyaan SO )

Aturan praktis yang saya gunakan adalah bahwa segala sesuatu yang dapat dan akan berubah, tanpa mempengaruhi keadaan keseluruhan sistem, harus dapat dikonfirmasikan.

Jadi, IMHO, konyol untuk tidak melakukan hardcode hal-hal yang tidak pernah berubah (pi, konstanta gravitasi, konstanta dalam rumus matematika - pikirkan volume bola).

Juga konyol untuk tidak melakukan hardcode pada hal-hal atau proses yang akan berdampak pada sistem Anda yang akan memerlukan pemrograman dalam hal apa pun, yaitu pemborosan untuk memperbolehkan pengguna untuk menambahkan bidang dinamis ke formulir, jika bidang tambahan apa pun membutuhkan pengembang pemeliharaan untuk masuk dan tulis beberapa skrip yang akan membuat hal itu bekerja. Juga itu bodoh (dan saya sudah melihatnya beberapa kali di lingkungan perusahaan) untuk membuat beberapa alat konfigurasi, jadi tidak ada yang di-hardcode, namun, hanya pengembang di departemen IT yang dapat menggunakannya, dan hanya sedikit lebih mudah untuk menggunakannya daripada untuk melakukannya di Visual Studio.

Jadi, intinya, apakah suatu hal harus hardcoded adalah fungsi dari dua variabel:

  • akan nilainya berubah
  • bagaimana perubahan nilai akan mempengaruhi sistem
SWeko
sumber
4

Apakah pernah ada ide bagus untuk nilai hardcode ke dalam aplikasi kita?

Saya nilai-nilai hardcode hanya jika nilai-nilai yang ditentukan dalam Spesifikasi (pada rilis akhir spesifikasi), mis. Respons HTTP OK akan selalu 200(kecuali jika berubah dalam RFC), jadi, Anda akan melihat (dalam beberapa kode saya ) konstanta seperti:

public static final int HTTP_OK = 200;

Kalau tidak, saya menyimpan konstanta dalam file properti.

Alasan mengapa saya menentukan spesifikasi, adalah bahwa perubahan konstanta dalam spesifikasi memerlukan manajemen perubahan, di mana, para pemangku kepentingan akan meninjau perubahan dan menyetujui / menolak. Itu tidak pernah terjadi dalam semalam dan butuh berbulan-bulan / tahun untuk persetujuan. Jangan lupa bahwa banyak pengembang menggunakan spesifikasi (misalnya HTTP) sehingga mengubahnya berarti melanggar jutaan sistem.

Buhake Sindi
sumber
3
  • jika nilai dapat berubah, dan memang mungkin berubah, maka soft-code sedapat mungkin selama upaya yang terlibat tidak melebihi pengembalian yang diharapkan
  • beberapa nilai tidak dapat dikodekan secara lunak; ikuti pedoman Jonathan dalam kasus-kasus (jarang) itu
Steven A. Lowe
sumber
3

Saya perhatikan bahwa setiap kali Anda dapat mengekstrak data dari kode Anda, itu meningkatkan apa yang tersisa. Anda mulai memperhatikan refactor baru dan meningkatkan seluruh bagian kode Anda.

Itu hanya ide yang baik untuk bekerja mengekstraksi konstanta, jangan menganggapnya sebagai aturan bodoh, pikirkan itu sebagai kesempatan untuk kode yang lebih baik.

Keuntungan terbesar adalah cara Anda dapat menemukan konstanta yang sama menjadi satu-satunya perbedaan dalam kelompok kode - mengabstraksi mereka menjadi array telah membantu saya mengurangi beberapa file hingga 90% dari ukurannya dan memperbaiki beberapa bug copy & paste sementara itu .

Saya belum melihat satu keuntungan untuk tidak mengekstraksi data.

Bill K
sumber
2

Baru-baru ini saya membuat kode fungsi MySQL untuk menghitung jarak antara dua pasangan lat / panjang dengan benar. Anda tidak bisa hanya melakukan pythagorus; garis bujur semakin dekat seiring dengan meningkatnya lintang ke arah kutub, jadi ada beberapa trigonometri berbulu yang terlibat. Intinya adalah, saya cukup terpecah tentang apakah kode-keras nilai mewakili jari-jari bumi dalam mil.

Saya akhirnya melakukannya, meskipun kenyataannya adalah, garis lat / lng lebih dekat bersama, katakanlah, bulan. Dan fungsi saya akan secara drastis melaporkan jarak antara titik-titik di Jupiter. Saya pikir peluang situs web yang saya bangun memiliki lokasi luar angkasa yang masuk cukup kecil.

Dan Ray
sumber
Ya, mungkin, tetapi bagaimana dengan google.com/moon
Residuum
1

Yah itu tergantung jika bahasa Anda dikompilasi. Jika tidak dikompilasi, itu bukan masalah besar, Anda cukup mengedit kode sumber, bahkan jika itu akan sedikit rumit untuk non programmer.

Jika Anda memprogram dengan bahasa yang dikompilasi, ini jelas bukan ide yang baik, karena jika variabel berubah, Anda harus mengkompilasi ulang, yang merupakan pemborosan waktu jika Anda ingin menyesuaikan variabel ini.

Anda tidak perlu membuat slider atau antarmuka untuk mengubah variabelnya secara dinamis, tetapi yang paling bisa Anda lakukan adalah file teks.

Sebagai contoh dengan proyek raksasa saya, saya selalu menggunakan kelas ConfigFile untuk memuat variabel yang saya tulis ke file konfigurasi.

jokoon
sumber
1

Dua kesempatan di mana konstanta (menurut saya setidaknya) OK:

  1. Konstanta yang tidak berhubungan dengan hal lain; Anda dapat mengubah konstanta tersebut kapan pun Anda suka tanpa harus mengubah apa pun. Contoh: Lebar default kolom kisi.

  2. Konstanta yang benar-benar abadi, tepat, dan jelas, seperti "jumlah hari per minggu". days = weeks * 7Mengganti 7dengan konstanta DAYS_PER_WEEKhampir tidak memberikan nilai apa pun.

pengguna281377
sumber
0

Saya setuju sepenuhnya dengan Jonathan tetapi karena semua aturan ada pengecualian ...

"Nomor ajaib dalam spec: Nomor ajaib dalam kode"

Pada dasarnya menyatakan bahwa setiap angka ajaib yang tetap dalam spesifikasi setelah upaya yang masuk akal untuk mendapatkan konteks deskriptif untuk mereka harus tercermin dalam kode. Jika angka ajaib tetap ada dalam kode, setiap upaya harus dilakukan untuk mengisolasi mereka dan membuatnya jelas terkait dengan titik asal mereka.

Saya telah melakukan beberapa kontrak interfacing di mana perlu mengisi pesan dengan nilai-nilai yang dipetakan dari database. Dalam kebanyakan kasus, pemetaannya cukup lurus ke depan dan cocok dengan garis panduan umum Jonathan, tetapi saya telah menemukan kasus di mana struktur pesan target sangat buruk. Lebih dari 80% nilai yang harus diwariskan dalam struktur adalah konstanta yang ditegakkan oleh spesifikasi sistem yang jauh. ini ditambah dengan fakta bahwa struktur pesan itu raksasa sehingga BANYAK konstanta seperti itu harus diisi. Dalam kebanyakan kasus mereka tidak memberikan arti atau alasan, hanya mengatakan "taruh M di sini" atau "taruh 4.10.53.10100.889450.4452 di sini". Saya tidak mencoba untuk memberikan komentar di sebelah mereka semua itu akan membuat kode yang dihasilkan tidak dapat dibaca.

Yang mengatakan, ketika Anda memikirkannya ... itu hampir semua tentang membuatnya jelas ...

Newtopian
sumber
0

Jika Anda melakukan hardcoding nilai konstanta gravitasi bumi, tidak ada yang akan peduli. Jika Anda meng-hardcode alamat IP server proxy Anda, berarti Anda dalam masalah.

jwenting
sumber
1
Anda mungkin perlu lebih presisi untuk konstanta gravitasi bumi, jadi meng-hardcarnya beberapa kali dapat menimbulkan masalah.
user281377
1
Peter Noone? Dari Herman's Hermits?
David Conrad
Akselerasi gravitasi di Bumi cukup banyak 9,81 m / s ^ 2 untuk sebagian besar garis lintang dan ketinggian (tentu saja, jika Anda mencari minyak di bawah tanah, atau menembakkan ICBM di Kutub Utara, mengetahui variasi gravitasi sangat penting untuk lebih banyak tempat desimal), dengan percepatan gravitasi di planet lain menjadi angka yang berbeda, tetapi sejauh yang saya tahu, tetapan gravitasi adalah konstan di sekitar alam semesta. Ada banyak fisika yang harus berubah jika g adalah variabel.
Tangurena
0

Kebanyakan tidak, tapi saya pikir patut dicatat bahwa Anda akan memiliki masalah paling banyak ketika Anda mulai menduplikasi nilai hard-coded. Jika Anda tidak menduplikasi (mis. Menggunakannya hanya sekali dalam implementasi kelas) maka tidak menggunakan konstanta mungkin baik-baik saja.


sumber