Architectuur
ArchitectuurCode-first GraphQL-server

Code-first GraphQL-server

Het GraphQL-schema definieert de contracten voor een GraphQL-service door de set typen, velden en mutaties te exporteren die tegen de service kunnen worden uitgevoerd. Bij het maken van een GraphQL-service kun je kiezen voor:

  • het schema als bron van waarheid gebruiken en alle implementatiecode laten aansluiten op de definities ervan
  • de code als bron van waarheid gebruiken en het schema als een artefact uit de code laten genereren

In beide gevallen krijg je een volledig werkende GraphQL-service, maar afhankelijk van de gekozen aanpak kun je in de toekomst meer of minder functies realiseren, met meer of minder gemak. Deze twee aanpakken worden respectievelijk "schema-first" (beter: "SDL-first") en "code-first" genoemd.

Gato GraphQL gebruikt de code-first aanpak. Laten we kijken waarom dat zo is.

Waarom Gato GraphQL code-first gebruikt

Bij de code-first aanpak begin je met het coderen van de resolvers en vervolgens — met de code als enige bron van waarheid — wordt het schema als artefact gegenereerd. Het schema wordt dus aangemaakt door een script uit te voeren, in plaats van handmatig te worden aangemaakt zoals bij SDL-first. Omdat code-first ook een schema heeft, mist het niets wezenlijks wat SDL-first biedt.

Code-first biedt echter een belangrijke functie ten opzichte van SDL-first: de mogelijkheid om dynamische schema's te leveren die hun vorm en attributen kunnen wijzigen afhankelijk van de context, en die via code tijdens de uitvoering worden geregeld. Alle geweldige functies die Gato GraphQL biedt, zijn inderdaad een direct gevolg van het omarmen van code-first.

Voordelen van code-first

Een dynamisch schema biedt onder meer alle onderstaande voordelen:

De bron van waarheid voor het schema is een superset van wat GraphQL vereist. De extra eigenschappen (zoals globale velden, globale verbindingen, globale directives en persistente fragmenten) kunnen al in onze API worden gebruikt zonder te hoeven wachten tot ze aan de GraphQL-spec worden toegevoegd — als dat al ooit gebeurt.

Omdat de bron van waarheid niet aan het schema is gebonden, kunnen we elk schema voor elk ander systeem genereren: GraphQL is slechts een van de doelen. Zo kan er bijvoorbeeld een JSON-schema voor een REST-service worden gegenereerd vanuit dezelfde bron van waarheid.

De API kan tegelijkertijd publiek/privaat zijn, afhankelijk van of de gebruiker is ingelogd of niet en van de rollen van de ingelogde gebruiker, of meer of minder velden aanbieden afhankelijk van een andere eigenschap, zoals of de gebruiker een PRO-lidmaatschap heeft gekocht.

Typen weten niet van tevoren welke velden ze zullen resolven. In plaats daarvan koppelen field resolvers zich aan type resolvers via het publish-subscribe patroon, en field resolvers kunnen andere field resolvers overschrijven. Deze eigenschap maakt de API zeer uitbreidbaar, waardoor we algemene code voor onze API kunnen hebben en deze op applicatieniveau kunnen aanpassen voor een specifieke client of project.

Een veld kan worden verwerkt door niet slechts één, maar door meerdere field resolvers: elke field resolver in de keten kan tijdens de uitvoering beslissen of het veld op basis van een eigenschap verwerkt wordt, of doorgestuurd wordt in de keten. Een speciale field resolver kan bijvoorbeeld alleen worden gebruikt als het veldargument "source: testing" wordt meegegeven, zodat het op een paar productiesites getest kan worden vóór de algemene release; dezelfde strategie maakt het ook mogelijk om snel bugfixes te leveren voor een specifieke client of omgeving zonder het risico van onbedoelde neveneffecten elders.

Typen en interfaces kunnen automatisch worden voorzien van namespaces om conflicten met externe bibliotheken te voorkomen.