GraphQL, entenderlo y usarlo en producción

GraphQL, entenderlo y usarlo en producción
by Janeth Kent Date: 20-02-2019 javascrypt nosql graphql node rest

A estas alturas, es probable que ya hayas escuchado el término GraphQL en conversaciones con otros desarrolladores.

Al igual que cualquier tecnología nueva y genial, se ha convertido en la "Next Big Thing"a que "tienes que estar usando".

Bueno, tal vez. GraphQL es genial y tiene su lugar, pero antes de que te dediques a integrarlo en tu pila de productos, es importante entender qué es, por qué es importante y cómo puede ayudar a tu producto específicamente.

¿Qué es GraphQL?

GraphQL son las siglas de Graph Query Language.

En su esencia, esto es lo que GraphQL es en realidad: un lenguaje para escribir consultas de datos estandarizadas. Aunque el nombre se usa para referirse a una colección de convenciones:

Ejemplo de GraphQL Query

{
  documents {
    title
    body    
  }
}

Esta es una consulta GraphQL. Aunque no lo parezca, este código dice "Quiero que me devuelvan una serie de documentos y sólo quiero el title y el campo del body de cada uno". Traducción:

Ejemplo de respuesta a una consulta GraphQL

{
  "data": {
        "documents": [
            {
                title: "El gran día en la playa de Mark Zuckerberg",
                body: "Poco sabía Mark que le esperaba un maravilloso mundo de caprichos...."            
            },
            {
                title: "EL Xilófono del Zoo de Zuck",
                body: "Los sonidos son brillantes y enloquecen al mismo tiempo! Jh, ja!"            
            }       
        ]   
    }
}

Lo que es mágico de esto es que en teoría, podemos reescribir esta misma consulta para que se vea así sin tocar ningún código backend:

Otro ejemplo de GraphQL Query

{
  documents {
    _id
    title
    createdAt
    user {
      name
      emailAddress
    }
  }
}

Si alguna vez has conectado la lógica para hacer que una interfaz de usuario hable con una base de datos, esto probablemente te intriga bastante.

La razón es que, aunque se trata de un pequeño cambio —todavía estamos pidiendo una serie de documentos con ciertos campos—, hemos introducido un campo anidado, user (aquí, el usuario que creó el documento).

Tradicionalmente, cuando queremos hacer algo así, tenemos que hacer una de las dos cosas:

  1. Escribir un endpoint de la API o alguna lógica del lado del servidor específica para esta consulta exacta que devuelva cada uno de nuestros documentos con un usuario a la cola.
  2. Realizar múltiples llamadas a nuestra API/base de datos y luego combinar los datos de nuestro cliente.

Con GraphQL, podemos omitir todo esto y obtener todos nuestros datos en una sola solicitud. En otras palabras, nos permite pedir exactamente lo que necesitamos —y nada más— cuando lo necesitamos sin tener que escribir una lógica excesivamente rígida en el servidor para satisfacer esas peticiones.

Entender el Esquema

Para escribir consultas GraphQL, necesitamos un servidor GraphQL que las entienda y pueda responder a ellas.

Aunque "GraphQL Server" puede sonar como el apodo que Mark Zuckerberg usa para su infernal máquina que secuestra a miles de jóvenes, en realidad es sólo un buen servidor HTTP antiguo con un endpoint que acepta peticiones POST.

La mayoría de las veces, está activo en /graphql donde el servidor se define como http://localhost:3000/graphql or http://miservidorgraphql.ma-no.org/graphql.

Adjunto a ese servidor está lo que llamamos el esquema (schema). Un esquema se compone de dos partes distintas, TypeDefs y Resolvers:

Type Definitions [TypeDefs] (definiciones de tipo)

Las Type Definitions o definiciones de tipo son descripciones detalladas de los trozos de datos en nuestra aplicación y las "posibilidades" de interactuar con esos datos a través del lenguaje de consulta que vimos anteriormente. Por ejemplo, es posible que tenga un tipo (type) User....

type Avatar {
  url: String
  altText: String
}

type User {
  name: String
  emailAddress: String
  avatar: Avatar
  username: String
}

o un tipo (type) Tweet como este:

type Tweet {
  user: User
  createdAt: String
  tweet: String
  retweets: Int
  favorites: Int
}

Lo que notarás de los tipos es que pueden estar entrelazados. Aquí tenemos un tipo User que tiene una propiedad avatar igual a un tipo objeto anidado (nested object type) Avatar. En la misma línea, el tipo Tweet de arriba que tiene un campo user que apunta al tipo User.

Resolvers (Resolvedores)

Los Resolvers (Resolvedores) son funciones que responden y "resuelven" nuestras peticiones, confiando en las definiciones de tipo para entender lo que es y lo que no es una respuesta correctamente formada. Los resolvers son sólo funciones. Cuando una petición llega a nuestro servidor GraphQL que coincide con un resolver dado, se llama a esa función y se ejecuta la lógica que contiene.

Un resolver viene en tres formas diferentes o tipos de "root" (raiz): Query, Mutation, y Subscription.

Para que un resolver sea reconocido en nuestro esquema, debe ser definido de dos maneras: en su tipo de "root" (raíz) y como la función real que resolverá una petición.

Definición de Standalone Type y de Query Root Type (tipo autónomo y del tipo de consulta raíz)

type Document {
  _id: String
  title: String
  createdAt: String
  updatedAt: String
  body: String
  owner: String
}

type Query {
  documents(owner: String): [Document]
}

Aquí, mostramos un ejemplo del tipo `Document` definido junto a uno de los tres tipos de raíz `Query`. A cada tipo de raíz se le asignan los "fields" (campos) o resolvers que soporta el esquema. Aquí, vemos un field/resolver de documentos similar a nuestro ejemplo anterior, diciendo que devuelve una matriz del tipo `Document` y soporta un argumento llamado `owner` que puede ser pasado como `String`.

Con nuestro root Query type definido, añadiendo en nuestra documents resolver coincidente, nuestro esquema terminaría siendo algo así:

import gql from 'graphql-tag';

const schema = {
  typeDefs: gql`
    type Document {
      _id: String
      title: String
      createdAt: String
      updatedAt: String
      body: String
      owner: String
    }

    type Query {
      documents(owner: String): [Document]
    }
  `,
  resolvers: {
    Query: {
      documents: (parent, args, context) => {
        return db.mongodb
          .collection('Documents')
          .find({})
          .toArray();
      },
    },
  },
};

En este esquema de ejemplo, la "Q" mayuscula Query en la cadena typeDefs coincide con la "Q" mayuscula Query en el objecto resolvers que está justo por debajo. Los documents definidos dentro del type Query {}? Sí, que coincide con los documents definidos en el objeto Query dentro del objeto resolvers.

La idea aquí es que todo lo que hacemos en relación con nuestros datos está fuertemente mecanografiado y estructurado. Como principiante que puede parecer odioso, trivial y excesivo, pero en la práctica el trabajo extra que estamos haciendo aquí es una gran ayuda para el progreso posterior.

Para atar un bonito lazo alrededor de todo lo anterior, podemos introducir los otros dos tipos de raíz adicionales más allá de Query: Mutation y Subscription. A primera vista, los conceptos para definirlos son similares; es sólo en el contenido de sus resolvers donde vemos las diferencias.

import gql from 'graphql-tag';

const schema = {
  typeDefs: gql`
    type Document {
      _id: String
      title: String
      createdAt: String
      updatedAt: String
      body: String
      owner: String
    }

    type Query {
      documents(owner: String): [Document]
    }

    type Mutation {
      updateDocument(_id: String!, title: String, body: String): Document
    }

    type Subscription {
      documentUpdated: Document
    }
  `,
  resolvers: {
    Query: {
      documents: (parent, args, context) => {
        // Just for example. `db.mongodb` is not defined on the context by default.
        return context.db.mongodb
          .collection('Documents')
          .find({})
          .toArray();
      },
    },
    Mutation: {
      updateDocument: (parent, args, context) => {
        context.db.mongodb
          .collection('Documents')
          .update({ _id: args._id }, { $set: args });
        // Just for example. `pubsub` is not defined on the context by default.
        context.pubsub.publish('documentUpdated', args);
        return args;
      },
    },
    Subscription: {
      documentUpdated: {
        subscribe: (root, args, context) => context.pubsub.asyncIterator('documentUpdated'),
      },
    },
  },
};

Aunque no vamos a entrar en los detalles de lo que está pasando aquí, lo que podemos decir es que lo anterior es un ejemplo de un esquema de GraphQL simple, pero completo.

Lo que estamos dejando aquí es la implementación del lado del cliente. La razón es que una vez que llegas al cliente, la forma de realizar tus consultas depende de ti. Al momento de escribir, las dos soluciones más populares son Apollo y Relay. Sin embargo, estas son sólo librerías de lujo que ayudan a acelerar el consumo de una API GraphQL. También puedes hacer una petición HTTP POST a tu servidor GraphQL y hacerla bastante compleja y de buen nivel.

Vale, entonces, ¿por qué es GraphQL importante de nuevo?

Lo que probablemente hayas notado sobre GraphQL y su ciclo de publicidad es que fue rápidamente adoptado por grandes organizaciones. Estamos hablando de corporaciones grandes como: Airbnb, The New York Times y Ticketmaster, entre otros.

Lo que esas personas "consiguieron" con GraphQL va más allá del costo de la inversión inicial para empezar con ella. Una explicación totalmente tonta y específica del contexto podría leerse como "GraphQL es lo que React fue para construir interfaces con JavaScript".

Nos crea estructuras

Si has escrito cualquier tipo de API antes, ya sea una API REST o una interna basada en ORM, es probable que hayas llegado a un cierto tamaño de aplicación en el que las cosas se pongan un poco difíciles si no ha pensado mucho al principio. Todos hemos tenido que añadir ese punto final extra para esa extraña petición que un tipo en Arizona necesita para su informe de marketing. O, menos románticamente, todos hemos sido el perezoso que añade spaguetti code extra sólo para hacer que nuestra interfaz de usuario funcione y terminar por hoy.

Nos da un lenguaje estándar para interactuar con los datos (y con nuestro equipo).

Atrás quedaron los días en que había que aprender varios idiomas sólo para consultar algunos datos. Una aplicación puede usar un adaptador especial de base de datos mientras que otra simplemente hace peticiones HTTP usando "algún paquete que un freelance usó una vez hace unos años y nosotros simplemente lo dejamos".

En cambio, GraphQL nos da un lenguaje único para escribir consultas e interactuar con datos que son agnósticos a la plataforma.

Donde esto se vuelve aún más valioso es en el contexto de un equipo. En lugar de que todos tengan que aprender un montón de herramientas y técnicas diferentes o interpretar tu explicación de "sí, pasé como 12 segundos en este ejemplo artificial", pueden usar una sintaxis simple y sucia para comunicar sus deseos/necesidades (para la gente de la parte delantera) y sus posibilidades (para la gente de la parte trasera).

Una buena manera de pensar es que GraphQL es como el esperanto de los datos, pero con objetivos más realistas de adopción.

Nos permite interactuar con múltiples fuentes de datos

Similar a lo anterior pero lo suficientemente diferente para una mención especial, quizás uno de los usos más ordenados de GraphQL es estandarizar la comunicación con múltiples fuentes de datos. Dependiendo de lo que estés construyendo (y con quién), es posible que tengas que soportar una base de datos MySQL heredada y una antigua API SOAP que se está desmoronando como una bruja a la luz del día, o un nuevo y moderno software de blockchain.

Mientras que sigues siendo responsable de traer los adaptadores, GraphQL-y más específicamente, su esquema-evitarás que tengas que reescribir la validación para todas esas diferentes fuentes de datos. Por no mencionar, que te ofrece una forma única y consistente de interactuar con ellos a través de los resolvers.

Nos da más oportunidades para mejorar el rendimiento

Mientras que ninguna tecnología ha cumplido realmente con sus promesas de rendimiento en un Box™, GraphQL nos da el potencial de reducir significativamente nuestro consumo de datos y ancho de banda para llegar a esos datos.

Como sugerimos anteriormente, una consulta GraphQL bien escrita puede abarcar un paquete de peticiones HTTP en una única petición. Eso no es nada para estornudar, ¿sabes?

Además, si estás acostumbrado a una plataforma en tiempo real como Meteor, el cambio de GraphQL a sólo permitir actualizaciones en tiempo real a través de suscripciones hace que su dependencia de la técnica sea mucho más consciente.

Hace que el consumo de datos de varios clientes sea muy sencillo.

Si estás construyendo múltiples aplicaciones que dependen de los mismos datos, GraphQL es un sueño hecho realidad.

Por ejemplo, digamos que estás escribiendo una aplicación como Twitter. En el cliente de escritorio, el aumento de los bienes inmuebles da a sus diseñadores espacio para añadir más información en pantalla. En un cliente móvil, sin embargo, los bienes raíces son muy caros, por lo que utilizan menos información.

Con GraphQL, ya no tenemos que tener puntos finales de API específicos para web o móviles ni preocuparnos por enviar más datos de los necesarios para que el cliente los consuma. Sólo pedimos lo que necesitamos en ese contexto exacto y dejamos que nuestro esquema GraphQL se encargue de ello por nosotros.

¿Por qué no debería usar GraphQL?

Aunque hemos pasado la mayor parte de este post discreto convenciéndote de por qué deberías usar GraphQL, sería irresponsable de nuestra parte unirnos al carro y dejar fuera algunos contrapuntos.

Eres un noobie de Web Dev.

Realmente: GraphQL es complejo. Estoy seguro de que un tonto de San Francisco se quejó con esa frase, pero es verdad. Comparado con las peticiones HTTP de vainilla o algo así como las publicaciones y suscripciones de Meteor, tiene más piezas móviles.

Si eres un noob total para el desarrollo web, probablemente es mejor evitar GraphQL por ahora. En cambio, sería bueno aprender los medios fundamentales para leer datos en su aplicación, como las peticiones HTTP. No es glamoroso y no te llevarás a cabo una reunión sobre los hombros de nadie, pero aprenderás por qué algo como GraphQL tiene mérito.

Sólo estás buscando perder el tiempo

Debido a que GraphQL viene con varias partes móviles, puede ser un paraíso para la gente a la que le gusta jugar. Debido a que le permite ser tan granular, usted puede potencialmente pasar mucho tiempo afinando realmente sus tipos y consultas sin mucha necesidad de hacerlo.

Si estás construyendo una aplicación que un pequeño número de personas usa regularmente, es probable que sea exagerada a menos que esa aplicación tenga una tonelada de datos corriendo a través de ella.

Quieres llevar la camiseta de la band y conocer sus canciones.

Mira. Seré sincero contigo. En la escuela secundaria tenía rastas y compré algunos brazaletes de púas porque pensé que los niños pálidos me querrían más. En muchos casos, el uso de GraphQL puede ser el fumar cigarrillos fuera del gimnasio de desarrollo web.

Si sólo estás tratando de llamar la atención y decir que eres uno de los niños geniales, probablemente es mejor guardar GraphQL para los proyectos de fin de semana y después del trabajo de tallarines en lugar de una proclamación para "reescribirlo todo".

Ninguna de las cosas técnicas anteriores te hizo menearte en tu asiento.

Es seguro decir que puedes lograr todo lo que GraphQL hace usando una API REST tradicional. Te llevará más trabajo, sin duda, pero si has pasado una cantidad decente de tiempo con un sistema de datos específico y te sientes totalmente cómodo y productivo con él: sigue bebiendo.

Si estás contento con tu configuración actual y tu sustento no depende de saber lo último y lo mejor, es mejor que hagas lo tuyo y llegues a GraphQL cuando tengas algo de tiempo para hacer fideos.

Adelante y GraphQL

No hay duda de que GraphQL jugará un papel no trivial en el futuro de los productos de construcción. Si usted tiene el tiempo, los recursos, y/o la necesidad, definitivamente vale la pena aprender y tomar la oportunidad de construir algo con ellos..

 
by Janeth Kent Date: 20-02-2019 javascrypt nosql graphql node rest visitas : 10568  
 
Janeth Kent

Janeth Kent

Licenciada en Bellas Artes y programadora por pasión. Cuando tengo un rato retoco fotos, edito vídeos y diseño cosas. El resto del tiempo escribo en MA-NO WEB DESIGN AND DEVELOPMENT.

 
 
 

Artículos relacionados

Node.js: herramientas de código abierto para los desarrolladores

De la amplia gama de herramientas disponibles para simplificar el desarrollo de Node.js, aquí están las mejores. Una encuesta en StackOverflow afirma que el 49% de los desarrolladores usan Node.js para…

Vue.js - Cómo usar (con seguridad) un plugin de jQuery con Vue.js

No es una buena idea usar jQuery y Vue.js en la misma interfaz. No lo hagas si puedes evitarlo, pero probablemente si estás leyendo esto no porque quieras usar jQuery…

Como construir una web application con Styled Components en Vue.js

Styled-Components es una biblioteca muy popular dentro de la comunidad React y React Native, y ahora puedes usarla en Vue.js. Para aquellos que no lo saben, Styled-Components es una biblioteca muy…

Cómo convertirte en un desarrollador web actual

Hay un montón de tutoriales en línea completamente gratis. Si eres lo suficientemente autodirigido e interesado, no tienes ninguna dificultad para entrenarte a ti mismo. El punto para aprender a…

Los Mejores Recursos de Node.js, Cursos y Tutoriales

NodeJS es una plataforma que permite a los desarrolladores escribir aplicaciones de alto rendimiento y en red en el lado del servidor. Y usando el buen y viejo Javascript también.…

Las mejores librerías JavaScript 2018

Javascript sigue siendo el lenguaje de programación más popular y utilizado en 2018. El ecosistema a su alrededor està sigue creciendo sigue creciendo y el número de frameworks y librerías que…

node.js: 13 enlaces para empezar a programar

Estos enlaces tratarán de responder a los que es Node.js, cómo funciona, cómo ejecutar una aplicación simple y, finalmente, dónde Node es una buena solución. Gracias a los enlaces podrás…

Ejemplo completo de CRUD con Redux y React

El objetivo de este artículo es explicar los conceptos básicos de Redux mediante una aplicación CRUD. La mayoría de las aplicaciones son aplicaciones CRUD. Si no sabes lo que CRUD…

Wordpress pasa a Node.js con Calypso

Hoy el popular sitio de blogs WordPress.com dio a conocer una nueva interfaz de administración actual de la gestión de blogs, publicación de contenido, y lectura de sitios de otras…

YouPorn: El desarrollo tecnológico para el mundo del porno

The Internet is for porn. Esto es un axioma innegociable. Las webs porno más importantes reciben millones de visitas al día y tienen que servir gigas y gigas de vídeo…

Clicky