2009-03-20 27 views
13

Vì vậy, khi người dùng gửi yêu cầu đăng ký tài khoản, họ sẽ gửi tên người dùng, mật khẩu, email và thông tin khác của họ. Chức năng đăng ký phải xác minh tất cả dữ liệu của họ. Một ví dụ sẽ là:Làm thế nào để kiểm tra một cách trang nhã nhiều điều kiện trong Erlang?

  • xác minh email không sử dụng
  • xác minh tên người dùng không sử dụng
  • xác minh username là chữ và số
  • xác minh tất cả các trường là trên nhân vật X dài
  • xác minh tất cả các lĩnh vực ít dài hơn Y ký tự dài

Bây giờ tôi không muốn có tuyên bố về trường hợp nếu có hoặc viết 5 cấp, nhưng tôi có những tùy chọn nào khác? Chia nó thành các chức năng riêng biệt nghe có vẻ giống như một ý tưởng hay, nhưng sau đó tôi chỉ cần kiểm tra giá trị trả về của các hàm trong một số loại điều kiện và nó quay trở lại vấn đề ban đầu.

Tôi có thể tách chúng thành các hàm và sau đó gọi câu lệnh if với tất cả các điều kiện HOẶC cùng nhau, nhưng điều đó sẽ không cho tôi điều tôi muốn bởi vì tôi cần báo cho người dùng biết lỗi cụ thể nếu có một.

Làm thế nào để xử lý loại tình huống này trong erlang? Có tương đương với một câu lệnh trả về hay nó phải là dòng thực thi cuối cùng trong một hàm để trở thành một giá trị trả về?

+0

Một bài đăng chéo với danh sách gửi thư của Erlang - hiện đang nhận được một số lượng hợp lý các bài đăng qua bây giờ ... –

Trả lời

32

Một trong những gợi ý của Joe Armstrong: mã trường hợp thành công của chương trình được tách biệt với việc xử lý lỗi. Bạn có thể thực hiện theo cách này

create_user(Email, UserName, Password) -> 
    try 
    ok = new_email(Email), 
    ok = valid_user_name(UserName), 
    ok = new_user(UserName), 
    ok = strong_password(Password), 
    ... 
    _create_user(Email, UserName, Password) 
    catch 
    error:{badmatch, email_in_use} -> do_something(); 
    error:{badmatch, invalid_user_name} -> do_something(); 
    error:{badmatch, user_exists} -> do_something(); 
    error:{badmatch, weak_password} -> do_something(); 
    ... 
    end. 

lưu ý rằng bạn có thể thực hiện tất cả các lỗi phát sinh từ hàm create_user tốt hơn.

create_user(Email, UserName, Password) -> 
    ok = new_email(Email), 
    ok = valid_user_name(UserName), 
    ok = new_user(UserName), 
    ok = strong_password(Password), 
    ... 
    _create_user(Email, UserName, Password). 

main() -> 
    try 
    ... 
    some_function_where_create_user_is_called(), 
    ... 
    catch 
    ... 
    error:{badmatch, email_in_use} -> do_something(); 
    error:{badmatch, invalid_user_name} -> do_something(); 
    error:{badmatch, user_exists} -> do_something(); 
    error:{badmatch, weak_password} -> do_something(); 
    ... 
    end. 

Khớp mẫu là một trong những điều tuyệt vời nhất trong Erlang. Lưu ý rằng bạn có thể liên quan đến từ khóa của bạn để badmatch lỗi

{my_tag, ok} = {my_tag, my_call(X)} 

và tùy chỉnh dữ liệu quá

{my_tag, ok, X} = {my_tag, my_call(X), X} 

Nếu ngoại lệ là đủ nhanh cho bạn phụ thuộc của sự mong đợi của bạn. Tốc độ trên Core2 Duo 2,2GHz của Intel Intel: khoảng 2 triệu ngoại lệ trong một giây (0,47us) so với 6 triệu cuộc gọi hàm thành công (bên ngoài) (0,16us) - người ta có thể đoán rằng xử lý ngoại lệ mất khoảng 0,32us. Trong mã gốc nó là 6,8 vs 47 triệu mỗi giây và xử lý có thể mất khoảng 0.125us. Có thể có một số chi phí bổ sung cho cấu trúc try-catch, khoảng 5-10% cho cuộc gọi hàm thành công ở cả mã gốc và byte.

+2

+1 cho câu trả lời: Trên cả hai sách cũ là không rõ ràng rằng bạn có thể đặt nhiều hơn một biểu hiện trên try/catches. Ty cho thông tin! – scooterman

+0

thực hiện điều này có yêu cầu các chức năng như 'new_email' để ném một loại lỗi cụ thể như' email_in_use'? – Tommy

+0

@Tommy: Không, chỉ cần quay lại: 'try ok = (fun() -> email_in_use end)() bắt lỗi: {badmatch, email_in_use} -> io: format (" OK! ~ N ", []) kết thúc. ' –

4
User = get_user(), 

Check_email=fun(User) -> not is_valid_email(User#user.email) end, 
Check_username=fun(User) -> is_invalid_username(User#user.name) end, 

case lists:any(fun(Checking_function) -> Checking_function(User) end, 
[Check_email, Check_username, ... ]) of 
true -> % we have problem in some field 
    do_panic(); 
false -> % every check was fine 
    do_action() 
end 

Vì vậy, nó không sâu hơn 5 cấp nữa. Đối với chương trình thực sự tôi đoán bạn nên sử dụng danh sách: foldl để tích lũy thông báo lỗi từ mọi chức năng kiểm tra. Bởi vì bây giờ nó đơn giản nói 'tất cả tốt' hoặc 'một số vấn đề'.

Lưu ý rằng theo cách này thêm hoặc loại bỏ kiểm tra điều kiện không phải là một vấn đề lớn

Và đối với "Có một tương đương với một câu lệnh return ..." - nhìn vào thử lệnh catch ném, ném hành vi như trở lại trong trường hợp này.

-3

Có lẽ bạn sẽ cần phải sử dụng các

receive 
    message1 -> code1; 
    message2 -> code2; 
    ... 
end. 

Nhưng, tất nhiên, sẽ có đẻ trứng) phương pháp (.

Các vấn đề liên quan