graphql-go_GraphQL-好与坏

graphql-go

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API as well as gives clients the power to ask for exactly what they need and nothing more.

GraphQL是API的查询语言,是用于使用现有数据来完成这些查询的运行时。 GraphQL为您的API中的数据提供了完整且易于理解的描述,并且使客户有权要求他们确切需要什么,仅此而已。

It makes it easier to evolve APIs over time and enables powerful developer tools. At least that's what we all know it to be. In this post, we'll look at all the wonderful things about GraphQL and also look at the unpopular "not so good" things about it. Let's kick it off with the good parts :)

随着时间的推移,它使开发API变得更加容易,并启用了功能强大的开发人员工具。 至少那是我们所有人都知道的。 在这篇文章中,我们将研究有关GraphQL的所有奇妙事物,并研究它不受欢迎的“不太好”的事物。 让我们从好部分开始:)

善良 ( The Good )

确切的数据获取 ( Exact data fetching )

The importance and usefulness of GrphQL exact data fetching feature cannot be overemphasized. With GraphQL, you can send a query to your API and get exactly what you need, nothing more and nothing less. It's really that simple. If you compare this feature with the conventional intuitive nature of REST, you'll understand that this is a major improvement to the way we initially do things.

GrphQL精确数据获取功能的重要性和实用性不能过分强调。 使用GraphQL,您可以将查询发送到您的API并获得所需的信息,仅此而已。 真的就是这么简单。 如果将此功能与REST的传统直观特性进行比较,您将了解到,这是对我们最初的处理方式的重大改进。

GraphQL minimizes the amount of data which is transferred across the wire by being selective about the data depending on the client application’s needs. Thus, a mobile client can fetch less information, because it may not be needed on a small screen compared to the larger screen for the web application.

GraphQL通过根据客户端应用程序的需求选择数据,从而最大程度地减少了通过导线传输的数据量。 因此,移动客户端可以获取较少的信息,因为与Web应用程序的大屏幕相比,在小屏幕上可能不需要该信息。

So instead of multiple endpoints that return fixed data structures, a GraphQL server only exposes a single endpoint and responds with precisely the data a client requested.

因此,GraphQL服务器不是返回固定数据结构的多个端点,而是仅公开一个端点,并精确地响应客户端请求的数据。

Consider a situation where you want to call an API endpoint that has two resources, artists and their tracks. To be able to request for a particular artist or their music tracks, you will have an API structure like this:

考虑一种情况,您要调用一个具有两个资源的API端点,即艺术家及其足迹。 为了能够请求特定的艺术家或其音乐曲目,您将具有以下API结构:

METHOD /api/:resource:/:id:

With the traditional REST pattern, if we want to look up a list of every artist using the provided API, we would have to make a GET request to the root resource endpoint like this:

使用传统的REST模式,如果我们想使用提供的API查找每个艺术家的列表,则必须向根资源端点发出GET请求,如下所示:

GET /api/artists

What if we want to query for an individual artist from the list of artists? then we will have to append the resource ID to the endpoint like this:

如果我们要从艺术家列表中查询单个艺术家该怎么办? 那么我们将必须将资源ID附加到端点,如下所示:

GET /api/artists/1

In essence, we have to call two different endpoints to get the required data. With GraphQL, every request can be performed on one endpoint, with the actions being taken and data being returned all defined within the query itself. Let's say we want to get an artisits track and duration, with GraphQL, we'll have a query like this:

本质上,我们必须调用两个不同的端点来获取所需的数据。 使用GraphQL,可以在一个端点上执行每个请求,并在查询本身中定义所有动作和返回数据。 假设我们要获取一个工匠跟踪和持续时间,使用GraphQL,我们将有一个类似以下的查询:

GET /api?query={ artists(id:"1") { track, duration } }

This query instructs the API to look up an artist with the ID of 1 and then return its track and duration which is exactly what we wanted, no more, no less. This same endpoint can also be used to perform actions within the API as well.

此查询指示API查找ID为1的艺术家,然后返回其曲目和持续时间,这正是我们想要的内容,不多也不少。 该端点也可以用于在API中执行操作。

一个请求,很多资源 ( One request, many resources )

Another useful feature of GraphQL is that it makes it simple to fetch all required data with one single request. The structure of GraphQL servers makes it possible to declaratively fetch data as it only exposes a single endpoint.

GraphQL的另一个有用功能是,它使通过单个请求获取所有必需的数据变得简单。 GraphQL服务器的结构使声明式获取数据成为可能,因为它仅公开一个端点。

Consider a situation where a user wants to request for the details of a particular artist, say (name, id, tracks etc). With the traditional REST intuitive pattern, this will require at least two requests to two endpoints /artists and /tracks. However, with GraphQL, we can define all the data we need in the query as shown below:

考虑一种情况,用户想要请求特定艺术家的详细信息,例如(姓名,ID,曲目等)。 使用传统的REST直观模式,这将至少需要两个端点/artists/tracks两个请求。 但是,使用GraphQL,我们可以定义查询中需要的所有数据,如下所示:

// thequery request

artists(id: "1") {
  id
  name
  avatarUrl
  tracks(limit: 2) {
    name
    urlSlug
  }
}

Here, we have defined a single GraphQL query to request for multiple resources (artists and tracks). This query will return all and only the requested resources like so:

在这里,我们定义了一个GraphQL查询来请求多种资源(艺术家和曲目)。 该查询将仅返回所有请求的资源,如下所示:

// the query result{
  "data": {
    "artists": {
      "id": "1",
      "name": "Michael Jackson",
      "avatarUrl": "https://artistsdb.com/artist/1",
      "tracks": [
        {
          "name": "Heal the world",
          "urlSlug": "heal-the-world"
        },
        {
          "name": "Thriller",
          "urlSlug": "thriller"
        }
      ]
    }
  }
}

As can be seen from the response data above, we have fetched the resources for both /artists and /tracks with a single API call. This is a powerful feature that GraphQL offers. As you can already imagine, the applications of this feature for highly declarative API structures are limitless.

从上面的响应数据可以看出,我们已经通过一个API调用获取了/artists/tracks的资源。 这是GraphQL提供的强大功能。 您已经可以想象到,此功能在高度声明性的API结构中的应用是无限的。

现代兼容性 ( Modern compatibility )

Modern applications are now built in comprehensive ways where a single backend application supplies the data that is needed to run multiple clients. Web applications, mobile apps, smart screens, watches etc can now depend only on a single backend application for data to function efficiently.

现在,现代应用程序以全面的方式构建,其中单个后端应用程序提供了运行多个客户端所需的数据。 Web应用程序,移动应用程序,智能屏幕,手表等现在只能依靠单个后端应用程序来使数据有效运行。

GraphQL embraces these new trends as it can be used to connect the backend application and fulfill each client's requirements ( nested relationships of data, fetching only the required data, network usage requirements, etc.) without dedicating a separate API for each client.

GraphQL包含了这些新趋势,因为它可用于连接后端应用程序并满足每个客户端的要求(数据的嵌套关系,仅获取所需数据,网络使用要求等),而无需为每个客户端单独使用API​​。

Most times, to do this, the backend would be broken down into multiple microservices with distinct functionalities. This way, it becomes easy to dedicate specific functionalities to the microservices through what we call schema stitching. Schema stitching makes it possible to create a single general schema from different schemas. As a result, each microservice can define its own GraphQL schema.

通常,要做到这一点,后端将被分解为具有不同功能的多个微服务。 这样,通过我们称为模式缝合的方式将特定功能专用于微服务变得很容易。 模式拼接使从不同模式创建单个通用模式成为可能。 结果,每个微服务都可以定义自己的GraphQL模式。

Afterward, you could use schema stitching to weave all individual schemas into one general schema which can then be accessed by each of the client applications. In the end, each microservice can have its own GraphQL endpoint whereas one GraphQL API gateway consolidates all schemas into one global schema to make it available to the client applications.

之后,您可以使用模式缝合将所有单个模式编织为一个通用模式,然后每个客户端应用程序都可以访问它们。 最后,每个微服务可以拥有自己的GraphQL端点,而一个GraphQL API网关将所有模式整合到一个全局模式中,以使其可用于客户端应用程序。

To demonstrate schema stitching, let's consider the same situation employed by Sakho Stubailo while explaining stitching where we have two related APIs's. The new public Universes GraphQL API for Ticketmaster’s Universe event management system and the Dark Sky weather API on Launchpad, created by Matt Dionis. Let’s look at two queries we can run against these APIs separately. First, with the Universe API, we can get the details about a specific event ID:

With the Dark sky weather API, we can get the details of the same location like so:

为了演示模式拼接,让我们在解释具有两个相关API的拼接时,考虑Sakho Stubailo所采用的相同情况。 由Matt Dionis创建的用于Ticketmaster的Universe事件管理系统的新的公共Universes GraphQL API和Launchpad上的Dark Sky weather API。 让我们看一下可以针对这些API分别运行的两个查询。 首先,使用Universe API,我们可以获得有关特定事件ID的详细信息:

Now with GraphQL schema stitching, we could do an operation to merge the two schemas in such a way that we could easily send those two queries side by side:

Wonderful isn't it. You can take an in-depth look at GraphQL schema stitching by Sashko Stubailo to get a deeper understanding of the concepts involved. This way, GraphQL makes it possible to merge different schemas into one general schema where all the clients can get resources from hence, embracing the new modern style of development with ease.

是不是很棒。 您可以深入研究Sashko Stubailo的GraphQL模式拼接 ,以更深入地了解所涉及的概念。 通过这种方式,GraphQL可以将不同的模式合并为一个通用模式,所有客户都可以从中获得资源,从而轻松地拥抱新的现代开发风格。

场级弃用 ( Field level deprecation )

This is one GraphQL feature that personally gives me joy. As developers, we are used to calling different versions of an API and often times getting really weird responses. Traditionally, we version API's when we've made changes to the resources or to the structure of the resources we currently have hence, the need to deprecate and evolve a new version.

这是GraphQL的一项功能,它给我带来了欢乐。 作为开发人员,我们习惯于调用不同版本的API,并且常常会收到真正奇怪的响应。 传统上,当对资源或当前拥有的资源的结构进行更改时,我们将对API进行版本控制,因此需要弃用并开发新版本。

For example we can have an API like api.domain.com/resources/v1 and at some point in the later months or years, a few changes would have happened and resources or the structure of the resources will have changed, hence, the next best thing to do will be to evolve this API to api.domain.com/resources/v2 to capture all the recent changes.

例如,我们可以有一个像api.domain.com/resources/v1这样的API,在接下来的几个月或几年中的某些时候,将会发生一些变化,资源或资源的结构也会发生变化,因此,下一个最好的办法是将此API升级到api.domain.com/resources/v2以捕获所有最近的更改。

At this point, some resources in v1 will have been deprecated (or left active for a while until users have migrated to the new version) and on receiving a request for those resources, will get unexpected responses like deprecation notices.

此时, v1某些资源将被弃用(或保持一段时间,直到用户迁移到新版本为止),并且在收到对这些资源的请求后,将收到意外的响应,例如弃用通知。

In GraphQL, it is possible to deprecate API's on a field level. When a particular field is to be deprecated, a client receives a deprecation warning when querying the field. After a while, the deprecated field may be removed from the schema when not many clients are using it anymore.

在GraphQL中,可以在字段级别上弃用API。 当要弃用特定字段时,客户端在查询该字段时会收到弃用警告。 一段时间后,当不再有很多客户端正在使用该字段时,可能会将其从架构中删除。

As a result, instead of completely versioning the API, it is possible to gradually evolve the API over time without having to restructure the entire API schema.

结果,代替完全版本化API,可以随着时间的推移逐步发展API,而不必重组整个API架构。

不好 ( The bad )

快取 ( Caching )

Caching is the storage of data so that future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation or the duplicate of data stored elsewhere. The goal of caching an API response is primarily to obtain the response from future requests faster. Unlike GraphQL, caching is built into in the HTTP specification which RESTful APIs are able to leverage.

缓存是数据的存储,以便将来可以更快地满足对该数据的请求; 存储在缓存中的数据可能是较早计算的结果,也可能是其他位置存储的数据的重复。 缓存API响应的目的主要是为了更快地从将来的请求中获取响应。 与GraphQL不同,HTTP规范内置了RESTful API可以利用的缓存。

With REST you access resources with URLs, and thus you would be able to cache on a resource level because you have the resource URL as identifier. In GraphQL, this becomes complex as each query can be different even though it operates on the same entity.

使用REST,您可以使用URL访问资源,因此,由于您具有资源URL作为标识符,因此您可以在资源级别进行缓存。 在GraphQL中,这变得很复杂,因为即使每个查询在同一个实体上运行也可能不同。

In one query you might be interested in just the name of an artist, however, in the next query you might want to get the artists' tracks and release dates. This is the point where caching is mostly complex as it'll require field level caching which isn't an easy thing to achieve with GraphQL since it uses a single endpoint.

在一个查询中,您可能只对艺术家的名字感兴趣,但是,在下一个查询中,您可能想要获取艺术家的曲目和发行日期。 这是缓存最复杂的地方,因为它需要字段级缓存,而对于GraphQL来说,由于它使用单个端点,因此这并非易事。

That said, the GraphQL community recognizes this difficulty and has since been making efforts to make caching easier for GraphQL users. Libraries like Prisma and Dataloader (built on GraphQL) have been developed to help with similar scenarios. However, it still doesn't completely cover things like browser and mobile caching.

就是说,GraphQL社区认识到了这一困难,并一直在努力使GraphQL用户的缓存变得更容易。 已经开发了Prisma和Dataloader(基于GraphQL构建)之类的库来帮助解决类似情况。 但是,它仍然没有完全涵盖浏览器和移动缓存之类的内容。

查询效果 ( Query performance )

GraphQL gives clients the power to execute queries to get exactly what they need. This is an amazing feature however, it could be a bit controversial as it could also mean that users can ask for as many fields in as many resources as they want.

GraphQL使客户端能够执行查询以准确获得他们的需求。 这是一个了不起的功能,但是它可能会引起一些争议,因为它也可能意味着用户可以根据需要在任意数量的资源中请求多个字段。

For instance, a user defines a query that asks for a list of all the users that commented on all the tracks of a particular artist. This will require a query like this:

例如,一个用户定义了一个查询,要求查询对特定艺术家的所有曲目进行评论的所有用户的列表。 这将需要这样的查询:

artist(id: '1') {
  id
  name
  tracks {
    id
    title
    comments {
      text
      date
      user {
        id
        name
      }
    }
  }
}

This query could potentially get tens of thousands of data in response.

该查询可能会得到数以万计的数据作为响应。

Therefore, as much as it is a good thing to allow users to request for whatever they need, at certain levels of complexity, requests like this can slow down performs and immensely affect the efficiency of GraphQL applications.

因此,允许用户以某种程度的复杂性来请求他们所需要的任何东西,这是一件好事,这可能会降低性能并极大地影响GraphQL应用程序的效率。

For complex queries, a REST API might be easier to design because you can have several endpoints for specific needs, and for each endpoint, you can define specific queries to retrieve the data in an efficient way. This might also be a bit controversial given that the fact that several network calls can as well take a lot of time, but if you are not careful, a few big queries can bring your server down to its knees.

对于复杂的查询,REST API可能会更容易设计,因为您可以有多个满足特定需求的端点,并且对于每个端点,您都可以定义特定的查询以高效地检索数据。 考虑到多个网络呼叫也可能花费大量时间这一事实,这也可能会引起争议,但是如果您不小心,一些大查询可能会使您的服务器瘫痪。

数据不匹配 ( Data mismatch )

As we exemplified before while building with GraphQL on the backend, often than not, your database and GraphQL API will have similar but different schemas, which translate to different document structures. As a result, a track from the database will have a trackId property while the same track fetched through your API will instead have a track property on the client. This makes for client/server-side data mismatch.

正如我们之前在后端使用GraphQL进行构建时所举例说明的那样,您的数据库和GraphQL API通常会具有相似但不同的架构,这会转换为不同的文档结构。 结果,来自数据库的track将具有trackId属性,而通过您的API获取的相同轨道将在客户端上具有track属性。 这导致客户端/服务器端数据不匹配。

Consider getting the name of the artist of a particular track on the client-side, it'll look like this:

考虑在客户端获取特定曲目的艺术家的姓名,它看起来像这样:

const getArtistNameInClient= track => {
  return artist.user.name
}

However, doing the exact same thing on the server-side will result in an entirely different code like this:

但是,在服务器端执行完全相同的操作将导致完全不同的代码,如下所示:

const getArtistNameInServer= track => {
  const trackArtist = Users.findOne(track.userId)
  return trackArtist.name
}

By extention, this means that you’re missing out on GraphQL’s great approach to data querying on the server. Thankfully, this is not without a fix, It turns out that you can run server-to-server GraphQL queries just fine. How? you can do this by passing your GraphQL executable schema to the GraphQL function, along with your GraphQL query:

从某种程度上讲,这意味着您会错过GraphQL在服务器上进行数据查询的出色方法。 幸运的是,这并非没有解决办法,事实证明,您可以运行服务器到服务器的GraphQL查询就可以了。 怎么样? 您可以通过将GraphQL可执行模式与GraphQL查询一起传递给GraphQL函数来实现:

const result= await graphql(executableSchema, query, {}, context, variables);

According to Sesha Greif, it is important to not just see GraphQL as just a pure client-server protocol. GraphQL can be used to query data in any situation, including client-to-client with Apollo Link State or even during a static build process with Gatsby.

根据Sesha Greif的观点,重要的是不要仅仅将GraphQL视为纯粹的客户端-服务器协议。 GraphQL可用于在任何情况下查询数据,包括具有Apollo Link State的客户端到客户端,甚至在使用Gatsby的静态构建过程中。

模式相似 ( Schema similarities )

When building with GraphQL on the backend, you can't seem to be able to avoid duplication and code repetition especially when it comes to schemas. First, you need a schema for your database and another for your GraphQL endpoint, this involves similar-but-not-quite-identical code, especially when it comes to schemas.

在后端使用GraphQL进行构建时,您似乎无法避免重复和代码重复,特别是在涉及架构时。 首先,您需要为数据库提供一个模式,为GraphQL端点需要一个模式,这涉及相似但不完全相同的代码,尤其是在涉及模式时。

It is hard enough that you have to write very similar code for your schemas regularly, but it's even more frustrating that you also have to continually keep them in sync.

您必须定期为模式编写非常相似的代码已经很困难了,但是更令人沮丧的是,您还必须不断地使它们保持同步。

Apparently, other developers have noticed this difficulty, and so far, efforts have been made in the GraphQL community to fix it. Here are the two most popular fixes we found:

显然,其他开发人员已经注意到了这一困难,到目前为止,在GraphQL社区中已经做出了努力来修复它。 这是我们发现的两个最受欢迎的修复程序:

  1. PostGraphile generates a GraphQL schema from your PostgreSQL database, and

    PostGraphile从您的PostgreSQL数据库生成GraphQL模式,并且
  2. Prisma will also help you generate types for your queries and mutations.

    Prisma还可以帮助您生成查询和突变的类型。

结论 ( Conclusion )

GraphQL is an exciting new technology, but it is important to understand the tradeoffs before making expensive and important architectural decisions. Some APIs such as those with very few entities and relationships across entities like analytics APIs may not be very suited for GraphQL. However, applications with many different domain objects like e-commerce applications where you have items, users, orders, payments, and so on may be able to leverage GraphQL much more.

GraphQL是一项令人兴奋的新技术,但是在制定昂贵且重要的架构决策之前,必须了解折衷方案,这一点很重要。 某些API(例如,那些实体很少且跨实体之间的关系的API)(例如分析API)可能不适合GraphQL。 然而,像电子许多不同的域对象的应用程序- 电子商务应用中,你有项目,用户,订单,付款,等可能能够利用GraphQL得多。

GraphQL is a powerful tool, and there are many reasons to choose it in your projects but do well not to forget that the most important and often times the best choice, is choosing whichever tool is right for the project in consideration. The good and bad points I have presented here may not always apply, but it is worth taking them into consideration while looking at GraphQL to see if they can help your project or to know if the cons have been addressed.

GraphQL是一个功能强大的工具,有很多理由在您的项目中选择它,但不要忘记,最重要且通常是最佳选择是选择要考虑的项目中合适的工具。 我在这里提出的优缺点可能并不总是适用,但是在查看GraphQL以确定它们是否可以帮助您的项目或知道是否解决了缺点时,有必要将它们考虑在内。

翻译自: https://scotch.io/tutorials/graphql-the-good-and-the-bad

graphql-go

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值