Nó có được coi là một mẫu chống đọc từ STDIN từ trong thư viện không?


39

Trong khi viết thư viện cho một dự án lớn mà tôi đang làm việc, một vấn đề đã xuất hiện yêu cầu mã thông báo được gửi đến địa chỉ email, sau đó gửi lại vào mã nơi nó có thể được sử dụng để tiếp tục sử dụng.

Đồng nghiệp của tôi nói rằng chỉ cần đọc từ STDIN (sử dụng Python code = input("Enter code: "):) và sau đó có một người dùng vượt qua nó, tuy nhiên với tôi điều này có vẻ như thực tế tồi tệ như thư viện có thể (trong trường hợp này chắc chắn sẽ) được sử dụng trong tác vụ nền trên máy chủ .

Tôi đã tự hỏi liệu điều này có được coi là chống mẫu hay không.


45
Không phải tất cả mọi thứ xấu đều là "chống mẫu", mặc dù điều này chắc chắn là xấu.
Phoshi

4
"Mẫu" có nghĩa là một cái gì đó mà các lập trình viên thường làm. Nó chỉ là một mô hình chống nếu cả hai (A) một ý tưởng tồi và (B) một cái gì đó mà bạn thấy các nhà phát triển làm mọi lúc.
Solomon chậm

20
Điều này là quá ngu ngốc để là một mô hình chống. Một mô hình chống là một cái gì đó có vẻ tự nhiên và hợp lý nhưng hóa ra là xấu khi bạn đào sâu vào nó. Những gì bạn đang mô tả ở đây rõ ràng là khủng khiếp.
Evan Harper

Tôi không thấy điểm của bất kỳ câu trả lời. Điểm của bài tập mã thông báo người dùng phải là để chứng minh rằng địa chỉ email của người dùng hoạt động. Nếu đó không phải là vấn đề, thì việc lưu trữ mã thông báo sẽ đơn giản hơn nhiều.
emory

2
Điều này là khá khủng khiếp. Nếu việc chuyển một mã thông báo như thế là hoàn toàn bắt buộc, bạn có thể tạo một tệp thực thi riêng bằng thư viện và chuyển mã thông báo của bạn đến stdin của nó. Nhưng để chiếm quyền điều khiển cuộc gọi thực thi, đó là điều không nên.
GrandmasterB

Câu trả lời:


78

Theo nguyên tắc chung, các thư viện nên hoàn toàn bị ngắt kết nối với môi trường. Điều đó có nghĩa là họ không nên thực hiện các thao tác trên các luồng tiêu chuẩn, trên các tệp cụ thể hoặc có bất kỳ kỳ vọng nào về môi trường hoặc bối cảnh chúng được sử dụng.

Tất nhiên, có những ngoại lệ cho quy tắc này, nhưng phải có một lý do rất tốt cho nó. Trong trường hợp sử dụng stdin, tôi không thể tìm thấy bất kỳ lý do nào (trừ khi thư viện của bạn thực sự cung cấp các thói quen để đọc từ stdin, như std::cintừ C ++). Ngoài ra, việc lấy các luồng I / O từ một tham số thay vì mã hóa chúng sẽ tăng thêm tính linh hoạt đến mức không đáng để không thực hiện.


36
Ngoại lệ là một thư viện có mục tiêu cụ thể là tương tác với môi trường. Ngay cả sau đó, các chi tiết của môi trường nên được trừu tượng hóa. Ví dụ, trình điều khiển đồ họa phải giao tiếp với bus PCIe, nhưng ID bus phải được cung cấp thông qua cấu hình.

Đây là loại ngoại lệ, tôi nghĩ: ý tưởng của tôi là gần gũi hơn với ncurses - nói chung, một text-môi trường thư viện giao diện người dùng. Nếu mục đích của nó là đọc đầu vào của người dùng và cung cấp đầu ra của người dùng, đó là một lý do chính đáng.
SF.

5
@SF. Ngay cả một thư viện như ncurses cũng nên lấy một cặp mô tả tệp làm đối số thay vì mã hóa việc sử dụng 0 và 1. Bạn có thể muốn viết chương trình trong đó stdin và stdout có thể được chuyển hướng và thay vào đó bạn muốn mở /dev/ttyđể giao tiếp với người sử dụng. Chương trình thậm chí có thể được bắt đầu mà không cần thiết bị đầu cuối và mở thiết bị đầu cuối của chính nó bằng cách sử dụng xterm -S.
kasperd

3
@kasperd: Cách tiếp cận tốt nhất là cung cấp các mặc định hợp lý và khả năng ghi đè chúng.
SF.

1
Trong trường hợp cụ thể này, tôi thấy không có lý do gì để yêu cầu một luồng làm đầu vào. Tại sao không chỉ chấp nhận mã thông báo làm tham số?
jpmc26

16

Tôi sẽ xem xét điều này không nhất thiết là một mô hình chống, chỉ là một thư viện được thiết kế kém. Sẽ là tầm thường khi yêu cầu một chuỗi làm tham số phương thức, trong đó đầu vào có thể được truyền trực tiếp vào.

Nếu điều đó không phù hợp với cách sử dụng này, thì một tham số phương thức có thể là một luồng, với STDIN được truyền vào phương thức.

Nếu điều đó không phù hợp với cách sử dụng này, thì thư viện không đủ linh hoạt.


4

Có thể xem xét khả năng trong thư viện của bạn để đặt lại hàm gọi cho hàm do người dùng cung cấp sẽ đọc đầu vào từ bất cứ đâu và sau đó trả lại giá trị phù hợp cho bất kỳ phần nào của thư viện đang sử dụng hàm đó.


1

Nếu nó được đọc từ stdin, điều đó có nghĩa là nó muốn có quyền sở hữu cấp chương trình của stdin. Nó có thể không tương thích với bất kỳ thư viện nào khác đọc từ stdin, giao thức ít cụ thể hơn cho cách họ chia sẻ sử dụng. Trong ít nhất là thuật ngữ cá nhân của riêng tôi, điều này sẽ làm cho thư viện trở thành một khung , đó là một sự đánh đổi đắt giá.

Nhưng trong trường hợp này, thư viện có lẽ chỉ nên lấy một bộ mô tả tệp đầu vào.


0

Câu trả lời của @ Paul92 là thảo luận chung tốt, nhưng tôi muốn đưa ra một giải pháp (ish) sạch có thể cho vấn đề này:

Một thư viện, mã này cần có khả năng thích ứng với mọi môi trường thời gian chạy, vì vậy bạn thực sự không thể yêu cầu STDINmột số dữ liệu quan trọng. Đối với một, người dùng thư viện của bạn có thể không có sẵn stdin vì một số lý do. Thay vào đó, bạn có thể muốn sử dụng một số dạng mẫu chiến lược để tùy chỉnh cách lấy mã thông báo.

Trong Python, có lẽ tùy chọn tốt nhất là chuyển chiến lược tìm nạp mã thông báo dưới dạng tham số hàm. Một cái gì đó như thế:

def stdin_prompt():
    return input("Enter code: ")

def my_library_function(arg1, arg2, ... argn, token_provider = stdin_prompt):
    ...
    token = token_provider()
    ...
    return stuff

# somewhere in the user code
stuff = my_library_function(a1, a2, ... an, lambda: "123456")

Hãy nghĩ về nó như thế này. Mã thông báo mà bạn yêu cầu, là một đối số cho chức năng thư viện. Vì giá trị của mã thông báo có thể không được biết đến tĩnh tại trang web cuộc gọi, bạn thực sự không thể yêu cầu giá trị làm đối số. Thay vào đó, người gọi phải cung cấp một chức năng sẽ chịu trách nhiệm cung cấp mã thông báo khi được gọi.

Tất cả trách nhiệm cung cấp các cơ chế chính xác của mã thông báo hiện được đưa ra khỏi chức năng thư viện. Người tiêu dùng của chức năng hiện chịu trách nhiệm nhận mã thông báo bằng bất kỳ phương tiện nào có sẵn trong thời gian chạy. Nó có thể yêu cầu STDIN, nhưng nó cũng có thể hoạt động như một cổng thư, chờ thư xuất hiện trong hộp thư đến, đọc nó, trích xuất mã thông báo và tự động hóa hoàn toàn quy trình. Nó có thể là một hộp thoại GUI hoặc một hình thức dựa trên web. Bất cứ điều gì thực sự - tất cả các tùy chọn hiện đang nằm trong tay của người tiêu dùng thư viện.

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.