paint-brush
Cuando es hora de darle un descanso al DESCANSOpor@johnjvester
2,255 lecturas
2,255 lecturas

Cuando es hora de darle un descanso al DESCANSO

por John Vester13m2024/05/13
Read on Terminal Reader

Demasiado Largo; Para Leer

Este artículo compara las API GraphQL y REST para la recuperación de datos y muestra cómo la flexibilidad y eficiencia de GraphQL sobresalen en escenarios complejos. Detalla la implementación de Apollo Server con Heroku y muestra el próximo contenido sobre autenticación y datos en tiempo real en GraphQL.
featured image - Cuando es hora de darle un descanso al DESCANSO
John Vester HackerNoon profile picture
0-item
1-item


A lo largo de mis años de creación de servicios, la API RESTful ha sido mi principal opción. Sin embargo, aunque REST tiene sus ventajas, eso no significa que sea el mejor enfoque para cada caso de uso. A lo largo de los años, he aprendido que, en ocasiones, puede haber mejores alternativas para determinados escenarios. Seguir con REST solo porque me apasiona (cuando no es la opción adecuada) solo resulta en deuda tecnológica y una relación tensa con el propietario del producto.


Uno de los mayores puntos débiles del enfoque RESTful es la necesidad de realizar múltiples solicitudes para recuperar toda la información necesaria para una decisión comercial.


Como ejemplo, supongamos que quiero una vista de 360 grados de un cliente. Necesitaría hacer las siguientes solicitudes:


  • GET /customers/{some_token} proporciona la información base del cliente
  • GET /addresses/{some_token} proporciona una dirección requerida
  • GET /contacts/{some_token} devuelve la información de contacto
  • GET /credit/{some_token} devuelve información financiera clave


Si bien entiendo que el objetivo subyacente de REST es mantener las respuestas enfocadas en cada recurso, este escenario requiere más trabajo por parte del consumidor. Sólo para crear una interfaz de usuario que ayude a una organización a tomar decisiones relacionadas con negocios futuros con el cliente, el consumidor debe realizar varias llamadas.


En este artículo, mostraré por qué GraphQL es el enfoque preferido sobre una API RESTful y demostraré cómo implementar Apollo Server (y Apollo Explorer) para comenzar a utilizar GraphQL rápidamente.


Planeo crear mi solución con Node.js e implementarla en Heroku.

Cuándo usar GraphQL sobre REST

Hay varios casos de uso comunes en los que GraphQL es un mejor enfoque que REST:


  • Cuando necesita flexibilidad en la forma de recuperar datos: puede recuperar datos complejos de varios recursos, pero todo en una sola solicitud . (Me sumergiré en este camino en este artículo).
  • Cuando el equipo de frontend necesita evolucionar la interfaz de usuario con frecuencia: los requisitos de datos que cambian rápidamente no requerirán que el backend ajuste los puntos finales y genere bloqueadores.
  • Cuando desea minimizar la recuperación excesiva y insuficiente : a veces, REST requiere que acceda a varios puntos finales para recopilar todos los datos que necesita (obtención insuficiente), o alcanzar un único punto final devuelve muchos más datos de los que realmente necesita (obtención excesiva). atractivo).
  • Cuando trabaja con sistemas complejos y microservicios: a veces, varias fuentes solo necesitan acceder a una única capa de API para sus datos. GraphQL puede proporcionar esa flexibilidad a través de una única llamada API .
  • Cuando necesita que le envíen datos en tiempo real: GraphQL presenta suscripciones , que brindan actualizaciones en tiempo real. Esto es útil en el caso de aplicaciones de chat o transmisiones de datos en vivo. (Cubriré este beneficio con más detalle en un artículo siguiente).

¿Qué es el servidor Apollo?

Como mis habilidades con GraphQL no están pulidas, decidí utilizar Apollo Server para este artículo.


Apollo Server es un servidor GraphQL que funciona con cualquier esquema GraphQL. El objetivo es simplificar el proceso de creación de una API GraphQL. El diseño subyacente se integra bien con marcos como Express o Koa. Exploraré la capacidad de aprovechar las suscripciones (a través de la biblioteca Graphql-ws ) para obtener datos en tiempo real en mi próximo artículo.


Donde realmente brilla Apollo Server es Apollo Explorer, una interfaz web integrada que los desarrolladores pueden utilizar para explorar y probar sus API GraphQL. El estudio será perfecto para mí, ya que permite la fácil construcción de consultas y la capacidad de ver el esquema API en formato gráfico.

Mi caso de uso de Customer 360

Para este ejemplo, supongamos que necesitamos el siguiente esquema para proporcionar una vista de 360 grados del cliente:


 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 }


Planeo centrarme en las siguientes consultas GraphQL:


 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 }


Los consumidores proporcionarán el token al Cliente que desean ver. También esperamos recuperar los objetos de Dirección, Contacto y Crédito correspondientes. El objetivo es evitar realizar cuatro llamadas API diferentes para toda esta información en lugar de realizar una sola llamada API.

Primeros pasos con el servidor Apollo

Comencé creando una nueva carpeta llamada graphql-server-customer en mi estación de trabajo local. Luego, utilizando la sección Primeros pasos de la documentación del servidor Apollo, seguí los pasos uno y dos utilizando un enfoque mecanografiado.


A continuación, definí mi esquema y también incluí algunos datos estáticos para realizar pruebas. Normalmente, nos conectaríamos a una base de datos, pero los datos estáticos funcionarán bien para esta demostración.


A continuación se muestra mi archivo index.ts actualizado:


 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 } ];


Con todo configurado como se esperaba, ejecutamos el siguiente comando para iniciar el servidor:


 $ npm start


Con el servidor Apollo ejecutándose en el puerto 4000, utilicé la URL http://localhost:4000/ para acceder a Apollo Explorer. Luego configuré la siguiente consulta de ejemplo:


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


Así es como se ve en Apollo Explorer:


Al presionar el botón Consulta de ejemplo , validé que la carga útil de respuesta estuviera alineada con los datos estáticos que proporcioné en 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" } ] } }


Antes de continuar abordando mi caso de uso de Customer 360, quería ejecutar este servicio en la nube.

Implementación del servidor Apollo en Heroku

Dado que este artículo trata sobre hacer algo nuevo, quería ver qué tan difícil sería implementar mi servidor Apollo en Heroku.


Sabía que tenía que abordar las diferencias en el número de puerto entre la ejecución local y la ejecución en algún lugar de la nube. Actualicé mi código para iniciar el servidor como se muestra a continuación:


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


Con esta actualización, usaremos el puerto 4000 a menos que haya un valor de PUERTO especificado en una variable de entorno.


Usando Gitlab, creé un nuevo proyecto para estos archivos e inicié sesión en mi cuenta de Heroku usando la interfaz de línea de comandos (CLI) de Heroku:


 $ heroku login


Puede crear una nueva aplicación en Heroku con su CLI o la interfaz de usuario web del panel de Heroku. Para este artículo, usaremos la CLI:


 $ heroku create jvc-graphql-server-customer


El comando CLI devolvió la siguiente respuesta:


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


El comando también agregó automáticamente el repositorio utilizado por Heroku como remoto:


 $ git remote heroku origin


De forma predeterminada, Apollo Server desactiva Apollo Explorer en entornos de producción. Para mi demostración, quiero dejarla ejecutándose en Heroku. Para hacer esto, necesito configurar la variable de entorno NODE_ENV en desarrollo. Puedo configurar eso con el siguiente comando CLI:


 $ heroku config:set NODE_ENV=development


El comando CLI devolvió la siguiente respuesta:


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


Ahora estamos en condiciones de implementar nuestro código en Heroku:


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


Una vista rápida del Panel de Heroku muestra mi servidor Apollo ejecutándose sin ningún problema:


Si es nuevo en Heroku, esta guía le mostrará cómo crear una nueva cuenta e instalar Heroku CLI.

Criterios de aceptación cumplidos: ejemplo de Mi cliente 360

Con GraphQL, puedo cumplir con los criterios de aceptación para mi caso de uso de Customer 360 con la siguiente consulta:


 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 } }


Todo lo que necesito hacer es pasar una única variable token de Cliente con un valor de customer-token-1 :


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


Podemos recuperar todos los datos utilizando una única llamada a la 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 } } }


A continuación se muestra una captura de pantalla de Apollo Explorer ejecutándose desde mi aplicación Heroku:


Conclusión

Recuerdo que al principio de mi carrera Java y C# competían entre sí por la adopción por parte de los desarrolladores. Los defensores de cada lado del debate estaban listos para demostrar que la tecnología que eligieron era la mejor opción... incluso cuando no lo era.


En este ejemplo, podríamos haber cumplido con mi caso de uso de Customer 360 de varias maneras. Usar una API RESTful probada habría funcionado, pero habría requerido múltiples llamadas a la API para recuperar todos los datos necesarios. Usar Apollo Server y GraphQL me permitió alcanzar mis objetivos con una sola llamada API.


También me encanta lo fácil que es implementar mi servidor GraphQL en Heroku con solo unos pocos comandos en mi terminal. Esto me permite concentrarme en la implementación: descargar las cargas de la infraestructura y ejecutar mi código en un proveedor externo confiable. Lo más importante es que esto coincide perfectamente con mi declaración de misión personal:


“Concentre su tiempo en ofrecer características/funcionalidades que amplíen el valor de su propiedad intelectual. Aproveche los marcos, productos y servicios para todo lo demás”.

– J. Vester


Si está interesado en el código fuente de este artículo, está disponible en GitLab .


¡Pero espera hay mas!


En mi publicación de seguimiento, desarrollaremos aún más nuestro servidor GraphQL para implementar la autenticación y la recuperación de datos en tiempo real con suscripciones.


¡Que tengas un gran día!