Risorse
RisorseBest practice GraphQL

Best practice GraphQL

GraphQL è abbastanza maturo, ed è presente da abbastanza tempo, da aver portato la community a pubblicare numerosi articoli che condividono best practice. Queste guide coprono praticamente tutti gli aspetti di GraphQL, tra cui la progettazione dello schema, le convenzioni di denominazione, la gestione della sicurezza e la fornitura di errori significativi.

Ecco alcune delle guide più autorevoli sulle best practice in GraphQL.

Best practice su graphql.org

Il sito ufficiale di GraphQL offre un'introduzione generale alle best practice in GraphQL.

Questi punti coprono principalmente preoccupazioni di alto livello, come:

Dove è posizionato il layer GraphQL all'interno dell'architettura

Le raccomandazioni di Lee Byron

Poco dopo aver presentato GraphQL al mondo, il creatore di GraphQL Lee Byron ha pubblicato l'articolo Lessons From 4 Years of GraphQL, descrivendo come dovremmo concettualmente cercare di lavorare con GraphQL:

  • Il naming è importante
  • Pensa in grafi, non in endpoint
  • Descrivi i dati, non la vista
  • GraphQL è un'interfaccia leggera
  • Nascondi i dettagli di implementazione

Illustra inoltre diversi principi e lezioni di valore appresi utilizzando GraphQL in Facebook.

GraphQL Rules

GraphQL Rules è un sito dedicato specificamente a presentare le best practice quotidiane per lavorare con GraphQL, riguardanti principalmente la progettazione dello schema GraphQL.

Questa risorsa è molto completa. Raccoglie le informazioni da alcune risorse eccezionali (come l'articolo Designing GraphQL Mutations e il tutorial di Shopify Designing a GraphQL API) e le presenta tutte insieme in modo conciso.

Le regole descritte includono:

  1. Regole di denominazione
    • Usa camelCase per i campi e gli argomenti GraphQL.
    • Usa UpperCamelCase per i tipi GraphQL.
    • Usa CAPITALIZED_WITH_UNDERSCORES per nominare i tipi ENUM.
  2. Regole dei tipi
    • Usa tipi scalari personalizzati se vuoi dichiarare campi o argomenti con un valore semantico specifico.
    • Usa Enum per i campi che contengono un insieme specifico di valori.
  3. Regole dei campi (Output)
    • Usa nomi semantici per i campi ed evita di far trapelare i dettagli di implementazione nei nomi dei campi.
    • Usa il campo Non-Null se il campo avrà sempre un valore dato.
    • Raggruppa il maggior numero possibile di campi correlati in un Object type personalizzato.
  4. Regole degli argomenti (Input)
    • Raggruppa gli argomenti correlati in un nuovo input-type.
    • Usa tipi scalari rigorosi per gli argomenti, ad es. DateTime invece di String.
    • Contrassegna gli argomenti come required se sono necessari per l'esecuzione della query.
  5. Regole delle liste
    • Per filtrare le liste, usa l'argomento filter, che contiene tutti i filtri disponibili.
    • Usa l'argomento sort di tipo Enum o [Enum!] per l'ordinamento delle liste.
    • Usa limit con un valore predefinito e skip per limitare il numero di elementi restituiti nella lista.
    • Usa gli argomenti page, perPage per la paginazione e restituisci un output type con items (array di elementi) e pageInfo (metadati).
    • Per le liste infinite (scroll infinito), usa la Relay Cursor Connections Specification.
  6. Regole delle mutation
    • Usa i Namespace-type per raggruppare le mutation all'interno di una singola risorsa.
    • Vai oltre il CRUD – crea mutation piccole per diverse operazioni di business sulle risorse.
    • Considera la possibilità di eseguire mutation su più elementi (modifiche batch dello stesso tipo).
    • Le mutation devono descrivere chiaramente tutti gli argomenti obbligatori, non devono esserci opzioni either-either.
    • Nelle mutation, inserisci tutte le variabili in un unico argomento input.
    • Ogni mutation deve avere un payload type univoco.

Best practice per i resolver

L'articolo GraphQL Resolvers: Best Practices descrive come creare al meglio i resolver dei campi. Sebbene sia rivolto ai server Node.js (l'infrastruttura di PayPal è basata su Express), diverse delle sue lezioni possono essere applicate anche ad altre tecnologie, incluso PHP.

I principali insegnamenti sono:

  • Il recupero e il passaggio di dati da genitore a figlio deve essere usato con parsimonia.
  • Usa librerie come dataloader per deduplicare le richieste downstream.
  • Sii consapevole della pressione che stai esercitando sulle tue sorgenti di dati.
  • Non mutare "context". Garantisce un codice coerente e meno soggetto a bug.
  • Scrivi resolver leggibili, manutenibili e testabili. Non troppo complessi.
  • Rendi i tuoi resolver il più leggeri possibile. Estrai la logica di recupero dei dati in funzioni async riutilizzabili.

OWASP - GraphQL Cheat Sheet

OWASP (Open Web Application Security Project) è una fondazione senza scopo di lucro che lavora per migliorare la sicurezza del software. Svolge ricerche su come diverse tecnologie siano vulnerabili agli exploit, e descrive in dettaglio soluzioni ai problemi di sicurezza, rendendo più facile per gli sviluppatori prevenire gli attacchi.

OWASP ha pubblicato la GraphQL Cheat Sheet, spiegando quali sono gli attacchi più comuni e i maggiori problemi di sicurezza in GraphQL, e come affrontarli.

Gli attacchi comuni a GraphQL sono:

  1. Injection - questo di solito include ma non si limita a:
    • Injection SQL e NoSQL
    • Injection di comandi OS
    • Injection SSRF e CRLF / Request Smuggling
  2. DoS (Denial of Service)
  3. Abuso di autorizzazione non funzionante: accesso improprio o eccessivo, incluso IDOR
  4. Batching Attacks, un metodo di attacco brute force specifico di GraphQL
  5. Abuso di configurazioni predefinite non sicure

OWASP fornisce quindi raccomandazioni su come evitare ciascuna di queste situazioni.

Best practice con le queries GraphQL

Il team di Apollo ha pubblicato le GraphQL query best practices, offrendo spunti pratici su come comporre la query GraphQL.

Ad esempio, queste due queries raggiungono lo stesso obiettivo, ma poiché la prima ha un nome di operazione, è più comprensibile e utile durante il debugging:

# Consigliato ✅
query GetBooks {
  books {
    title
  }
}
 
# Non consigliato ❌
query {
  books {
    title
  }
}

I loro suggerimenti includono:

  • Nominare tutte le operazioni
  • Usare variabili per fornire gli argomenti GraphQL
  • Interrogare solo i dati di cui hai bisogno, dove ne hai bisogno
  • Usare i fragment per incapsulare insiemi di campi correlati
  • Interrogare i dati globali e i dati specifici dell'utente separatamente

Sfruttare il one graph

Sempre dal team di Apollo, il sito Principled GraphQL spiega che GraphQL non è solo una specifica ma, forse più importante, un'interfaccia per interagire con il "grafo" dei dati della nostra azienda.

Attraverso un elenco di 10 principi, questo sito descrive come trarre il massimo dal grafo unico:

  1. One Graph: la tua azienda dovrebbe avere un grafo unificato, invece di molteplici grafi creati da ogni team.
  2. Federated Implementation: sebbene ci sia un solo grafo, l'implementazione di quel grafo dovrebbe essere federata tra più team.
  3. Track the Schema in a Registry: dovrebbe esserci un'unica fonte di verità per registrare e tracciare il grafo.
  4. Abstract, Demand-Oriented Schema: lo schema dovrebbe agire come un layer di astrazione che offre flessibilità ai consumatori nascondendo i dettagli di implementazione del servizio.
  5. Use an Agile Approach to Schema Development: lo schema dovrebbe essere costruito in modo incrementale sulla base di requisiti reali ed evolvere gradualmente nel tempo.
  6. Iteratively Improve Performance: la gestione delle prestazioni dovrebbe essere un processo continuo, basato sui dati, che si adatta progressivamente ai carichi di query e alle implementazioni dei servizi in evoluzione.
  7. Use Graph Metadata to Empower Developers: gli sviluppatori dovrebbero essere dotati di una ricca consapevolezza del grafo durante l'intero processo di sviluppo.
  8. Access and Demand Control: concedi l'accesso al grafo su base per-client, e gestisci cosa e come i client possono accedervi.
  9. Structured Logging: acquisisci log strutturati di tutte le operazioni del grafo e sfruttali come strumento principale per comprendere l'utilizzo del grafo.
  10. Separate the GraphQL Layer from the Service Layer: adotta un'architettura a strati con la funzionalità del grafo suddivisa in un livello separato piuttosto che integrata in ogni servizio.