Có phải là một thực hành tốt để có một giá trị đặc biệt


11

Tôi đang phát triển một dịch vụ mới trong môi trường dịch vụ vi mô. Đây là một dịch vụ REST. Để đơn giản, hãy nói rằng đường dẫn là: / historyBooks

Và phương thức POST cho đường dẫn này tạo ra một cuốn sách lịch sử mới.

Chúng ta hãy giả sử rằng một cuốn sách lịch sử bao gồm một hoặc nhiều thời đại trong lịch sử.

Để cho ngắn gọn, hãy giả sử rằng chúng ta chỉ có các thời đại sau của lịch sử loài người:

  • Cổ xưa
  • Bài cổ điển
  • Hiện đại

Trong mã của tôi, tôi muốn đại diện cho họ trong một enum.

Phần thân của phương thức (tải trọng) có định dạng JSON và phải bao gồm tên trường eras. Trường này là một danh sách các eragiá trị, mà cuốn sách này bao gồm.

Cơ thể có thể trông như:

{
  "name": "From the cave to Einstein - a brief history review",
  "author": "Foo Bar",
  "eras": ["Ancient", "Post Classical", "Modern"]
}

Trong dịch vụ cụ thể này, logic nghiệp vụ là:
Nếu không có thời đại nào được cung cấp trong đầu vào, thì cuốn sách này được coi là bao gồm tất cả các thời đại.

Trong đánh giá API, một đề xuất đã được đưa ra:
Bao gồm một giá trị khác ALL, cho eras enum, để chỉ rõ rằng tất cả các thời đại đều được bảo hiểm.

Tôi nghĩ rằng nó có một số ưu và nhược điểm.

Ưu điểm:

Đầu vào rõ ràng

Nhược điểm:

Nếu hai mục trong danh sách được cung cấp, hãy nói ALLAncient- những gì sẽ được lấy từ ứng dụng? Tôi đoán rằng ALLsẽ ghi đè lên các giá trị khác, nhưng đó là logic kinh doanh mới.

Nếu tôi chạy một truy vấn, đối với những cuốn sách bao gồm (các) thời đại cụ thể, làm thế nào tôi có thể đại diện cho một cuốn sách bao gồm tất cả các thời đại? Nếu ALLcũng được sử dụng cho đầu ra (sử dụng cùng logic), thì đó là trách nhiệm của người tiêu dùng để hiểu ALL["Ancient", "Post Classical", "Modern"].

Câu hỏi của tôi

Tôi nghĩ rằng có những ALLnguyên nhân mới gây ra nhiều nhầm lẫn hơn là không có nó.

Bạn nghĩ sao? Bạn sẽ thêm ALLgiá trị này hoặc giữ API của bạn mà không có nó?


7
Điều gì xảy ra nếu bạn quyết định muốn thêm thời đại nguyên tử? Những cuốn sách bao gồm "tất cả" eras kỳ diệu có được nội dung mới không? Bạn có bắt đầu nói dối về nội dung của những cuốn sách? Bạn có đi qua và cập nhật mọi thứ? Điều đó có thể là không cần thiết nếu một số cuốn sách thực sự đã có nội dung về kỷ nguyên nguyên tử.
8bittree

Câu trả lời:


13

Phụ thuộc vào việc thời đại có sẵn của bạn có sẵn cho ứng dụng gọi điện hay không. Có lẽ họ là người dùng có thể chọn những gì họ quan tâm. Nếu đó là vấn đề thì đó là vấn đề mặt trước để cung cấp tùy chọn "TẤT CẢ". Nếu là tôi, nó sẽ gửi danh sách tất cả các thời đại chứ không phải là tùy chọn "tất cả". Nếu không, thì bạn cần một tùy chọn "TẤT CẢ" và gặp rủi ro thì giao diện người dùng sẽ lấy lại mọi thứ từ thời đại mà nó không hiểu.

Như bạn chỉ ra, TẤT CẢ với các tùy chọn khác có nghĩa là bạn có thể nhận được các yêu cầu xung đột. Một điều cần cân nhắc nữa là bạn có thể vượt qua "TẤT CẢ" sau đó bất kỳ enum nào khác trở thành loại trừ thay vì bao gồm, ví dụ "TẤT CẢ", "Cổ đại" có nghĩa là "Mọi thứ trừ Người cổ đại". Điều đó có ý nghĩa gì đó nhưng rõ ràng UI sau đó phải phản ánh rằng điều đó có thể quá phức tạp.

TL; DR; Chủ yếu là "TẤT CẢ" là một giao diện người dùng tốt và bạn có thể đạt được điều tương tự ở cấp độ dịch vụ mà không có sự mơ hồ, vì vậy đừng làm điều đó.


6

Nếu không có thời đại nào được cung cấp trong đầu vào, thì cuốn sách này được coi là bao gồm tất cả các thời đại.

Điều này và cũng có trường hợp 'TẤT CẢ' đặc biệt, là IMHO xấu - API của bạn phải rõ ràng nếu có thể. Có các trường hợp đặc biệt như 'không có gì thực sự có nghĩa là tất cả mọi thứ' có nghĩa là bất kỳ ai sử dụng API của bạn cũng phải biết tất cả các trường hợp đặc biệt của bạn, hoặc, với trường hợp 'TẤT CẢ', dẫn đến các yêu cầu trong đó ý định và / hoặc kết quả không rõ ràng.

Các trường hợp đặc biệt cũng thường dẫn đến mã phức tạp hơn cả về mặt xác thực xem liệu đầu vào của người dùng có hợp lệ hay không và cũng xử lý yêu cầu chính xác.


1

Đối với các biến phân loại, tôi sẽ tránh đặt ký tự đại diện "tất cả" ở cùng cấp.

Có vẻ như bạn có một tiêu chí tìm kiếm hai cấp trong khoảng thời gian:

  1. boolean, is_selective?
  2. thiết lập, phân biệt các loại cụ thể

Người gọi có thể chỉ định (sai, bỏ qua) hoặc (đúng, {'cổ', 'hiện đại'}).

Hoặc bạn có thể chọn giải thích tập hợp trống là ký tự đại diện, nó biểu thị Không chọn lọc.

Đối với trường hợp cụ thể của bạn, có vẻ như bạn có một biến liên tục, năm, được phân tách thành một vài giá trị nổi tiếng và điều bạn thực sự muốn là thực hiện số học khoảng. Vì vậy, các truy vấn của bạn sẽ chấp nhận một phạm vi (bắt đầu, kết thúc) năm và enums có thể cung cấp các thuộc tính đó một cách thuận tiện.


1

tl; dr
Đối với câu hỏi thực tế của bạn - liên quan đến cấu trúc dữ liệu cục bộ khi triển khai - Tôi đồng ý với kết luận của bạn: Tránh mọi giá trị đặc biệt của eras bởi vì nó chủ yếu làm tăng thêm sự phức tạp và cơ hội để phạm sai lầm. Tuy nhiên, đặc biệt là giao diện người dùng cuối và có thể dữ liệu tải trọng được tuần tự hóa có thể là những câu chuyện khác nhau.

Cấu trúc dữ liệu cục bộ

Chúng ta hãy xem xét điều này từ một quan điểm hệ thống loại. Về cơ bản, enum là một loại xác định một tập hợp các loại cụ thể (liệt kê) khác nhau, như đã được chỉ ra trong câu trả lời của @JH . Một biến của kiểu enum giữ chính xác một trong những loại đó. Nếu bạn muốn đại diện cho một tập hợp các giá trị liệt kê, bạn cần một loại thứ hai:

// C++-inspired pseudo-code
enum Era { ancient, post_classical, modern };
using Eras = Collection<Era>;

Một allđiều tra viên là không nên bởi vì nó trộn lẫn hai loại đó với nhau. Đây không phải là một danh mục đơn lẻ, mà là một tập hợp tất cả các danh mục có thể.

Ở mức độ thực tế nghiêm ngặt đối phó với bất kỳ loại giá trị đặc biệt nào làm phức tạp việc triển khai - và do đó làm tăng khả năng xảy ra lỗi - bởi vì bạn phải xử lý trường hợp đặc biệt ở mọi nơi hoặc giải nén nó để phù hợp với ý nghĩa thực tế của nó. Ồ, và những gì về một bộ sưu tập rõ ràng của tất cả các điều tra viên có thể. Khi nào và ở đâu nên được thu gọn đến allgiá trị đặc biệt ? Có nên sụp đổ tất cả?

Kiến trúc ưa thích của tôi là không có bất kỳ đại diện nào của tất cả các thời đại trong mã. Điều đó bao gồm allđiều tra viên, nhưng cũng có một bộ sưu tập trống rỗng có nghĩa là tất cả các thời đại . Đó chính xác là cùng một trường hợp đặc biệt, chỉ trong một cách ngụy trang khác.

Nếu hai mục trong danh sách được cung cấp, hãy nói TẤT CẢ và Cổ đại - những gì sẽ được lấy từ ứng dụng? [...]

Tôi chỉ định trong thông số API rằng tất cả các dấu eras phải luôn tự xuất hiện vì có một cái gì đó ở trên nó không có ý nghĩa gì. Sau đó, tôi sẽ từ chối điều này như là một vi phạm hợp đồng. Nhưng đó là một ví dụ hay về cách tất cả các thời đại làm phức tạp cả việc thực hiện và logic kinh doanh.

Vấn đề chính là bạn buộc phải chỉ định các quy tắc để chuyển đổi giữa giá trị đặc biệt và ý nghĩa cơ bản của nó. Và sau đó, bạn và mọi người khác sử dụng API phải thực hiện các quy tắc đó một cách chính xác. Sự hoài nghi trong tôi nói với tôi rằng đó không phải là câu hỏi liệu ai đó sẽ hiểu sai, mà đơn giản là khi nào .

Dữ liệu nối tiếp (JSON)

Ban đầu tôi có cả một phần ở đây về việc sửa đổi so với các truy vấn chỉ đọc và các vai trò khác nhau cho "eras"danh sách. Nhưng cuối cùng tôi đã xóa nó vì HÔN. Các quy tắc cho enum / bộ sưu tập không phải là không hợp lý đối với dữ liệu JSON, vì vậy giữ cho mọi thứ nhất quán là giải pháp đơn giản nhất.

Giao diện người dùng cho người dùng cuối

Tôi giả sử sẽ có một chuyển đổi dữ liệu giữa UI và các cấu trúc dữ liệu cơ bản, rất có thể là do bạn có một loại kiến ​​trúc MVC-ish. Vì vậy, sử dụng bất cứ điều gì thuận tiện và trực quan nhất cho người dùng. Trong câu trả lời của mình, @Markus đã đưa ra một ví dụ tuyệt vời với các tùy chọn lựa chọn khác nhau cho các ngày trong tuần.


1

Tôi nghĩ rằng việc có TẤT CẢ mới gây ra nhiều nhầm lẫn hơn là không có nó.

Đúng.

Nếu bạn nghĩ từ góc độ bộ sưu tập: bạn có cả một bộ sưu tập một cái gì đó. Và mỗi khi bạn chỉ muốn một tập hợp con của bộ sưu tập đó, bạn phải cung cấp một số loại bộ lọc , khi một phần tử được coi là một phần tử của tập hợp con này. Và ALLlà trường hợp, khi không có bộ lọc nào được áp dụng, không phải "bộ lọc là ALL" .

Nếu không có thời đại nào được cung cấp trong đầu vào, thì cuốn sách này được coi là bao gồm tất cả các thời đại.

Tôi sẽ lật ngược nó lại: Cuốn sách này không bao gồm thời đại cụ thể .

Điều này cũng phù hợp từ góc độ truy vấn:

Nếu không có thời đại nào được chọn, tất cả các cuốn sách được trả lại (bao gồm cả thời đại này với trường thời đại trống); và khi một thời đại được chọn, chỉ những cuốn sách có thời đại được chọn mới được trả về - việc lấy tất cả các cuốn sách từ thời đại đặc biệt cộng với những cuốn sách chung sẽ gây bất ngờ.

Điểm duy nhất, nơi tôi sẽ thêm ALLdanh mục - là để thuận tiện cho người dùng, bởi vì có thể khó chịu hơn khi chọn "Không có gì" thay vì "Mọi thứ".


0

Gần đây tôi đã triển khai một trình lập lịch cơ bản và vì @LoztInSpace đã đề cập hầu hết trong số đó là UI đường.

Giao diện người dùng cần phải hoàn toàn rõ ràng về những gì người dùng sẽ đạt được khi chọn một trong các tùy chọn.

Trong trường hợp của tôi, tôi có các ngày trong tuần để lựa chọn. Ngoài "Tất cả" tôi đã thêm "Ngày làm việc" và "Cuối tuần" làm tùy chọn. Chọn từng tùy chọn sẽ đưa nó vào sử dụng sau và bạn sẽ phải bỏ chọn thủ công bất kỳ ngày nào bạn không muốn đưa vào.

Về mặt kỹ thuật, điều này có nghĩa là nếu người dùng chọn "Các ngày trong tuần" thì UI sẽ có năm hộp kiểm được đánh dấu và enum sẽ sử dụng giá trị "Ngày làm việc". Nếu một trong các hộp kiểm chưa được sử dụng, giá trị "Ngày làm việc" sẽ được thay thế bằng bản đồ bit hoặc ed của bốn ngày còn lại.

Không sử dụng một phần của các tùy chọn để bao gồm tất cả mọi thứ và đồng thời để loại trừ một cái gì đó để tránh xung đột và đảm bảo giao diện người dùng có ý nghĩa với người dùng.

Tôi nghĩ một định hướng tốt là sử dụng và tùy chọn "Tất cả" có ý nghĩa nếu người dùng có thể dễ dàng nắm bắt khái niệm "Tất cả" bao gồm (tất cả các ngày trong một tuần) hoặc nếu không quan trọng (tìm kiếm tất cả các danh mục trên amazon)


0

Tôi thích ý tưởng mang một TẤT CẢ enum, nhưng tôi muốn đặt chúng làm cờ

const enum = {
    ALL: { value: 0 },
    ANCIENT: { name: 'Ancient', value: 1 },
    POST_CLASSICAL: { name: 'Post Classical', value: 2 },
    MODERN: { name: 'Modern', value: 4 }
}

Sử dụng một thư viện như flagon hoặc chơi thủ công với các thao tác bitwise khi tất cả các giá trị được chọn, thay vào đó bạn sử dụng TẤT CẢ.

Hãy nhớ rằng giá trị của enum phải luôn là gấp đôi so với người tiền nhiệm của họ. Và để kiểm tra sự tỉnh táo, bạn không bao giờ nên xóa enum, mặc dù bạn có thể vô hiệu hóa nó, điều chỉnh mã của bạn để luôn tính những người khuyết tật là một phần của TẤT CẢ.

Mặc dù tôi sẽ có một cờ KHÔNG thay thế và để khách hàng quyết định phải làm gì khi NONE được sử dụng, trong trường hợp doanh nghiệp thay đổi sau đó.

Nếu việc triển khai này được thực hiện, thay vì chuyển các enun xung quanh, bạn sẽ chuyển tổng các giá trị được chọn thay thế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.