Đây là một ví dụ về cách bạn có thể tiếp cận điều này từ góc độ chức năng và cách nó giúp tránh những cạm bẫy tiềm ẩn. Tôi đang làm việc tại Haskell, nơi tôi cho rằng bạn không biết, vì vậy tôi sẽ giải thích chi tiết khi tôi đi cùng.
data Application = Applied ApplicationDetails |
InReview ApplicationDetails |
Approved ApplicationDetails |
Declined ApplicationDetails
Điều này xác định một kiểu dữ liệu có thể ở một trong bốn trạng thái tương ứng với trạng thái ứng dụng của bạn. ApplicationDetails
được coi là một loại hiện có chứa thông tin chi tiết.
newtype UpdatableApplication = UpdatableApplication Application
Một bí danh loại cần chuyển đổi rõ ràng đến và từ Application
. Điều này có nghĩa là nếu chúng ta xác định hàm sau chấp nhận và hủy bỏ một hàm UpdatableApplication
và thực hiện một cái gì đó hữu ích với nó,
updateApplication :: UpdatableApplication -> ApplicationDetails -> Application
updateApplication (UpdatableApplication app) details = ...
sau đó chúng ta phải chuyển đổi rõ ràng Ứng dụng thành ứng dụng UpdizableApplication trước khi chúng ta có thể sử dụng nó. Điều này được thực hiện bằng cách sử dụng chức năng này:
findUpdatableApplication :: Application -> Maybe UpdatableApplication
findUpdatableApplication app@(Applied _) = Just (UpdatableApplication app)
findUpdatableApplication _ = Nothing
Ở đây chúng tôi làm ba điều thú vị:
- Chúng tôi kiểm tra trạng thái của ứng dụng (sử dụng kết hợp mô hình, mà là thực sự tiện dụng cho các loại mã này), và
- nếu nó có thể được cập nhật, chúng tôi gói nó trong một
UpdatableApplication
(chỉ liên quan đến một ghi chú kiểu biên dịch về sự thay đổi của loại được thêm vào, vì Haskell có một tính năng cụ thể để thực hiện loại thủ thuật cấp độ loại này, nó không mất gì khi chạy) và
- chúng tôi trả về kết quả bằng "Có thể" (tương tự như
Option
trong C # hoặc Optional
trong Java - đó là một đối tượng bao bọc một kết quả có thể bị thiếu).
Bây giờ, để thực sự kết hợp nó, chúng ta cần gọi hàm này và, nếu kết quả thành công, hãy chuyển nó sang hàm cập nhật ...
case findUpdatableApplication application of
Just updatableApplication -> do
storeApplicationInDatabase (updateApplication updatableApplication)
showConfirmationPage
Nothing -> do
showErrorPage
Vì updateApplication
hàm cần đối tượng được bao bọc, chúng ta không thể quên kiểm tra các điều kiện tiên quyết. Và bởi vì chức năng kiểm tra điều kiện tiên quyết trả về đối tượng được bọc bên trong một Maybe
đối tượng, chúng ta không thể quên kiểm tra kết quả và trả lời tương ứng nếu thất bại.
Bây giờ ... bạn có thể làm điều này trong một ngôn ngữ hướng đối tượng. Nhưng nó không thuận tiện:
- Không có ngôn ngữ OO nào tôi từng thử có một cú pháp đơn giản để tạo loại trình bao bọc an toàn loại, do đó, đó là bản tóm tắt.
- Nó cũng sẽ kém hiệu quả hơn, vì ít nhất là đối với hầu hết các ngôn ngữ họ sẽ không thể loại bỏ loại trình bao bọc, vì nó sẽ được yêu cầu tồn tại và có thể phát hiện được trong thời gian chạy (Haskell không có kiểm tra loại thời gian chạy, tất cả các kiểm tra loại đều được thực hiện tại thời gian biên dịch).
- Mặc dù một số ngôn ngữ OO có các loại tương đương với
Maybe
chúng thường không có cách trích xuất dữ liệu thuận tiện và chọn đường dẫn để đi cùng một lúc. Kết hợp mẫu là thực sự hữu ích ở đây, quá.