web-dev-qa-db-ja.com

グローバルリクエストコンテキスト-アンチパターン?

今日、私の同僚とPython Webフレームワークとそれらについての印象について話していました。Flaskグローバルリクエストを行うと悪臭がし、アンチパターンです。

docs リクエストコンテキストについて言う:

対照的に、リクエストの処理中は、他にもいくつかのルールがあります。

  • リクエストがアクティブである間、コンテキストローカルオブジェクト(flask.requestなど)は現在のリクエストを指します。
  • どのコードでも、いつでもこれらのオブジェクトを取得できます。

この設計の決定の背後にある考えを理解したと思います-アプリケーションをより単純にするためです。 Thread Locals の場合のように、これは単なる妥協です。

はい、通常、スレッドローカルを使用するのはそれほど賢明ではありません。これらは、スレッドの概念に基づいていないサーバーに問題を引き起こし、大規模なアプリケーションの保守を困難にします。ただし、Flaskは、大規模なアプリケーションや非同期サーバー用に設計されたものではありません。Flaskは、従来のWebアプリケーションをすばやく簡単に作成できるようにしたいと考えています。

現在のリクエスト情報でグローバルオブジェクトにパッチを当てることはアンチパターンですか?

静的コードアナライザーのビューではグローバルな状態ですが、そうではないためです。そして、プログラマーとして docs を注意深く読まないと、それがどのように機能するか理解できません。そして、これには テストの結果 があります。

リクエストを引数としてビューに渡すことは良い習慣ではありませんか?読みやすく、明示的で、デバッグが簡単だと思います。そして、グローバルな状態を避けます。

12
warvariuc

多くのWebフレームワークは、これと同じ構造、つまりグローバルリクエストを持っています。ある意味で、これは正しいことです。なぜなら、本当にIS一度に1つの要求しか存在しないからです。

それで、リクエストをパラメータとして渡すことに意味がありますか?いいえ。リクエストはリクエストであり、パラメータはさまざまなタイミングでさまざまなものを渡すためのものです。

大規模なアプリケーションの低レベルを検討し始めると、問題が発生します。グローバルなリクエストでは、リクエストにグローバルにアクセスする場所全体にコードを書く誘惑があります。 非常に悪いことです。コードの異なる部分間の結合を生成し、変更を困難にし、テストを困難にします。

だから私の答えは、グローバルな要求を維持し、それと共存することです。ただし、個々のモジュールまたは関数がリクエスト全体を必要としない場合は、必要なデータのみをパラメーターとして渡します。リファラー、URL、またはコマンドテールと、必要なビットを関数に渡します。これにより、コードをモジュール化し、結合を減らし、テスト容易性を向上させることができます。

小さなプログラムの場合はほとんど問題になりませんが、大きなプログラムの場合、これは実際の命の恩人になります。

4
david.pfx

(私はいくつかの反対票を獲得するかもしれませんが、私は大胆に行き、これを答えにします。)

フラスコはマイクロフレームワークです。フリルをあきらめながら、シンプルさの恩恵を受けます。直感的には同意しますが、あるショップでflask + gunicornを使用して、必要なマルチスレッドを実現しました。うまくいきましたreallyうまくいきました。スクリプトの各インスタンスは1つの要求(つまり1つのスレッド)を渡しただけで、gunicornは複数のスレッド間で「ファンアウト」を処理しました。

つまり、複数のスレッドがグローバルな状態をめぐって争う可能性があると感じるマイナス面は、スレッドごとに1つのスクリプトであるため、問題にはなりません。

(ここで問題が発生する可能性があります)Pythonの世界ではスレッド化と並行処理が異なります。Java私の経験では、Javaで当たり前のことと見なした同時実行性の問題、またはアプリケーションコンテナによって透過的に処理されることは、Pythonの表面にかなり近いということでした。

1つのスレッドが1つのスクリプトの呼び出しを処理するのは不思議でしたが、同時に数十のボックスで実行した後、私はそれについて気分が良くなりました。

3
Rob

Pythonには、標準出力に出力するprintコマンド(v3以降の機能)があります。STDOUTに出力することを明示的に指定しないでください-これは、あなたは暗黙のうちに舞台裏にいます。

暗黙的に。 Pythonで。そして、誰もそれに問題はありません。どうして?

printはPython言語の一部であり、Pythonでのプログラミングの1つの要件は... Pythonを知っていることです。そしてPythonを知っていれば、printがSTDOUTをターゲットにしていることがわかります。

Pythonは(言語として)独自の規則を定義し、プログラマーがそれらを認識していると想定できます。

フレームワークもその特権を享受します-それはフレームワークとライブラリの間の主な違いの1つです。ライブラリを使用するためにライブラリを学習する必要はありません。必要なAPIの部分を見つけ、言語(またはフレームワーク)の規則に従っていると想定するだけです。そのため、GSONやApache Commonsの知識を持つ人材を探している採用担当者は見当たりません。しかし、リクルーターがJQueryまたはRuby on RailsまたはASP.NET MVC)の経験を持つ人を探しているのはわかります。学び、気づく必要があります。

Flaskは、フレームワークとして、スレッドローカルグローバルにコンテキストを格納するための規則を定義できます。これは、誰も驚かないはずです。そのため、アンチパターンではありません。

2
Idan Arye