Contesto della richiesta globale - anti-pattern?

11

Oggi stavo parlando con un mio collega sui framework web Python e le nostre impressioni su di loro. Gli ho detto che penso che Flask avere una richiesta globale abbia un cattivo odore ed è un anti-pattern.

I documenti dicono sul contesto della richiesta:

In contrast, during request handling, a couple of other rules exist:

  • while a request is active, the context local objects (flask.request and others) point to the current request.
  • any code can get hold of these objects at any time.

Penso di capire l'idea alla base di questa decisione progettuale - per semplificare l'applicazione. È solo un compromesso, come nel caso di Thread locals :

Yes it is usually not such a bright idea to use thread locals. They cause troubles for servers that are not based on the concept of threads and make large applications harder to maintain. However Flask is just not designed for large applications or asynchronous servers. Flask wants to make it quick and easy to write a traditional web application.

Si sta rattoppando un oggetto globale con le informazioni sulla richiesta corrente con un anti-pattern?

Credo che lo sia, perché è nell'ottica dell'analizzatore di codici statici uno stato globale, sebbene non lo sia. E io come programmatore non capirò come funziona senza leggere attentamente i documenti . E questo ha conseguenze sui test .

Non è una buona pratica passare la richiesta come argomento per le viste? Penso che sia più leggibile, esplicito e più facile da eseguire il debug. Ed evita lo stato globale.

    
posta warvariuc 11.03.2014 - 06:48
fonte

3 risposte

3

(Vado in grassetto e ne faccio una risposta, anche se potrei avere dei downvotes.)

Flask è una micro-struttura; approfittate della semplicità mentre rinunciate a fronzoli. Mentre sono a livello di pancia sono d'accordo con te, so che ho usato la fiaschetta + gunicorn in un negozio per darmi il multi-threading di cui avevo bisogno. Ha funzionato veramente bene. Ogni istanza dello script ha appena passato una richiesta (ad esempio un thread) e Gunicorn ha gestito il "fan out" tra più thread. È stato grandioso.

Quindi il lato negativo percepito che senti - che più thread potrebbero contendersi per lo stato globale - non è un problema, perché è uno script per thread.

(Qui è dove potrei finire nei guai) La discussione e la concorrenza sono diverse nel mondo Python, e se vieni con una mentalità Java, è difficile comprimerla. La mia esperienza era che i problemi di concorrenza che Ho dato per scontato in Java, o che sono gestiti in modo trasparente dal contenitore delle applicazioni, sono molto più vicini alla superficie in Python.

Per me era strano che un thread gestisse un'invocazione del mio script, ma dopo averne eseguito alcune dozzine contemporaneamente, mi sono sentito meglio.

    
risposta data 11.03.2014 - 07:24
fonte
3

Molti framework web hanno la stessa struttura: una richiesta globale. In un certo senso, è la cosa giusta da fare perché hey, c'è davvero solo una richiesta alla volta.

Quindi c'è un punto nel trasmettere la richiesta come parametro? No. La richiesta è la richiesta, ei parametri sono per passare in cose diverse in tempi diversi.

Il problema reale viene quando inizi a considerare i livelli inferiori di un'applicazione più grande. Con una richiesta globale c'è la tentazione di scrivere il codice ovunque che acceda la richiesta globalmente. Questa è una cosa molto brutta . Produce l'accoppiamento tra diverse parti del codice, rende difficile cambiare le cose e rende difficile testare le cose.

Quindi la mia risposta è: mantieni la richiesta globale e vivi con essa. Tuttavia, ogni volta che un singolo modulo o funzione non ha bisogno dell'intera richiesta, passa solo i dati di cui ha bisogno come parametro. Passa solo il referrer, o l'url, o il comando tail e qualsiasi bit necessario nelle tue funzioni. Ciò contribuirà a mantenere modulare il codice, ridurre l'accoppiamento e migliorare la testabilità.

Per piccoli programmi non ha importanza, ma per i più grandi questo può essere un vero risparmiatore.

    
risposta data 11.03.2014 - 11:17
fonte
2

In Python hai il comando print (funzione dalla v3) che stampa sullo standard output. Non specifichi esplicitamente che vuoi stampare su STDOUT: è fatto per te implicitamente dietro le quinte.

Implicitamente. In Python. E nessuno ha un problema con quello. Perché?

print fa parte del linguaggio Python, e un requisito per la programmazione in Python è ... beh ... conoscendo Python. E se conosci Python, sai che print bersaglia STDOUT. Nessuna sorpresa lì.

Python - come lingua - può definire la propria convenzione e assumere che i programmatori ne siano a conoscenza.

Anche i framework godono di questo privilegio - questa è una delle differenze chiave tra un framework e una libreria. Non è necessario imparare una libreria per utilizzarla: è sufficiente trovare la parte dell'API di cui si ha bisogno e assumere che segua le convenzioni del linguaggio (o framework). Ecco perché non vedi i reclutatori in cerca di persone con conoscenze in GSON o Apache Commons. Ma vedi i reclutatori in cerca di persone con esperienza con JQuery o Ruby on Rails o ASP.NET MVC - perché sono framework che definiscono le proprie convenzioni di cui hai bisogno per imparare ed essere a conoscenza.

Flask, come framework, può definire una convenzione per archiviare il contesto in un thread locale globale e non dovrebbe sorprendere nessuno, quindi non è un anti-pattern.

    
risposta data 11.03.2014 - 10:25
fonte

Leggi altre domande sui tag