全局请求上下文-反模式?


12

今天我在和我的一位同事谈论Python Web框架以及我们对它们的印象。我告诉他,我认为Flask具有全局请求的气味很难闻,并且是一种反模式。

文档说关于请求上下文:

相反,在请求处理期间,存在其他一些规则:

  • 当请求处于活动状态时,上下文本地对象(flask.request和其他对象)指向当前请求。
  • 任何代码都可以随时获取这些对象。

我认为我了解此设计决策背后的想法-使应用程序更简单。这只是一个折衷,就像在Thread Locals的情况下:

是的,使用线程本地化通常不是一个好主意。它们给不基于线程概念的服务器造成麻烦,并使大型应用程序难以维护。但是Flask并不是专门为大型应用程序或异步服务器设计的。Flask希望使其能够轻松快捷地编写传统的Web应用程序。

使用当前请求信息修补全局对象是否是反模式?

我相信是这样,因为从静态代码分析器的角度来看,它是一个全局状态,尽管事实并非如此。作为程序员,如果不仔细阅读文档,我将无法理解其工作原理。这对测试有影响

将请求作为参数传递给视图不是一个好习惯吗?我认为它更具可读性,明确性且易于调试。并避免全局状态。


2
您尚未真正说明这种反模式的具体负面影响是什么。我不相信没有事实依据的广泛概括。
罗伯特·哈维

2
好问题,但可惜的是答案不多
sleepycal

Answers:


4

许多Web框架具有相同的结构:全局请求。从某种意义上说,这是正确的事情,因为嘿,一次确实只有一个请求。

那么传递请求作为参数有什么意义吗?否。请求是请求,参数用于在不同时间传递不同的事物。

真正的问题就来了,你开始考虑一个更大的应用水平较低。对于全局请求,存在在全球访问该请求的整个地方编写代码的诱惑。那是非常不好的事情。它会在代码的不同部分之间产生耦合,使更改内容和测试变得困难。

因此,我的答案是:保留全局请求并接受它。但是,无论哪个模块或功能不需要整个请求,都只需将其需要的数据作为参数传递。仅将引荐来源网址,URL或命令尾巴以及任何需要的位传递到函数中。这将有助于保持代码模块化,减少耦合并提高可测试性。

对于小型程序,几乎没有关系,但是对于大型程序,这可能是真正的救星。


3

(尽管我可能会有些不赞成,但我将大胆地提出来,作为一个答案。)

烧瓶是一个微框架。您会从简单中受益,同时放弃多余的装饰。虽然我完全同意您的观点,但我确实知道我在一家商店使用了flask + gunicorn给我所需的多线程。它的工作真的很好。脚本的每个实例仅发出一个请求(即一个线程),而gunicorn处理多个线程之间的“扇出”。那太好了。

因此,您感觉到的缺点是-多个线程可能争夺全局状态-这不是问题,因为每个线程一个脚本。

(这是我可能会遇到麻烦的地方)线程和并发在Python世界中是不同的,如果您以Java的心态来研究它,那么很难将其压入。我的经验是我所处理的并发问题Java授予的许可权,或由应用程序容器透明处理的许可权,离Python的表面很近。

对我来说很奇怪,一个线程可以处理一次我的脚本调用,但是当我在一个盒子上同时运行几十个线程后,我对此感觉更好。


4
我不担心线程安全等等。我相信Flask在这些情况下效果很好。我的问题是关于应用程序设计和体系结构的。将请求作为参数传递给视图不是一个好习惯吗?我认为它更具可读性,明确性且易于调试。
warvariuc

2

在Python中,您有print可以打印到标准输出的命令(自v3起具有此功能)。您无需明确指定要打印到STDOUT的位置-隐式地为您完成了此操作。

隐含地。在Python中。而且没有人对此有问题。为什么?

print是Python语言的一部分,并且使用Python进行编程的一个要求是……很了解Python。而且,如果您了解Python,就知道它print以STDOUT为目标。没有惊喜。

Python作为一种语言,可以定义它自己的约定,并假定程序员已经意识到它们。

框架也享有这种特权-这是框架和库之间的主要区别之一。您无需学习库即可使用它-您只需要找到所需的API部分,并假定它遵循语言(或框架)的约定。因此,您不会看到招聘人员在寻找具有GSON或Apache Commons知识的人员。但是您会看到招聘人员正在寻找具有JQuery或Ruby on Rails或ASP.NET MVC经验的人员-因为这些框架定义了您需要学习和了解的约定。

Flask作为框架,可以定义用于将上下文存储在线程局部全局变量中的约定-不应让任何人感到惊讶,因此它不是反模式。


2
请注意,“ stdout”表示指向的文件描述符sys.stdout。如果更改此设置,则打印将移至其他位置。
Phoshi 2014年

1
另外,您可以使用>>运算符或将file参数传递给printPython3中的函数来覆盖输出流。因此,sys.stdout只是可以覆盖的默认值。
warvariuc 2014年
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.