在为我正在工作的大型项目编写库时,出现了一个问题,该问题要求将令牌发送到电子邮件地址,然后传递回代码中,以供以后使用。
我的同事说,只是从STDIN中读取(使用Python:)code = input("Enter code: ")
,然后让用户传递它,但是对我来说,这似乎是一种不好的做法,因为该库可能(在这种情况下肯定会)用在服务器上的后台任务中。
我想知道这是否被视为反模式。
在为我正在工作的大型项目编写库时,出现了一个问题,该问题要求将令牌发送到电子邮件地址,然后传递回代码中,以供以后使用。
我的同事说,只是从STDIN中读取(使用Python:)code = input("Enter code: ")
,然后让用户传递它,但是对我来说,这似乎是一种不好的做法,因为该库可能(在这种情况下肯定会)用在服务器上的后台任务中。
我想知道这是否被视为反模式。
Answers:
作为一般准则,应该将库与环境完全断开。这意味着他们不应该对标准流,特定文件执行操作,或者对所使用的环境或上下文有任何期望。
当然,该规则也有例外,但是必须有很好的理由。在使用的情况下stdin
,我找不到任何原因(除非您的库实际上提供了从stdin读取例程,例如std::cin
从C ++ 读取)。同样,从参数获取I / O流而不是对其进行硬编码会增加太多的灵活性,因此不值得这样做。
/dev/tty
以便与用户。该程序甚至可以在没有终端的情况下启动,并使用来打开自己的终端xterm -S
。
我认为这不一定是反模式,只是设计不良的库。要求将字符串作为方法参数,将输入直接传递到其中应该是微不足道的。
如果不适合这种用法,则方法参数可以是流,并将STDIN传递到方法中。
如果这不适合这种用法,则该库不够灵活。
也许可以考虑在您的库中设置对用户提供的函数的回调,该回调将从任何位置读取输入,然后将适当的值返回给使用该函数的库的任何部分。
@ 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的表单。真的-所有选项现在都由图书馆用户掌握。