Apakah ini penggunaan berlebihan konstan simbolik?

34

Saya cukup baru dalam rekayasa perangkat lunak, dan sebagai latihan belajar saya menulis permainan catur. Teman saya melihatnya dan menunjukkan bahwa kode saya terlihat seperti

for (int i = 0; i < 8; i++){
    for (int j = 0; j < 8; j++){

sementara dia bersikeras bahwa itu seharusnya terjadi

for (int i = 0; i < CHESS_CONST; i++){
    for (int j = 0; j < CHESS_CONST; j++){

dengan beberapa nama simbol yang lebih baik yang tidak bisa saya pikirkan saat ini.

Sekarang tentu saja saya tahu umumnya menghindari menggunakan angka ajaib, tapi saya merasa seperti itu

  1. jumlah ini tidak akan pernah berubah;
  2. namanya tidak bisa deskriptif karena nomor tersebut digunakan di banyak tempat di seluruh kode; dan
  3. siapa pun yang melalui kode sumber untuk program catur harus cukup tahu tentang catur untuk mengetahui apa tujuan 8 catur itu,

benar-benar tidak perlu untuk konstanta simbolis.

Jadi apa yang kalian pikirkan? Apakah ini berlebihan, atau haruskah saya pergi dengan konvensi dan menggunakan simbol?

cokelat jahat
sumber
46
CHESS_CONST jauh lebih buruk daripada hanya menggunakan angka 8, tetapi konstanta dengan nama deskriptif akan menjadi peningkatan. Anda bilang siapa pun harus tahu 8 kepanjangan dari kode, tapi ini tidak benar. Huruf integer tanpa konteks dapat berarti sejumlah hal, seperti sejumlah gerakan, jumlah potongan di papan tulis dan sebagainya. Nama deskriptif untuk konstanta akan memperjelas maksud dan karenanya kode lebih mudah dimengerti.
JacquesB
43
Secara pribadi, apa yang saya temukan jauh lebih menggelegar daripada angka ajaib adalah nama idan juntuk variabel loop. Saya tidak bisa seumur hidup saya mencari tahu mana yang seharusnya mewakili peringkat dan mana yang seharusnya mewakili file. Peringkat berkisar dari 1..8 dan file berkisar dari a .. h, tetapi dalam kasus Anda, keduanya idan jberkisar dari 0..7, sehingga tidak membantu saya melihat mana yang mana. Apakah ada krisis kekurangan surat internasional yang tidak saya ketahui, atau apa salahnya mengubah nama mereka menjadi rankdan file?
Jörg W Mittag
4
Mainkan advokat iblis untuk sesaat; Bayangkan membaca kode catur seseorang di mana mereka telah menggunakan angka ajaib 8. Bisakah Anda menganggap Anda tahu apa yang digunakan untuk itu? Bagaimana Anda bisa 100% yakin? Apakah ada kemungkinan itu bisa berarti sesuatu yang lain? Bukankah itu hanya akan sedikit lebih baik jika Anda bahkan tidak harus membuat asumsi? Berapa banyak waktu yang Anda habiskan untuk menelusuri kode untuk mengetahui apakah asumsi Anda benar? Apakah Anda akan menghabiskan lebih sedikit waktu jika kodenya lebih banyak didokumentasikan sendiri menggunakan nama yang bermakna dan berwawasan luas?
Ben Cottrell
16
@ JacquesB: Memang. Ada 8 peringkat, 8 file, 8 pion. Beberapa mesin catur menggunakan sistem poin di mana potongan-potongan tertentu, bidang tertentu, dan gerakan tertentu memiliki poin yang melekat padanya dan mesin memilih gerakan dengan skor tertinggi. 8 mungkin skor seperti itu. 8 mungkin kedalaman pencarian default. Mungkin cukup banyak apa saja.
Jörg W Mittag
9
Saya akan mempertimbangkan menggunakan foreach loop, mis foreach(var rank in Ranks). Saya juga akan mempertimbangkan untuk menggabungkan kedua loop menjadi satu di mana setiap elemen adalah tuple (peringkat, file).
CodesInChaos

Jawaban:

101

IMHO teman Anda benar dalam menggunakan nama simbolis, meskipun saya pikir nama pasti lebih deskriptif (seperti BOARD_WIDTHbukan CHESS_CONST).

Bahkan ketika nomor tidak akan pernah berubah selama masa program, mungkin ada tempat lain di program Anda di mana nomor 8 akan terjadi dengan makna yang berbeda. Mengganti "8" dengan BOARD_WIDTHdimanapun lebar papan dimaksud, dan menggunakan nama simbolis lain ketika hal yang berbeda dimaksudkan membuat makna yang berbeda ini eksplisit, jelas dan keseluruhan program Anda lebih mudah dibaca dan dipelihara. Ini memungkinkan Anda juga untuk melakukan pencarian global atas program Anda (atau pencarian simbol terbalik, jika lingkungan Anda menyediakannya) jika Anda perlu dengan cepat mengidentifikasi semua tempat dalam kode yang bergantung pada lebar papan.

Lihat juga posting SE.SE ini sebelumnya untuk diskusi bagaimana (atau bagaimana tidak) memilih nama untuk angka.

Sebagai catatan tambahan, karena dibahas di sini di komentar : jika, dalam kode program nyata Anda, penting jika variabel imerujuk ke baris dan jkolom papan, atau sebaliknya, maka disarankan untuk memilih nama variabel yang buat perbedaannya jelas, seperti rowdan col. Manfaat dari nama-nama tersebut adalah, mereka membuat kode yang salah terlihat salah.

Doc Brown
sumber
22
Saya ingin menambahkan, jika OP telah menulis mesin catur yang benar-benar hebat maka ingin mengembangkannya untuk memasukkan catur 3D, atau varian lainnya, maka yang perlu diubah adalah tantangan.
Steve Barnes
32
@SteveBarnes: Saya mencoba menghindari argumen seperti itu, karena terlalu mudah mengarah ke argumen yang dikembalikan seperti "Saya pikir itu sangat tidak seperti membuat program ini permainan yang berbeda, jadi saya dapat meninggalkan angka ajaib 8 di tempatnya. "
Doc Brown
4
@IllusiveBrian Itu argumen klasik "manusia jerami" karena dua alasan: (1) hanya mendefinisikan konstanta tidak berarti programmer masih tidak bisa mengetikkan "8" (apakah karena kecelakaan, desain, atau kedengkian!) Dan (2) hanya karena ada BOARD_WIDTH = 8 yang konstan tidak menjadikan BOARD_WIDTH konstanta yang benar untuk digunakan di tempat tertentu dalam program.
alephzero
3
@ Bllfl ... atau akan menyebabkan rekayasa ulang kode. Adalah tanggung jawab pengembang untuk menyadari apa yang dapat berubah di masa depan dan kode yang sesuai. Pengkodean persyaratan seperti tidak akan berubah menyebabkan masalah, tetapi ekstrem lainnya tidak lebih baik.
Malcolm
4
@corsiKa Ketika variabel loop sesuai dengan sumbu fisik, mereka harus dinamai x, y atau baris, col atau, untuk catur, file, peringkat.
user949300
11

Ok, berikut beberapa komentar yang saya miliki:

Menyingkirkan angka ajaib adalah ide bagus. Ada konsep yang dikenal sebagai KERING, yang sering salah diartikan, tetapi idenya adalah Anda tidak menduplikasi pengetahuan konsep-konsep dalam proyek Anda. Jadi, jika Anda memiliki kelas yang disebut ChessBoard, Anda bisa menyimpan konstanta yang disebut BOARD_SIZE atau ChessBoard.SIZE terlampir padanya. Dengan cara ini ada satu sumber tunggal untuk informasi ini. Juga, ini membantu keterbacaan nanti:

for (int i = 0; i < ChessBoard.SIZE; i++){
  for (int j = 0; j < ChessBoard.SIZE; j++){

Bahkan jika angkanya tidak pernah berubah, program Anda bisa dibilang lebih baik. Setiap orang yang membacanya mengetahui lebih banyak informasi tentang apa yang dilakukan kode.

Nama yang buruk lebih buruk daripada tidak ada nama, tetapi itu tidak berarti bahwa sesuatu tidak boleh disebutkan namanya. Cukup ganti namanya. Jangan membuang bayi dengan air mandi. : p Nama dapat deskriptif selama Anda memahami dengan baik apa yang dijelaskan. Kemudian, konsep itu dapat digunakan untuk banyak hal yang berbeda.

unflores
sumber
8
ini sepertinya hanya mengulangi poin-poin yang sudah dibuat dan dijelaskan dalam jawaban teratas
nyamuk
-7

Yang benar-benar Anda inginkan adalah menghilangkan referensi ad nauseum ke konstanta, apakah itu diberi nama atau kosong:

for_each_chess_square (row, col) {
  /*...*/
}

Jika Anda benar-benar akan memperbanyak konstanta dengan mengulang loop seperti itu dan yang lainnya, yang terbaik adalah tetap melakukannya 8.

8menggambarkan diri sendiri; itu bukan makro yang berarti sesuatu yang lain.

You Ain't Never Gonna (TM) mengubahnya menjadi program catur 9x9 dan jika Anda melakukannya, proliferasi 8 tidak akan menjadi kesulitan utama.

Kita dapat mencari 150.000 basis kode baris untuk token 8, dan mengklasifikasikan kejadian mana artinya dalam hitungan detik.

Jauh lebih penting adalah memodulasi kode sehingga pengetahuan catur terkonsentrasi di tempat sesedikit mungkin. Lebih baik untuk memiliki satu, dua, mungkin tiga modul khusus catur di mana 8 literal terjadi, daripada tiga puluh tujuh modul dicampur dengan tanggung jawab spesifik catur, merujuk 8 melalui nama simbolis.

Ketika atau jika konstanta 8 ini menjadi sumber ketegangan dalam program Anda, Anda dapat dengan mudah memperbaikinya saat itu. Perbaiki masalah nyata yang sedang terjadi sekarang. Jika Anda tidak merasa terhambat oleh angka 8 itu, pergilah dengan naluri itu.

Misalkan di masa depan Anda ingin mendukung dimensi papan alternatif. Dalam hal itu, loop tersebut harus berubah apakah mereka menggunakan konstanta bernama atau 8, karena dimensi akan diambil oleh beberapa ekspresi seperti board.widthdan board.height. Jika sudah, BOARD_SIZEalih - alih 8, tempat-tempat ini akan lebih mudah ditemukan. Jadi itu kurang usaha. Namun, Anda tidak boleh lupa tentang upaya penggantian 8dengan BOARD_SIZEdi tempat pertama. Upaya keseluruhan tidak lebih rendah. Membuat satu lulus melalui kode untuk perubahan 8untuk BOARD_SIZE, dan kemudian lain untuk mendukung dimensi alternatif, tidak lebih murah daripada hanya pergi dari 8dukungan dimensi alternatif.

Kita juga dapat melihat ini dari analisis risiko / manfaat yang murni dingin, obyektif. Program ini memiliki konstanta kosong di dalamnya sekarang. Jika ini digantikan oleh konstanta, tidak ada manfaatnya; programnya identik. Dengan perubahan apa pun, ada risiko yang bukan nol. Dalam hal ini kecil. Namun, tidak ada risiko yang harus diambil tanpa manfaat. Untuk "menjual" perubahan dalam menghadapi alasan ini, kita harus berhipotesis manfaat: manfaat masa depan yang akan membantu dengan program yang berbeda: versi masa depan dari program yang tidak ada sekarang. Jika program semacam itu sedang direncanakan, hipotesis ini dan alasannya yang terkait adalah bonafid dan harus ditanggapi dengan serius.

Misalnya, jika Anda beberapa hari lagi menambahkan kode yang akan semakin memperbanyak konstanta ini, Anda mungkin ingin menghapusnya. Jika instance konstanta itu kira-kira semua instance yang pernah ada maka mengapa repot-repot.

Jika Anda pernah bekerja pada perangkat lunak komersial, argumen ROI juga akan berlaku. Jika suatu program tidak menjual, dan mengubah beberapa nomor kode-keras menjadi konstanta tidak akan meningkatkan penjualan, Anda tidak akan dikompensasikan dengan upaya tersebut. Perubahan tidak memiliki pengembalian investasi waktu. Argumen ROI menggeneralisasi di luar uang. Anda menulis sebuah program, menginvestasikan waktu dan usaha, dan mendapatkan sesuatu dari itu: itu pengembalian Anda, "R" Anda. Jika dengan melakukan perubahan itu sendiri, Anda mendapatkan lebih banyak dari "R" itu, apa pun itu, maka dengan segala cara. Jika Anda memiliki beberapa rencana untuk pengembangan lebih lanjut, dan perubahan itu meningkatkan "R" Anda, lagi. Jika perubahan itu tidak memiliki "R" yang dapat langsung atau dapat Anda lakukan, lupakan saja.

Kaz
sumber
13
8BUKAN menggambarkan diri sendiri, itu angka yang bisa berarti apa saja. Dan mungkin mereka ingin melakukan permainan catur 9x9, mengapa tidak? Jika Anda memiliki 150.000 baris kode, tidak mungkin Anda dapat menghafal arti setiap 8kode, dan bahkan jika Anda bisa, mengapa Anda melakukannya? Itu hanya banyak kerumitan ekstra. Sejauh modularisasi, mengganti 8dengan sesuatu seperti NUM_RANKStidak merusak modularitas, pada kenyataannya, itu membantu karena membuat kode lebih mudah untuk bermain-main.
Jerfov2
4
@ Ka, aku juga melakukannya. Dan kemudian saya memperkenalkan bug aneh yang signifikan karena beberapa penggunaan tidak sesuai dengan yang saya kira, karena sulit untuk memperhatikan sebanyak itu penggantian dan juga benar setiap waktu. Karena itu saya menghindari skenario ini sejak awal, jadi saya tidak bisa mendukung saran yang memaafkan.
doppelgreener
1
"Namun, Anda tidak boleh lupa tentang upaya penggantian 8dengan BOARD_SIZEdi tempat pertama" - Waktu yang Anda habiskan meneliti kode Anda mencoba untuk mencari tahu apa yang masing 8- masing lakukan dalam program Anda beberapa bulan dari sekarang kemungkinan besar akan melebihi waktu yang dihabiskan untuk mengganti 8dengan konstanta tingkat modul yang bermakna.
Christian Dean
1
@doppelganger Skenario itu sudah ada di sini. Saya tidak mengatakan, ambil program catur yang menggunakan konstanta, dan ganti dengan 8. Juga saya tidak mengatakan, "rencanakan untuk tidak menggunakan konstanta dalam program catur yang belum ditulis"
Kaz
1
@ Ka Mengapa Anda ingin membuat diri Anda harus membaca semua kode di sekitar 8, dan mungkin kadang-kadang salah konteks ketika Anda hanya bisa menghabiskan 3 detik ekstra memberi dalam nama yang bermakna? Adapun mengetahui nilai aktual dari konstanta, itu jauh lebih mudah mencari nilai yang tepat untuk variabel daripada mencoba mundur-insinyur apa arti beberapa integer ajaib dalam kode
Jerfov2