从库中的STDIN读取是否被认为是反模式?


39

在为我正在工作的大型项目编写库时,出现了一个问题,该问题要求将令牌发送到电子邮件地址,然后传递回代码中,以供以后使用。

我的同事说,只是从STDIN中读取(使用Python:)code = input("Enter code: "),然后让用户传递它,但是对我来说,这似乎是一种不好的做法,因为该库可能(在这种情况下肯定会)用在服务器上的后台任务中。

我想知道这是否被视为反模式。


45
并非所有坏事都是“反模式”,尽管这肯定是坏事。
Phoshi

4
“模式”是指程序员经常做的事情。如果这既是(A)一个坏主意,又是(B)您看到开发人员一直在做的事情,那么这只是一个反模式。
所罗门慢

20
这太愚蠢了,不能成为反模式。反模式似乎是自然而明智的,但是当您深入研究时却发现它是不好的。您在这里描述的内容显然很可怕。
埃文·哈珀

我没有看到任何答案的意义。用户令牌练习的重点必须是证明用户的电子邮件地址有效。如果那不是重点,那么简单地存储令牌将简单得多。
emory

2
这太可怕了。如果绝对需要传递这样的令牌,则可以使用该库制作一个单独的可执行文件,并将令牌传递到其stdin。但是要劫持调用可执行文件的标准输入,这是不行的。
GrandmasterB

Answers:


78

作为一般准则,应该将库与环境完全断开。这意味着他们不应该对标准流,特定文件执行操作,或者对所使用的环境或上下文有任何期望。

当然,该规则也有例外,但是必须有很好的理由。在使用的情况下stdin,我找不到任何原因(除非您的库实际上提供了从stdin读取例程,例如std::cin从C ++ 读取)。同样,从参数获取I / O流而不是对其进行硬编码会增加太多的灵活性,因此不值得这样做。


36
一个例外是具有与环境进行交互的特定目标的库。即使这样,也应该抽象出环境的细节。例如,图形驱动程序必须与PCIe总线进行通信,但是应通过配置提供总线ID。

我认为这是一种例外:我的想法更接近ncurses-通常是文本环境用户界面库。如果其目的是读取用户输入并提供用户输出,则这是一个很好的理由。
SF。

5
@SF。甚至ncurses之类的库也应将一对文件描述符作为参数,而不是对0和1的使用进行硬编码。您可能想编写一个程序,在其中可以重定向stdin和stdout,而您想打开/dev/tty以便与用户。该程序甚至可以在没有终端的情况下启动,并使用来打开自己的终端xterm -S
kasperd

3
@kasperd:最好的方法是提供合理的默认值并覆盖它们。
SF。

1
在这种情况下,我认为没有理由要求将作为输入。为什么不只接受令牌作为参数呢?
jpmc26

16

我认为这不一定是反模式,只是设计不良的库。要求将字符串作为方法参数,将输入直接传递到其中应该是微不足道的。

如果不适合这种用法,则方法参数可以是流,并将STDIN传递到方法中。

如果这不适合这种用法,则该库不够灵活。


4

也许可以考虑在您的库中设置对用户提供的函数的回调,该回调将从任何位置读取输入,然后将适当的值返回给使用该函数的库的任何部分。


1

如果确实从stdin中读取,则表示它希望获得stdin的程序级所有权。它可能与从stdin读取的任何其他库(与它们共享使用方式的特定性较低的协议)不兼容。至少在我个人的词汇表中,这将使库成为框架,这是一个昂贵的折衷。

但是在这种情况下,库可能应该只接受输入文件描述符。


0

@ Paul92的回答是一个很好的一般性讨论,但是我想为此提供一个可能的干净解决方案:

作为一个库,此代码需要适用于任何运行时环境,因此您不能真正要求STDIN一些关键的数据。一方面,由于多种原因,您的库用户可能没有标准输入。相反,您可能想使用某种形式的策略模式来定制如何检索令牌。

在Python中,最好的选择可能是将令牌获取策略作为函数参数传递。像这样:

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")

这样想吧。您需要的令牌是库函数的参数。由于令牌的值在调用站点可能不是静态已知的,因此您不能真正要求将值作为参数。相反,调用者必须提供一个函数,该函数将在被调用时负责提供令牌。

库功能现在已将提供令牌的确切机制的所有责任从外部化了。函数的使用者现在负责通过运行时可用的任何方式获取令牌。它可能会询问STDIN,但它也可能充当邮件网关,等待消息弹出到收件箱中,阅读它,提取令牌并完全自动化该过程。它可能是GUI对话框或基于Web的表单。真的-所有选项现在都由图书馆用户掌握。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.