Tôi thường được giao nhiệm vụ yêu cầu người dùng nhập liệu. Tôi đã luôn luôn viết lời nhắc của tôi "là cần thiết" trong các kịch bản thực thi chính của tôi. Đây là loại xấu xí, và bởi vì tôi thường yêu cầu cùng một kiểu đầu vào trên nhiều tập lệnh, một tấn mã của tôi chỉ là các vòng lặp được sao chép/dán. Dưới đây là những gì tôi đã làm trong quá khứ:Viết lời nhắc nhập người dùng sạch, linh hoạt và dễ bảo trì
while True:
username = input("Enter New Username: ")
if ldap.search(username):
print " [!] Username already taken."
if not validator.validate_username(username):
print " [!] Invalid Username."
else:
break
tôi muốn tạo một cái gì đó có thể được gọi như:
username = prompt(prompt="Enter New Username: ",
default=None,
rules=["user_does_not_exist",
"valid_username"])
Sau đó, chức năng nhanh chóng trông giống như:
def prompt(prompt, default, rules):
while True:
retval = input(prompt)
if default and retval == "":
break
return default
if not rule_match(retval, rules):
continue
break
return retval
def rule_match(value, rules):
if "user_does_not_exist" in rules:
if not user.user_exists(value):
return False
if "valid_username" in rules:
if not validator.username(value):
return False
if "y_n_or_yes_no" in rules:
if "ignore_case" in rules:
if value.lower() not in ["y", "yes", "n", "no"]:
return False
else:
if value not in ["y", "yes", "n", "no"]:
return False
return True
Một giải pháp thay thế mà tôi đang cân nhắc là tạo một lớp Prompt, điều này sẽ cho phép sự linh hoạt hơn với kết quả. Ví dụ: nếu tôi muốn chuyển đổi "y" hoặc "n" thành True hoặc False, thì điều trên không thực sự hiệu quả.
create_another = Prompt(prompt="Create another user? (y/n): ,"
default=False,
rules=["y_n_or_yes_no",
"ignore_case"]).prompt().convert_to_bool()
Cách thay thế khác mà tôi đang xem xét chỉ là tạo lời nhắc riêng và đặt tên cho chúng, với mỗi mã được viết giống với mã rất ban đầu của tôi. Điều này không thực sự thay đổi bất cứ điều gì. Nó chỉ phục vụ để có được những vòng ra mã thực thi chính của tôi mà làm cho mã thực thi chính dễ dàng hơn để duyệt:
username = prompt("get_new_username")
def prompt(prompt_name):
if prompt_name == "get_new_username":
while True:
username = input("Enter New Username: ")
if ldap.search(username):
print " [!] Username already taken."
if not validator.validate_username(username):
print " [!] Invalid Username."
else:
break
return username
if prompt_name == "y_n_yes_no_ignore_case":
# do prompt
if prompt_name == "y_n_yes_no":
# do prompt
if prompt_name == "y_n":
# do prompt
if prompt_name == "y_n_ignore_case":
# do prompt
if prompt_name == "yes_no":
# do prompt
if prompt_name == "yes_no_ignore_case":
# do prompt
Tôi nhận ra rằng nó có thể chỉ là một ý tưởng tốt để giải quyết trên một chấp nhận "/ y n" định dạng cho tất cả các chương trình của tôi, và tôi sẽ. Đây chỉ là để cho thấy rằng, trong trường hợp tôi sẽ cần một dấu nhắc rất giống nhau nhưng hơi khác nhau, nó sẽ dẫn đến rất nhiều mã sao chép/dán (không có sự linh hoạt với phương pháp này cả).
Cách tiếp cận tốt để viết lời nhắc người dùng sạch, linh hoạt và dễ duy trì là gì?
(Tôi đã thấy điều này: Asking the user for input until they give a valid response và một số câu trả lời khác. Câu hỏi của tôi không phải là về cách nhập và xác thực, đó là cách tạo hệ thống nhập linh hoạt có thể được sử dụng lại với nhiều chương trình).
Tôi luôn thấy rằng các trường hợp sử dụng của mình cần phải được tùy chỉnh đủ để làm cho việc viết một giải pháp mục đích chung khó khăn. Tôi rất vui khi thấy có ai đưa ra giải pháp thực tế hay không, câu hỏi hay. –
Thiết kế hệ thống nhắc nhở linh hoạt, có thể tái sử dụng hơi vượt quá phạm vi của Stack Overflow. – chepner
@chepner Vâng, đó là loại câu hỏi của tôi! Có phải thứ gì đó phải được thiết kế "chuyên sâu" (trong trường hợp này tôi đồng ý, chúng tôi không thể đăng toàn bộ chương trình trong câu trả lời SO), hoặc, và đây là câu hỏi của tôi, có giải pháp hay cách nào đó để điều này là sạch sẽ và đơn giản mà tôi chỉ không nghĩ đến? Từ những gì tôi thu thập, câu trả lời là đây thực sự là một câu hỏi đòi hỏi một giải pháp phức tạp. Ngay cả trong trường hợp của cựu, câu hỏi vẫn còn phục vụ công đức tôi nghĩ, để hiển thị những người khác với những câu hỏi tương tự mà thực sự nó không phải là đơn giản, đủ để trả lời trong một bài viết. – CptSupermrkt