Najlepsze praktyki w GraphQL
GraphQL jest wystarczająco dojrzały i obecny na rynku wystarczająco długo, by społeczność opublikowała wiele artykułów dotyczących najlepszych praktyk. Przewodniki te obejmują praktycznie wszystkie aspekty GraphQL, w tym projektowanie schema, konwencje nazewnictwa, obsługę bezpieczeństwa i dostarczanie sensownych błędów, między innymi.
Oto kilka najbardziej wartościowych przewodników na temat najlepszych praktyk w GraphQL.
Najlepsze praktyki na graphql.org
Oficjalna strona GraphQL oferuje ogólne wprowadzenie do najlepszych praktyk w GraphQL.
Te zagadnienia dotyczą głównie kwestii wysokiego poziomu, takich jak:
- Jaki jest najlepszy sposób na paginację wyników
- Gdzie warstwa GraphQL mieści się w architekturze
- Jak używać interfejsu Node do globalnej identyfikacji obiektów
- Jak buforować wyniki
- I wiele innych

Rekomendacje Lee Byrona
Niedługo po udostępnieniu GraphQL światu, twórca GraphQL Lee Byron opublikował artykuł Lessons From 4 Years of GraphQL, opisując, jak konceptualnie powinniśmy podchodzić do pracy z GraphQL:
- Nazewnictwo ma znaczenie
- Myśl w kategoriach grafów, nie endpointów
- Opisuj dane, nie widok
- GraphQL to lekki interfejs
- Ukrywaj szczegóły implementacji
Szczegółowo opisuje też kilka cennych zasad i lekcji, które wyciągnął z używania GraphQL w Facebooku.
GraphQL Rules
GraphQL Rules to strona specjalnie poświęcona prezentowaniu codziennych najlepszych praktyk pracy z GraphQL, dotyczących głównie projektowania schema GraphQL.
Ten zasób jest bardzo szczegółowy. Kompiluje informacje z kilku wyjątkowych źródeł (takich jak artykuł Designing GraphQL Mutations i samouczek Shopify Designing a GraphQL API) i przedstawia je wszystkie razem w zwięzły sposób.
Opisane reguły obejmują:
- Reguły nazewnictwa
- Używaj
camelCasedla pól i argumentów GraphQL. - Używaj
UpperCamelCasedla typów GraphQL. - Używaj
CAPITALIZED_WITH_UNDERSCORESdo nazewnictwa typów ENUM.
- Używaj
- Reguły typów
- Używaj niestandardowych typów skalarnych, jeśli chcesz zadeklarować pola lub argumenty o określonej wartości semantycznej.
- Używaj Enum dla pól zawierających określony zestaw wartości.
- Reguły pól (Output)
- Używaj semantycznych nazw dla pól i unikaj ujawniania szczegółów implementacji w nazwach pól.
- Używaj pola
Non-Null, jeśli pole zawsze będzie miało daną wartość. - Grupuj jak najwięcej powiązanych pól w niestandardowy typ obiektowy.
- Reguły argumentów (Input)
- Grupuj powiązane argumenty w nowy input-type.
- Używaj ścisłych typów skalarnych dla argumentów, np.
DateTimezamiastString. - Oznaczaj argumenty jako
required, jeśli są wymagane do wykonania queries.
- Reguły list
- Do filtrowania list używaj argumentu
filter, który zawiera wszystkie dostępne filtry. - Używaj argumentu
sorttypuEnumlub[Enum!]do sortowania list. - Używaj
limitz wartością domyślną iskip, aby ograniczyć liczbę zwracanych elementów na liście. - Używaj argumentów
page,perPagedo paginacji i zwracaj typ wyjściowy zitems(tablicą elementów) ipageInfo(metadanymi). - Dla nieskończonych list (nieskończone przewijanie) używaj Relay Cursor Connections Specification.
- Do filtrowania list używaj argumentu
- Reguły mutations
- Używaj Namespace-types do grupowania mutations w ramach jednego zasobu.
- Wychodź poza CRUD — twórz małe mutations dla różnych operacji biznesowych na zasobach.
- Rozważ możliwość wykonywania mutations na wielu elementach (batch zmiany tego samego typu).
- Mutations powinny jasno opisywać wszystkie obowiązkowe argumenty; nie powinno być opcji albo-albo.
- W mutations umieszczaj wszystkie zmienne w jednym unikalnym argumencie input.
- Każda mutation powinna mieć unikalny payload type.
Najlepsze praktyki dotyczące resolverów
Artykuł GraphQL Resolvers: Best Practices opisuje, jak najlepiej tworzyć resolvery pól. Choć jest skierowany do serwerów Node.js (infrastruktura PayPal oparta jest na Express), wiele jego lekcji można też zastosować do innych technologii, w tym PHP.
Główne wnioski to:
- Pobieranie i przekazywanie danych od rodzica do dziecka powinno być stosowane oszczędnie.
- Używaj bibliotek takich jak dataloader do deduplikacji żądań downstream.
- Bądź świadomy obciążenia, jakie nakładasz na swoje źródła danych.
- Nie mutuj "context". Zapewnia to spójny, mniej podatny na błędy kod.
- Pisz resolvery czytelne, łatwe w utrzymaniu i testowalnych. Nie za sprytne.
- Spraw, aby twoje resolvery były jak najcieńsze. Wyodrębnij logikę pobierania danych do wielokrotnie używanych funkcji async.
OWASP - GraphQL Cheat Sheet
OWASP (Open Web Application Security Project) to fundacja non-profit pracująca na rzecz poprawy bezpieczeństwa oprogramowania. Prowadzi badania nad podatnościami różnych technologii na exploity i szczegółowo opisuje rozwiązania problemów bezpieczeństwa, ułatwiając deweloperom zapobieganie atakom.
OWASP opublikowało GraphQL Cheat Sheet, wyjaśniając, jakie są najczęstsze ataki i największe problemy bezpieczeństwa w GraphQL oraz jak je rozwiązać.
Częste ataki na GraphQL to:
- Injection - zazwyczaj obejmuje, ale nie ogranicza się do:
- Injection SQL i NoSQL
- Injection poleceń systemu operacyjnego
- Injection SSRF i CRLF / Request Smuggling
- DoS (Denial of Service)
- Nadużycie złamanej autoryzacji: niewłaściwy lub nadmierny dostęp, w tym IDOR
- Batching Attacks, specyficzna dla GraphQL metoda ataku brute force
- Nadużycie niebezpiecznych domyślnych konfiguracji
OWASP następnie dostarcza rekomendacji, jak unikać każdego z tych przypadków.
Najlepsze praktyki z queries GraphQL
Zespół Apollo opublikował GraphQL query best practices, oferując praktyczne wskazówki dotyczące konkretnych sposobów komponowania queries GraphQL.
Na przykład te dwa queries osiągają ten sam cel, ale ponieważ pierwsze ma nazwę operacji, jest bardziej zrozumiałe i pomocne podczas debugowania:
# Zalecane ✅
query GetBooks {
books {
title
}
}
# Niezalecane ❌
query {
books {
title
}
}Ich sugestie obejmują:
- Nadawaj nazwy wszystkim operacjom
- Używaj zmiennych do dostarczania argumentów GraphQL
- Pobieraj tylko potrzebne dane, tam gdzie ich potrzebujesz
- Używaj fragments do enkapsulacji powiązanych zestawów pól
- Pobieraj dane globalne i dane specyficzne dla użytkownika osobno
Wykorzystanie one graph
Również od zespołu Apollo pochodzi strona Principled GraphQL, która wyjaśnia, że GraphQL to nie tylko specyfikacja, ale — być może co ważniejsze — interfejs do interakcji z "grafem" danych naszej firmy.
Poprzez listę 10 zasad strona ta opisuje, jak w pełni wykorzystać pojedynczy graf:
- One Graph: twoja firma powinna mieć jeden ujednolicony graf, zamiast wielu grafów tworzonych przez każdy zespół.
- Federated Implementation: choć istnieje tylko jeden graf, implementacja tego grafu powinna być sfederowana między wieloma zespołami.
- Track the Schema in a Registry: powinno istnieć jedno źródło prawdy do rejestrowania i śledzenia grafu.
- Abstract, Demand-Oriented Schema: schema powinno działać jako warstwa abstrakcji zapewniająca elastyczność konsumentom, ukrywając jednocześnie szczegóły implementacji usług.
- Use an Agile Approach to Schema Development: schema powinno być budowane przyrostowo na podstawie rzeczywistych wymagań i ewoluować płynnie w czasie.
- Iteratively Improve Performance: zarządzanie wydajnością powinno być ciągłym, opartym na danych procesem, płynnie dostosowującym się do zmieniających się obciążeń queries i implementacji usług.
- Use Graph Metadata to Empower Developers: deweloperzy powinni być wyposażeni w bogatą świadomość grafu przez cały proces deweloperski.
- Access and Demand Control: przyznawaj dostęp do grafu na podstawie klienta i zarządzaj tym, co i jak klienci mogą uzyskać do niego dostęp.
- Structured Logging: rejestruj strukturalne logi wszystkich operacji grafu i wykorzystuj je jako główne narzędzie do rozumienia użycia grafu.
- Separate the GraphQL Layer from the Service Layer: przyjmij architekturę warstwową z funkcjonalnością grafu podzieloną na osobną warstwę, a nie wbudowaną w każdą usługę.