graphql_graphql如何提升您的设计影响力第1部分

graphql

When I was working for a major bank, we designed a solution to help a user collect their tax statements. We had lots of data that this was a constant user pain-point. Many users didn’t know which statements counted as tax statements, and even if they did, it was tedious to look through their accounts to find and download them. Meanwhile, on the bank side, we KNOW which statements are tax statements. They are tagged as such in our data. With this in mind, we proposed a simple solution: we added a single button a user could press to download all tax statements for the last n years. It tested great in mock-ups and was rated “highly desirable” by our user panel.

当我在一家大型银行工作时,我们设计了一种解决方案来帮助用户收集他们的纳税表。 我们有很多数据,这一直是用户的痛点。 许多用户不知道哪些报表算作税收报表,即使他们知道,也要仔细查看他们的帐户以查找并下载它们。 同时,在银行方面,我们知道哪些报表是税务报表。 它们在我们的数据中被标记为此类。 考虑到这一点,我们提出了一个简单的解决方案:我们添加了一个按钮,用户可以按下该按钮来下载最近n年的所有税单。 它在实体模型中进行了出色的测试,并被我们的用户面板评为“非常理想”。

Unfortunately, the solution was rejected by our development team. It turns out that the way the back-end was written, there was no way to do what we wanted efficiently. From their side, they only had the following API calls:

不幸的是,该解决方案被我们的开发团队拒绝了。 事实证明,后端的编写方式无法有效地完成我们想要的事情。 从他们的角度来看,他们只有以下API调用:

  • fetch a list of account IDs for a user

    获取用户的帐户ID列表
  • fetch a list of statement IDs(within a time range) for an account ID

    提取帐户ID的语句ID列表(在一个时间范围内)
  • fetch a particular statement by its ID

    通过ID获取特定的语句

To make our button work, we would need to fetch all of a user’s accounts, and then for each account fetch n years’ worth of statements, and then fetch each of those statements to see which were tax statements. We had customers with dozens or even hundreds of accounts. This would result in hundreds and thousands of API calls to get the data, or require the back-end team to create a whole new API just for us. At the bank, new APIs required an incredible amount of testing and security, so that solution would take over a year to be vetted and approved. We argued the merits of this UI for months, but in the end we had to abandon our ideal solution and the user just had to continue to suffer. Which leads us to the central theme:

为了使我们的按钮正常工作,我们需要获取用户的所有帐户,然后为每个帐户获取n年的对帐单,然后对每个对帐单进行核对,以查看哪些是纳税表。 我们的客户拥有数十个甚至数百个帐户。 这将导致成千上万的API调用来获取数据,或者需要后端团队为我们创建一个全新的API。 在银行,新的API需要大量的测试和安全性,因此该解决方案将花费一年多的时间进行审核和批准。 我们已经争论了几个月这个UI的优点,但是最后我们不得不放弃理想的解决方案,而用户不得不继续遭受痛苦。 这引出了中心主题:

If you truly want to own the design of the user experience, you cannot just stop at the front-end.

如果您确实想拥有用户体验的设计,则不能只停留在前端。

了解您的UI实际工作方式 (Understanding how your UI actually works)

When the user clicks a button or drags a spinner on the screen, their interaction is usually intended to bring about some change in the world — sending message, transferring money, and so on. The actual change is happening elsewhere — sometimes on the device itself, more commonly on a server, in the cloud. This is why we call it “user interface” — your screen controls are an interface between the user and the back-end reality.

当用户单击按钮或在屏幕上拖动微调器时,他们的交互通常旨在带来一些变化,例如发送消息,转移资金等。 实际的变化发生在其他地方-有时在设备本身上,更常见的是在服务器上,在云中。 这就是我们称之为“用户界面”的原因-您的屏幕控件是用户与后端现实之间的界面。

The back-end is designed by the engineers, not the designers. They decide how the data is stored and how it can be accessed, changed, or deleted. There are usually many factors involved beyond the UI functionality. The back-end engineer has to worry about security, availability, replication, consistency, speed, cost, and a host of other factors. All of this functionality is typically exposed through APIs — Application Programmatic Interfaces — and these APIs are what are called by front-end UI code to do the back-end work.

后端是由工程师而不是设计师设计的。 他们决定如何存储数据以及如何访问,更改或删除数据。 除了UI功能,通常还涉及许多因素。 后端工程师必须担心安全性,可用性,复制,一致性,速度,成本以及许多其他因素。 所有这些功能通常都是通过API(应用程序编程接口)公开的,这些API被前端UI代码称为进行后端工作。

Due to these numerous concerns, back-end work typically takes longer than front-end work, especially for non-trivial enterprise applications. If the back-end developers wait for the front-end design to be complete before starting, it can add week or months to a project. So it is more typical for these developers to get a list of basic capabilities that will be expected in the next release — perhaps in a quarterly planning session — and they will do the back-end at the same time the UI team is designing the front-end.

由于存在这些众多问题,后端工作通常比前端工作花费更长的时间,尤其是对于非平凡的企业应用程序而言。 如果后端开发人员在开始之前等待前端设计完成,则可能会增加一个星期或几个月的时间。 因此,对于这些开发人员来说,获得典型的基本功能列表(通常在季度计划会议中)将更为常见,他们将在UI团队设计前端的同时做后端。 -结束。

And this is where things go awry — the back-end team ends up deciding how the data can be accessed and updated before the UI team has figured out exactly what is best for the user experience.

这就是问题所在-后端团队最终决定了如何在UI团队找出最适合用户体验的方法之前,如何访问和更新数据。

一个简单的例子 (A simple example)

Let’s say we are making a simple blog. People can sign in, and then post and comment. Posts and comments are just text. Users have a user name and a profile picture. While the UI teams starts designing the cool UI, the back-end team starts working. Typically they will use a database like SQL or MongoDB to store the data. But no one wants to expose direct database calls to the end user, so they would typically create an API to access that data. It might look something like this:

假设我们正在制作一个简单的博客。 人们可以登录,然后发表评论。 帖子和评论只是文本。 用户具有用户名和个人资料图片。 UI团队开始设计出色的UI时,后端团队开始工作。 通常,他们将使用SQL或MongoDB之类的数据库来存储数据。 但是没有人愿意向最终用户公开直接的数据库调用,因此他们通常会创建一种API来访问该数据。 它可能看起来像这样:

getPosts() => [post id 1, post id 2, ...]getPost(id) => {post text, author id, creation date}getPostComments(postId) => [comment id 1, comment id 2, ...]getComment(commentId) => {comment text, author Id, creation date}getUser(userId)=> {user name, profile picture url, last login date}

Note to devs: I am keeping the examples purposely simple to make it easy to follow. I realize that a real system would support many more functions like cursors, sorting, creation and deletion methods, etc.

开发人员注意事项:为了使易于理解,我故意使示例保持简单。 我意识到一个真实的系统将支持更多的功能,例如游标,排序,创建和删除方法等。

Meanwhile, the UI team might make a simple UI that has a list of posts, and if you click on a post, it becomes selected and you can see the comments:

同时,UI团队可能会制作一个具有帖子列表的简单UI,如果您单击某个帖子,它将被选中,并且您可以看到评论:

Image for post
A (very simple) blog app
一个(非常简单的)博客应用

The front end development team builds the UI and connects it the APIs. All is good, except that the network performance is terrible. We don’t need to be a developer to understand what the issue is. Just walk through what is needed to render this UI:

前端开发团队构建UI并将其连接到API。 一切都很好,但是网络性能很差。 我们无需成为开发人员即可了解问题所在。 只需浏览呈现此UI所需的内容:

  1. call getPosts to get the ids of the posts

    调用getPosts以获取帖子的ID
  2. for each post, call getPost to get its text and creation date

    对于每个帖子,请调用getPost以获取其文本和创建日期
  3. for each post, call getUser to get the name of the user

    对于每个帖子,请调用getUser以获取用户名
  4. sort the lists of posts by date

    按日期排序帖子列表
  5. if a post is selected, get its comments by calling get getPostComments

    如果选择了帖子,则通过调用getPostComments来获取其评论
  6. for each comment, call getComment to get its text and creation date

    对于每个注释,请调用getComment以获取其文本和创建日期
  7. sort the list of comments by date

    按日期对评论列表进行排序

So for the screen above, where there are four posts and the selected post has 7 comments, we need to make 1 (getPosts)+ 4 (getPost) + 4 (getUser)+ 1 (getPostComments)+ 7 (getComments)= 17 network calls. If the user is on a slow network where each call is taking a second to respond, that could make the UI feel really slow. At the same time, we also get a lot of information, such as the user’s login date, that we aren’t using. This makes our app more bloated.

因此,对于上面的屏幕,这里有四个帖子,所选的帖子有7条评论,我们需要使1(getPosts)+ 4(getPost)+ 4(getUser)+1(getPostComments)+ 7(getComments)= 17个网络电话。 如果用户所在的网络速度很慢,每个呼叫都需要花费一秒钟来响应,那么这可能会使UI感觉非常慢。 同时,我们还获得了很多我们不使用的信息,例如用户的登录日期。 这使我们的应用更加肿。

So we discuss with the back-end team, and they support our design by adding two new API calls for the back-end:

因此,我们与后端团队进行了讨论,他们通过为后端添加两个新的API调用来支持我们的设计:

getRecentPostsWithInfo() => [{post text, post date, author name}, …]
getPostCommentsWithInfo(postId) => [{comment text, comment date}, ...]

Now to draw the UI, we only need two calls: one to get all of the info for the posts, and one to get all of the info on the comments for the selected posts. Major improvement! Everyone is happy. Design gets their design working with good performance, and while the back-end team had to do more work to get these new APIs in, they are happy to help the UI team.

现在绘制UI,我们只需要调用两个即可:一个获取所有帖子的信息,另一个获取所选帖子的评论的所有信息。 重大改进! 每个人都很开心。 设计使他们的设计具有良好的性能,并且后端团队必须做更多的工作才能获得这些新的API,但他们很乐意为UI团队提供帮助。

In fact, we are now in the ideal state, where the APIs exactly match the user experience.

实际上,我们现在处于理想状态,其中API与用户体验完全匹配。

All is good until we do some usability testing. We find some small changes, like the users want to see the name on the comments as well, and they want profile images by everything. We make the new UI design:

在我们进行一些可用性测试之前,一切都很好。 我们发现了一些小的变化,例如用户希望在注释上也看到名称,并且他们希望所有内容都包含个人资料图像。 我们进行新的UI设计:

Image for post
slightly improved UI
用户界面略有改善

When we code it, the performance goes down again. Because the profile image was not returned in the getRecentPostsWithInfo call, and the image and user name was not in the getPostCommentsWithInfo call, the front-end team has call getUser for each post and each comment.

当我们对其进行编码时,性能再次下降。 由于概要文件图像未在getRecentPostsWithInfo调用中返回,并且图像和用户名不在getPostCommentsWithInfo调用中,因此前端团队对每个帖子和每个注释都调用了getUser。

This is the point in development where the dev team starts asking whether or not this change is really worth it. How much value do we really get from adding this information? Is it really worth slowing down the experience, or going through the pain of changing those back-end APIs again?

这就是开发团队开始询问此更改是否真正值得的点。 通过添加这些信息,我们真正获得了多少价值? 真的值得放慢体验,还是经历再次更改这些后端API的痛苦?

While that discussion is going on, more user feedback comes in. Turns out the users are most interested in seeing if any of their own posts have new comments. Based on that, the UI team comes up with another UI that tests better than any before:

在进行讨论时,会收到更多用户反馈。原来,用户最感兴趣的是查看自己的帖子中是否有新评论。 基于此,UI团队提出了另一个UI,该UI的测试效果比以前更高:

Image for post
new and improved UI, with recent activity!
新的和改进的用户界面,以及最近的活动!

Now the front-end will need to fetch every post, find the ones by the current user, fetch all of those comments, then see if any of those comments were posted since the user’s last login date. That could be hundreds of calls, all to get a few pieces of information in the UI. The performance is unacceptable. There is no way to do it without changing the back-end.

现在,前端将需要获取每个帖子,找到当前用户的帖子,获取所有这些评论,然后查看自用户上次登录日期以来是否发布了这些评论。 那可能是数百个调用,全部都是为了在UI中获取一些信息。 性能是不能接受的。 不更改后端就无法做到这一点。

At this point, the back-end team is frustrated. Of course it is possible to add these calls, but are we REALLY sure that they are needed? It will be a lot of work. Is this the LAST CHANGE we are going to ask for?

在这一点上,后端团队感到沮丧。 当然可以添加这些调用,但是我们真的确定需要它们吗? 这将是很多工作。 这是我们要要求的最后一次变更吗?

And of course, the UX team can’t promise that. All we can say is that it looks good now. Customers liked it in the usability lab. When we ship it, we can watch the analytics and feedback and see. The back-end team is skeptical.

当然,UX团队不能保证这一点。 我们只能说现在看起来不错。 客户在可用性实验室中喜欢它。 发货时,我们可以观看分析和反馈并查看。 后端团队对此表示怀疑。

At some point, every complex projects meets this barrier — where the UX team’s vision is blocked by capacity of the back-end team.

在某个时候,每个复杂的项目都会遇到这个障碍-UX团队的愿景被后端团队的能力所阻挡。

更改游戏:输入GraphQL (Changing the Game: Enter GraphQL)

GraphQL logo

GraphQL can change this equation dramatically.

GraphQL可以大大改变此方程。

GraphQL is different approach to APIs. GraphQL works by defining a schema — a description of all of the data in the system — and then allowing arbitrary queries against that schema.

GraphQL是使用API​​的不同方法。 GraphQL的工作方式是定义一个模式 (对系统中所有数据的描述),然后允许对该模式进行任意查询。

For instance, the schema for our blog might be something like this:

例如,我们博客的架构可能是这样的:

User {
userId: ID
userName: String
profileURL: String
lastLogin: Date
posts: [Post]
comments: [Comment]
}Post {
postId: ID
postText: String
author: User
creationDate: Date
comments: [Comment]
}Comment {
commentId: ID
commentText: String
author: User
post: Post
creationDate: Date
}

The schema is implemented by the back-end team. This is done by writing functions called resolvers. The resolvers are typically simple, and often just call existing APIs, or back-end databases, or just return mock data, or a mix of the above. The back-end team has total freedom here, and can implement resolvers however they want, as long they match the schema.

该架构由后端团队实现。 这可以通过编写称为解析器的函数来完成。 解析器通常很简单,并且通常只调用现有的API或后端数据库,或者仅返回模拟数据,或以上两者的混合。 后端团队在这里拥有完全的自由,并且只要他们与模式匹配,就可以根据需要实施解析器。

Once we have a schema, we can query any arbitrary subset of it with a single call. For instance, we catch fetch the data for our first UI as follows:

一旦有了模式,就可以通过一次调用查询其任意子集。 例如,我们为第一个UI抓取数据,如下所示:

query {
Posts {
postText
creationDate
author {
userName
}
comments {
commentText
creationDate
}
}
}

This will fetch the text and date of all posts and their comments, all in a single call. GraphQL itself will handle calling the appropriate resolver functions needed to get the data. This might be the same number of calls as before — there is no magic here — but the advantage is that these calls all take place in the back-end and are not impacted by the processor speed or network bandwidth of the client. The client makes one call, and gets exactly it wants and none it doesn’t. We are back in our ideal state of a 1-to-1 match between user interface and the API.

这将在一次调用中获取所有帖子的文本和日期及其评论。 GraphQL本身将处理调用获取数据所需的适当解析器函数。 这可能与以前的呼叫次数相同-此处没有魔术,但优点是这些呼叫全部发生在后端,并且不受处理器速度或客户端网络带宽的影响。 客户端拨打一个电话,并且完全得到了它想要的,没有一个没有。 我们回到了用户界面和API之间一对一匹配的理想状态。

Now what happens when we want to make our first change, to show the profile images and names? We just change our query to this:

现在,当我们要进行第一次更改以显示个人资料图像和名称时会发生什么? 我们只是将查询更改为此:

query {
Posts {
postText
creationDate
author {
userNameprofileURL
}
comments {
commentText
creationDate author {
userName
profileURL
}

}
}
}

Now we get the author name and profile URL as well. It is still just one call. And what does the back-end team need to do? Nothing. Because we did not change the schema, the back-end team does not have to do any work at all.

现在,我们还获得了作者姓名和个人资料URL。 它仍然只是一个电话。 后端团队需要做什么? 没事 因为我们没有更改架构,所以后端团队根本不需要做任何工作。

What about the more radical change in the next proposal, where we needed the posts with recent comments? We can still do it using the existing schema:

在下一个提案中,如果我们需要带有最新评论的帖子,那该怎么做呢? 我们仍然可以使用现有架构来做到这一点:

query {User {
userName
lastLogin
posts {
postText
comments {
commentText
creationDate
author {
userName
}
}
}
}

Posts {
postText
creationDate
author {
userName
profileURL
}
comments {
commentText
creationDate
author {
userName
profileURL
}
}
}
}

Notice how we are once again describing exactly what data we want given the schema. It will still be a single call to the server. And once again, we do not need to bother our back-end team. The UX team and front-end devs are able to control their destiny.

请注意,我们如何再次准确描述给定架构所需的数据。 仍然是对服务器的单个调用。 再一次,我们不需要打扰我们的后端团队。 UX团队和前端开发人员能够控制自己的命运。

If the new design turns out to be a keeper, we can work with the back-end team to figure out if it is worth a. For instance, with the current schema we need to fetch a lot of posts and bring them to the client in order to find the ones with recent comments. Even though it is one fetch, it is a lot of data we don’t need. We might want to specifically add an “new post comments” property to the user’s schema, that only returns recent comments on the user’s posts.

如果新设计最终得以解决,我们可以与后端团队合作,确定是否值得。 例如,在当前模式下,我们需要获取大量帖子并将其带给客户端,以便找到带有最新注释的帖子。 即使是一次获取,它也是我们不需要的许多数据。 我们可能要专门向用户的架构添加“新帖子评论”属性,该属性仅返回有关用户帖子的最新评论。

User {
userId: ID
userName: String
profileURL: String
lastLogin: Date
posts: [Post]
comments: [Comment]newPostComments: [Comments]
}

Now our query would use that new property, and the front-end could be updated accordingly:

现在,我们的查询将使用该新属性,并且前端可以相应地更新:

query {
User {
userName
lastLoginnewPostComments {
commentText
author {
userName
}
post {
postText
}
}

}
Posts {
postText
creationDate
author {
userName
profileURL
}
comments {
commentText
creationDate
author {
userName
profileURL
}
}
}
}

Because we changed the schema, the back-end team would now have to do some work. However, the work is very scoped. They only have to create the single new resolver function. And for that, they have a variety of choices. They could just use the existing API calls just like the front end had been doing — fetching all of the users posts and checking for recent comments. This is not as efficient, but depending on circumstances, it might be fine. Or, they could create a new API call that gets the exact data for the new comments from the database directly.

因为我们更改了架构,所以后端团队现在必须做一些工作。 但是,这项工作的范围很广。 他们只需要创建单个新的解析器功能即可。 为此,他们有多种选择。 他们可以像使用前端一样使用现有的API调用-获取所有用户帖子并检查最近的评论。 这不是那么有效,但是根据情况,可能会很好。 或者,他们可以创建一个新的API调用,以直接从数据库中获取新注释的确切数据。

The key win with GraphQL is that the back-end can decide for themselves which of these makes sense. They can even do it the quick but less efficient way at first and then switch to the more advanced technique later if they decide it is worth it. No matter what they do, any change they make does not require any change on the front-end. We just keep making the same query.

GraphQL的主要优势在于后端可以自行决定其中哪一个有意义。 他们甚至可以一开始以快速但效率不高的方式进行操作,然后如果他们认为值得的话,然后再切换到更高级的技术。 无论他们做什么,他们所做的任何更改都不需要在前端进行任何更改。 我们只是继续进行相同的查询。

The result: the front-end team can continue to innovate and experiment in the UI, only bothering the back-end team when absolutely necessary. Everyone is happy!

结果是:前端团队可以继续在UI中进行创新和试验,只有在绝对必要时才打扰后端团队。 每个人都很开心!

UI团队的重点 (Key Take-away for the UI team)

As we can see, a GraphQL schema can serve as the contract between the front-end UI team and the back-end dev team. But this only works if the design team can start thinking about their designs in those terms — the schema and the queries against that schema.

如我们所见,GraphQL模式可以充当前端UI团队和后端开发团队之间的契约。 但这只有在设计团队可以开始以这些术语(架构和针对该架构的查询)来考虑其设计时才有效。

You don’t need to wait for your dev team to embrace GraphQL to get started in this journey. No matter what your back-end looks like, it will help everyone by thinking about what the data looks like that you need to realize your UI.

您无需等待开发团队加入GraphQL即可开始此旅程。 不管您的后端是什么样,它都会通过考虑实现UI所需的数据外观来为所有人提供帮助。

In part II, I will talk more in detail about how to do this, and also discuss how to advocate for GraphQL within your org if they are not already convinced.

在第二部分中,我将更详细地讨论如何执行此操作,还讨论了如果尚未说服GraphQL在组织中倡导的方法。

翻译自: https://medium.com/ringcentral-ux/how-graphql-can-elevate-your-design-impact-part-1-652a3d7b7a48

graphql

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值