Apakah konstanta satu karakter lebih baik daripada literal?

127

Saya baru-baru ini menemukan kelas yang menyediakan hampir setiap karakter tunggal sebagai konstanta; semuanya dari COMMAsampai BRACKET_OPEN. Ingin tahu apakah ini perlu; Saya membaca "artikel" yang menunjukkan bahwa mungkin bermanfaat untuk menarik literal satu karakter ke dalam konstanta. Jadi, saya skeptis.

Daya tarik utama menggunakan konstanta adalah mereka meminimalkan pemeliharaan ketika perubahan diperlukan. Tetapi kapan kita akan mulai menggunakan simbol yang berbeda dari ',' untuk mewakili koma?

Satu-satunya alasan saya melihat untuk menggunakan konstanta alih-alih literal adalah untuk membuat kode lebih mudah dibaca. Tetapi apakah city + CharacterClass.COMMA + state(misalnya) benar-benar lebih mudah dibaca daripada city + ',' + state?

Bagi saya kontra lebih besar daripada pro, terutama bahwa Anda memperkenalkan kelas lain dan impor lainnya. Dan saya percaya pada sedikit kode jika memungkinkan. Jadi, saya bertanya-tanya apa konsensus umum di sini.

Hari Austin
sumber
33
Hmm ... mungkin berguna untuk lokasi yang berbeda, mungkin? Sebagai contoh, beberapa bahasa menggunakan guillements (kutipan sudut, «dan ») sebagai tanda kutip alih-alih standar bahasa Inggris "(atau lebih bagus dan tampak ). Terlepas dari itu, itu hanya terdengar seperti serangkaian karakter sihir. Dengan asumsi dua contoh CharacterClassdipanggil englishCharsdan frenchChars, mungkin itu englishChars.LEFT_QUOTEmungkin , sementara frenchChars.LEFT_QUOTEmungkin «.
Justin Time
4
Ada banyak varian berbeda di koma: en.wikipedia.org/wiki/Comma#Comma_variants - mungkin ini bukan ide yang bodoh, terutama jika kode sumber Anda dapat dikodekan sebagai utf-8.
Aaron Hall
21
Dalam kasus Anda, itu seperti memanggil variabel "angka". Konstanta Anda seharusnya disebut DELIMITER. Atau seharusnya CITY_STATE = "{0}, {1}"
the_lotus
13
Artikel yang Anda tautkan sangat mengerikan. Konstanta tidak boleh dilemparkan ke dalam ember seperti itu. Letakkan mereka di kelas di mana mereka memiliki konteks: pada dasarnya, kelas dengan konstanta menyediakan konteks di mana konstanta digunakan. Misalnya, Java File.separator. Kelas memberi tahu Anda jenis pemisah. Memiliki kelas bernama Constsatau Constantstidak memberikan konteks dan membuat konstanta lebih sulit untuk digunakan dengan benar.

Jawaban:

183

Tautologi :

Sangat jelas jika Anda membaca kalimat pertama dari pertanyaan bahwa pertanyaan ini bukan tentang penggunaan yang tepat seperti menghilangkan angka ajaib , ini tentang konsistensi bodoh yang tidak ada artinya . Yang dimaksud dengan jawaban ini

Akal sehat memberi tahu Anda bahwa const char UPPER_CASE_A = 'A';atau const char A = 'A'tidak menambahkan apa pun selain pemeliharaan dan kompleksitas ke sistem Anda. const char STATUS_CODE.ARRIVED = 'A'adalah kasus yang berbeda.

Konstanta seharusnya mewakili hal-hal yang tidak berubah pada saat runtime, tetapi mungkin perlu dimodifikasi di masa depan pada waktu kompilasi. Kapan akan const char A =sama dengan benar selain dari apa A?

Jika Anda melihat public static final char COLON = ':'dalam kode Java, cari siapa yang menulis itu dan hancurkan keyboard mereka. Jika representasi untuk COLONselamanya berubah dari :Anda akan memiliki mimpi buruk pemeliharaan.

Kebingungan:

Apa yang terjadi ketika seseorang mengubahnya COLON = '-'karena di mana mereka menggunakannya membutuhkan di -mana-mana? Apakah Anda akan menulis unit test yang pada dasarnya mengatakan assertThat(':' == COLON)untuk setiap constreferensi tunggal untuk memastikan mereka tidak berubah? Hanya ada seseorang yang memperbaiki tes ketika mereka mengubahnya?

Jika seseorang benar-benar berpendapat bahwa public static final String EMPTY_STRING = "";itu bermanfaat dan bermanfaat, Anda hanya memenuhi syarat pengetahuan mereka dan mengabaikannya dengan aman pada hal lain.

Memiliki setiap karakter yang dapat dicetak yang tersedia dengan versi bernama hanya menunjukkan bahwa siapa pun yang melakukannya, tidak memenuhi syarat untuk menulis kode tanpa pengawasan.

Kohesi:

Itu juga secara artifisial menurunkan kohesi, karena itu menjauhkan sesuatu dari hal-hal yang menggunakannya dan terkait dengannya.

Dalam pemrograman komputer, kohesi mengacu pada sejauh mana unsur-unsur modul dimiliki bersama. Dengan demikian, kohesi mengukur kekuatan hubungan antara bagian-bagian fungsionalitas dalam modul yang diberikan. Misalnya, dalam fungsionalitas sistem yang sangat kohesif sangat terkait.

Kopel:

Itu juga pasangan banyak kelas yang tidak terkait bersama-sama karena mereka semua akhirnya merujuk file yang tidak benar-benar terkait dengan apa yang mereka lakukan.

Kopling ketat adalah ketika sekelompok kelas sangat tergantung satu sama lain. Skenario ini muncul ketika suatu kelas mengambil terlalu banyak tanggung jawab, atau ketika satu masalah tersebar di banyak kelas daripada memiliki kelasnya sendiri.

Jika Anda menggunakan nama yang lebih baik seperti DELIMITER = ','Anda masih akan memiliki masalah yang sama, karena nama itu generik dan tidak membawa semantik. Menugaskan kembali nilai tidak lebih membantu melakukan analisis dampak daripada mencari dan mengganti literal ','. Karena beberapa kode apa yang menggunakannya dan perlu ,dan beberapa kode lain digunakan tetapi perlu ;sekarang? Masih harus melihat setiap penggunaan secara manual dan mengubahnya.

Di alam liar:

Saya baru-baru ini refactored 1,000,000+ LOCaplikasi yang berusia 18 tahun. Itu memiliki hal-hal seperti public static final COMMA = SPACE + "," + SPACE;. Itu sama sekali tidak lebih baik dari sekadar " , "menjelaskan di mana ia dibutuhkan.

Jika Anda ingin memperdebatkan keterbacaan, Anda perlu mempelajari Anda untuk mengonfigurasi IDE Anda untuk menampilkan whitespacekarakter di mana Anda dapat melihatnya atau apa pun, itu hanya alasan yang sangat malas untuk memasukkan entropi ke dalam sistem.

Itu juga telah ,didefinisikan beberapa kali dengan beberapa salah eja kata COMMAdalam beberapa paket dan kelas. Dengan referensi ke semua variasi yang dicampurkan bersama dalam kode. Itu bukan mimpi buruk untuk mencoba memperbaiki sesuatu tanpa merusak sesuatu yang sama sekali tidak berhubungan.

Sama dengan alfabet, ada beberapa UPPER_CASE_A, A, UPPER_A, A_UPPERyang sebagian besar waktu yang sama dengan A namun dalam beberapa kasus tidak . Untuk hampir setiap karakter, tetapi tidak semua karakter.

Dan dari sejarah edit tidak tampak bahwa satu pun dari ini pernah diedit atau diubah selama 18 tahun, karena apa yang sekarang menjadi alasan jelas adalah terlalu banyak hal yang tidak dapat dilacak, sehingga Anda memiliki variabel baru nama yang menunjuk ke hal yang sama yang tidak pernah dapat diubah karena alasan yang sama.

Dalam kenyataan yang tidak waras, Anda dapat berargumen bahwa praktik ini tidak melakukan apa pun kecuali memulai dengan entropi maksimum.

Saya refactored semua kekacauan ini dan menggarisbawahi semua tautologi dan mempekerjakan perguruan tinggi baru jauh lebih produktif karena mereka tidak harus memburu melalui beberapa tingkat tipuan apa constreferensi ini sebenarnya menunjuk, karena mereka tidak dapat diandalkan dalam apa yang mereka sebut vs apa yang dikandungnya.


sumber
112
Mungkin Anda harus menambahkan contoh balasan: const char DELIMITER = ':'akan sangat berguna.
Bergi 6-16
115
Saya akan membuat beberapa argumen yang EMPTY_STRINGbermanfaat. (1) Saya bisa lebih mudah menemukan semua kegunaan EMPTY_STRINGdalam file daripada yang saya dapat menemukan semua kegunaan "". (2) ketika saya melihat EMPTY_STRINGsaya tahu untuk darn yakin bahwa pengembang bermaksud agar string kosong, dan bahwa itu bukan salah edit atau pengganti untuk string yang akan disediakan nanti. Sekarang, Anda mengklaim bahwa dengan saya membuat argumen ini bahwa Anda mungkin memenuhi syarat pengetahuan saya, dan mengabaikan saya dengan aman selamanya Jadi, bagaimana Anda memenuhi kualifikasi pengetahuan saya? Dan apakah Anda berencana mengabaikan saran saya selamanya? Saya juga tidak memiliki masalah.
Eric Lippert
39
@immibis: Kita bisa berhenti memikirkan hal-hal ini sebagai berguna dalam konteks mengelola perubahan. Mereka adalah konstanta. Mereka tidak berubah. Anggap mereka berguna dalam konteks manusia mencari dan memahami kode semantik . Mengetahui bahwa sesuatu adalah kunci-nilai-pasangan-pembatas jauh lebih berguna daripada mengetahui itu adalah titik dua; itu adalah fakta tentang domain semantik yang menjadi perhatian program, bukan sintaksisnya .
Eric Lippert
15
@ EricLippert: Saya agak mengerti maksud orang lain di sini yang menunjukkan bahwa satu-satunya jaminan yang constdisediakan adalah bahwa itu tidak akan berubah saat runtime (setelah kompilasi), meskipun saya setuju dengan Anda bahwa arti semantik dari constis adalah jauh lebih penting daripada penggunaannya sebagai alat manajemen perubahan. Yang mengatakan, saya pasti bisa membayangkan const EARLIEST_OS_SUPPORTEDyang tidak hanya konsisten secara semantik, tetapi juga akan berubah dari waktu ke waktu seiring program berkembang dan cacat lama dihapus.
Robert Harvey
16
@DanielJour: Jadi ini adalah argumen ketiga untuk EMPTY_STRING; bahwa IDE yang dirancang dengan baik akan memunculkan alat yang memungkinkan saya untuk memperlakukan entitas ini secara simbolis, bukan secara sintaksis. Generalisasi ini ke argumen keempat: bahwa pustaka alat analisis kode yang berada di bawah IDE memungkinkan analisis terprogram lanjutan atas kebenaran kode di tingkat simbolik . Seorang pengembang yang ingin memanfaatkan alat lebih maju daripada yang ditulis secara harfiah 40 tahun yang lalu hanya perlu melakukan perubahan kecil pada kebiasaan mereka untuk menuai hasil dari alat canggih.
Eric Lippert
145

Daya tarik utama menggunakan konstanta adalah mereka meminimalkan pemeliharaan ketika perubahan diperlukan.

BENAR-BENAR TIDAK. Ini sama sekali bukan alasan untuk menggunakan konstanta karena konstanta tidak berubah menurut definisi . Jika sebuah konstanta berubah maka itu bukan konstanta, bukan?

Daya tarik menggunakan konstanta tidak ada hubungannya dengan manajemen perubahan dan segala sesuatu yang berkaitan dengan membuat program yang dapat ditulis, dipahami dan dikelola oleh orang-orang . Jika saya ingin tahu di mana saja dalam program saya di mana titik dua digunakan sebagai pemisah URL, maka saya bisa tahu itu dengan mudah jika saya memiliki disiplin untuk mendefinisikan URLSeparator yang konstan, dan tidak dapat mengetahui dengan mudah sama sekali jika saya harus mencari :dan dapatkan setiap tempat dalam kode :yang digunakan untuk menunjukkan kelas dasar, atau ?:operator, atau apa pun.

Saya benar-benar tidak setuju dengan jawaban lain yang menyatakan bahwa ini adalah buang-buang waktu yang tidak ada gunanya. Konstanta yang dinamai menambah makna pada suatu program, dan semantik tersebut dapat digunakan oleh manusia dan mesin untuk memahami suatu program lebih dalam dan memeliharanya lebih efektif.

Kuncinya di sini bukan untuk menghindari konstanta, tetapi untuk memberi nama mereka dengan sifat semantik mereka daripada sifat sintaksis mereka . Untuk apa konstanta digunakan? Jangan menyebutnya Commakecuali domain bisnis program Anda adalah tipografi, penguraian bahasa Inggris, atau sejenisnya. Sebut saja ListSeparatoratau semacamnya, untuk membuat semantik hal itu jelas.

Eric Lippert
sumber
42
Sementara saya setuju dengan semangat apa yang Anda katakan di sini, kalimat kedua / ketiga Anda tidak benar. Konstanta dapat berubah di antara versi file. Bahkan, sebagian besar program yang saya tulis memiliki konstanta bernama sesuatu seperti MY_VER, yang berisi nomor versi program saat ini, yang kemudian dapat digunakan sepanjang sisa program daripada string ajaib seperti "5.03.427.0038". Manfaat tambahan adalah ketika Anda mengatakan bahwa itu memberikan informasi semantik.
Monty Harder
50
Agar adil, titik konstanta adalah bahwa itu tidak berubah selama runtime setelah diinisialisasi, bukan bahwa itu tidak berubah di antara kompilasi. Dari perspektif kompiler, intinya adalah bahwa kompiler dapat membuat asumsi bahwa program tidak dapat memodifikasinya; apakah pemrogram diizinkan untuk memodifikasinya ketika mereka mengkompilasi ulang tidak mengubah konstannya. Mungkin juga ada kasus di mana perangkat lunak mengambil nilai hanya-baca dari perangkat keras, mungkin dengan mendereferensi const volatile T*pointer ke alamat yang telah ditentukan; sementara program tidak dapat mengubahnya, perangkat keras bisa.
Justin Time
6
@MontyHarder: Poin bagus. Pendapat saya diinformasikan oleh fakta bahwa saya biasanya menggunakan bahasa yang membedakan antara konstanta - yang harus selamanya tidak berubah - dan variabel yang dapat ditetapkan satu kali - yang dapat berubah dari versi ke versi, jalankan untuk menjalankan, atau apa pun. Konstanta dan variabel adalah hal yang berbeda; satu tetap sama dan satu bervariasi dari waktu ke waktu.
Eric Lippert
7
@SteveCox: Saya setuju; cara C / C ++ mencirikan "const" aneh dan penggunaannya terbatas. Properti yang saya inginkan dari konstanta adalah bahwa nilainya tidak berubah, bukan karena saya dibatasi untuk mengubahnya dalam beberapa fungsi tetapi tidak pada yang lain.
Eric Lippert
15
"Ini sama sekali bukan alasan untuk menggunakan konstanta karena konstanta tidak berubah menurut definisi. Jika sebuah konstanta pernah berubah maka itu bukan konstanta, bukan?" Mengubah konstanta pada waktu kompilasi (bukan runtime jelas) adalah sangat normal. Karena itulah Anda menjadikannya "benda" dengan jelas berlabel. Tentu saja, konstanta OP adalah sampah, tetapi pikirkan sesuatu seperti const VERSION='3.1.2'atau const KEYSIZE=1024atau apa pun.
AnoE
61

Tidak, itu bodoh.

Apa yang tidak perlu bodoh adalah menarik hal-hal seperti itu ke label bernama untuk alasan lokalisasi. Misalnya, pembatas ribuan adalah koma di Amerika (1.000.000), tetapi bukan koma di lokal lain. Menariknya ke dalam label bernama (dengan nama non-koma yang sesuai) memungkinkan programmer untuk mengabaikan / mengabstraksikan rincian itu.

Tetapi membuat konstan karena "string sihir buruk" hanyalah pemuatan kargo.

Telastyn
sumber
8
Lokalisasi biasanya lebih rumit daripada konstanta string saja. Misalnya, beberapa bahasa menginginkan pembatas daftar di antara semua item daftar, sementara yang lain mengecualikan pembatas sebelum item terakhir. Jadi, biasanya kita tidak perlu konstanta yang dilokalkan, tetapi aturan yang dilokalkan .
Vlad
19
Sebenarnya pembatas ribuan belum tentu ribuan pembatas di lokal lain (Cina / Jepang). Itu bahkan tidak ditetapkan setelah angka konstan (India). Oh, dan mungkin ada pembatas yang berbeda tergantung pada apakah pembatas 1000 atau pembatas 1000000 (Meksiko). Tapi itu kurang masalah daripada tidak menggunakan angka ASCII 0-9 di beberapa lokal (Persia). ux.stackexchange.com/questions/23667/…
Peter
1
@Vlad Localization jauh lebih kompleks dari itu, namun, pemisah ribuan adalah contoh terkenal yang dikenal orang.
Itu tergantung pada strategi pelokalan ... apakah Anda mengubah semua konstanta dalam program Anda untuk menerjemahkannya? Atau sebaiknya Anda lebih suka membaca nilai dari file (atau penyimpanan data lainnya), menjadikannya variabel runtime yang efektif?
Paŭlo Ebermann
Itu tidak akan berguna sama sekali sebagai konstanta, kalau begitu. Program ini perlu dikompilasi ulang untuk lokal, yang merupakan praktik yang mengerikan. Mereka harus berupa variabel yang diambil dari file definisi dan dicari sesuai kebutuhan. Bukannya saya tidak setuju dengan intinya (saya memilih jawabannya), tetapi saya akan mengambil posisi yang lebih sulit dalam masalah ini.
29

Ada beberapa karakter yang bisa ambigu atau digunakan untuk beberapa tujuan berbeda. Sebagai contoh, kita menggunakan '-'tanda hubung, tanda minus, atau bahkan tanda hubung. Anda dapat membuat nama terpisah sebagai:

static const wchar_t HYPHEN = '-';
static const wchar_t MINUS = '-';
static const wchar_t EM_DASH = '-';

Kemudian, Anda dapat memilih untuk mengubah kode Anda menjadi disambiguasi dengan mendefinisikan kembali sebagai:

static const wchar_t HYPHEN = '-';
static const wchar_t MINUS = '\u2122';
static const wchar_t EM_DASH = '\u2014';

Itu mungkin menjadi alasan mengapa Anda mempertimbangkan untuk mendefinisikan konstanta untuk karakter tunggal tertentu . Namun , jumlah karakter yang ambigu dengan cara ini kecil. Paling-paling, tampaknya Anda hanya akan melakukannya untuk mereka. Saya juga berpendapat bahwa Anda bisa menunggu sampai Anda benar-benar perlu membedakan karakter yang mendua sebelum Anda memfaktorkan kode dengan cara ini.

Karena konvensi tipografi dapat bervariasi menurut bahasa dan wilayah, Anda mungkin lebih baik memuat tanda baca yang ambigu dari tabel terjemahan.

Adrian McCarthy
sumber
Bagi saya ini adalah satu-satunya alasan yang valid untuk membuat konstanta karakter
FP
2
Menggunakannya -sebagai em dash cukup menyesatkan ... terlalu pendek untuk sebagian besar font. (Bahkan lebih pendek dari en dash.)
Paŭlo Ebermann
OK, bukan contoh terbaik. Saya mulai dengan strings agak wchar_ts dan menggunakan konvensi standar naskah "--"untuk tanda hubung. Tetapi contoh asli menggunakan karakter tunggal, jadi saya beralih untuk tetap setia pada pertanyaan. Ada orang-orang yang mengetik -tanda hubung, terutama ketika bekerja dalam huruf pitch tetap.
Adrian McCarthy
1
@ PaŭloEbermann Tidak, secara tradisional em dash adalah lebar dari karakter huruf 'm' dan en das adalah lebar karakter 'n'.
Dizzley
@ Patrick ya, dan lebar tanda hubung <n-lebar <m-lebar.
Paŭlo Ebermann
22

Konstanta harus menambahkan makna.

Menentukan COMMA menjadi koma tidak menambah makna, karena kita tahu bahwa koma adalah koma. Sebaliknya, kami menghancurkan makna, karena sekarang COMMA mungkin sebenarnya bukan koma lagi.

Jika Anda menggunakan koma untuk suatu tujuan dan ingin menggunakan konstanta bernama, beri nama setelah tujuan itu. Contoh:

  • city + CharacterClass.COMMA + state = buruk
  • city + CITY_STATE_DELIMITER + state = bagus

Gunakan fungsi untuk memformat

Saya pribadi lebih suka FormatCityState(city, state)dan tidak peduli bagaimana tubuh fungsi itu terlihat selama pendek dan lolos uji kasus.

Peter
sumber
1
Ah, tapi koma tidak selalu koma yang sama. Saya dapat mendefinisikan COMMA = '\ u0559' atau '\ u060C' dll. (Lihat Unicode) atau bahkan mengubahnya menjadi variabel nanti dan membacanya dari file konfigurasi. Dengan begitu, ia akan tetap memiliki makna yang sama , tetapi hanya nilainya yang berbeda. Bagaimana tentang itu.
Tn. Lister
2
@ Tuanister: YAGNI. Jika Anda memiliki kebutuhan itu: hebat! Anda punya solusi yang bagus. Tetapi jika Anda tidak - jangan mengacaukan kode Anda karena mungkin suatu hari Anda mungkin. Juga, dalam pengalaman saya jika Anda mencoba memperkenalkan abstraksi tanpa fungsi dalam basis kode Anda, orang tidak hebat dalam konsisten. Jadi, bahkan jika Anda mendefinisikan COMMA dengan maksud menggunakan beberapa codepoint lain, dalam program ukuran dan usia yang cukup sehingga pilihan itu penting, Anda cenderung menemukan bahwa konstanta tidak digunakan di mana pun seharusnya. telah (dan sebaliknya, mungkin telah digunakan secara tidak tepat juga).
Eamon Nerbonne
17

Gagasan bahwa COMMA konstan lebih baik daripada ','atau ","agak mudah ditolak. Tentu ada kasus di mana itu masuk akal, misalnya membuat final String QUOTE = "\"";menghemat banyak pada readibility tanpa semua garis miring, tetapi pembatasan karakter kontrol bahasa seperti \ 'dan "saya belum menemukan mereka sangat berguna.

Menggunakan final String COMMA = ","bukan hanya bentuk yang buruk, itu berbahaya! Ketika seseorang ingin mengubah pemisah dari ","ke ";"mereka mungkin pergi mengubah file konstanta ke COMMA = ";"karena lebih cepat bagi mereka untuk melakukannya dan itu hanya berfungsi. Kecuali, Anda tahu, semua hal lain yang menggunakan COMMA sekarang juga adalah titik koma, termasuk hal-hal yang dikirim ke konsumen eksternal. Jadi itu melewati semua tes Anda (karena semua kode marshalling dan unmarshalling juga menggunakan COMMA) tetapi tes eksternal akan gagal.

Apa yang berguna adalah memberi mereka nama yang berguna. Dan ya, terkadang konstanta berganda akan memiliki konten yang sama tetapi nama yang berbeda. Sebagai contoh final String LIST_SEPARATOR = ",".

Jadi pertanyaan Anda adalah "apakah konstanta char tunggal lebih baik daripada literal" dan jawabannya tidak, mereka tidak. Tetapi yang lebih baik dari keduanya adalah nama variabel dengan cakupan sempit yang secara eksplisit mengatakan apa tujuannya. Tentu, Anda akan menghabiskan beberapa byte tambahan pada referensi tambahan (dengan asumsi mereka tidak dikompilasi pada Anda, yang mungkin akan mereka lakukan) tetapi dalam pemeliharaan jangka panjang, di mana sebagian besar biaya aplikasi adalah, mereka sepadan dengan waktu untuk membuat.

corsiKa
sumber
Bagaimana dengan mendefinisikan DISP_APOSTROPHE secara kondisional sebagai ASCII 0x27 atau karakter kutipan kanan tunggal Unicode (yang merupakan penyampaian tanda kutip yang lebih sesuai tipografi), tergantung pada platform target?
supercat
3
sebenarnya QUOTEcontoh membuktikan itu adalah ide yang buruk juga karena Anda menugaskannya untuk apa yang secara umum / populer dikenal sebagai DOUBLE QUOTEdan QUOTEmenyiratkan SINGLE_QUOTEyang lebih tepat disebut sebagai APOSTROPHE.
3
@JarrodRoberson Saya tidak merasa penawaran menyiratkan kutipan tunggal, secara pribadi - tapi itu alasan bagus untuk menghapus ambiguitas di mana Anda bisa!
corsiKa
2
Saya tidak suka QUOTEcontoh untuk alasan tambahan - itu membuat bacaan string dibangun dengan itu lebih sulit "Hello, my name is " + QUOTE + "My Name" + QUOTEini adalah contoh sepele namun masih terlihat buruk. Oh, tentu saja, alih-alih gabungan Anda dapat menggunakan token pengganti, juga "Hello, my name is %sMy Name%s".format(QUOTE, QUOTE)mungkin lebih buruk. Tapi, hei, mari kita coba token yang diindeks "Hello, my name is {0}My Name{0}".format(QUOTE)ugh, tidak jauh lebih baik. Setiap string non-sepele yang dihasilkan dengan tanda kutip akan lebih buruk.
VLAZ
2
@corsiKa - Saya akan hidup dengan tanda kutip aktual yang lolos. Jika saya kehilangan satu, IDE yang saya gunakan akan segera mengeluh. Kode kemungkinan besar tidak akan dikompilasi. Cukup mudah dikenali. Betapa mudahnya membuat kesalahan ketika melakukan "My name is" + QUOTE + "My Name" + QUOTEsaya benar-benar membuat kesalahan yang sama tiga kali menulis komentar di atas. Bisakah Anda menemukannya? Jika butuh sedikit, itu adalah ruang yang hilang setelah ini . Apakah Anda memformat string? Dalam hal ini, string dengan beberapa token yang akan diganti akan menjadi lebih buruk untuk dikerjakan. Bagaimana saya menggunakannya agar lebih mudah dibaca?
VLAZ
3

Saya telah melakukan beberapa pekerjaan menulis lexers dan parser dan menggunakan konstanta integer untuk mewakili terminal. Terminal karakter tunggal kebetulan memiliki kode ASCII sebagai nilai numeriknya demi kesederhanaan, tetapi kode itu bisa saja merupakan sesuatu yang sepenuhnya berbeda. Jadi, saya memiliki T_COMMA yang diberi kode ASCII untuk ',' sebagai nilai konstannya. Namun, ada juga konstanta untuk nonterminals yang diberi bilangan bulat di atas ASCII set. Dari melihat generator parser seperti yacc atau bison, atau parser yang ditulis menggunakan alat-alat ini, saya mendapat kesan bahwa pada dasarnya semua orang melakukannya.

Jadi, sementara, seperti orang lain, saya pikir tidak ada gunanya mendefinisikan konstanta untuk tujuan eksplisit menggunakan konstanta alih-alih literal di seluruh kode Anda, saya pikir ada kasus tepi (parser, katakanlah) di mana Anda mungkin menemukan kode yang penuh dengan kode. konstanta seperti yang Anda gambarkan. Perhatikan bahwa dalam kasus parser, konstanta tidak hanya ada untuk mewakili karakter literal; mereka mewakili entitas yang mungkin saja terjadi menjadi literal karakter.

Saya dapat memikirkan beberapa kasus yang lebih terisolasi di mana mungkin masuk akal untuk menggunakan konstanta alih-alih literal yang sesuai. Misalnya, Anda mungkin mendefinisikan NEWLINE sebagai '' n 'literal pada kotak unix, tetapi' \ r \ n 'atau' \ n \ r 'jika Anda berada di windows atau kotak mac. Hal yang sama berlaku untuk parsing file yang mewakili data tabular; Anda dapat mendefinisikan konstanta FIELDSEPARATOR dan RECORDSEPARATOR. Dalam kasus ini, Anda sebenarnya mendefinisikan konstanta untuk mewakili karakter yang melayani fungsi tertentu. Namun, jika Anda adalah seorang programmer pemula, mungkin Anda akan menamai COMMA konstanta pemisah bidang Anda, tidak menyadari bahwa Anda seharusnya menyebutnya FIELDSEPARATOR, dan pada saat Anda menyadari, kode tersebut akan dalam produksi dan Anda akan berada di berikutnya proyek,

Akhirnya, latihan yang Anda gambarkan mungkin masuk akal dalam beberapa kasus di mana Anda menulis kode untuk menangani data yang dikodekan dalam pengkodean karakter tertentu, katakanlah iso-8859-1, tetapi berharap pengodean akan berubah nanti. Tentu saja dalam kasus seperti itu akan jauh lebih masuk akal untuk menggunakan pelokalan atau pengkodean dan decoding perpustakaan untuk menanganinya, tetapi jika karena alasan tertentu Anda tidak dapat menggunakan perpustakaan seperti itu untuk menangani masalah pengkodean untuk Anda, menggunakan konstanta Anda hanya akan harus mendefinisikan ulang dalam satu file alih-alih literal kode-keras yang berserakan di seluruh kode sumber Anda mungkin merupakan cara untuk melakukannya.

Mengenai artikel yang Anda tautkan: Saya tidak berpikir ia mencoba membuat kasus untuk mengganti literal karakter dengan konstanta. Saya pikir ini mencoba menggambarkan metode untuk menggunakan antarmuka untuk menarik konstanta ke bagian lain dari basis kode Anda. Contoh konstanta yang digunakan untuk menggambarkan hal ini dipilih dengan sangat buruk, tetapi saya tidak menganggapnya penting.

Pascal
sumber
2
Saya pikir ini mencoba menggambarkan metode untuk menggunakan antarmuka untuk menarik konstanta ke bagian lain dari basis kode Anda. yang merupakan anti-pola yang bahkan lebih buruk dan erat berpasangan dan kohesi rendah juga, tidak ada alasan yang sah untuk melakukan itu juga.
3

Selain semua jawaban yang bagus di sini, saya ingin menambahkan sebagai bahan pemikiran, bahwa pemrograman yang baik adalah tentang menyediakan abstraksi yang tepat yang dapat dibangun di atas oleh Anda sendiri dan mungkin orang lain, tanpa harus mengulangi kode yang sama berulang-ulang.

Abstraksi yang baik membuat kode mudah digunakan di satu sisi, dan mudah untuk mempertahankan di sisi lain.

Saya sepenuhnya setuju bahwa DELIMITER=':'dalam dan dari dirinya sendiri adalah abstraksi yang buruk, dan hanya lebih baik daripada COLON=':'(karena yang terakhir benar-benar miskin).

Abstraksi yang baik yang melibatkan string dan pemisah akan mencakup cara untuk mengemas satu atau lebih item konten individu ke dalam string dan untuk membongkar mereka dari string yang dikemas juga, pertama dan terutama, sebelum memberi tahu Anda apa pembatas itu. Abstraksi semacam itu akan digabungkan sebagai konsep, dalam sebagian besar bahasa sebagai kelas; misalnya, sehingga penggunaannya bisa secara praktis mendokumentasikan diri sendiri, di mana Anda dapat mencari semua tempat di mana kelas ini digunakan dan yakin akan apa maksud programmer mengenai format string yang dikemas dalam setiap kasus di mana beberapa abstraksi digunakan.

Setelah abstraksi seperti itu diberikan, akan mudah digunakan tanpa harus berkonsultasi apa nilai dari DELIMITERatau COLON, dan, mengubah rincian implementasi umumnya akan terbatas pada implementasi. Jadi, singkatnya, konstanta ini harus benar-benar menjadi detail implementasi yang tersembunyi dalam abstraksi yang sesuai.

Daya tarik utama menggunakan konstanta adalah mereka meminimalkan pemeliharaan ketika perubahan diperlukan.

Abstraksi yang baik, yang biasanya merupakan komposisi dari beberapa kemampuan terkait, lebih baik dalam meminimalkan pemeliharaan. Pertama, mereka dengan jelas memisahkan penyedia dari konsumen. Kedua, mereka menyembunyikan detail implementasi dan alih-alih menyediakan fungsionalitas langsung yang bermanfaat. Ketiga, mereka mendokumentasikan pada tingkat tinggi kapan dan di mana mereka digunakan.

Erik Eidt
sumber
2

Satu kali saya telah melihat konstanta seperti itu digunakan secara efektif adalah untuk mencocokkan API atau dokumen yang ada. Saya telah melihat simbol seperti yang COMMAdigunakan karena perangkat lunak tertentu terhubung langsung ke parser yang digunakan COMMAsebagai tag di pohon sintaksis abstrak. Saya juga pernah melihatnya cocok dengan spesifikasi formal. dalam spesifikasi formal, Anda kadang-kadang akan melihat simbol seperti COMMAbukan ','karena mereka ingin sejelas mungkin.

Dalam kedua kasus, penggunaan simbol bernama seperti COMMAmembantu memberikan kekompakan untuk produk yang terpisah. Nilai itu seringkali dapat melebihi biaya notasi yang terlalu bertele-tele.

Cort Ammon
sumber
2

Perhatikan bahwa Anda mencoba membuat daftar.

Jadi, refactor sebagai: String makeList(String[] items)

Dengan kata lain, faktor keluar logika bukan data .
Bahasa mungkin berbeda dalam cara mereka mewakili daftar, tetapi koma selalu koma (itu tautologi). Jadi jika bahasa berubah, mengubah karakter koma tidak akan membantu Anda - tetapi ini akan.

Mehrdad
sumber
0

Jika ini adalah kelas yang ditulis sebagai bagian dari aplikasi oleh rekan pengembang Anda, ini hampir pasti merupakan ide yang buruk. Seperti yang sudah ditunjukkan oleh orang lain, masuk akal untuk mendefinisikan konstanta seperti di SEPARATOR = ','mana Anda dapat mengubah nilai dan konstanta tetap masuk akal tetapi konstanta yang namanya hanya menggambarkan nilainya saja.

Namun, setidaknya ada dua kasus di mana masuk akal untuk mendeklarasikan konstanta yang namanya mendeskripsikan secara tepat isinya dan di mana Anda tidak dapat mengubah nilainya tanpa mengubah nama konstanta dengan tepat:

  • Konstanta matematika atau fisik, misalnya PI = 3.14159. Di sini, peran konstanta adalah bertindak sebagai mnemonik karena nama simbolik PIjauh lebih pendek dan lebih mudah dibaca daripada nilai yang diwakilinya.
  • Daftar lengkap simbol dalam parser atau tombol pada keyboard. Bahkan mungkin masuk akal untuk memiliki daftar konstanta dengan sebagian besar atau semua karakter Unicode dan ini adalah kasus Anda. Beberapa karakter seperti Ajelas dan mudah dikenali. Tetapi bisakah Anda dengan mudah membedakan Аdan Amembedakan? Yang pertama adalah Cyrillic surat А sedangkan yang kedua adalah Latin huruf A . Mereka adalah huruf yang berbeda, diwakili oleh titik kode Unicode yang berbeda, meskipun secara grafis mereka hampir identik. Saya lebih suka memiliki konstanta CYRILLIC_CAPITAL_AdanLATIN_CAPITAL_Adalam kode saya dari dua karakter yang tampak hampir identik. Tentu saja, ini tidak ada gunanya jika Anda tahu Anda hanya akan bekerja dengan karakter ASCII yang tidak mengandung Cyrillic. Demikian juga: Saya menggunakan alfabet Latin sehari-hari jadi jika saya menulis sebuah program yang membutuhkan karakter Cina, saya mungkin akan lebih suka menggunakan konstanta daripada memasukkan karakter yang saya tidak mengerti. Untuk seseorang yang menggunakan karakter Cina sehari-hari, karakter Cina mungkin jelas tetapi yang Latin mungkin lebih mudah untuk direpresentasikan sebagai konstanta bernama. Jadi, seperti yang Anda lihat, itu tergantung pada konteksnya. Namun, perpustakaan mungkin berisi konstanta simbolis untuk semua karakter karena penulis tidak dapat mengetahui sebelumnya bagaimana perpustakaan akan digunakan dan karakter mana yang mungkin membutuhkan konstanta untuk meningkatkan keterbacaan dalam aplikasi tertentu.

Namun, kasus-kasus seperti ini biasanya ditangani oleh kelas sistem atau pustaka tujuan khusus dan kemunculannya dalam kode yang ditulis oleh pengembang aplikasi harus sangat jarang kecuali Anda mengerjakan proyek yang sangat istimewa.

Michał Kosmulski
sumber
-1

Mungkin.

Konstanta karakter tunggal relatif sulit dibedakan. Jadi bisa agak mudah untuk melewatkan fakta bahwa Anda menambahkan titik daripada koma

city + '.' + state

padahal itu adalah kesalahan yang relatif sulit dilakukan

city + Const.PERIOD + state

Bergantung pada lingkungan internasionalisasi dan globalisasi Anda, perbedaan antara tanda kutip ASCII dan tanda kutip buka dan tutup Windows-1252 (atau tanda kutip ganda ASCII dan tanda kutip ganda terbuka dan tutup Windows-1252) mungkin signifikan dan sangat sulit untuk memvisualisasikan penampilan. di kode.

Sekarang, mungkin, jika keliru menempatkan titik daripada koma adalah masalah fungsional yang signifikan, Anda akan memiliki tes otomatis yang akan menemukan kesalahan ketik. Jika perangkat lunak Anda menghasilkan file CSV, saya akan berharap bahwa test suite Anda akan menemukan dengan sangat cepat bahwa Anda memiliki periode antara kota dan negara. Jika perangkat lunak Anda seharusnya dijalankan untuk klien dengan berbagai konfigurasi internasionalisasi, mungkin test suite Anda akan berjalan di setiap lingkungan dan akan diambil jika Anda memiliki kutipan terbuka Microsoft jika Anda bermaksud memiliki tanda kutip.

Saya bisa membayangkan sebuah proyek di mana lebih masuk akal untuk memilih kode verbose lebih banyak yang dapat mencegah masalah ini terutama ketika Anda punya kode lama yang tidak memiliki test suite yang komprehensif walaupun saya mungkin tidak akan kode seperti ini di proyek pengembangan bidang hijau. Dan menambahkan konstanta untuk setiap karakter tanda baca daripada hanya mereka yang berpotensi bermasalah dalam aplikasi khusus Anda mungkin berlebihan.

Gua Justin
sumber
2
apa yang terjadi ketika beberapa orang bodoh berubah Const.PERIODmenjadi sama ~? Tidak ada pembenaran untuk tautologi karakter bernama, itu hanya menambah pemeliharaan dan kompleksitas yang tidak dibutuhkan dalam lingkungan pemrograman modern. Apakah Anda akan menulis serangkaian unit test yang pada dasarnya mengatakan assert(Const.PERIOD == '.')?
3
@JarrodRoberson - Pasti payah. Tetapi Anda akan berada dalam banyak masalah jika seseorang menambahkan konstanta Unicode yang terlihat hampir persis seperti koma daripada koma yang sebenarnya. Seperti yang saya katakan, ini bukan hal yang akan saya lakukan dalam proyek pengembangan greenfield. Tetapi jika Anda memiliki basis kode lawas dengan rangkaian tes jerawatan di mana Anda telah melakukan kesalahan koma / periode atau apostrof / apostrophes kekejian Microsoft beberapa kali, membuat beberapa konstanta dan memberi tahu orang untuk menggunakannya mungkin merupakan cara yang masuk akal untuk membuat kode lebih baik tanpa menghabiskan satu tahun tes menulis.
Justin Cave
3
contoh warisan Anda adalah yang buruk, saya baru saja selesai refactoring basis kode 1.000.000 LOC yang berusia 18 tahun. Itu setiap karakter yang dapat dicetak didefinisikan seperti ini berkali-kali dengan nama yang bertentangan bahkan berbeda. Dan sering kali hal-hal yang disebutkan COMMAbenar-benar diatur = SPACE + "," + SPACE. Ya, beberapa idiot memiliki SPACEkonstanta. Saya refactored mereka SEMUA keluar dan kode adalah perintah magitude lebih mudah dibaca dan karyawan perguruan tinggi jauh lebih mampu melacak hal-hal dan memperbaikinya tanpa memiliki 6 tingkat tipuan untuk mencari tahu apa sesuatu yang sebenarnya diatur untuk diatur.
-1

Apakah konstanta satu karakter lebih baik daripada literal?

Ada banyak conflations mengambang di sini. Biarkan saya melihat apakah saya bisa menggoda mereka.

Konstanta menyediakan:

  • semantik
  • berubah, selama pengembangan
  • tipuan

Turun ke nama karakter tunggal hanya berdampak pada semantik. Sebuah nama harus bermanfaat sebagai komentar dan jelas dalam konteksnya. Seharusnya mengekspresikan makna, bukan nilai. Jika dapat melakukan semua itu dengan satu karakter saja. Jika tidak bisa, tolong jangan.

Sebuah literal dan konstanta dapat berubah selama pengembangan. Inilah yang memunculkan masalah angka ajaib. String dapat berupa angka ajaib juga.

Jika makna semantik ada, dan karena keduanya konstan, maka apakah konstanta memiliki nilai lebih dari literal turun ke tipuan.

Tipuan dapat memecahkan masalah, selain tipuan banyak.

Tipuan dapat memecahkan masalah angka ajaib karena memungkinkan Anda untuk memutuskan nilai untuk ide di satu tempat. Semantik, untuk menjadi bermanfaat nama harus membuat apa ide itu jelas. Nama harus tentang ide, bukan nilainya.

Tipuan bisa berlebihan. Beberapa lebih suka mencari dan mengganti literal untuk membuat perubahan mereka. Tidak apa-apa asalkan 42 jelas arti kehidupan dan tidak bercampur dengan 42, nomor atom molibdenum.

Di mana Anda dapat membuat perbedaan yang bermanfaat seperti itu dengan satu huruf sangat tergantung pada konteks. Tapi saya tidak akan menjadikannya kebiasaan.

candied_orange
sumber
1
Semantik adalah kuncinya. Jika dan "A" memiliki lebih banyak semantik daripada sekadar menjadi "A" maka ada baiknya mengikat semantik yang sama dengan "referensi" yang sama. Tidak masalah apakah itu konstan atau tidak. Saya sangat setuju.
oopexpert
-1

Sebagai kontrapunctus filosofis terhadap pendapat mayoritas, saya harus menyatakan bahwa ada beberapa dari kita, yang menghargai programmer petani Prancis abad ke-19 yang tidak canggih dan

teringat akan kejernihannya yang monoton dan abadi, pandangannya yang sangat masuk akal tentang segala sesuatu, kepuasan luar biasa dengan truisme hanya karena itu benar. "Bingung semuanya!" teriak Turnbull pada dirinya sendiri, "jika dia di rumah sakit jiwa, tidak mungkin ada orang di luar."

GK Chesterton, The Ball and The Cross

Tidak ada yang salah menghargai kebenaran dan tidak ada yang salah dengan menyatakan kebenaran, terutama ketika berbicara dengan komputer.

Jika Anda berbohong ke komputer, itu akan membuat Anda

Perry Farrar - Germantown, Maryland (dari More Programming Pearls)


Tetapi, sebagian besar saya setuju dengan orang-orang yang mengatakan itu bodoh. Saya terlalu muda untuk belajar memprogram FORTRAN, tetapi saya pernah mendengar bahwa Anda dapat mendefinisikan ulang 'A' = 'Q'dan menghasilkan semua jenis cryptogram yang luar biasa. Anda tidak melakukan ini.

Di luar masalah i18n yang diangkat sebelumnya (yang tidak mendefinisikan kembali mesin terbang "COMMA", tetapi benar-benar mendefinisikan ulang mesin terbang dari DECIMAL_POINT). Membangun kutipan wortel Prancis atau kutipan tunggal Inggris untuk menyampaikan makna kepada manusia ada pada sesuatu dan mereka benar-benar harus variabel, bukan konstanta. Konstanta akan menjadi AMERICAN_COMMA := ','dancomma := AMERICAN_COMMA

Dan, jika saya menggunakan pola builder untuk membangun SQL Query, saya lebih suka melihatnya

sb.append("insert into ")
 .append(table_name)
 .append(" values ")
 .append(" ( ")
 .append(val_1)
 .append(",")
 .append(val_2)
 .append(" ); ")

daripada hal lain, tetapi jika Anda akan menambahkan konstanta, itu akan menjadi

INSERT_VALUES_START = " ( "
INSERT_VALUES_END = " ) "
INSERT_VALUES_SEPARATOR = " , "
QUERY_TERMINATOR = ";"

sb.append("insert into ")
 .append(table_name)
 .append(" values ")
 .append(INSERT_VALUES_START)
 .append(val_1)
 .append(INSERT_VALUES_SEPARATOR)
 .append(val_2)
 .append(INSERT_VALUES_END)
 .append(QUERY_TERMINATOR)

Namun, jika Anda pernah menonton acara orang lain (atau mengetik), Anda mungkin melihat beberapa kebiasaan yang menarik. Tidak semua dari kita adalah pengetik bintang. Banyak dari kita yang terlambat pemrograman atau dibesarkan dengan keyboard Soviet (di mana tombol ketik pada Anda) dan kami suka memotong dan menempelkan masing-masing huruf alih-alih mencoba menemukannya di keyboard dan / atau mengandalkan autocomplete.

Tidak ada yang akan melengkapi string secara otomatis untuk Anda, jadi jika saya bisa mendapatkan koma dengan menekan 'con', alt-space, turun, turun, turun, masukkan dan dapatkan penawaran dengan menekan 'con', alt-space, bawah, bawah, masuk. Saya mungkin akan melakukannya.


Satu hal yang perlu diingat tentang string literal adalah cara mereka dikompilasi. Setidaknya dalam Delphi, (yang merupakan satu-satunya bahasa yang saya terobsesi dengan tumpukan) Anda akan memutar literal Anda muncul di tumpukan setiap fungsi. Jadi, banyak literal = banyak fungsi overhead; "," dalam function_A tidak sedikit memori yang sama dengan "," dalam function_B ". Untuk mengatasi ini, ada" sumber daya string "yang dapat dibangun dan dihubungkan secara menyamping - dan ini adalah cara mereka melakukan hal-hal i18n (membunuh dua burung dengan satu semak) .Dalam Python semua string string Anda adalah objek, dan mungkin sebenarnya tampak bagus untuk digunakan utils.constants.COMMA.join(["some","happy","array","strings"]), tetapi itu bukan ide bintang untuk poin yang berulang di halaman ini.

Peter Turner
sumber
-4

Tetapi kapan kita akan mulai menggunakan simbol yang berbeda dari ',' untuk mewakili koma?

Untuk lokalisasi.

Di negara-negara berbahasa Inggris, simbol yang memisahkan keseluruhan dan bagian pecahan dari desimal adalah ".", Yang kami sebut "titik desimal". Di banyak negara lain, simbolnya adalah "," dan biasanya disebut setara dengan "koma" dalam bahasa lokal. Demikian pula, di mana negara-negara berbahasa Inggris menggunakan "," untuk memisahkan kelompok-kelompok dari tiga digit dalam jumlah besar (seperti 1.000.000 untuk satu juta), negara-negara yang menggunakan koma sebagai titik desimal menggunakan titik (1.000.000).

Jadi ada kasus untuk membuat konstanta DECIMAL_POINT dan COMMA jika Anda melakukan globalisasi.

Paul G
sumber
2
Tapi kemudian COMMA dan DECIMAL_POINT bukan nama yang tepat untuk entitas (yang mungkin mengapa Anda telah downvoted).
Kyle Strand
Anda perlu mengompilasi versi lokal yang spesifik. Konstanta literal tidak cocok untuk itu; use case akan memanggil file definisi dan mencari mereka (yang mungkin melibatkan konstanta, tetapi konstanta pencarian, bukan karakter konstan).