Contexte de demande global - anti-modèle?

12

Je parlais aujourd'hui à un de mes collègues des frameworks Web Python et de nos impressions à leur sujet. Je lui ai dit que je pense que Flask ayant une demande globale sent mauvais et est un anti-modèle.

Les documents disent à propos du contexte de la demande:

En revanche, pendant le traitement des demandes, deux autres règles existent:

  • lorsqu'une requête est active, les objets locaux de contexte (flask.request et autres) pointent vers la requête en cours.
  • n'importe quel code peut mettre la main sur ces objets à tout moment.

Je pense que je comprends l'idée derrière cette décision de conception - pour rendre l'application plus simple. C'est juste un compromis, comme dans le cas des sections locales de thread :

Oui, ce n'est généralement pas une bonne idée d'utiliser des sections locales de threads. Ils causent des problèmes aux serveurs qui ne sont pas basés sur le concept de threads et rendent les grandes applications plus difficiles à maintenir. Cependant, Flask n'est tout simplement pas conçu pour les grandes applications ou les serveurs asynchrones. Flask souhaite faciliter l'écriture rapide et facile d'une application Web traditionnelle.

L'application d'un correctif à un objet global avec les informations de demande en cours est-elle un anti-modèle?

Je crois que c'est le cas, car il est de l'avis de l'analyseur de code statique un état global, bien qu'il ne le soit pas. Et en tant que programmeur, je ne comprendrai pas comment cela fonctionne sans lire attentivement les documents . Et cela a des conséquences sur les tests .

N'est-ce pas une bonne pratique de passer la demande en argument aux vues? Je pense que c'est plus lisible, explicite et plus facile à déboguer. Et évite l'état global.

warvariuc
la source
2
Vous n'avez pas vraiment déclaré quels pourraient être les effets négatifs spécifiques d'un tel contre-modèle. Je me méfie des généralités radicales qui n'ont aucun fondement factuel.
Robert Harvey
2
Bonne question, mais malheureusement pas beaucoup de réponses de qualité
sleepycal

Réponses:

4

De nombreux frameworks web ont cette même structure: une requête globale. Dans un sens, c'est la bonne chose à faire car bon, il n'y a vraiment qu'une seule demande à la fois.

Est-il donc utile de transmettre la demande en tant que paramètre? Non. La demande est la demande et les paramètres permettent de transmettre différentes choses à différents moments.

Le vrai problème survient lorsque vous commencez à envisager des niveaux inférieurs d'une application plus importante. Avec une requête globale, il y a la tentation d'écrire du code partout qui accède à la requête globalement. C’est une très mauvaise chose . Il produit un couplage entre différentes parties du code, rend difficile le changement et rend difficile le test.

Donc ma réponse est: garder la demande globale et vivre avec. Cependant, chaque fois qu'un module ou une fonction individuelle n'a pas besoin de la totalité de la demande, transmettez uniquement les données dont il a besoin en tant que paramètre. Passez juste le référent, ou l'url, ou la queue de commande et les bits dont vous avez besoin dans vos fonctions. Cela aidera à garder le code modulaire, à réduire le couplage et à améliorer la testabilité.

Pour les petits programmes, cela n'a guère d'importance, mais pour les plus grands, cela peut être une véritable bouée de sauvetage.

david.pfx
la source
3

(Je vais faire preuve d'audace et en faire une réponse, bien que je puisse obtenir des votes négatifs.)

Flask est un micro-cadre; vous bénéficiez de la simplicité tout en abandonnant les fioritures. Bien que je sois d'accord avec vous, je sais que j'ai utilisé flacon + gunicorn dans un magasin pour me donner le multi-threading dont j'avais besoin. Cela a très bien fonctionné. Chaque instance du script vient de transmettre une demande (c'est-à-dire un thread), et gunicorn a géré le "fan out" parmi plusieurs threads. C'était génial pour ça.

Donc, l'inconvénient perçu que vous ressentez - que plusieurs threads pourraient lutter pour l'état global - n'est tout simplement pas un problème, car c'est un script par thread.

(Voici où je peux avoir des problèmes) Le threading et la concurrence sont différents dans le monde Python, et si vous y arrivez avec un état d'esprit Java, il est difficile de les intégrer. Mon expérience était que les problèmes de concurrence que j'ai pris pour accordées en Java, ou gérées de manière transparente par le conteneur d'application, sont beaucoup plus proches de la surface en Python.

C'était étrange pour moi qu'un thread puisse gérer une invocation de mon script, mais après que j'en ai eu quelques dizaines en cours d'exécution sur une boîte en même temps, je me sentais mieux.

Rob
la source
4
Je ne m'inquiète pas pour la sécurité des fils et autres. Je pense que Flask fonctionne bien dans ces cas. Ma question concerne la conception et l'architecture des applications. N'est-ce pas une bonne pratique de passer la demande en argument aux vues? Je pense que c'est plus lisible, explicite et plus facile à déboguer.
warvariuc
2

En Python, vous avez la printcommande (fonction depuis la v3) qui imprime sur la sortie standard. Vous ne spécifiez pas explicitement que vous souhaitez imprimer sur STDOUT - c'est fait pour vous implicitement dans les coulisses.

Implicitement. En Python. Et personne n'a de problème avec ça. Pourquoi?

printfait partie du langage Python, et une exigence de programmation en Python est ... bien ... de connaître Python. Et si vous connaissez Python, vous savez qu'il printcible STDOUT. Pas de surprise là-bas.

Python - en tant que langage - peut définir sa propre convention et supposer que les programmeurs en sont conscients.

Les cadres bénéficient également de ce privilège - c'est l'une des principales différences entre un cadre et une bibliothèque. Vous n'avez pas besoin d'apprendre une bibliothèque pour l'utiliser - il vous suffit de trouver la partie de l'API dont vous avez besoin et de supposer qu'elle suit les conventions du langage (ou du framework). C'est pourquoi vous ne voyez pas de recruteurs à la recherche de personnes ayant des connaissances dans GSON ou Apache Commons. Mais vous voyez des recruteurs à la recherche de personnes ayant de l'expérience avec JQuery ou Ruby on Rails ou ASP.NET MVC - car ce sont des cadres qui définissent leurs propres conventions que vous devez apprendre et connaître.

Flask, en tant que framework, peut définir une convention pour stocker le contexte dans un global thread-local - et cela ne devrait surprendre personne, donc ce n'est pas un anti-modèle.

Idan Arye
la source
2
Notez que "stdout" signifie tout descripteur de fichier pointé par sys.stdout. Si vous changez cela, l'impression va ailleurs.
Phoshi
1
En outre, vous pouvez remplacer le flux de sortie en utilisant l' >>opérateur ou en passant un fileargument pour printfonctionner en Python3. Donc, sys.stdoutc'est juste une valeur par défaut qui peut être remplacée.
warvariuc