Misalkan saya memiliki 4 jenis layanan yang saya tawarkan (mereka tidak mungkin sering berubah):
- Pengujian
- Desain
- Pemrograman
- Lain
Misalkan saya memiliki 60-80 layanan aktual yang masing-masing termasuk dalam salah satu kategori di atas. Misalnya, 'layanan' dapat berupa "Program Uji menggunakan teknik A" dan merupakan jenis "Pengujian".
Saya ingin menyandikannya ke dalam basis data. Saya datang dengan beberapa opsi:
Opsi 0:
Gunakan VARCHAR
langsung untuk menyandikan tipe layanan secara langsung sebagai string
Pilihan 1:
Gunakan basis data enum
. Tapi enum itu jahat
Pilihan 2:
gunakan dua tabel:
service_line_item (id, service_type_id INT, description VARCHAR);
service_type (id, service_type VARCHAR);
Saya bahkan dapat menikmati integritas referensial:
ALTER service_line_item
ADD FOREIGN KEY (service_type_id) REFERENCES service_type (id);
Kedengarannya bagus, ya?
Tapi saya masih harus mengkodekan hal-hal dan berurusan dengan bilangan bulat, yaitu saat mengisi tabel. Atau saya harus membuat pemrograman rumit atau konstruksi DB saat mengisi atau berurusan dengan tabel. Yaitu, BERGABUNG ketika berurusan dengan database secara langsung, atau membuat entitas berorientasi objek baru di sisi pemrograman, dan memastikan saya mengoperasikannya dengan benar.
Opsi 3:
Jangan gunakan enum
, jangan gunakan dua tabel, tetapi cukup gunakan kolom integer
service_line_item (
id,
service_type INT, -- use 0, 1, 2, 3 (for service types)
description VARCHAR
);
Ini seperti 'enum palsu' yang membutuhkan lebih banyak overhead pada sisi kode hal-hal, seperti mengetahui itu {2 == 'Programming'}
dan menghadapinya dengan tepat.
Pertanyaan:
Saat ini saya telah menerapkannya menggunakan Opsi 2 , dipandu dengan konsep
- jangan gunakan enum (opsi 1)
- hindari menggunakan database sebagai spreadsheet (opsi 0)
Tetapi saya tidak dapat menahan perasaan yang tampaknya sia-sia bagi saya dalam hal pemrograman dan overhead kognitif - saya harus menyadari dua tabel, dan berurusan dengan dua tabel, vs satu.
Untuk 'cara yang kurang boros', saya melihat Option 3
. TI lebih ringan dan pada dasarnya memerlukan konstruksi kode yang sama untuk beroperasi (dengan sedikit modifikasi tetapi kompleksitas dan struktur pada dasarnya sama tetapi dengan satu tabel)
Saya kira idealnya tidak selalu sia-sia, dan ada kasus yang baik untuk kedua opsi, tetapi apakah ada pedoman yang baik tentang kapan seseorang harus menggunakan Opsi 2 dan kapan Opsi 3?
Ketika hanya ada dua jenis (biner)
Untuk menambahkan sedikit lebih banyak ke pertanyaan ini ... di tempat yang sama, saya memiliki opsi biner dari Layanan "Standar" atau "Pengecualian", yang dapat diterapkan pada item baris layanan. Saya telah menyandikannya menggunakan Opsi 3 .
Saya memilih untuk tidak membuat tabel baru hanya untuk menyimpan nilai {"Standard", "Exception"}. Jadi kolom saya hanya menampung {0, 1} dan nama kolom saya dipanggil exception
, dan kode saya sedang melakukan terjemahan dari {0, 1} => {STANDARD, EXCEPTION}
(yang saya encode sebagai konstanta dalam bahasa pemrograman)
Sejauh ini tidak menyukai cara itu juga ..... (tidak menyukai opsi 2 atau opsi 3). Saya memang menemukan opsi 2 lebih unggul dari 3, tetapi dengan lebih banyak overhead, dan masih saya tidak dapat melarikan diri pengkodean hal-hal sebagai bilangan bulat tidak peduli opsi mana yang saya gunakan dari 2, dan 3.
ORM
Untuk menambahkan beberapa konteks, setelah membaca jawaban - Saya baru saja mulai menggunakan ORM lagi (baru-baru ini), dalam kasus saya Doctrine 2. Setelah mendefinisikan skema DB melalui Annotations, saya ingin mengisi basis data. Karena seluruh kumpulan data saya relatif kecil, saya ingin mencoba menggunakan konstruksi pemrograman untuk melihat cara kerjanya.
Saya pertama kali mengisi service_type
s, dan kemudian service_line_item
s, karena ada daftar yang ada dari spreadsheet yang sebenarnya. Jadi hal-hal seperti 'standar / pengecualian' dan 'Pengujian' semuanya adalah string pada spreadsheet, dan mereka harus dikodekan ke dalam tipe yang tepat sebelum menyimpannya dalam DB.
Saya menemukan jawaban SO ini: Apa yang Anda gunakan daripada ENUM di doctrine2? , yang menyarankan untuk tidak menggunakan enum construct DB, tetapi untuk menggunakan INT
bidang dan untuk mengkodekan tipe menggunakan konstruk 'const' dari bahasa pemrograman.
Tetapi seperti yang ditunjukkan dalam pertanyaan SO di atas, saya dapat menghindari menggunakan bilangan bulat secara langsung dan menggunakan konstruksi bahasa - konstanta - setelah mereka didefinisikan ....
Tapi tetap saja .... tidak peduli bagaimana Anda mengubahnya, jika saya mulai dengan string
sebagai tipe, saya harus terlebih dahulu mengubahnya menjadi tipe yang tepat, bahkan ketika menggunakan ORM.
Jadi jika katakan $str = 'Testing';
, saya masih perlu memiliki blok di suatu tempat yang melakukan sesuatu seperti:
switch($str):
{
case 'Testing': $type = MyEntity::TESTING; break;
case 'Other': $type = MyEntity::OTHER; break;
}
Hal yang baik adalah Anda tidak berurusan dengan bilangan bulat / angka ajaib [sebagai gantinya, berurusan dengan jumlah konstan yang disandikan], tetapi hal buruknya adalah Anda tidak dapat secara otomatis menarik masuk dan keluar dari database tanpa langkah konversi ini, menurut saya pengetahuan.
Dan itulah yang saya maksud, sebagian, dengan mengatakan hal-hal seperti "masih harus menyandikan hal-hal dan berurusan dengan bilangan bulat". (Memang, sekarang, setelah komentar Ocramius, saya tidak perlu berurusan langsung dengan bilangan bulat, tetapi berurusan dengan konstanta bernama dan beberapa konversi ke / dari konstanta, sesuai kebutuhan).