Saya kira ini adalah pertanyaan lain tentang hard coding dan praktik terbaik. Katakanlah saya memiliki daftar nilai, katakanlah buah, disimpan dalam basis data (harus ada dalam basis data karena tabel digunakan untuk keperluan lain seperti laporan SSR), dengan ID:
1 Apple
2 Banana
3 Grapes
Saya dapat menyajikannya kepada pengguna, ia memilih satu, itu akan disimpan di profilnya sebagai FavouriteFruit dan ID disimpan dalam catatannya di database.
Ketika datang ke aturan bisnis / logika domain, apa saja rekomendasi untuk menetapkan logika ke nilai tertentu. Katakanlah jika pengguna telah memilih Grapes Saya ingin melakukan beberapa tugas tambahan, apa cara terbaik untuk referensi nilai Grapes:
// Hard coded name
if (user.FavouriteFruit.Name == "Grapes")
// Hard coded ID
if (user.FavoriteFruit.ID == 3) // Grapes
// Duplicate the list of fruits in an enum
if (user.FavouriteFruit.ID == (int)Fruits.Grapes)
atau sesuatu yang lain?
Karena tentu saja FavouriteFruit akan digunakan di seluruh aplikasi, daftar dapat ditambahkan ke, atau diedit.
Seseorang mungkin memutuskan bahwa mereka ingin 'Grape' diganti namanya menjadi 'Grape' dan ini tentu saja akan mematahkan opsi string hardcoded.
Hardcoded ID tidak sepenuhnya jelas, seperti yang ditunjukkan, Anda bisa menambahkan komentar untuk mengidentifikasi item mana yang cepat.
Opsi enum melibatkan duplikasi data dari database yang tampaknya salah karena mungkin tidak sinkron.
Bagaimanapun, terima kasih sebelumnya atas segala komentar atau saran.
MyApplication.Grape.ID
berbicara gagap. "Apple" bukan "Red_Apple" lebih dari ID 3 juga 4. Jadi potensi untuk mengubah nama "Apple" menjadi "Red_Apple" tidak masuk akal daripada menyatakan bahwa 3 adalah 4 (dan mungkin bahkan 3). Tujuan dari enum adalah untuk memisahkan DNA numeriknya. Jadi mungkin sudah saatnya untuk benar - benar memisahkan kunci DB relasional sewenang-wenang yang secara harfiah tidak memiliki makna dalam model bisnis seseorang.Jawaban:
Hindari string dan konstanta sihir di semua biaya. Mereka benar-benar keluar dari pertanyaan, mereka bahkan tidak boleh dianggap sebagai pilihan. Ini tampaknya membuat Anda hanya memiliki satu opsi yang aktif: pengidentifikasi, yaitu enum. Namun, ada juga satu opsi lagi, yang menurut saya adalah yang terbaik. Mari kita sebut opsi ini "Objek Dimuat". Dengan Objek yang Dimuat, Anda dapat melakukan hal berikut:
Apa yang baru saja terjadi di sini adalah bahwa saya sudah jelas memuat seluruh baris
Grape
ke dalam memori, jadi saya memiliki ID-nya yang siap digunakan dalam perbandingan. Jika Anda menggunakan Pemetaan Objek-Relasional (ORM), itu terlihat lebih baik:(Itu sebabnya saya menyebutnya "Objek Preloaded".)
Jadi, yang saya lakukan adalah selama startup saya memuat semua tabel "enumerasi" (tabel kecil seperti hari dalam seminggu, bulan dalam setahun, jenis kelamin, dll.) Ke dalam kelas domain aplikasi utama. Saya memuatnya dengan nama, karena jelas,
MyApplication.Grape
harus menerima baris yang disebut "Anggur", dan saya menyatakan bahwa masing-masing dari mereka ditemukan. Jika tidak, kami memiliki galat run-time yang dijamin selama startup, yang merupakan kesalahan paling ganas dari semua galat run-time.sumber
Grape = fetchRow( Fruit.class, NameColumn, "Grape" );
Dan jika Anda lakukan sesuatu dengan tidak benar, suratAssertionError
wasiat akan memberi tahu Anda.enum
string ajaib. Intinya adalah konsentrasi semua ikatan-dengan-nama hanya di satu tempat , validasi semuanya selama startup , dan ketik keamanan .Memeriksa string adalah yang paling mudah dibaca, tetapi itu tugas ganda: itu digunakan baik sebagai pengidentifikasi dan deskripsi (yang dapat berubah karena alasan yang tidak terkait).
Saya biasanya membagi kedua tugas menjadi bidang yang terpisah:
Di mana deskripsi dapat berubah (tetapi bukan "Anggur" menjadi "Pisang"), tetapi kode tidak diizinkan untuk berubah, selamanya.
Meskipun ini sebagian besar karena id kita hampir selalu dihasilkan secara otomatis, dan karenanya tidak cocok. Jika Anda dapat memilih id secara bebas, mungkin Anda dapat menjamin bahwa mereka selalu benar dan menggunakannya.
Juga, seberapa sering seseorang benar-benar mengedit "Anggur" menjadi "Anggur"? Mungkin semua ini tidak diperlukan.
sumber
Apa yang Anda harapkan di sini adalah logika pemrograman agar secara otomatis dapat beradaptasi dengan perubahan data. Opsi statis sederhana seperti Enum tidak berfungsi di sini karena Anda tidak dapat secara layak menambahkan enum tambahan dalam runtime.
Beberapa pola yang saya lihat:
Secara umum saya suka data yang lengkap dalam hal merujuk pada tindakan yang menyiratkan - meskipun tindakan itu sendiri dapat diimplementasikan di tempat lain. Kode apa pun yang menentukan tindakan yang tidak bergantung pada data baru saja membelokkan representasi data Anda yang kemungkinan besar akan menyimpang dan mengarah ke bug.
sumber
Menyimpannya di kedua tempat (di meja dan di ENUM) tidak terlalu buruk. Alasannya adalah sebagai berikut:
Dengan menyimpannya dalam tabel basis data, kita dapat menegakkan integritas referensial dalam basis data melalui kunci asing. Jadi, ketika Anda mengasosiasikan seseorang atau entitas apa pun untuk buah, itu hanya buah yang ada di tabel database.
Menyimpannya sebagai ENUM juga masuk akal karena kita dapat menulis kode tanpa string ajaib dan membuat kode lebih mudah dibaca. Ya, mereka harus tetap menyinkronkan, tetapi betapa sulitnya menambahkan baris ke ENUM dan pernyataan penyisipan baru ke database.
Satu hal, setelah ENUM didefinisikan, jangan ubah nilainya. Misalnya, jika Anda memiliki:
JANGAN mengganti nama Grape menjadi Grapes. Cukup tambahkan ENUM baru.
Jika Anda perlu melakukan migrasi data, maka terapkan pembaruan untuk memindahkan semua Anggur ke Anggur.
sumber
Anda benar untuk menanyakan pertanyaan ini, ini adalah pertanyaan yang bagus ketika Anda berusaha untuk bertahan terhadap evaluasi kondisi yang tidak akurat.
Yang mengatakan, evaluasi (
if
kondisi Anda ) tidak perlu menjadi fokus bagaimana Anda mengatasinya. Alih-alih, perhatikan cara Anda menyebarkan perubahan yang akan menyebabkan masalah 'tidak sinkron'.Pendekatan String
Jika Anda harus menggunakan string, mengapa tidak memaparkan fungsionalitas mengubah daftar melalui UI? Rancang sistem sehingga saat diubah
Grape
menjadiGrapes
, misalnya, Anda memperbarui semua catatan yang saat ini dirujukGrape
.Pendekatan ID
Saya selalu lebih suka referensi ID, meskipun ada kompromi dari beberapa keterbacaan.
The list may be added to
lagi dapat menjadi sesuatu yang Anda akan diberitahu jika Anda mengekspos fitur UI seperti itu. Jika Anda khawatir dengan pemesanan ulang item yang mengubah id, sebarkan lagi perubahan tersebut ke semua catatan dependen lagi. Demikian pula untuk di atas. Pilihan lain (mengikuti konvensi normalisasi yang tepat, adalah memiliki kolom enum / id Anda - dan merujukFruitDetail
tabel yang lebih terperinci , yang memiliki kolom 'Pesanan' yang dapat Anda cari).Apa pun itu, Anda dapat melihat saya menyarankan untuk mengontrol amandemen atau memperbarui daftar Anda. Apakah Anda melakukan ini melalui penggunaan ORM atau akses data lainnya ditentukan oleh spesifikasi teknologi Anda. Apa yang Anda, pada dasarnya, lakukan adalah mengharuskan orang yang jauh dari DB untuk perubahan seperti itu - yang menurut saya baik-baik saja. Sebagian besar CRM utama akan membuat persyaratan yang sama.
sumber
Masalah yang sangat umum. Sementara menduplikasi sisi klien data mungkin tampaknya melanggar prinsip KERING , itu sebenarnya karena perbedaan paradigma antara lapisan.
Memiliki enum (atau apa pun) keluar dari langkah dengan database sebenarnya tidak biasa juga. Anda mungkin telah mendorong nilai lain ke tabel metadata untuk mendukung fitur laporan baru yang belum digunakan dalam kode sisi klien.
Kadang-kadang terjadi sebaliknya juga. Nilai enum baru akan ditambahkan ke sisi klien tetapi pembaruan DB tidak dapat terjadi sampai DBA dapat menerapkan perubahan.
sumber
Dengan asumsi bahwa kita sedang berbicara tentang apa yang pada dasarnya adalah pencarian statis maka opsi ketiga - enum - pada dasarnya adalah satu-satunya pilihan yang waras. Ini yang akan Anda lakukan jika database tidak terlibat sehingga masuk akal.
Pertanyaannya kemudian menjadi satu tentang bagaimana menjaga enums dan tabel statis / lookup di database dalam sinkronisasi dan sayangnya itu bukan masalah saya belum memiliki jawaban yang lengkap.
Secara pilihan saya melakukan semua pemeliharaan skema saya dalam kode dan oleh karena itu saya dapat menjaga hubungan antara membangun aplikasi dan versi skema yang diharapkan sehingga mudah untuk menjaga pencarian dan enum dalam sinkronisasi tetapi itu adalah sesuatu yang harus diingat untuk melakukan. Akan lebih baik jika lebih otomatis (dan juga tes integrasi otomatis untuk memastikan bahwa enum dan pencarian cocok akan membantu) tetapi itu bukan sesuatu yang pernah saya terapkan.
sumber