Phải làm gì khi bạn không thể xác định giá trị boolean?


38

Chúng tôi đang xây dựng một ứng dụng web cho công ty, quản trị chỉ tồn tại trong các trang tính Excel. Bây giờ chúng ta gần như đã hoàn thành, nhưng gần đây tôi được giao một nhiệm vụ nhập tất cả dữ liệu của họ từ các trang tính đó vào hệ thống mới của chúng tôi. Hệ thống được xây dựng bằng Java, nhưng vì quá trình nhập này chỉ là một lần nên tôi quyết định viết các tập lệnh bằng Python và nhập trực tiếp bằng các truy vấn SQL. Đây là vấn đề. Các mô hình dữ liệu mới chứa một số thuộc tính mới, không bao gồm trong dữ liệu hiện có của chúng. Trong hầu hết các trường hợp, đây không phải là vấn đề, tôi chỉ đặt một nơi không thể tìm thấy thông tin. Nhưng sau đó tôi đã chạy vào một vài thuộc tính, đó là booleans và không thể là NULL theo mặc định. Đầu tiên tôi đã cố gắng chỉ cho phép null cho các trường đó trong cơ sở dữ liệu của chúng tôi, nhưng nhà phát triển cấp cao của tôi bảo tôi không làm điều đó, vì nó sẽ gây ra một vấn đề trong hệ thống của chúng tôi trong tương lai. Và bây giờ tôi không chắc phải làm gì. Giải pháp rõ ràng là mặc định mọi giá trị boolean chưa biết thành false, nhưng tôi nghĩ điều đó cũng sai, vì tôi thực sự không biết, liệu nó có sai hay không.

Ví dụ: Giả sử bạn có một chiếc xe thực thể có tham số hasRadio. Bây giờ bạn cần nhập dữ liệu vào mô hình dữ liệu này, nhưng trong dữ liệu chỉ có các cột "Kiểu" và "Màu", không có gì về việc nó có hoặc không có radio. Bạn đặt gì vào cột "hasRadio", nếu thiết kế không thể rỗng?

Cách tiếp cận tốt nhất trong tình huống này là gì? Chúng ta có nên nói với công ty tự điền dữ liệu còn thiếu không? Hoặc mặc định nó thành false?


70
Đối với tôi, cho phép NULL sẽ là giải pháp chính xác. Là tiền bối của bạn cụ thể hơn "gây ra một vấn đề trong hệ thống của chúng tôi trong tương lai"? Nếu không, hãy hỏi anh ấy cho lý do cụ thể hơn.
larsbe

48
Bạn nên mặc định nó FileNotFound, rõ ràng.
Bạn

7
Có thể thêm một trường boolean, "isValidHasRadio" hoặc một cái gì đó, hoặc điều đó sẽ phá vỡ mọi thứ?
hyde

9
Giải pháp chính xác là xem xét rác dữ liệu đầu vào và hủy bỏ toàn bộ giao dịch, sau đó yêu cầu điều chỉnh định nghĩa nhiệm vụ nếu dữ liệu đó không được coi là rác. Không có cách nào khác ở đây.
Sange Borsch

17
Nhân tiện, tôi không phải là fan hâm mộ lớn của các giá trị null. Tôi thà sử dụng một enum với 'Unknown', 'Có Radio' và 'Không có Radio'. Bằng cách này, bạn đáp ứng các yêu cầu của bạn và có chỗ để phát triển nếu bạn phải chỉ định một loại radio trong tương lai, như 'Radio với TV tích hợp' hoặc đại loại như thế.
Machado

Câu trả lời:


129

Đây chủ yếu là một vấn đề phân tích yêu cầu và nó không liên quan gì đến thực tế dữ liệu bị đe dọa là "boolean". Nếu bạn phải khởi tạo các bảng trong cơ sở dữ liệu hoặc trong bất kỳ loại lưu trữ dữ liệu nào khác và bạn có đầu vào không đầy đủ cho một số cột, trước tiên bạn cần tìm hiểu xem người dùng của hệ thống hoặc khách hàng của bạn nghĩ gì sẽ là giá trị mặc định phù hợp đối với các cột đó và bạn cần tìm ra điều này cho mọi thuộc tính , không có câu trả lời nào đúng cả.

Điều này thường sẽ dẫn đến một trong những trường hợp sau:

  • Có một giá trị mặc định tốt cho cột cụ thể, người dùng không phiền nếu giá trị ban đầu giống nhau cho tất cả các bản ghi, họ có thể dễ dàng đặt các giá trị chính xác sau khi cần

  • có một quy tắc làm thế nào để xác định giá trị mặc định lý tưởng từ các thông tin khác, vì vậy bạn có thể đặt quy tắc này vào mã

  • người dùng hoặc khách hàng của bạn sẽ mở rộng dữ liệu đầu vào và cung cấp các giá trị còn thiếu (có thể theo cách thủ công), trước khi được nhập vào cơ sở dữ liệu

  • không có giá trị mặc định tốt cho cột cụ thể và / hoặc bất kỳ bản ghi nào, dữ liệu nên được nhập, nhưng người dùng muốn biết bản ghi nào có giá trị cụ thể đã được khởi tạo và không có bản ghi nào. Vì vậy, họ có thể nhập giá trị sau đó và theo dõi bản ghi nào giá trị đã được đặt chính xác và giá trị nào không.

Trường hợp cuối cùng yêu cầu một cái gì đó như NULL để thể hiện trạng thái chưa được khởi tạo hoặc chưa biết, ngay cả đối với giá trị boolean, nếu cấp cao của bạn thích hay không. Nếu có một số lý do kỹ thuật tối nghĩa cấm sử dụng giá trị NULL cho một cột cụ thể, bạn cần mô phỏng trạng thái "không xác định" theo một cách khác, bằng cách giới thiệu một cột boolean bổ sung (như hasRadioIsUnknown) hoặc bằng cách sử dụng 3 liệt kê -valued thay vì một boolean (như HasNoRadio=0, HasRadio=1, Unknown=2). Nhưng nói chuyện với cấp trên của bạn một lần nữa, sau khi bạn thực hiện một phân tích yêu cầu kỹ lưỡng, để đảm bảo một cách giải quyết như vậy là thực sự cần thiết.


29
Bạn cũng nên lưu ý rằng câu trả lời tương tự áp dụng cho các cột khác nơi bạn sử dụng NULL một cách thuận tiện. Bạn nên xác minh xem đây có phải là giá trị mặc định chính xác hay không. Ví dụ: nếu một số cột khác nói "processIsFinished" và bạn nhập dữ liệu cũ từ lịch sử đặt hàng của khách hàng (nghĩ về một cửa hàng web), bạn có thể cần đặt giá trị thành "true" thay vì "NULL" để tránh một số quy trình được kích hoạt khi họ gặp các mục chưa được xử lý (theo cách giải thích của họ về cột đó).
Frank Hopkins

1
Đây là một vấn đề chức năng. Do các mô hình (vượt trội và mô hình mới) không khớp, quá trình di chuyển nên được xem xét có tính đến các trường hợp này. Điều duy nhất có thể nói cách tiến hành là / là các bên liên quan (khách hàng hoặc bất cứ ai). Về mặt kỹ thuật bạn có thể giải quyết điều này theo nhiều cách, nhưng về mặt chức năng chỉ trong một. Bên phải.
Laiv

12
Tôi thích sự cố này. Sự chán ghét của tôi đối với null trong bối cảnh này chủ yếu là do nó thiếu ý nghĩa rõ ràng. Không biết là rõ ràng. Nhưng null có nghĩa là không biết hoặc không áp dụng? Làm thế nào có ai biết? Chỉ vì nó có ý nghĩa với bạn không có nghĩa là mọi người khác sẽ nhìn thấy nó theo cùng một cách.
candied_orange

Tùy chọn 4: Các bản ghi thiếu một giá trị cột cụ thể thực sự vô dụng và cần được loại trừ khỏi quá trình nhập. Tùy chọn 5: Ai đó cần sửa tất cả dữ liệu đến trước khi nhập. Rất nhiều lựa chọn, chỉ phụ thuộc vào nhu cầu và ngân sách. Nhập dữ liệu cũ luôn là một mớ hỗn độn rất lớn.
jpmc26

@ jpmc26: tốt, tôi không bao gồm tùy chọn 4 vì tôi muốn dán những gì OP đã viết theo nghĩa đen (một trường hợp dữ liệu bị thiếu chắc chắn không được bao gồm trong dữ liệu nhập, không có bản ghi). Tùy chọn 5 thực sự đáng được đề cập, vì đó là một cách khác để tránh sự cần thiết cho các giá trị NULL. Chỉnh sửa câu trả lời của tôi cho phù hợp.
Doc Brown

39

Đây không phải là một câu hỏi kỹ thuật; đó là một câu hỏi về quy tắc kinh doanh. Vì vậy, bạn cần phải hỏi "doanh nghiệp."

Tiếp cận chủ sở hữu sản phẩm và / hoặc các bên liên quan và nói điều gì đó như:

Chúng tôi có dữ liệu không đầy đủ cho một trong các lĩnh vực bạn yêu cầu trong ứng dụng. Bạn có muốn chúng tôi sử dụng một giá trị mặc định? Bạn có muốn chúng tôi thêm "không xác định" làm giá trị hợp lệ không? Hoặc, bạn có muốn ai đó trong nhóm của mình sửa dữ liệu trước khi nhập không?

Một số cuộc thảo luận có thể sẽ xảy ra sau đó. Nhưng, về cơ bản là vậy. Các giải pháp kỹ thuật sẽ chảy tự nhiên từ các quy tắc kinh doanh xác thực hơn.


9

Vấn đề chung là toàn bộ một chương trình được gọi là làm sạch dữ liệu , là một phần của một tiểu vùng lớn hơn được gọi là tích hợp dữ liệu . Tránh các loại vấn đề này có thể là một phần lớn lý do cho việc di chuyển từ các trang tính Excel và tại sao nhà phát triển cấp cao không muốn cho phép một trường trở nên vô hiệu. Tôi không nghĩ rằng thật vô lý khi nói rằng đây là một trong những nguồn phức tạp lớn hơn trong việc di chuyển dữ liệu.

Chỉ cần chọn sử dụng NULL bất cứ khi nào bạn có thể rất có thể làm sai , hãy để một mình thay đổi mô hình dữ liệu để làm cho nhiều trường trở nên vô hiệu hơn. Excel có kiểm tra tính toàn vẹn yếu hoặc không có khả năng là nguyên nhân của nhiều vấn đề này. Điều sai lầm cần làm là loại bỏ kiểm tra tính toàn vẹn trong cơ sở dữ liệu mới và đổ rác vào đó. Điều này chỉ khắc phục được vấn đề và tăng thêm độ phức tạp đáng kể cho các tích hợp trong tương lai mà phải bằng cách nào đó xử lý dữ liệu vô nghĩa.

Một số khác biệt có thể là do mô hình dữ liệu không khớp. Đối phó với điều này phần lớn là vấn đề (thân mật) quen thuộc với cả hai mô hình dữ liệu và biết cách ánh xạ mô hình cũ sang mô hình mới. Chừng nào những cái mới khả năng chụp cũ. (Nếu không, nhóm của bạn có thể có một vấn đề rất lớn.) Điều này có thể dễ dàng yêu cầu thực hiện nhiều công việc hơn là chỉ sao chép các cột. Darkwing đưa ra một ví dụ tuyệt vời về điều này (cũng như lý do tại sao chèn NULL một cách mù quáng là điều sai trái). Xây dựng dựa trên nó, nếu mô hình cũ có một ReceivedDatevà một InProgresschút và mô hình mới có một StartDateProcessingEndTime, bạn sẽ cần phải quyết định xem và làm thế nào để thiết lập ProcessingEndTime. Tùy thuộc vào cách sử dụng, một lựa chọn hợp lý (nhưng tùy ý) có thể là đặt nó giống nhưStartDate (hoặc ngay sau đó nếu điều đó sẽ gây ra vấn đề).

Tuy nhiên, một số khác biệt có thể là do dữ liệu "nên" ở đó bị thiếu hoặc bị hỏng. (Rất có thể là do lỗi nhập dữ liệu hoặc xử lý kém trong quá trình di chuyển hoặc lỗi trong hệ thống xử lý dữ liệu.) Nếu không có ai trong nhóm của bạn lường trước điều này, thì bạn (gọi chung) đã tự đặt ra 20% thời gian của dự án " sắp xong. (Đó là một số trang điểm, nhưng nó có thể xatệ hơn thế, hoặc tốt hơn. Nó phụ thuộc vào lượng dữ liệu không chính xác, mức độ quan trọng của nó, mức độ phức tạp, mức độ dễ dàng có được sự tham gia của những người chịu trách nhiệm về dữ liệu và các yếu tố khác.) Một khi bạn đã xác định rằng dữ liệu "được cho là "có nhưng mất tích. Thông thường, bạn sẽ cố gắng xác định mức độ của vấn đề bằng cách truy vấn các nguồn dữ liệu cũ. Nếu đó là hàng chục hoặc hàng trăm mục nhập, thì có lẽ đó là lỗi nhập dữ liệu và khách hàng chịu trách nhiệm về dữ liệu sẽ tự giải quyết nó (nghĩa là cho bạn biết các giá trị sẽ là gì.) Nếu đó là hàng triệu mục (hoặc một phần đáng kể của dữ liệu) , sau đó bạn có thể cần xem xét lại xem bạn có xác định chính xác rằng nó "nên" ở đó không. Điều này có thể chỉ ra lỗi mô hình hóa trong hệ thống mới.

Ví dụ: hãy tưởng tượng một hóa đơn có số lượng và tổng số mặt hàng (nhưng không phải đơn giá), ngoại trừ một số lượng bị thiếu không thể giải thích được. Nói chuyện với người xử lý các hóa đơn đó có thể tạo ra một (hoặc nhiều) các tình huống sau: 1) "oh, số lượng trống có nghĩa là số lượng 1", 2) "oh, tôi biết những mặt hàng đó có giá khoảng 1.000 đô la, vì vậy, rõ ràng đây là một đơn đặt hàng cho 2 ", 3)" khi điều đó xảy ra, tôi tra cứu giá trong hệ thống khác này và chia và làm tròn ", 4)" Tôi tìm kiếm nó trong một hệ thống khác ", 5)" đó không phải là dữ liệu thực ", 6)" chưa từng thấy điều đó trước đây ".

Theo đề xuất, điều này có thể chỉ ra một số cách tự động giải quyết tình huống, nhưng bạn phải cẩn thận rằng giải pháp áp dụng cho tất cả các trường hợp. Thông thường các hệ thống khác có liên quan có thể kiểm tra chéo dữ liệu và đây là một điều tốt. Tuy nhiên, đó thường là một điều tồi tệ khi khó có thể truy cập và tích hợp với các hệ thống này để thực hiện kiểm tra chéo và thường thấy rằng các hệ thống xung đột với nhau không chỉ thiếu một số dữ liệu. Một số can thiệp thủ công thường được yêu cầu, và tùy thuộc vào quy mô, cũng có thể yêu cầu công cụ và giao diện được tạo riêng cho nhiệm vụ làm sạch dữ liệu. Thông thường những gì được thực hiện là dữ liệu được nhập một phần nhưng các hàng có dữ liệu bị thiếu được gửi đến một bảng riêng biệt nơi chúng có thể được xem xét.


14
Tóm lại: nếu bạn nghĩ rằng việc xử lý mã kế thừa là khó chịu, hãy thử xử lý dữ liệu cũ.
Peter Taylor

0

Thay đổi datamodel.

Bạn có thể bình thường hóa hasradio và sau đó bạn sẽ không còn null nào nữa.

Nếu bạn không thể xác định giá trị boolean, thì đừng sử dụng boolean.

Bằng cách cho phép giá trị boolean trở thành null, nó không còn là giá trị boolean. Một boolean có thể có 2 trạng thái: Sai, Đúng.

Những gì bạn cần là 3 trạng thái: Sai, Đúng, Không biết.

Bạn có tùy chọn để thay đổi datamodel?

.


2
Bằng cách thay đổi mô hình dữ liệu và "bình thường hóa ra hasRadio", tôi giả sử bạn có nghĩa là một cái gì đó giống như thêm một bảng mới CarFeatures, với các lĩnh vực Car_ID, Feature_ID, Has_Feature? Có vẻ như là một ý kiến ​​hay.
JPA

2
@jpa đó là một chút tình huống khó khăn. Bạn phải rất rõ ràng trong những gì bạn làm, bởi vì sự vắng mặt của một hồ sơ trong tình huống của chúng tôi có nghĩa là không rõ. Mặc dù thường không có bản ghi nghĩa là nó không có tính năng này.
Pieter B

1
Bạn đang nhìn nó sai, Pieter. Không ai nói a boolcó nhiều hơn hai giá trị, bởi vì, như bạn đã nói, nó không có. A booltruehoặc false. Tuy nhiên, trong trường hợp OP, OP không giao dịch booltrực tiếp mà là một Option<bool>/Maybe<bool>, có thể có Some -> true/falsehoặc None.
Andy

@DavidPacker lập luận của tôi là vì đó là Có thể <bool> bạn nên ngừng gọi nó là bất cứ điều gì tương tự từ xa nếu không bạn sẽ bị nhầm lẫn. Và nếu bạn khăng khăng sử dụng boolean thì hãy tìm một cách an toàn để làm điều đó.
Pieter B

4
Theo tôi, boolean nullable là hoàn toàn tốt. Tôi chưa bao giờ gặp vấn đề với các giá trị null, mặc dù tôi đã gặp các nhà phát triển đã làm.
Andy

-1

Như những người khác đã chỉ ra, những gì bạn có ở đây là một giá trị boolean không thực sự là boolean và vấn đề là buộc nó phải là boolean hoặc xử lý nó theo cách khác.

Những gì bạn có thể làm là, thay vì có một kết quả boolean duy nhất, để có hai kết quả boolean. Đây có thể đồng ý hoặc không đồng ý. Nếu họ đồng ý, thì bạn có một kết quả đúng / sai.

Tuy nhiên, nếu họ không đồng ý thì bạn có một kết quả không xác định và bạn có cơ hội, tùy thuộc vào hoàn cảnh phát sinh, để quyết định cách xử lý điều đó. Trong một số trường hợp, kết quả không xác định có thể được giải thích tốt nhất là đúng, trong khi ở những trường hợp khác, kết quả không xác định tương tự có thể được hiểu là sai, theo tùy chọn an toàn nhất.

Điều này vẫn sẽ cho phép kết quả được báo cáo là không xác định, do đó, sắc thái bổ sung của giá trị này sẽ không bị mất hoàn toàn, cho đến khi giá trị có thể được giải quyết dứt điểm và đặt lại.

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.