Giả sử tôi có 4 loại dịch vụ tôi cung cấp (chúng không có khả năng thay đổi thường xuyên):
- Kiểm tra
- Thiết kế
- Lập trình
- Khác
Giả sử tôi có 60-80 dịch vụ thực tế, mỗi dịch vụ thuộc một trong các loại trên. Ví dụ: 'một dịch vụ' có thể là "Chương trình thử nghiệm sử dụng kỹ thuật A" và nó thuộc loại "Thử nghiệm".
Tôi muốn mã hóa chúng vào cơ sở dữ liệu. Tôi đã đưa ra một vài lựa chọn:
Tùy chọn 0:
Sử dụng VARCHAR
trực tiếp để mã hóa loại dịch vụ trực tiếp dưới dạng chuỗi
Lựa chọn 1:
Sử dụng cơ sở dữ liệu enum
. Nhưng, enum là ác
Lựa chọn 2:
sử dụng hai bảng:
service_line_item (id, service_type_id INT, description VARCHAR);
service_type (id, service_type VARCHAR);
Tôi thậm chí có thể tận hưởng tính toàn vẹn tham chiếu:
ALTER service_line_item
ADD FOREIGN KEY (service_type_id) REFERENCES service_type (id);
Nghe có vẻ hay đấy chứ?
Nhưng tôi vẫn phải mã hóa mọi thứ và xử lý các số nguyên, tức là khi điền vào bảng. Hoặc tôi phải tạo lập trình phức tạp hoặc các cấu trúc DB khi điền hoặc xử lý bảng. Cụ thể, THAM GIA khi trực tiếp xử lý cơ sở dữ liệu hoặc tạo các thực thể hướng đối tượng mới ở phía lập trình và đảm bảo tôi vận hành chúng chính xác.
Tùy chọn 3:
Không sử dụng enum
, không sử dụng hai bảng, mà chỉ sử dụng một cột số nguyên
service_line_item (
id,
service_type INT, -- use 0, 1, 2, 3 (for service types)
description VARCHAR
);
Điều này giống như một 'enum giả' đòi hỏi nhiều chi phí hơn về mặt mã của mọi thứ, như nghĩa là biết điều đó {2 == 'Programming'}
và xử lý nó một cách thích hợp.
Câu hỏi:
Hiện tại tôi đã triển khai nó bằng cách sử dụng Tùy chọn 2 , được hướng dẫn theo các khái niệm
- không sử dụng enum (tùy chọn 1)
- tránh sử dụng cơ sở dữ liệu dưới dạng bảng tính (tùy chọn 0)
Nhưng tôi không thể cảm thấy điều đó có vẻ lãng phí đối với tôi về mặt lập trình và chi phí nhận thức - tôi phải nhận thức được hai bảng và đối phó với hai bảng, so với một bảng.
Đối với một "cách ít lãng phí", tôi đang xem xét Option 3
. CNTT nhẹ hơn và về cơ bản đòi hỏi các cấu trúc mã giống nhau để hoạt động (với các sửa đổi nhỏ nhưng độ phức tạp và cấu trúc về cơ bản là giống nhau nhưng với một bảng duy nhất)
Tôi cho rằng lý tưởng không phải lúc nào cũng lãng phí, và có những trường hợp tốt cho một trong hai lựa chọn, nhưng liệu có một hướng dẫn tốt về việc khi nào nên sử dụng Tùy chọn 2 và khi Tùy chọn 3 không?
Khi chỉ có hai loại (nhị phân)
Để thêm một chút cho câu hỏi này ... trong cùng một địa điểm, tôi có tùy chọn nhị phân của Dịch vụ "Tiêu chuẩn" hoặc "Ngoại lệ", có thể áp dụng cho chi tiết đơn hàng dịch vụ. Tôi đã mã hóa bằng cách sử dụng Tùy chọn 3 .
Tôi đã chọn không tạo bảng mới chỉ để giữ các giá trị {"Tiêu chuẩn", "Ngoại lệ"}. Vì vậy, cột của tôi chỉ giữ {0, 1} và tên cột của tôi được gọi exception
và mã của tôi đang thực hiện một bản dịch từ {0, 1} => {STANDARD, EXCEPTION}
(mà tôi đã mã hóa thành hằng số trong ngôn ngữ lập trình)
Cho đến nay cũng không thích cách đó ..... (không thích tùy chọn 2 cũng không phải tùy chọn 3). Tôi tìm thấy tùy chọn 2 vượt trội hơn 3, nhưng với nhiều chi phí hơn, và tôi vẫn không thể thoát khỏi những thứ được mã hóa dưới dạng số nguyên cho dù tôi sử dụng tùy chọn nào trong số 2 và 3.
ORM
Để thêm một số ngữ cảnh, sau khi đọc câu trả lời - Tôi mới bắt đầu sử dụng lại ORM (gần đây), trong trường hợp của tôi Tài liệu 2. Sau khi xác định lược đồ DB thông qua Chú thích, tôi muốn điền vào cơ sở dữ liệu. Vì toàn bộ tập dữ liệu của tôi tương đối nhỏ, tôi muốn thử sử dụng các cấu trúc lập trình để xem nó hoạt động như thế nào.
Lần đầu tiên tôi điền service_type
s, và sau đó service_line_item
là s, vì đã có một danh sách từ bảng tính thực tế. Vì vậy, những thứ như 'tiêu chuẩn / ngoại lệ' và 'Kiểm tra' đều là các chuỗi trên bảng tính và chúng phải được mã hóa thành các loại thích hợp trước khi lưu trữ chúng trong DB.
Tôi tìm thấy câu trả lời SO này: Bạn sử dụng gì thay vì ENUM trong doctrine2? , đã đề xuất không sử dụng cấu trúc enum của DB, mà sử dụng một INT
trường và mã hóa các kiểu sử dụng cấu trúc 'const' của ngôn ngữ lập trình.
Nhưng như đã chỉ ra trong câu hỏi SO ở trên, tôi có thể tránh sử dụng trực tiếp các số nguyên và sử dụng các cấu trúc ngôn ngữ - hằng số - một khi chúng được định nghĩa ....
Nhưng vẫn .... cho dù bạn xoay nó như thế nào, nếu tôi bắt đầu với string
tư cách là một loại, trước tiên tôi phải chuyển đổi nó thành một loại thích hợp, ngay cả khi sử dụng ORM.
Vì vậy, nếu nói $str = 'Testing';
, tôi vẫn cần phải có một khối ở đâu đó thực hiện một cái gì đó như:
switch($str):
{
case 'Testing': $type = MyEntity::TESTING; break;
case 'Other': $type = MyEntity::OTHER; break;
}
Điều tốt là bạn không xử lý số nguyên / số ma thuật [thay vào đó, xử lý số lượng không đổi được mã hóa], nhưng điều tệ là bạn không thể tự động kéo mọi thứ vào và ra khỏi cơ sở dữ liệu mà không cần bước chuyển đổi này hiểu biết.
Và đó là điều tôi muốn nói, một phần, bằng cách nói những điều như "vẫn phải mã hóa mọi thứ và xử lý số nguyên". (Được cấp, bây giờ, sau nhận xét của Ocramius, tôi sẽ không phải giao dịch trực tiếp với số nguyên, nhưng xử lý các hằng số được đặt tên và một số chuyển đổi sang / từ các hằng số, nếu cần).