paint-brush
Quand il est temps de se reposerpar@johnjvester
2,364 lectures
2,364 lectures

Quand il est temps de se reposer

par John Vester13m2024/05/13
Read on Terminal Reader

Trop long; Pour lire

Cet article compare les API GraphQL et REST pour la récupération de données, montrant comment la flexibilité et l'efficacité de GraphQL excellent dans des scénarios complexes. Il détaille le déploiement d'Apollo Server avec Heroku et annonce le contenu à venir sur l'authentification et les données en temps réel dans GraphQL.
featured image - Quand il est temps de se reposer
John Vester HackerNoon profile picture
0-item
1-item


Au cours de mes années de création de services, l' API RESTful a été ma principale référence. Cependant, même si REST a ses avantages, cela ne signifie pas qu’il constitue la meilleure approche pour chaque cas d’utilisation. Au fil des années, j’ai appris que, parfois, il peut y avoir de meilleures alternatives pour certains scénarios. S'en tenir à REST simplement parce que cela me passionne (quand ce n'est pas la bonne solution) n'entraîne qu'une dette technologique et une relation tendue avec le propriétaire du produit.


L’un des plus gros problèmes de l’approche RESTful est la nécessité de faire plusieurs requêtes pour récupérer toutes les informations nécessaires à une décision commerciale.


À titre d'exemple, supposons que je souhaite une vue à 360° d'un client. Il me faudrait faire les demandes suivantes :


  • GET /customers/{some_token} fournit les informations de base sur le client
  • GET /addresses/{some_token} fournit une adresse requise
  • GET /contacts/{some_token} renvoie les informations de contact
  • GET /credit/{some_token} renvoie des informations financières clés


Même si je comprends que l'objectif sous-jacent de REST est de garder les réponses ciblées sur chaque ressource, ce scénario nécessite davantage de travail du côté du consommateur. Juste pour remplir une interface utilisateur qui aide une organisation à prendre des décisions liées aux futures activités avec le client, le consommateur doit passer plusieurs appels.


Dans cet article, je vais montrer ici pourquoi GraphQL est l'approche préférée par rapport à une API RESTful, en démontrant comment déployer Apollo Server (et Apollo Explorer) pour être opérationnel rapidement avec GraphQL.


Je prévois de créer ma solution avec Node.js et de déployer ma solution sur Heroku.

Quand utiliser GraphQL sur REST

Il existe plusieurs cas d'utilisation courants dans lesquels GraphQL constitue une meilleure approche que REST :


  • Lorsque vous avez besoin de flexibilité dans la façon dont vous récupérez des données : vous pouvez récupérer des données complexes à partir de diverses ressources, mais le tout en une seule requête . (Je vais approfondir ce chemin dans cet article.)
  • Lorsque l'équipe front-end doit faire évoluer fréquemment l'interface utilisateur : l'évolution rapide des exigences en matière de données n'exigera pas que le backend ajuste les points de terminaison et provoque des blocages.
  • Lorsque vous souhaitez minimiser la sur-récupération et la sous-récupération : Parfois, REST vous oblige à atteindre plusieurs points de terminaison pour collecter toutes les données dont vous avez besoin (sous-récupération), ou l'accès à un seul point de terminaison renvoie beaucoup plus de données que ce dont vous avez réellement besoin (sur-récupération). aller chercher).
  • Lorsque vous travaillez avec des systèmes et des microservices complexes : Parfois , plusieurs sources doivent simplement accéder à une seule couche API pour leurs données. GraphQL peut offrir cette flexibilité via un seul appel d'API .
  • Lorsque vous avez besoin de données en temps réel : GraphQL propose des abonnements , qui fournissent des mises à jour en temps réel. Ceci est utile dans le cas des applications de chat ou des flux de données en direct. (Je couvrirai cet avantage plus en détail dans un article de suivi.)

Qu'est-ce que le serveur Apollo ?

Étant donné que mes compétences avec GraphQL ne sont pas perfectionnées, j'ai décidé d'utiliser Apollo Server pour cet article.


Apollo Server est un serveur GraphQL qui fonctionne avec n'importe quel schéma GraphQL. L'objectif est de simplifier le processus de création d'une API GraphQL. La conception sous-jacente s'intègre bien aux frameworks tels que Express ou Koa. J'explorerai la possibilité de tirer parti des abonnements (via la bibliothèque graphql-ws ) pour des données en temps réel dans mon prochain article.


Là où Apollo Server brille vraiment, c'est Apollo Explorer, une interface Web intégrée que les développeurs peuvent utiliser pour explorer et tester leurs API GraphQL. Le studio me conviendra parfaitement, car il permet de construire facilement des requêtes et de visualiser le schéma de l'API dans un format graphique.

Cas d'utilisation de Mon client 360

Pour cet exemple, supposons que nous ayons besoin du schéma suivant pour fournir une vue à 360° du client :


 type Customer { token: String name: String sic_code: String } type Address { token: String customer_token: String address_line1: String address_line2: String city: String state: String postal_code: String } type Contact { token: String customer_token: String first_name: String last_name: String email: String phone: String } type Credit { token: String customer_token: String credit_limit: Float balance: Float credit_score: Int }


Je prévois de me concentrer sur les requêtes GraphQL suivantes :


 type Query { addresses: [Address] address(customer_token: String): Address contacts: [Contact] contact(customer_token: String): Contact customers: [Customer] customer(token: String): Customer credits: [Credit] credit(customer_token: String): Credit }


Les consommateurs fourniront le jeton au client qu'ils souhaitent voir. Nous prévoyons également de récupérer les objets Adresse, Contact et Crédit appropriés. Le but est d’éviter de faire quatre appels API différents pour toutes ces informations plutôt qu’avec un seul appel API.

Premiers pas avec le serveur Apollo

J'ai commencé par créer un nouveau dossier appelé graphql-server-customer sur mon poste de travail local. Ensuite, à l'aide de la section Prise en main de la documentation d'Apollo Server, j'ai suivi les étapes un et deux en utilisant une approche Typescript.


Ensuite, j'ai défini mon schéma et inclus également des données statiques à des fins de test. Normalement, nous nous connecterions à une base de données, mais les données statiques fonctionneront bien pour cette démo.


Vous trouverez ci-dessous mon fichier index.ts mis à jour :


 import { ApolloServer } from '@apollo/server'; import { startStandaloneServer } from '@apollo/server/standalone'; const typeDefs = `#graphql type Customer { token: String name: String sic_code: String } type Address { token: String customer_token: String address_line1: String address_line2: String city: String state: String postal_code: String } type Contact { token: String customer_token: String first_name: String last_name: String email: String phone: String } type Credit { token: String customer_token: String credit_limit: Float balance: Float credit_score: Int } type Query { addresses: [Address] address(customer_token: String): Address contacts: [Contact] contact(customer_token: String): Contact customers: [Customer] customer(token: String): Customer credits: [Credit] credit(customer_token: String): Credit } `; const resolvers = { Query: { addresses: () => addresses, address: (parent, args, context) => { const customer_token = args.customer_token; return addresses.find(address => address.customer_token === customer_token); }, contacts: () => contacts, contact: (parent, args, context) => { const customer_token = args.customer_token; return contacts.find(contact => contact.customer_token === customer_token); }, customers: () => customers, customer: (parent, args, context) => { const token = args.token; return customers.find(customer => customer.token === token); }, credits: () => credits, credit: (parent, args, context) => { const customer_token = args.customer_token; return credits.find(credit => credit.customer_token === customer_token); } }, }; const server = new ApolloServer({ typeDefs, resolvers, }); const { url } = await startStandaloneServer(server, { listen: { port: 4000 }, }); console.log(`Apollo Server ready at: ${url}`); const customers = [ { token: 'customer-token-1', name: 'Acme Inc.', sic_code: '1234' }, { token: 'customer-token-2', name: 'Widget Co.', sic_code: '5678' } ]; const addresses = [ { token: 'address-token-1', customer_token: 'customer-token-1', address_line1: '123 Main St.', address_line2: '', city: 'Anytown', state: 'CA', postal_code: '12345' }, { token: 'address-token-22', customer_token: 'customer-token-2', address_line1: '456 Elm St.', address_line2: '', city: 'Othertown', state: 'NY', postal_code: '67890' } ]; const contacts = [ { token: 'contact-token-1', customer_token: 'customer-token-1', first_name: 'John', last_name: 'Doe', email: '[email protected]', phone: '123-456-7890' } ]; const credits = [ { token: 'credit-token-1', customer_token: 'customer-token-1', credit_limit: 10000.00, balance: 2500.00, credit_score: 750 } ];


Avec tout configuré comme prévu, nous exécutons la commande suivante pour démarrer le serveur :


 $ npm start


Avec le serveur Apollo fonctionnant sur le port 4000, j'ai utilisé l'URL http://localhost:4000/ pour accéder à Apollo Explorer. Ensuite, j'ai mis en place l'exemple de requête suivant :


 query ExampleQuery { addresses { token } contacts { token } customers { token } }


Voici à quoi cela ressemble dans Apollo Explorer :


En appuyant sur le bouton Exemple de requête , j'ai validé que la charge utile de la réponse était alignée sur les données statiques que j'avais fournies dans index.ts :


 { "data": { "addresses": [ { "token": "address-token-1" }, { "token": "address-token-22" } ], "contacts": [ { "token": "contact-token-1" } ], "customers": [ { "token": "customer-token-1" }, { "token": "customer-token-2" } ] } }


Avant d'aller plus loin dans mon cas d'utilisation Customer 360, je souhaitais exécuter ce service dans le cloud.

Déploiement du serveur Apollo sur Heroku

Puisque cet article vise à faire quelque chose de nouveau, je voulais voir à quel point il serait difficile de déployer mon serveur Apollo sur Heroku.


Je savais que je devais tenir compte des différences de numéros de port entre une exécution locale et une exécution quelque part dans le cloud. J'ai mis à jour mon code pour démarrer le serveur comme indiqué ci-dessous :


 const { url } = await startStandaloneServer(server, { listen: { port: Number.parseInt(process.env.PORT) || 4000 }, });


Avec cette mise à jour, nous utiliserons le port 4000 sauf si une valeur PORT est spécifiée dans une variable d'environnement.


À l'aide de Gitlab, j'ai créé un nouveau projet pour ces fichiers et je me suis connecté à mon compte Heroku à l'aide de l'interface de ligne de commande (CLI) Heroku :


 $ heroku login


Vous pouvez créer une nouvelle application dans Heroku avec leur CLI ou l'interface utilisateur Web du tableau de bord Heroku. Pour cet article, nous utiliserons la CLI :


 $ heroku create jvc-graphql-server-customer


La commande CLI a renvoyé la réponse suivante :


 Creating ⬢ jvc-graphql-server-customer... done https://jvc-graphql-server-customer-b62b17a2c949.herokuapp.com/ | https://git.heroku.com/jvc-graphql-server-customer.git


La commande a également ajouté automatiquement le référentiel utilisé par Heroku comme télécommande :


 $ git remote heroku origin


Par défaut, Apollo Server désactive Apollo Explorer dans les environnements de production. Pour ma démo, je souhaite la laisser fonctionner sur Heroku. Pour ce faire, je dois définir la variable d'environnement NODE_ENV sur development. Je peux définir cela avec la commande CLI suivante :


 $ heroku config:set NODE_ENV=development


La commande CLI a renvoyé la réponse suivante :


 Setting NODE_ENV and restarting ⬢ jvc-graphql-server-customer... done, v3 NODE_ENV: development


Nous sommes maintenant en mesure de déployer notre code sur Heroku :


 $ git commit --allow-empty -m 'Deploy to Heroku' $ git push heroku


Un aperçu rapide du tableau de bord Heroku montre que mon serveur Apollo fonctionne sans aucun problème :


Si vous êtes nouveau sur Heroku, ce guide vous montrera comment créer un nouveau compte et installer la CLI Heroku.

Critères d'acceptation respectés : exemple de Mon client 360

Avec GraphQL, je peux répondre aux critères d'acceptation de mon cas d'utilisation Customer 360 avec la requête suivante :


 query CustomerData($token: String) { customer(token: $token) { name sic_code token }, address(customer_token: $token) { token customer_token address_line1 address_line2 city state postal_code }, contact(customer_token: $token) { token, customer_token, first_name, last_name, email, phone }, credit(customer_token: $token) { token, customer_token, credit_limit, balance, credit_score } }


Tout ce que j'ai à faire est de transmettre une seule variable token Customer avec une valeur customer-token-1 :


 { "token": "customer-token-1" }


Nous pouvons récupérer toutes les données à l'aide d'un seul appel d'API GraphQL :


 { "data": { "customer": { "name": "Acme Inc.", "sic_code": "1234", "token": "customer-token-1" }, "address": { "token": "address-token-1", "customer_token": "customer-token-1", "address_line1": "123 Main St.", "address_line2": "", "city": "Anytown", "state": "CA", "postal_code": "12345" }, "contact": { "token": "contact-token-1", "customer_token": "customer-token-1", "first_name": "John", "last_name": "Doe", "email": "[email protected]", "phone": "123-456-7890" }, "credit": { "token": "credit-token-1", "customer_token": "customer-token-1", "credit_limit": 10000, "balance": 2500, "credit_score": 750 } } }


Vous trouverez ci-dessous une capture d'écran d'Apollo Explorer exécuté à partir de mon application Heroku :


Conclusion

Je me souviens plus tôt dans ma carrière, lorsque Java et C# se faisaient concurrence pour l'adoption par les développeurs. Les défenseurs des deux côtés du débat étaient prêts à prouver que la technologie qu'ils avaient choisie était le meilleur choix… même si ce n'était pas le cas.


Dans cet exemple, nous aurions pu répondre à mon cas d'utilisation Customer 360 de plusieurs manières. L'utilisation d'une API RESTful éprouvée aurait fonctionné, mais cela aurait nécessité plusieurs appels d'API pour récupérer toutes les données nécessaires. L'utilisation d'Apollo Server et de GraphQL m'a permis d'atteindre mes objectifs avec un seul appel API.


J'aime aussi la facilité avec laquelle déployer mon serveur GraphQL sur Heroku avec seulement quelques commandes dans mon terminal. Cela me permet de me concentrer sur la mise en œuvre, en déchargeant les charges de l'infrastructure et en exécutant mon code auprès d'un fournisseur tiers de confiance. Plus important encore, cela correspond parfaitement à ma déclaration de mission personnelle :


« Concentrez votre temps sur la fourniture de caractéristiques/fonctionnalités qui augmentent la valeur de votre propriété intellectuelle. Tirez parti des frameworks, des produits et des services pour tout le reste.

– J.Vester


Si vous êtes intéressé par le code source de cet article, il est disponible sur GitLab .


Mais attendez… il y a plus !


Dans mon article de suivi, nous développerons davantage notre serveur GraphQL, pour implémenter l'authentification et la récupération de données en temps réel avec les abonnements.


Passez une très bonne journée !