Sebagai pengembang perangkat lunak yang berpengalaman, saya telah belajar untuk menghindari string sihir.
Masalah saya adalah sudah lama sekali saya tidak menggunakannya, saya lupa sebagian besar alasannya. Akibatnya, saya kesulitan menjelaskan mengapa itu masalah bagi kolega saya yang kurang berpengalaman.
Apa alasan objektif yang ada untuk menghindarinya? Masalah apa yang mereka sebabkan?
anti-patterns
Kramii
sumber
sumber
Jawaban:
Dalam bahasa yang mengkompilasi, nilai string sihir tidak dicentang pada waktu kompilasi . Jika string harus cocok dengan pola tertentu, Anda harus menjalankan program untuk menjamin itu cocok dengan pola itu. Jika Anda menggunakan sesuatu seperti enum, nilainya paling tidak valid pada waktu kompilasi, bahkan jika itu mungkin nilai yang salah.
Jika string ajaib sedang ditulis di banyak tempat Anda harus mengubah semuanya tanpa pengaman (seperti kesalahan waktu kompilasi). Ini dapat diatasi dengan hanya mendeklarasikannya di satu tempat dan menggunakan kembali variabelnya.
Kesalahan ketik dapat menjadi bug serius. Jika Anda memiliki fungsi:
dan seseorang secara tidak sengaja mengetik:
Ini lebih buruk jika stringnya lebih jarang atau lebih kompleks, terutama jika Anda memiliki programmer yang tidak terbiasa dengan bahasa asli proyek.
Senar ajaib jarang mendokumentasikan diri. Jika Anda melihat satu string, itu tidak memberi tahu Anda apa lagi yang bisa / seharusnya menjadi string tersebut. Anda mungkin harus melihat ke implementasi untuk memastikan Anda telah memilih string yang tepat.
Implementasi semacam itu bocor , membutuhkan dokumentasi eksternal atau akses ke kode untuk memahami apa yang harus ditulis, terutama karena itu harus sempurna karakter (seperti pada poin 3).
Pendek fungsi "temukan string" dalam IDE, ada sejumlah kecil alat yang mendukung pola.
Anda mungkin secara kebetulan menggunakan string sihir yang sama di dua tempat, padahal sebenarnya itu adalah hal yang berbeda, jadi jika Anda melakukan Find & Replace, dan mengubah keduanya, salah satunya dapat rusak sementara yang lain bekerja.
sumber
Puncak dari apa yang dijawab oleh jawaban-jawaban lain, bukanlah bahwa "nilai-nilai sihir" itu buruk, tetapi seharusnya:
Apa yang biasanya membedakan "konstanta" yang dapat diterima dari "nilai magis" adalah beberapa pelanggaran terhadap satu atau lebih aturan ini.
Digunakan dengan baik, konstanta hanya memungkinkan kita untuk mengekspresikan aksioma tertentu dari kode kita.
Yang membawa saya ke poin terakhir, bahwa penggunaan konstanta yang berlebihan (dan karena itu sejumlah asumsi atau kendala yang dinyatakan dalam nilai), bahkan jika itu sesuai dengan kriteria di atas (tetapi terutama jika menyimpang dari mereka), dapat menyiratkan bahwa solusi yang dirancang tidak cukup umum atau terstruktur dengan baik (dan karena itu kita tidak benar-benar berbicara tentang pro dan kontra dari konstanta lagi, tetapi tentang pro dan kontra dari kode terstruktur dengan baik).
Bahasa tingkat tinggi memiliki konstruk untuk pola dalam bahasa tingkat rendah yang harus menggunakan konstanta. Pola yang sama juga dapat digunakan dalam bahasa tingkat yang lebih tinggi, tetapi seharusnya tidak demikian.
Tapi itu mungkin penilaian ahli berdasarkan kesan dari semua keadaan dan seperti apa solusi seharusnya, dan bagaimana tepatnya penilaian itu akan sangat bergantung pada konteksnya. Memang itu mungkin tidak dapat dibenarkan dalam hal prinsip umum apa pun, kecuali untuk menyatakan "Saya sudah cukup umur untuk melihat pekerjaan seperti ini, yang dengannya saya kenal, dilakukan dengan lebih baik"!
EDIT: setelah menerima satu suntingan, menolak yang lainnya, dan sekarang telah melakukan edit saya sendiri, mungkin sekarang saya menganggap gaya pemformatan dan tanda baca dari daftar aturan saya harus diselesaikan sekali dan untuk semua haha!
sumber
value / 2
, daripadavalue / VALUE_DIVISOR
dengan yang terakhir didefinisikan sebagai di2
tempat lain. Jika Anda bermaksud menggeneralisasi metode yang menangani CSV, Anda mungkin ingin pemisah diteruskan sebagai parameter, dan tidak didefinisikan sebagai konstanta sama sekali. Tapi itu semua masalah penilaian dalam konteks - contoh @ WGroleauSPEED_OF_LIGHT
adalah sesuatu yang Anda ingin sebutkan secara eksplisit, tetapi tidak setiap literal membutuhkan ini.sumber
Contoh kehidupan nyata: Saya bekerja dengan sistem pihak ketiga di mana "entitas" disimpan dengan "bidang". Pada dasarnya sistem EAV . Karena cukup mudah untuk menambahkan bidang lain, Anda mendapatkan akses ke bidang itu dengan menggunakan nama bidang sebagai string:
(perhatikan string ajaib "ProductName")
Ini dapat menyebabkan beberapa masalah:
Jadi solusi saya untuk ini adalah menghasilkan konstanta untuk nama-nama ini, yang disusun berdasarkan tipe entitas. Jadi sekarang saya bisa menggunakan:
Ini masih berupa konstanta string dan mengkompilasi ke biner yang sama persis, tetapi memiliki beberapa keunggulan:
Berikutnya dalam daftar saya: sembunyikan konstanta ini di belakang kelas yang diketik dengan sangat kuat - kemudian juga tipe data diamankan.
sumber
nameField = myEntity.ProductName;
.Senar ajaib tidak selalu buruk , jadi ini mungkin alasan mengapa Anda tidak dapat menemukan alasan selimut untuk menghindarinya. (Dengan "string ajaib" Saya menganggap maksud Anda string literal sebagai bagian dari ekspresi, dan tidak didefinisikan sebagai konstanta.)
Dalam beberapa kasus tertentu, senar ajaib harus dihindari:
Tetapi dalam beberapa kasus, "senar ajaib" baik-baik saja. Katakanlah Anda memiliki parser sederhana:
Sebenarnya tidak ada keajaiban di sini, dan tidak ada masalah yang dijelaskan di atas berlaku. Tidak akan ada manfaat IMHO untuk mendefinisikan
string Plus="+"
dll. Sederhanakan.sumber
if (dx != 0) { grad = dy/dx; }
."+"
dan"-"
denganTOKEN_PLUS
danTOKEN_MINUS
. Setiap kali saya membacanya, saya merasa lebih sulit untuk membaca dan men-debug karena itu! Pasti tempat di mana saya setuju bahwa menggunakan string sederhana lebih baik.Untuk menambah jawaban yang ada:
Internasionalisasi (i18n)
Jika teks yang akan ditampilkan di layar adalah kode-keras dan dikubur dalam lapisan fungsi, Anda akan mengalami kesulitan menyediakan terjemahan teks itu ke bahasa lain.
Beberapa lingkungan pengembangan (misalnya Qt) menangani terjemahan dengan mencari dari string teks bahasa dasar ke bahasa yang diterjemahkan. String sihir umumnya dapat bertahan seperti ini - sampai Anda memutuskan ingin menggunakan teks yang sama di tempat lain dan mendapatkan salah ketik. Bahkan kemudian, sangat sulit untuk menemukan string ajaib mana yang perlu diterjemahkan ketika Anda ingin menambahkan dukungan untuk bahasa lain.
Beberapa lingkungan pengembangan (mis. MS Visual Studio) mengambil pendekatan lain dan mengharuskan semua string terjemahan disimpan dalam basis data sumber daya dan membaca kembali untuk lokal saat ini dengan ID unik dari string itu. Dalam hal ini aplikasi Anda dengan string ajaib tidak dapat diterjemahkan ke bahasa lain tanpa pengerjaan ulang besar. Pengembangan yang efisien mengharuskan semua string teks dimasukkan ke dalam basis data sumber daya dan diberikan ID unik ketika kode pertama kali ditulis, dan setelah itu relatif mudah. Mencoba untuk mengisi ulang ini setelah fakta biasanya akan membutuhkan upaya yang sangat besar (dan ya, saya pernah ke sana!) Jadi jauh lebih baik untuk melakukan hal-hal yang benar sejak awal.
sumber
Ini bukan prioritas untuk semua orang, tetapi jika Anda ingin dapat menghitung metrik kopling / kohesi pada kode Anda secara otomatis, string sihir membuat ini hampir mustahil. Sebuah string di satu tempat akan merujuk ke kelas, metode atau fungsi di tempat lain, dan tidak ada cara otomatis yang mudah untuk menentukan bahwa string tersebut digabungkan ke kelas / metode / fungsi hanya dengan menguraikan kode. Hanya kerangka kerja yang mendasarinya (Angular, misalnya) yang dapat menentukan bahwa ada keterkaitan - dan hanya dapat melakukannya pada saat run-time. Untuk mendapatkan informasi penggandengan sendiri, parser Anda harus mengetahui segala sesuatu tentang kerangka kerja yang Anda gunakan, di atas dan di luar bahasa dasar tempat Anda membuat kode.
Tapi sekali lagi, ini bukan sesuatu yang banyak pengembang pedulikan.
sumber