From 625ffaaae80a63b42e247caaea9130121e68f9ac Mon Sep 17 00:00:00 2001 From: 1992chenlu <2013luchen@gmail.com> Date: Sun, 16 Apr 2017 18:22:45 -0700 Subject: [PATCH 001/253] translation v1 --- TODO/rate-limiters.md | 127 +++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/TODO/rate-limiters.md b/TODO/rate-limiters.md index 897b69a6ca6..fc89eb14fe5 100644 --- a/TODO/rate-limiters.md +++ b/TODO/rate-limiters.md @@ -1,136 +1,135 @@ > * 原文地址:[Scaling your API with rate limiters](https://stripe.com/blog/rate-limiters) > * 原文作者:[Paul Tarjan](https://stripe.com/about#pt) > * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner) -> * 译者: +> * 译者:鲁辰(https://github.com/1992chenlu) > * 校对者: -# [Scaling your API with rate limiters](/blog/rate-limiters) # +# [使用速率限制扩展你的 API](/blog/rate-limiters) # -Availability and reliability are paramount for all web applications and APIs. If you’re providing an API, chances are you’ve already experienced sudden increases in traffic that affect the quality of your service, potentially even leading to a service outage for all your users. +对于所有的网络应用程序和 API 来说,可利用性和可靠性都是至关重要的。如果你是一个 API 提供者,那么很有可能你经历过对服务质量造成影响的、未预见的流量增长,它有可能会导致对所有用户服务中断。 -The first few times this happens, it’s reasonable to just add more capacity to your infrastructure to accommodate user growth. However, when you’re running a production API, not only do you have to make it robust with techniques like [idempotency](/blog/idempotency), you also need to build for scale and ensure that one bad actor can’t accidentally or deliberately affect its availability. +这种现象最初发生时,在基础设施中增加容量以承载用户增长是一种合理的解决方式。但是,对于运行在生产环境的 API,不仅要使用类似[idempotency](/blog/idempotency)的技术以确保健壮性,还需要为扩展建立基础,并保证一个异常用户不论是否故意都无法影响它的可利用性。 -Rate limiting can help make your API more reliable in the following scenarios: +下面这些情况中,速率限制可以让你的 API 更可靠: -- One of your users is responsible for a spike in traffic, and you need to stay up for everyone else. -- One of your users has a misbehaving script which is accidentally sending you a lot of requests. Or, even worse, one of your users is intentionally trying to overwhelm your servers. -- A user is sending you a lot of lower-priority requests, and you want to make sure that it doesn’t affect your high-priority traffic. For example, users sending a high volume of requests for analytics data could affect critical transactions for other users. -- Something in your system has gone wrong internally, and as a result you can’t serve all of your regular traffic and need to drop low-priority requests. +- 一个用户导致流量达到峰值,而你还有其他用户,不能挂掉。 +- 一个用户使用异常的脚本,意外地发送了许多请求。或者,更糟的情况下,一个用户故意想要压垮你的服务器。 +- 一个用户发送了许多低优先级的请求,你需要保证它们不会影响到高优先级的流量。比如,一个用户对分析数据的大量请求可能影响到其他用户的关键事务。 +- 系统内部发生一些问题,不能为所有正常请求提供服务,需要放弃一些低优先级的请求。 -At Stripe, we’ve found that carefully implementing a few [rate limiting](https://en.wikipedia.org/wiki/Rate_limiting) strategies helps keep the API available for everyone. In this post, we’ll explain in detail which rate limiting strategies we find the most useful, how we prioritize some API requests over others, and how we started using rate limiters safely without affecting our existing users’ workflows. +在 Stripe,我们发现谨慎地实现一些[速率限制](https://en.wikipedia.org/wiki/Rate_limiting)策略有助于保证 API 对所有用户的可利用性。在这篇文章中,我们会解释我们所发现的最有效的速率限制策略,怎样提高一部分 API 请求的优先级,以及怎么在没有影响到现有用户的工作流的情况下,开始安全地使用速率限制的。 -## Rate limiters and load shedders +## 速率限制与减载 -A *rate limiter* is used to control the rate of traffic sent or received on the network. When should you use a rate limiter? If your users can afford to change the pace at which they hit your API endpoints without affecting the outcome of their requests, then a rate limiter is appropriate. If spacing out their requests is not an option (typically for real-time events), then you’ll need another strategy outside the scope of this post (most of the time you just need more infrastructure capacity). +速率限制器可以控制在网络上发送或接收数据的比率。什么时候可以使用速率限制器呢?如果在用户向你的 API 端点发送请求的频率被改变的情况下,用户请求的结果不会受到影响。那么在这种情况下是适合使用速率限制器的。如果把请求之间的时间间隔来开不是一个选项(对于实时事件来说这很典型),那么你需要使用本文范围以外的其他策略(大多数时候你只是需要给基础设施中增加容量)。 -Our users can make a lot of requests: for example, batch processing payments causes sustained traffic on our API. We find that clients can always (barring some extremely rare cases) spread out their requests a bit more and not be affected by our rate limits. +我们的用户可以发送很多请求:例如,支付的批处理会给我们的 API 造成持续的流量。我们发现客户总是可以(除了某些极端少见的情况)将他们的请求分散,以保证不会受到我们速率限制的影响。 -Rate limiters are amazing for day-to-day operations, but during incidents (for example, if a service is operating more slowly than usual), we sometimes need to drop low-priority requests to make sure that more critical requests get through. This is called *load shedding*. It happens infrequently, but it is an important part of keeping Stripe available. +速率限制器对于日常的操作来说很有用,但是当意外发生时(例如,服务比延迟比平时大),我们有时需要放弃低优先级的请求,以保证更重要的请求被及时处理。这个过程叫做*减载*。这并不会经常发生,但对于保持 Stripe 的可利用性很重要。 -A *load shedder* makes its decisions based on the whole state of the system rather than the user who is making the request. Load shedders help you deal with emergencies, since they keep the core part of your business working while the rest is on fire. +减载器是基于整个系统的状态,而不是发出请求的用户来做决策的。减载器能帮助你处理紧急情况,因为当系统其他部分出问题的时候,它会保持你的业务核心稳定运行。 -## Using different kinds of rate limiters in concert +## 协调使用不同种类的速率限制器 -Once you know rate limiters can improve the reliability of your API, you should decide which types are the most relevant. +当你知道速率限制器可以提高你的 API 的可靠性之后,你需要决定哪一种最符合你的需要。 -At Stripe, we operate 4 different types of limiters in production. The first one, the *Request Rate Limiter*, is by far the most important one. We recommend you start here if you want to improve the robustness of your API. +在 Stripe,我们在生产环境使用 4 种不同的限制器。第一种,*请求速率限制(Request Rate Limiter)*,是最重要的。如果你想提高你的 API 的健壮性,我们建议你从这一种开始。 -### Request rate limiter +### 请求速率限制(Request Rate Limiter) -This rate limiter restricts each user to *N* requests per second. Request rate limiters are the first tool most APIs can use to effectively manage a high volume of traffic. +这种速率限制限定了每个用户每秒最多 *N* 个请求。在有效的管理高流量这个问题上,请求速率限制是大多数 API 可以使用的第一个工具。 -Our rate limits for requests is constantly triggered. It has rejected millions of requests this month alone, especially for test mode requests where a user inadvertently runs a script that’s gotten out of hand. +我们对于请求的速率限制一直处于被触发的状态。仅仅这一个月,它就拒绝了多达百万的请求,其中主要是用户漫不经心地运行脚本发出的测试模式请求。 -Our API provides the same rate limiting behavior in both test and live modes. This makes for a good developer experience: scripts won't encounter side effects due to a particular rate limit when moving from development to production. +在测试和实时模式,我们的 API 提供了相同的速率限制行为。这会给开发者带来更好的体验:脚本从开发环境迁移到生产环境的过程中,不会遇到因为特定的速率限制而产生的问题。 -After analyzing our traffic patterns, we added the ability to briefly burst above the cap for sudden spikes in usage during real-time events (e.g. a flash sale.) +在分析了我们的流量模式之后,我们对实时事件(比如:秒杀活动)加入了一项新能力,在突然的使用高峰到来时,暂时性地允许流量超过限制。 ![](https://stripe.com/img/blog/posts/rate-limiters/1-request-rate-limiter.svg) -Request rate limiters restrict users to a maximum number of requests per second. +请求速率限制限定了用户每秒钟可以发送的最大请求数。 -### Concurrent requests limiter +### 并发请求限制 -Instead of “You can use our API 1000 times a second”, this rate limiter says “You can only have 20 API requests in progress at the same time”. Some endpoints are much more resource-intensive than others, and users often get frustrated waiting for the endpoint to return and then retry. These retries add more demand to the already overloaded resource, slowing things down even more. The concurrent rate limiter helps address this nicely. +这种速率限制不会有“你每一秒钟最多可以使用我们的 API 1000 次”这种限制,而是使用“你最多只能同时有 20 个正在被处理的请求”这种限制。有一些端点会比其他端点有更密集地使用资源,等待端点返回结果接着又重试的过程会使用户也变得很沮丧。这些重试请求会给本来已经负荷过重的资源增加更多需求,让整个过程更加缓慢。并发请求限制可以很好的帮助你解决这个问题。 -Our concurrent request limiter is triggered much less often (12,000 requests this month), and helps us keep control of our CPU-intensive API endpoints. Before we started using a concurrent requests limiter, we regularly dealt with resource contention on our most expensive endpoints caused by users making too many requests at one time. The concurrent request limiter totally solved this. +我们的并发请求限制并不会那么经常被触发(这个月发生了 12000 次),它帮助我们控制那些 CPU 密集型的 API 端点。在我们开始使用并发请求限制之前,我们经常要处理,由于用户一次发出过多请求导致的,发生在我们最昂贵的端点上的资源争夺。并发请求限制完全解决了这个问题。 -It is completely reasonable to tune this limiter up so it rejects more often than the Request Rate Limiter. It asks your users to use a different programming model of “Fork off X jobs and have them process the queue” compared to “Hammer the API and back off when I get a HTTP 429”. Some APIs fit better into one of those two patterns so feel free to use which one is most suitable for the users of your API. +调整这种限制使它拒绝的请求比请求速率限制更多,这也是一种合理的做法。这会要求你的用户使用一种“分支出 X 个作业对队列做处理”的模式,而不是“连续对 API 发出请求并在收到 HTTP 429 响应时退避(back off)”(译注:这里的退避(back off)的意思是等待一定时间后重新发送请求)。有些 API 更适合这两种模式中的一种,所以请选择更适于你的 API 的使用者的模式。 ![](https://stripe.com/img/blog/posts/rate-limiters/2-concurrent-requests-limiter.svg) -Concurrent request limiters manage resource contention for CPU-intensive API endpoints. +并发请求限制为 CPU 密集型的 API 端点管理资源竞争。 -### Fleet usage load shedder +### 机队(fleet)使用量减载 -Using this type of load shedder ensures that a certain percentage of your fleet will always be available for your most important API requests. +使用这类减载保证了对于你最重要的 API 请求来说,你的机队(fleet)中一定的百分比一直是可利用的。 -We divide up our traffic into two types: critical API methods (e.g. creating charges) and non-critical methods (e.g. listing charges.) We have a Redis cluster that counts how many requests we currently have of each type. +我们把我们的流量分为两类:关键的 API 方法(比如:创建费用记录)和非关键的方法(比如:列出费用记录)。我们有一个 Redis 集群用来计算当前每种类型的请求分别有多少。 -We always reserve a fraction of our infrastructure for critical requests. If our reservation number is 20%, then any non-critical request over their 80% allocation would be rejected with status code 503. +我们一直为关键请求预留出我们基础设施的一部分。如果预留比例是 20%,那么任何超出 80% 配额的非关键请求都会被以 503 状态码拒绝。 -We triggered this load shedder for a very small fraction of requests this month. By itself, this isn’t a big deal—we definitely had the ability to handle those extra requests. But we’ve had other months where this has prevented outages. +这个月,只有很小比例的请求触发了我们的减载器。这些请求并不是很大量的——我们当时绝对有能力处理这些多余的请求。但是此前,这帮我们阻止了数次服务中断。 ![](https://stripe.com/img/blog/posts/rate-limiters/2-concurrent-requests-limiter.svg) -Fleet usage load shedders reserves fleet resources for critical requests. +机队(fleet)使用量减载为关键请求预留机队(fleet)资源。 -### Worker utilization load shedder +### Worker 使用率减载 -Most API services use a set of workers to independently respond to incoming requests in a parallel fashion. This load shedder is the final line of defense. If your workers start getting backed up with requests, then this will shed lower-priority traffic. +大多数 API 服务都有一组 worker 以并行的方式独立地响应请求。Worker 使用率减载是系统的最后一道防线。如果你的 worker 开始备份一些请求,那么之后低优先级的流量会被放弃。 -This one gets triggered very rarely, only during major incidents. +这种减载器被触发的情况很少见,只有在一些重大事件发生时会被触发。 -We divide our traffic into 4 categories: +我们把我们的流量分成四类: -1. Critical methods -2. POSTs -3. GETs -4. Test mode traffic +1. 关键方法 +2. POST 请求 +3. GET 请求 +4. 测试模式流量 -We track the number of workers with available capacity at all times. If a box is too busy to handle its request volume, it will slowly start shedding less-critical requests, starting with test mode traffic. If shedding test mode traffic gets it back into a good state, great! We can start to slowly bring traffic back. Otherwise, it’ll escalate and start shedding even more traffic. +我们时刻记录 worker 的数量及可利用的容量。如果一台主机太过繁忙以至于无法处理它的请求容量,它会一点点开始去除一些不那么关键的请求,从测试模式的流量开始。如果去掉测试模式的流量之后,它回到了正常状态,很好!我们可以开始慢慢地处理更多流量。否则,它会扩大减载的规模,并开始减去更多的流量。 -It’s very important that shedding and bringing load happen slowly, or you can end up flapping (“I got rid of testmode traffic! Everything is fine! I brought it back! Everything is awful!”). We used a lot of trial and error to tune the rate at which we shed traffic, and settled on a rate where we shed a substantial amount of traffic within a few minutes. +非常重要的一点是缓慢的减去和增加负载量,否则你会陷入持续的状态变动(“我摆脱了测试模式的流量!一切正常!我把它们拿回来处理了!一切糟透了!”)。我们用试错法多次调整我们减载的速率,最终确定了一个在几分钟的时间范围内减掉大量流量的速率。 -Only 100 requests were rejected this month from this rate limiter, but in the past it’s done a lot to help us recover more quickly when we have had load problems. This load shedder limits the impact of incidents that are already happening and provides damage control, while the first three are more preventative. +这个月只有 100 个请求被这种速率限制器拒绝,但是过去它帮助我们从负载过大的问题中更迅速的恢复。这种减载限制了已经发生的事故的影响,提供了对损失的控制,而前三种减载机制更具预防性。 ![](https://stripe.com/img/blog/posts/rate-limiters/4-worker-utilization-load-shedder.svg) -Worker utilization load shedders reserve workers for critical requests. +Worker 使用率减载为关键请求预留出一部分 worker。 -## Building rate limiters in practice +## 速率限制实现 -Now that we’ve outlined the four basic kinds of rate limiters we use and what they’re for, let’s talk about their implementation. What rate limiting algorithms are there? How do you actually implement them in practice? +现在,我们已经概述了四种基本类型的速率限制器,以及在什么情况下使用它们,我们再来谈谈它们是怎么实现的。有哪些速率限制算法?怎么在实际应用中实现它们? -We use the [token bucket algorithm](https://en.wikipedia.org/wiki/Token_bucket) to do rate limiting. This algorithm has a centralized bucket host where you take tokens on each request, and slowly drip more tokens into the bucket. If the bucket is empty, reject the request. In our case, every Stripe user has a bucket, and every time they make a request we remove a token from that bucket. +我们使用[令牌桶算法(token bucket algorithm)](https://en.wikipedia.org/wiki/Token_bucket)实现速率限制。这个算法有集中桶主机,在那里你可以为每个请求取出 token(译注:消耗令牌),同时缓慢的将更多的 token 被放进桶中(译注:生产令牌)。如果桶是空的,拒绝请求。在我们的例子中,每个 Stripe 用户都有一个桶,每次他们发出一个请求,我们就从令牌桶中移除一个 token。 -We implement our rate limiters using Redis. You can either operate the Redis instance yourself, or, if you use Amazon Web Services, you can use a managed service like [ElastiCache](https://aws.amazon.com/elasticache/). +我们使用 Redis 实现速率限制。你可以自己操作 Redis 实例,或者,如果你使用 AWS,你可以使用一个有管理的服务,比如[ElastiCache](https://aws.amazon.com/elasticache/)。 -Here are important things to consider when implementing rate limiters: +这里有一些实现速率限制时需要考虑的重要事项: -- **Hook the rate limiters into your middleware stack safely.** Make sure that if there were bugs in the rate limiting code (or if Redis were to go down), requests wouldn’t be affected. This means catching exceptions at all levels so that any coding or operational errors would fail open and the API would still stay functional. -- **Show clear exceptions to your users.** Figure out what kinds of exceptions to show your users. In practice, you should decide if you want [HTTP 429](https://tools.ietf.org/html/rfc6585#section-4) (Too Many Requests) or [HTTP 503](https://tools.ietf.org/html/rfc7231#section-6.6.4) (Service Unavailable) and what is the most accurate depending on the situation. The message you return should also be actionable. -- **Build in safeguards so that you can turn off the limiters.** Make sure you have kill switches to disable the rate limiters should they kick in erroneously. Having feature flags in place can really help should you need a human escape valve. Set up alerts and metrics to understand how often they are triggering. -- **Dark launch each rate limiter to watch the traffic they would block.** Evaluate if it is the correct decision to block that traffic and tune accordingly. You want to find the right thresholds that would keep your API up without affecting any of your users’ existing request patterns. This might involve working with some of them to change their code so that the new rate limit would work for them. +- **安全地连接你的中间件堆栈和速率限制器。**确保如果速率限制代码有 bug(或者如果 Redis 挂了),请求处理不会受到影响。这意味着要捕捉(来自速率限制的)所有级别的异常,这样任何代码或操作失误都会失败后继续运行,并且 API 还可以正常工作。 +- **向用户明确显示异常。**确定要现实给用户的异常类型。在实际操作中,你应该决定你想用[HTTP 429](https://tools.ietf.org/html/rfc6585#section-4) (Too Many Requests) 还是 [HTTP 503](https://tools.ietf.org/html/rfc7231#section-6.6.4) (Service Unavailable),哪个是最准确的取决于根据情况的不同。你返回的信息也应该是可操作的。 +- **内置保障措施,使你能够关闭限制器。**确保你的关闭按钮能够在速率限制器犯错的时候禁用它们。使用人工安全阀的同时,特性标记(feature flags)也是非常有帮助的。设置警报和指标以便了解它们被触发的频率。 +- **对速率限制使用灰度上线,以观察它们会阻挡哪些流量。**评估阻止那些流量是否是正确的决定,并做出相应的调整。你希望找到一个合适的阈值,它可以既保证你的 API 一直是可利用的,同时不会影响你的用户既有的请求模式。这可能涉及与部分用户一起修改他们的代码,以保证新的速率限制对他们来说是可行的。 -## Conclusion +## 结论 -Rate limiting is one of the most powerful ways to prepare your API for scale. The different rate limiting strategies described in this post are not all necessary on day one, you can gradually introduce them once you realize the need for rate limiting. +速率限制是为你的 API 扩大使用规模做好准备最有效的方法之一。这篇文章中描述的不同的速率限制策略并不需要在上线的第一天就全部实现,你可以逐渐引入它们,当你发现有速率限制的需要的时候。 -Our recommendation is to follow the following steps to introduce rate limiting to your infrastructure: +我们建议根据以下步骤将速率限制引入你的基础设施: -1. Start by building a Request Rate Limiter. It is the most important one to prevent abuse, and it’s by far the one that we use the most frequently. -2. Introduce the next three types of rate limiters over time to prevent different classes of problems. They can be built slowly as you scale. -3. Follow good launch practices as you're adding new rate limiters to your infrastructure. Handle any errors safely, put them behind feature flags to turn them off easily at any time, and rely on very good observability and metrics to see how often they’re triggering. +1. 从实现一个请求速率限制器开始。这是最重要的,也是目前为止最常用的一种防止滥用的方法。 +2. 逐步引入后续三种速率限制以预防不同类别的问题发生。可以在缓慢扩大规模的过程中逐渐实现它们。 +3. 将新的速率限制引入你的基础设施时,应当遵循良好的上线实践。安全地处理错误,使用特性标记(feature flags)以便在任何时候可以将它们关闭,依靠良好的可观测性和指标以便观察它们被触发的频率。 -To help you get started, we’ve created a [GitHub gist](https://gist.github.com/ptarjan/e38f45f2dfe601419ca3af937fff574d) to share implementation details based on the code we actually use in production at Stripe. +为了帮助你更好地开始使用速率限制,我们创建了一个[GitHub gist](https://gist.github.com/ptarjan/e38f45f2dfe601419ca3af937fff574d),用来分享基于我们在 Stripe 生产环境使用的代码的一些实现细节。 - Like this post? Join the Stripe engineering team. [View Openings](/jobs?ref=blog#engineering) --- From fdc97e680a387ad56901db5c1995e0601d785577 Mon Sep 17 00:00:00 2001 From: 1992chenlu <2013luchen@gmail.com> Date: Sun, 16 Apr 2017 18:32:55 -0700 Subject: [PATCH 002/253] tweak styling --- TODO/rate-limiters.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TODO/rate-limiters.md b/TODO/rate-limiters.md index fc89eb14fe5..373704a132e 100644 --- a/TODO/rate-limiters.md +++ b/TODO/rate-limiters.md @@ -112,10 +112,10 @@ Worker 使用率减载为关键请求预留出一部分 worker。 这里有一些实现速率限制时需要考虑的重要事项: -- **安全地连接你的中间件堆栈和速率限制器。**确保如果速率限制代码有 bug(或者如果 Redis 挂了),请求处理不会受到影响。这意味着要捕捉(来自速率限制的)所有级别的异常,这样任何代码或操作失误都会失败后继续运行,并且 API 还可以正常工作。 -- **向用户明确显示异常。**确定要现实给用户的异常类型。在实际操作中,你应该决定你想用[HTTP 429](https://tools.ietf.org/html/rfc6585#section-4) (Too Many Requests) 还是 [HTTP 503](https://tools.ietf.org/html/rfc7231#section-6.6.4) (Service Unavailable),哪个是最准确的取决于根据情况的不同。你返回的信息也应该是可操作的。 -- **内置保障措施,使你能够关闭限制器。**确保你的关闭按钮能够在速率限制器犯错的时候禁用它们。使用人工安全阀的同时,特性标记(feature flags)也是非常有帮助的。设置警报和指标以便了解它们被触发的频率。 -- **对速率限制使用灰度上线,以观察它们会阻挡哪些流量。**评估阻止那些流量是否是正确的决定,并做出相应的调整。你希望找到一个合适的阈值,它可以既保证你的 API 一直是可利用的,同时不会影响你的用户既有的请求模式。这可能涉及与部分用户一起修改他们的代码,以保证新的速率限制对他们来说是可行的。 +- **安全地连接你的中间件堆栈和速率限制器。** 确保如果速率限制代码有 bug(或者如果 Redis 挂了),请求处理不会受到影响。这意味着要捕捉(来自速率限制的)所有级别的异常,这样任何代码或操作失误都会失败后继续运行,并且 API 还可以正常工作。 +- **向用户明确显示异常。** 确定要现实给用户的异常类型。在实际操作中,你应该决定你想用[HTTP 429](https://tools.ietf.org/html/rfc6585#section-4) (Too Many Requests) 还是 [HTTP 503](https://tools.ietf.org/html/rfc7231#section-6.6.4) (Service Unavailable),哪个是最准确的取决于不同的情况。你返回的信息也应该是可操作的。 +- **内置保障措施,使你能够关闭限制器。** 确保你的关闭按钮能够在速率限制器犯错的时候禁用它们。使用人工安全阀的同时,特性标记(feature flags)也是非常有帮助的。设置警报和指标以便了解它们被触发的频率。 +- **对速率限制使用灰度上线,以观察它们会阻挡哪些流量。** 评估阻止那些流量是否是正确的决定,并做出相应的调整。你希望找到一个合适的阈值,它可以既保证你的 API 一直是可利用的,同时不会影响你的用户既有的请求模式。这可能涉及与部分用户一起修改他们的代码,以保证新的速率限制对他们来说是可行的。 ## 结论 From bc7b4e0fb614b60b47f94705c26ddf6278aacd9c Mon Sep 17 00:00:00 2001 From: Shirley Yang Date: Mon, 24 Apr 2017 01:32:35 +0800 Subject: [PATCH 003/253] translate/rxjava-part3 --- ...oid-rxjava2-what-the-hell-is-this-part3.md | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) diff --git a/TODO/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3.md b/TODO/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3.md index 987c44a2cb7..e625d1a042c 100644 --- a/TODO/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3.md +++ b/TODO/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3.md @@ -6,27 +6,43 @@ ## Functional Interfaces, Default Methods, { Higher Order – Pure – Side Effects in } + Functions, Im + { Mutable } , Lambda Expression & Functional Programming – Reactive Programming [ Android RxJava2 ] ( What the hell is this ) Part3 ## +##函数式接口,默认方法,纯函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程和 Lambda 表达式 - 响应式编程 [Android RxJava 2](这到底是什么)第三部分## + WOW, we got one more day so its time to make this day awesome by learning something new . Hello guys, hope you are doing good. This is our third post in series of RxJava2 Android [ [part1](http://www.uwanttolearn.com/android/reactive-programming-android-rxjava2-hell-part1/), [part2](http://www.uwanttolearn.com/android/pull-vs-push-imperative-vs-reactive-reactive-programming-android-rxjava2-hell-part2/) ]. In this post we are going to discuss about Functional Interfaces, Functional Programming, Lambda expressions and may be something bonus related to Java 8. Which will be helpful for everyone in near future. +大家好,希望你们都过得不错。这是我们的 RxJava2 Android 系列的第三篇文章[[第一部分](http://www.uwanttolearn.com/android/reactive-programming-android-rxjava2-hell-part1/), [第二部分](http://www.uwanttolearn.com/android/pull-vs-push-imperative-vs-reactive-reactive-programming-android-rxjava2-hell-part2/)]。在这篇文章中,我们将讨论函数式的接口,函数式编程,Lambda 表达式以及与 Java 8 的相关的其它内容。这对每个人近期都是有帮助的。 + **Motivation:** +**动机:** Motivation is same which I share with you in [part1](http://www.uwanttolearn.com/android/reactive-programming-android-rxjava2-hell-part1/). Lambda expressions, Functional programming, High Order Functions and blah blah blah always give me tough time specially when I am doing work in Java because every body know’s Java is Object Oriented Programming. So how Java can support Functional Paradigm. Then what is the role of Lambda expressions in Functional Programming. To make every thing clear and easy just like nothing, I will start from Functional Interfaces. One important point, my promise with you guys. I am 100% sure as you follow this part. In the end you will be comfortable with all the terms which we are listening in these days a lot. Functional Interfaces, Default Method, Pure Functions, Side Effects in Functions, Higher Order Functions, Mutable and Immutable, Functional Programming and Lambda expressions. I have a feeling lot of people are using Lambda expression in these days but may be after completing this post they know what is really Lambda expressions. Its time to ATTACK. +动机和我在分享[第一部分](http://www.uwanttolearn.com/android/reactive-programming-android-rxjava2-hell-part1/)时一致。Lambda 表达式,函数式编程,高阶函数等等总是让我在使用 Java 时很痛苦,因为大家都知道,Java 是面向对象编程的。所以,Java 怎么可能支持函数式编程。那么,在函数式编程里,Lambda 表达式的角色是什么呢?为了让所有问题变得简单明了,我会从函数式接口开始。重要的是,我向你们保证,只要你们 100% 看完这部分,你们将会对最近我们听到的所有名字都感觉自在很多。函数式接口,默认方法,完全的函数,函数的副作用,高阶函数,可变的与不可变的,函数式编程与 Lambda 表达式。我觉得很多人最近都在使用 Lambda 表达式,但或许在读完这篇文章后,他们会更了解 Lambda 表达式。攻克难题的时刻到了。 + **Revision:** +**修改:** In [part1](http://www.uwanttolearn.com/android/reactive-programming-android-rxjava2-hell-part1/) we discuss the most important, basic and core concept of Rx and that is a Observer Pattern. In [part2](http://www.uwanttolearn.com/android/pull-vs-push-imperative-vs-reactive-reactive-programming-android-rxjava2-hell-part2/) we discuss about Pull vs Push and Imperative vs Reactive programming. +在[第一部分](http://www.uwanttolearn.com/android/reactive-programming-android-rxjava2-hell-part1/),我们讨论的 Rx 最重要,最基础也最核心的概念,那就是观察者模式。在[第二部分](http://www.uwanttolearn.com/android/pull-vs-push-imperative-vs-reactive-reactive-programming-android-rxjava2-hell-part2/),我们讨论了拉模式和推模式,以及命令式和响应式编程。 + **Introduction:** +**介绍:** Today we are going to clear all confusions about Functional Interfaces, Default Method, Pure Functions, Side Effects in Functions, Higher Order Functions, Mutable and Immutable, Functional Programming and Lambda expressions. So guys I am not going to start from Lambda Expressions instead I am going to start from Functional Interfaces. +今天我们将会弄清楚所有关于函数式接口,默认方法,完全函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程以及 Lambda 表达式的所有困惑。所以,我不准备从 Lambda 表达式开始,反而我要从函数式接口开始。 + **Functional Interface:** +**函数式接口:** In simple words. *Functional Interface is an interface having one abstract method*. Simple no more confusions. Again, *any interface have only one abstract method is called Functional Interface*. Here I want to share some knowledge, which is not the part of this series but that is good if you know specially for interviews. If you read my definition. I used abstract keyword but we already know interface has always abstract methods. So that is before Java 8. In Java 8 we can define one method in interface and that is called default method like shown below. +简单地说,**函数式接口是个有一个抽象方法的接口。**同样简单地说,**任何拥有一个抽象方法的叫函数式接口。**这里我想分享一些背景知识,这些知识不属于这个系列,但是对你面试尤其有用。如果你读过我的定义。我用抽象的关键词,但是我们已经知道接口总是有抽象方法,所以那就是 Java 8 之前的。在 Java 8 里我们可以在接口里定义一个方法,这个方法叫默认方法,正如下面所示。 + ``` public interface Account { @@ -40,10 +56,16 @@ public interface Account { Now I am going to revise the definition. Functional Interface is an interface having one abstract method. +现在我们要修改一下定义。函数式接口是个拥有一个抽象方法的接口。 + So now if I ask you the above interface is a Functional Interface or not. What will be your answer. According to definition. Answer should be No but that is a valid Functional Interface. Why… +所以现在,如果我问你上面的接口是不是一个函数式接口,你的答案是什么?根据定义,答案应该是不是,但那却是一个有效的函数式接口,为什么呢…… + Now if interface use default method or may be try to use any method of **java.lang.Object** into interface. That interface remain Functional Interface because **java.lang.Object** methods will not count. Just like I am showing you one valid Functional Interface below. +现在,如果接口使用默认方法或者可能尝试使用 **java.lang.Object** 的任何方法。那个接口还是函数式接口,这是因为 **java.lang.Object** 方法并不算数。正如我在下面展示给你的真正的函数式接口。 + ``` public interface Add { void add(int a, int b); @@ -58,6 +80,8 @@ public interface Add { So any interface which has more then one method is not called a Functional Interface just like shown below. +所以,任何有多于一个方法的接口不叫函数式接口,正如下面所示。 + ``` public interface Do { @@ -69,8 +93,12 @@ public interface Do { I think you grasp the concept of Functional Interface. Guys that is a really core concept of Lambda expression so try to remember this concept. +我相信你已经理解了函数式接口的概念。这可真的是 Lambda 表达式的核心概念,所以试着记住这个概念吧。 + Some examples of Functional Interfaces which currently we are using in our daily development. +一些我们现在每天开发使用的函数式接口的例子: + ``` public interface **Runnable** { public abstract void **run**(); @@ -83,24 +111,40 @@ public interface **OnClickListener** { Now its time to show you Comparator interface in Java 7 and 8 both are valid Functional Interfaces. +现在是时候向你展示 Java 7 和 8 的比较器接口了。它们都是有效的函数式接口。 + In Java 7 Comparator: +Java 7 的比较器: + [![](http://www.uwanttolearn.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-04-at-9.23.27-AM-300x171.png) ](http://www.uwanttolearn.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-04-at-9.23.27-AM.png) In Java 8: +在 Java 8 里: + [![](http://www.uwanttolearn.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-04-at-9.25.44-AM-1024x773.png) ](http://www.uwanttolearn.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-04-at-9.25.44-AM.png)[![](http://www.uwanttolearn.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-04-at-9.29.23-AM-1024x650.png) ](http://www.uwanttolearn.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-04-at-9.29.23-AM.png) Do not confuse guys. Again both are valid Functional Interfaces. Only remember three things about Functional Interface. +可别搞混了。它们都是有效的函数式接口。只要记住函数式接口的三件事情。 + Only one abstract method – May have default methods – May use java.lang.Object methods +只有一个抽象方法 - 可以有默认方法 - 可以使用 java.lang.Object 方法。 + If any interface pass these three points that is a valid Functional Interface otherwise no. +如果任何接口满足这三点,那就一定是有效的函数式接口,反之则不是。 + In java 8 there is a whole new package **java.util.function.** In this package all interfaces are Functional Interfaces. That package is useful when we are working with Streams API. Which we will learn as a bonus when we will start Rx Android. +在 Java 8 里有一个新的工具包 **java.util.function**。在这个包里,所有的接口都是函数式接口。当我们需要用到流 API 时,这个工具包很有用。当我们开始学习 Rx Android 的时候,这个包会让我们学到更多。 + One very important point. Guys as we are going to start working with Rx Android. We will play a lot with these Functional Interfaces. Basically in Android we are dependent on Rx Java and Rx Android. Now I am going to show you package of Rx Java 1.0 and 2.0 Functional Interfaces. No need to remember this thing and no need to take tension that is only general knowledge. Only try to remember the concept of Functional Interface. These will automatically remember to you when we start working together on Rx. +很重要的一点。当我们要开始使用 Rx Android 时,我们会使用很多这样的函数式接口。基本上,在安卓平台中,我们依赖于 Rx Java 和 Rx Android。现在,我将要给你看一看 Rx Java 1.0 和 2.0 包里的函数式接口。没有必要去记住这个,也没有必要紧张,这只是通用知识。只要试着记得函数式接口的概念久可以了。当你开始使用 Rx,这些你都会不自觉地想起来。 + RxJava 1: [![](http://www.uwanttolearn.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-04-at-9.56.27-AM-120x300.png)](http://www.uwanttolearn.com/wp-content/uploads/2017/03/Screen-Shot-2017-03-04-at-9.56.27-AM.png)RxJava2: @@ -110,28 +154,49 @@ RxJava 1: WOW. Its time to celebrate now we know what is a Functional Interfaces, what are default methods in Java 8. As I write in introduction about the terms, which we are going to discuss in this post, two are gone . Functional Interfaces, Default Method, Pure Functions, Side Effects in Functions, Higher Order Functions, Mutable and Immutable, Functional Programming and Lambda expressions. +哇哦!我们该庆祝一下我们已经知道什么是函数式接口,以及在 Java 8 里什么是默认方法。当我在介绍里写到这些名词时,当然,我们将要这篇文章中讨论它们,两个新名词就解释完了。函数式接口,默认方法,纯函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程和 Lambda 表达式。 + **Functional Programming:** +**函数式编程:** Truly saying I mostly work with Java and C++ and both are imperative not pure functional. So I am going to try my best to clear all confusions which I faced but if I am wrong some where please forgive me and update me in comments. So I will update my post. +我真的大部分使用 Java 和 C++,而且它们都是命令式的而且不是纯函数式的。所以我打算尽力解决所有的我面对的困惑。请原谅我,可以在回复里提醒我来更新我的文章。 + Guys before going into boring definitions. I am going to revise some of our college or school days concepts. Which is really helpful here to clear all the ambiguities about the remaining terms. +在进入无聊的定义之前,我打算修改我们在学校学习到的概念。这对接下来阐释剩下模棱两可的名词是很有帮助的。 + Every body who is doing development know functions. But currently try to forget everything about programming and go back to college or school days. ——————- School Days, Present Madam. +每个做开发的人都知道函数。但是现在请试着忘记我们学习过的所有编程知识,重回学校。 + Good boy. +好孩子。 + Now what is a function in math class. [Guys for the time being forget all knowledge which you have related to functions in Java or C++ or in any language.] +在数学课上,什么是函数。[现在请忘掉你所知道的在 Java 或者 C++ 等任何编程语言关于函数的所有知识。] + What is a function? A function related an input to output. Boring ok forget. How many people know about the below sentence. +什么是函数?一个根据输入决定输出的方程式。挺无聊的,好的,那忘记这个。 + +有多少人听过下面的句子。 + f(x) = x+3 if x = 2 what will be the answer. +如果 x = 2,答案是什么。 + f(x) equal to y. +f(x) 等于 y。 + y = x+3 x = 2 @@ -150,16 +215,32 @@ Sin(x) [ Trigonometry ] We remember. Every time in school life when I gave theta value 45 degree. I get answer 1/2 like shown below. +所以,f(x) = x+3 是一个函数。当你给同一个输入,会给你同样的输出。 + +再来一个例子。 + +有多少人记得。 + +Sin(x) [ 三角函数 ] + +我们当然记得。在学校的时候,每当我们得到一个 45 度的 theta 角,我会得到 1/2 的答案,如下所示。 + y = Sin(45deg) y = 1/2 Later I used this same function in college and university. Every time when I have same input I got same result. That is called pure functions. I will explain more later. +接下来,我要用到这个在大学里常见的同样的函数。每次我给一样的输入,我会得到一样的记过。这就叫纯函数。我会在接下来解释。 + Here we revise some functions which we use a lot in our school or college life. Now when we use the same concept in programming. That is called Functional Programming. Do not take tension I am going to explain now. We are back from childhood memories. +这里我们要修改一些我们在学校里常用的函数。现在,当我们在编程中用同样的概念,这就叫函数式编程。不要紧张,我马上就会解释。我们从儿时的回忆里回来看看。 + First need to discuss some confusion. Like when we start programming we start like. Write a function which will calculate area of a circle. +首先,我们要讨论一些困惑。正如,当我们开始编程,我们开始写一个可以计算圆的面积的函数。 + ``` public double areaOfACircle(int radius){ return radius*radius*3.14; @@ -168,6 +249,8 @@ public double areaOfACircle(int radius){ Good. Now as I am going more professional my definition of function is changed. Like write a currency converter of USD into PKR. +很好。现在我要给函数一个更专业的定义,正如写一个 USD 和 PKR 的货币转换器。 + ``` public float convertUSDIntoPKR(int USD){ return USD*getTodayPKRValueFromAPI(); @@ -177,16 +260,28 @@ public float convertUSDIntoPKR(int USD){ In Programming that is a function but in math. There is some issue because in math we always say. Same input always give you same output. But our function may give your different output on same input because that is dependent upon the external value. So here I am going to introduce a one more term. That is called a Pure function. In Math we always know every function is a pure function just like Sin() but in our programming languages we have a lot of functions which always give us a different value. So for that we introduce a new term called a Pure function in programming. *A pure function is a function where the return value is only determined by its input values, without observable side effects.* +在编程中,上面的是一个函数。但是在数学中,这就有问题了。因为在数学中,我们总是说,同一个输入对应同样的输出。但是编程中的函数给同样的输入可以有不同的输出,因为它依赖于其它数值。所以这里,我们又要介绍一个名词,叫纯函数。在函数里,我们知道每个函数都是纯函数,如 Sin(),但是,在我们的编程语言里,我们有很多函数给我们不同的数值。所以,这就是我们要介绍的,编程语言里的纯函数。 **纯函数是返回值值决定于它的输入,而并没有观察者的副作用。** + One more term side effect. Any function which is not pure is called a impure function which may have a side effect. Or may be there is some function which is pure but if we can see any side effect in that then we are not able to say that is a Pure function. +下一个名词,副作用。任何不纯的函数叫非纯函数,它可能产生副作用。或者可以说,一些函数式纯的,但是如果我们看到它有任何负作用,那么我们就不能说这是一个纯函数。 + First impure function like Random. This always give you different value for same seed. Side effect like println() is an impure because it causes output to an I/O device as a side effect. In any function which is pure but I used println() note that function is not remain pure function due to side effect. +第一个非纯函数就是随机函数。它总是用同一个种子给你返回不同的结果。 + +副作用像 println(),是一个非纯的函数,因为为 I/O 设备提供输出是它的副作用。任何函数式纯的,但是如果我用 println() 来注释打印,那它就不再是纯函数了。 + Some examples: Pure: +一些例子: + +纯函数: + ``` public int squre(int x){ return x*x; @@ -195,6 +290,8 @@ public int squre(int x){ Impure due to Side Effect: +因为副作用而非纯的的函数; + ``` public int squre(int x){ System.out.println(x*x); @@ -204,6 +301,8 @@ public int squre(int x){ Impure: +非纯函数: + ``` public void login(String username, String password, Callback c){ API.login(username, password, callback); @@ -213,8 +312,14 @@ public void login(String username, String password, Callback c){ Now we grasp two more terms. Pure functions and Side effect. Functional Interfaces, Default Method, Pure Functions, Side Effects in Functions, Higher Order Functions, Mutable and Immutable, Functional Programming and Lambda expressions. +现在我们又理解了两个名词。纯函数和副作用。 + +函数式接口,默认方法,纯函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程和 Lambda 表达式。 + Next we are going to discuss Mutable and Immutable. In mathematics as we remember every time when I gave my value to some function. I always get the new value and my original value remain same. But in programming that concept has changed so that’s why we have two different definitions. Mutable and Immutable. In OO we mostly use to break immutability. Which may cause a lot of issue but in Functional Programming that always used immutability. Like every body know in Java String is Immutable. +接下来,我们准备讨论可变的不可变的。在数学中,我们记得,当我给函数一个值,我总能获得新的值,而我原来的值还是一样的。但是,在编程中,那个概念就变了。这时为什么我们有两种不同的定义。可变的和不可变的。在 00? 中我们差一点就打破了不可变性。这可能导致很多问题,但是函数式编程总是利用不可变性。正如每个人都知道在 Java 里,String 是不可变的。 + ``` String s = "Hello"; s = "World"; @@ -224,6 +329,10 @@ Here our original String never changed. Yes in second line I created a new Strin So what is mutable. One example. +这里,我们本来的字符串从未改变。虽然第二行我们创建了新的字符串并且把它赋给我的 s 对象。 + +所以,什么是可变的?给你一个例子。 + ``` int array []= {1,2,3,4,5}; for (int i = 0; i < array.length; i++) { @@ -233,6 +342,8 @@ for (int i = 0; i < array.length; i++) { In Java or in imperative programming if I call above code that is basically mutable. That changed my original array values. But in Functional Programming if I do the same thing I always get a new array with multiplied values and I have the original data remain unchanged. +在 Java 或者命令式编程中,我认为上面的代码基本上是可变的。它改变了原本的数组值。但是在函数式编程里,如果我做了同样的事情,我总是获得乘好的数值组成的新数组,而我原来的数据仍然保持不变。 + ``` Integer array []= {1,2,3,4,5}; Arrays.stream(array).map(v->v*2).forEach(i-> System.out.print(i+" ")); @@ -250,8 +361,12 @@ Output: The above example written in Java 8 but that will be same in Rx later. Only try to grasp the concept of mutable and Immutable. So as you see in output original array value has no change. +上面的例子是用 Java 8 写的,但是那跟之后讲 Rx 是一样的。只要试着理解可变的不可变的概念。正如你所看到的,所输出的原本的数组值并没有改变。 + Now may be you are thinking what is the benefit of this. So I am going to explain here one example. If I know all my functions are Pure and Immutable I can do lot of things without taking care of my data state. For example I am going in threading. +现在可能你在想这样的好处是什么。我这里用另外一个例子来解释。如果我知道我所有的函数都是纯的并且是不可变的,我可以做很多事情而不用管我数据的状态。例如,我要使用线程。 + ``` public class FunctionalLambda { @@ -278,6 +393,8 @@ public class FunctionalLambda { In this example basically I am using threading. One of my thread doing addition of value 1 in each member of array and the main or other thread is taking square of all the values in array. As a developer my expected value should be like shown below. +在这个例子里,基本上我用到了线程。其中一个线程对 1 和数组中的每个数值做加法,而主要的和其它线程则对数组中的数值做平方运算。作为一个开发者,我期望数值应如下所示。 + ``` 1 4 @@ -288,6 +405,8 @@ In this example basically I am using threading. One of my thread doing addition But when I run I got the below output. +但是,当我跑起程序,我得到的是下面的输出。 + ``` 4 9 @@ -298,6 +417,8 @@ But when I run I got the below output. This is wrong or actual output. Because I am not taking care of my mutability. Now I am going to right a proper Functional program. In which I will manage my immutability. +这是错的,但也是实际输出,因为我没有管数据可变性。现在我准备写一个合适的函数式程序,这段程序将管理我数据的不可变性。 + ``` public class FunctionalLambda { @@ -327,39 +448,74 @@ public class FunctionalLambda { Note: For running above example you need to [download rxjava jar](https://mvnrepository.com/artifact/io.reactivex/rxjava/1.0.2). +注意:如果要跑上面的例子,你需要[下载 rxjava jar](https://mvnrepository.com/artifact/io.reactivex/rxjava/1.0.2)。 + After running this example my expected and actual both outputs are same because here my program is not doing changes directly in array instead that is creating a copy of my data. So that’s why I can say my array is immutable. I also used Rx so for that sorry but from now I will add little bit Rx in my examples. I will explain you in next post but trust on me. That is a Functional Program in which I have one Pure Function square and my array is not mutated because I am using Functional Paradigm. +跑完这段例子后,我所期望的和实际输出的事一致的,因为我的程序没有对数组做直接改变,而是拷贝了我的数据。这就是为什么我可以说我的数组是不可变的。对不起,我也用 Rx 了。但是从现在开始,我会加一点 Rx 到我的例子里。我会在接下来的文章中解释清楚。但是,请相信我,那时一个函数式程序。在程序里,我有一个纯函数做平方运算,并且我的数组不改变,因为我将使用函数式范式。 + Functional Interfaces, Default Method, Pure Functions, Side Effects in Functions, Higher Order Functions, Mutable and Immutable, Functional Programming and Lambda expressions. +函数式接口,默认方法,纯函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程和 Lambda 表达式。 + Now its time to clear our ambiguity about Higher Order Functions (HOF). +是时候解释清楚高阶函数 (HOF) 的含义了。 + *A function with at least one parameter of type function or a function that returns function is called a higher order function*. +**拥有至少一个函数类型为参数的函数,或着返回一个函数的函数叫做高阶函数。** + Hmm that is really easy and we use a lot this concept in our Rx programming. Before Java 8 that is little bit difficult to show you HOF but we can use anonymous class as a HOF. We are mostly used this concept in C++. Where I can send function as a parameter. In Android like I am going to add a Click listener with anonymous class. So you can say that is an example of HOF. I will explain more when we are in Rx post. Functional Interfaces, Default Method, Pure Functions, Side Effects in Functions,Higher Order Functions,Mutable and Immutable, Functional Programming and Lambda expressions. +那简直太简单了,并且我们在 Rx 编程中用了很多这个概念。在 Java 8 之前,展示 HOF 还是有点困难的,但是我们使用匿名类作为 HOF。我们大多在 C++ 中使用这个概念,把函数作为一个参数。在安卓中,这就类似于添加一个匿名类为点击事件监听者。所以你可以说,这是 HOF 的一个例子。我会在介绍 Rx 的文章中更详细地解释这个。 + +函数式接口,默认方法,纯函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程和 Lambda 表达式。 + Now if we are using these concepts which we discuss Pure Functions, HOF, Immutable in any language you can say we are following Functional Paradigm. That is a Functional Programming. In OO we mostly manage the states but in Functional we have data and we do computation by taking care of immutability. +现在,如果我们使用这些概念,在任何语言中,我们所讨论的纯函数,HOF,不可变的都是接下来的函数式范式。那就是函数式编程。在 00?我们常要管理状态,但是在函数式程序里,我们有数据,管理好了不可变性,我们可以大胆地做运算。 + Functional Interfaces, Default Method, Pure Functions, Side Effects in Functions,Higher Order Functions,Mutable and Immutable,Functional Programming and Lambda expressions. +函数式接口,默认方法,纯函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程和 Lambda 表达式。 + Hurray we cleared our lot of ambiguities related to Functional Programming. Now its time to finish our this post by learning last thing Lambda Expressions. +加油呀!我们已经弄清楚了很多关于函数式编程模棱两可的概念。现在我们要用学习 Lambda 表达式来结束这篇文章。 + Before going to Lambda’s I want to revise what we did till now. +在进入 Lambda 的章节前,我想复习一下前面的内容。 + Functional Interface – an interface having one abstract method. +函数式接口 - 一个有一个抽象方法的接口。 + Default Method – In Java 8 we can define methods in interface these are called Default Method. +默认方法 - 在 Java 8 里,我们可以在接口中定义方法,这些叫默认方法。 + Pure Function – A function, where the return value is only determined by its input values, without observable side effects. +纯函数 - 一个函数的返回值仅由输入值决定,不需要做观察。 + **Lambda Expressions:** +**Lambda 表达式:** “*lambda expression in computer programming, also called anonymous function, a function (or a subroutine) defined, and possibly called, without being bound to an identifier*” (Wiki) +“**在计算机编程中,lambda 表达式,也叫匿名函数,是指一类无需定义标识符(函数名)的函数或子程序。**”(Wiki) + First and most important thing. RxJava is not dependent on Lambda’s. Instead Functional Programming has no relationship with Lambda’s as you already saw in all of my above examples I never mentioned I used lambda may be on some places IDE converted my code to lambda but we can do everything without lambda. Then questions is why in every blog of Rx or Functional Programming we saw lambda expressions as a core part of the blog. In my opinion, you can think they are simple, improved syntax form of anonymous functions. +首先,RxJava 并不依赖于 Lambda 表达式。实际上,函数式编程与 Lambda 表达式没有关系,正如你在我以上的例子中看到的那样,我从来没有说过我用了 lambda。只是 IDE 在某些地方可能把我的代码转换成了 lambda 表达式,但我可以不用它来写代码。那么,问题是,为什么在每一篇关于 Rx 或者函数式编程的博客里,我们看到 lambda 表达式总是核心内容。在我看来,你可以把它们认为简单的,有效的匿名函数形式。 + There is some prerequisite which I am going to explain you before going into more detail about Lambdas. As we already know Java is a static type language. Its mean all java program objects and variables always know about there data type at compile time. For example code as shown below. +在我详细介绍 Lambda 表达式前,有个条件。我们已经知道 Java 是一个静态类型语言。它意味着所有的 java 程序对象和变量总是在编译时间里知道数据类型,如下的例子这样。 + ``` int i = 1; float j = 3; @@ -369,12 +525,17 @@ String s = "Hello"; In a same way before Java 7 we are going to use Collections we need to write a complete List of initialization like shown below. +同样的,在 Java 7 之前,我们准备用 Collections 来写一个完整的 List 对象初始化,如下所示。 + ``` List list = new ArrayList(); ``` But in Java 7 we got Type Inference concept. By using that one we can write concise code just like shown below. +但在 Java 7,我们有类型引用的概念。使用这个概念,我们可以写出如下简洁的代码。 + + ``` List list = new ArrayList<>(); ``` @@ -383,10 +544,18 @@ So basically now compiler will determine the type by using the context at compil Guys again, type inference is very very important. So try to focus on this thing. In Lambda expressions, we are using a lot and lot of people confused due to lake of this concept. +所以现在,编译器在编译时根据上下文决定数据类型。这样,我们就节省了很多时间。 + +再一次,数据类型引用非常重要。所以我们要关注这个。在 Lambda 表达式中,我们要用到很多次,但是大家因为缺少这个概念而感到困惑。 + Going again to describe this same concept by taking different example. I have a one method in which I will send integer as param and that method will return me that same value without changing any thing like as shown below. +我们继续用另外一个例子来描述同一个概念。 + +我写了一个方法,整数作为参数传入,而这个方法将不改变任何东西,返回同样的数值给我,如下所示。 + ``` public static void main(String [] args){ System.out.println(**giveMeBack(1)**); @@ -399,10 +568,14 @@ public static int **giveMeBack**(int a){ This is a simple example. Now I want to give 3.14 to this method. So guys any body tell me what will happen? +这是简单的例子。现在我想传个 3.14 给这个方法,有没有人告诉我,会发生什么呢? + [![](http://www.uwanttolearn.com/wp-content/uploads/2017/02/Screen-Shot-2017-02-19-at-3.23.34-PM-300x227.png) ](http://www.uwanttolearn.com/wp-content/uploads/2017/02/Screen-Shot-2017-02-19-at-3.23.34-PM.png) Yes you are write program is not able to compile as shown above. I already mentioned that method only take Integer. Next my requirement is, I need to write this function for all data types. Now as a developer I am a lazy guy. I don’t want to write a same code again and again. Here I am going to take benefit of Java inference. +是的,你的程序将无法编译。我已经说过了,这个方法只能传入整数。我的下一个要求是,我要使得这个方法适用于所有数据类型。作为一个开发者,我是一个懒人。我不想写重复的代码。这里我想利用 Java 的引用。 + ``` public static T giveMeBack(T a){ return a; @@ -411,16 +584,24 @@ public static T giveMeBack(T a){ This is also called generics. Now by using generics I save my lot of time. I can use this method for any data type as shown below. +这也叫泛型。利用泛型,我节省了很多时间。这个方法可以适用于任何数据类型,如下图所示。 + [![](http://www.uwanttolearn.com/wp-content/uploads/2017/02/Screen-Shot-2017-02-19-at-3.27.35-PM-300x164.png) ](http://www.uwanttolearn.com/wp-content/uploads/2017/02/Screen-Shot-2017-02-19-at-3.27.35-PM.png) Now here I get a benefit from Java inference. How? As compiler, compile my program, that easily generate a code for my all these data types. Now compiler can easily determine from my param data type. So there is no magic. Every time when I am not mentioning the data type most probably compiler will take the context and assign the datatype according to the context because Java is a static type language. +现在我从 Java 引用中获得了好处。怎么样获得的呢?我的编译器,编译我的程序,为我的所有数据类型生成了代码。现在,编译器可以很容易地从我的参数的数据类型做决定。这里没有什么神奇的地方。每当我没有提到数据结构,我的编译器就从上下文中提取并且赋予其数据类型,因为 Java 是一个静态类型语言。 + Repeat. Java is a static type language. So if you feel in IDE you are writing some code which did not have any type or may be you think you are going as a Dynamic type language. You are wrong, basically you are taking benefit of Java inference. +再重复一遍,Java 是一个静态类型语言。所以如果你觉得你在 IDE 中写的代码没有任何类型。你可能会认为你使用的是一个动态类型语言。你错了,你只是在利用 Java 引用而已。 + Now its time to start work on Lambda expressions. Guys important thing currently Lambda expression only support to Java 8. So in Android if we want Lambda expressions we can use one library Retrolambda. Which is good. Now I am going to explain about LambdaExpressions. In Android I want a one button with Click Listener. So code as shown below. +现在,我们可以开始写 Lambda 表达式了。目前,Lambda 表达式只支持 Java 8。在安卓中,如果我们想用它,我们可以用 Retrolambda 库。现在们来解释一下 lambda 表达式。 + ``` Button button = new Button(this); button.setOnClickListener(new View.OnClickListener() { @@ -433,6 +614,8 @@ button.setOnClickListener(new View.OnClickListener() { Here I am setting one anonymous object of OnClickLisetener. So when user click, onClick method will be called. Now I am going to change this anonymous, shitty, complex code with Lambda expression. +这里我们翻入了一个 OnClickLisetener 的匿名对象。当用户点击,onClick 方法就会被调用。现在我们要用 Lambda 表达式改变这个匿名的,恶心的,复杂的代码。 + ``` Button button = new Button(this); button.setOnClickListener((View v)->{ @@ -442,12 +625,16 @@ button.setOnClickListener((View v)->{ Now by using Lambda expressions I made my code concise and easy to read. I am going to make more refactoring to the above example. +通过使用 Lambda 表达式,我的代码可读性更强了。我准备再重构一下上面的例子。 + ``` button.setOnClickListener(v -> /* Click */); ``` I really like to write code as shown above but in start I really confused how compiler know what I am doing here. First thing here we are using the benefit of Java inference. Like on compile time Java automatically know ‘v’ is a View because we have a **functional interface** which contain one method who has one argument and that is a view as shown below. +我真的很喜欢写类似上面的代码,但是在开始的时候,我真的很困惑,编译器是如何知道我这里在做什么。首先,我利用了 Java 引用。就像编译时,Java 自动知道‘v'是一个 View,因为我们用的是**函数式接口**。这个接口包含一个方法,它的参数是一个 view,如下所示。 + ``` /** * Interface definition for a callback to be invoked when a view is clicked. @@ -464,8 +651,12 @@ public interface **OnClickListener** { Hay, what I used, Functional Interface term. I think dots are connecting. We already discuss about Functional Interface. Its mean any method who will take a Functional Interface as an argument I can write as a Lambda Expression. Its mean Lambda Expression is a syntactic sugar. Guys I have a feeling now you are getting everything about Lambda Expressions. Why I focused on Functional Interfaces and other terms. +我用了函数接口的名字。我觉得点点点是连接中。我们已经讨论了函数式接口。它意味着任何以函数式接口为参数的方法,我就可以写成 Lambda 表达式。这意味着,Lambda 表达式是一个语法糖。我觉得你们现在已经知道 Lambda 表达式是个什么东西了。这就是为什么我要关注函数式接口和其它名词了。 + One more example. +再来一个例子。 + ``` Without Lambda: @@ -480,6 +671,7 @@ thread.start(); With Lambda: +使用 Lambda 表达式: ``` Thread thread = new Thread(()->{}); @@ -490,12 +682,18 @@ In Java 8 or Rx Java we have a lot of Functional Interfaces because we want to w If I only want to write a single line of code on Button press I can write my code as shown below. +在 Java 8 或者 Rx Java 中,我们会使用很多函数式接口,因为我们想写出简单明了的代码,并且寥寥数语就可以完成一个大功能。现在我觉得所有的困惑都已经清晰了。这里有一些关于 Lambda 表达式更重要的点。 + +如果当按钮被按下时,我想写一行代码,我可以写成下面这样。 + ``` button.setOnClickListener(v -> System.out.println()); ``` But If I want to write more then one line of code. Then I need to write in curly braces as shown below. +但如果我想写不只一行,那么我需要把它们写进花括号里,如下所示。 + ``` button.setOnClickListener(v -> { System.out.println(); @@ -505,12 +703,16 @@ button.setOnClickListener(v -> { I can mention data type of my params explicitly as shown below. +我可以明确提及数据类型,如下所示。 + ``` button.setOnClickListener(**(View v)** -> System.out.println()); ``` Now what about return type in Lambda. One more example. +现在,如何返回 Lambda 表达式类型呢?再给你一个例子。 + ``` public interface Add{ int add(int a, int b); @@ -528,6 +730,8 @@ int sum = add.add(1,2); Now I am going to use that same example with Lambda. +现在我使用 Lambda 表达式来表现同一个例子。 + ``` public interface Add{ int add(int a, int b); @@ -540,6 +744,8 @@ int sum = add.add(1,2); Now you can saw how much concise code I wrote. In functionality both are same. I am not mentioning any return type, due to type inference Java automatically determine that has int data type. Now If I have more then one line code in add implentation then I need to metion as shown below. +现在可以看到我写的代码有多简洁了。它们的功能是一样的。我没有提及任何返回的数据类型,因为 Java 的类型引用自动帮我决定了这是一个整型。现在,如果我想添加更多的代码到 add 方法的实现中,我需要提及如下所示。 + ``` public interface Add{ int add(int a, int b); @@ -556,12 +762,20 @@ int sum = add.add(1,2); Now we know Functional Interfaces, Default Methods in Interface, Higher Oder Functions, Side Effects in Functions, Pure Functions, Lambda Expression and Functional Programming. +现在我们知道函数式接口,默认方法,纯函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程和 Lambda 表达式。 + Conclusion: +结论: + Good work guys. Today we achieve a very big milestone in Rx. Next post [War against Learning Curve of Rx Java 2 + Java 8 Stream [ Android RxJava2 ] ( What the hell is this ) Part4](http://www.uwanttolearn.com/android/war-learning-curve-rx-java-2-java-8-stream-android-rxjava2-hell-part4/). Till now we know Observer Pattern, Pull vs Push, Reactive vs Imperative, Functional Interfaces, Default Methods, Higher Order Functions, Side Effects in Functions, Pure Functions, Lambda Expression and Functional Programming. In my opinion if you know all these terms then Rx learning curve is very very easy. Now I have a feeling we know all these terms so Rx learning curve is very easy for all of us. Guys have a nice weekend. We will met in next week with more good stuff. BYE BYE. +大家都太棒了。今天我们在 Rx 学习中有了非常大的里程碑。下一篇文章是 [War against Learning Curve of Rx Java 2 + Java 8 Stream [ Android RxJava2 ] ( What the hell is this ) Part4](http://www.uwanttolearn.com/android/war-learning-curve-rx-java-2-java-8-stream-android-rxjava2-hell-part4/)。到现在为止,我们了解了观察者模式,拉模式与推模式,响应式与命令式,函数式接口,默认方法,纯函数,函数的副作用,高阶函数,可变的和不可变的,函数式编程和 Lambda 表达式。我认为,如果你都了解了上述名词,Rx 的学习将会越来越简单。现在我感觉你们都已经了解了,所以接下来 Rx 的学习对于我们都会更简单。 + +祝你们有个愉快的周末。让我们下周再见吧。 + --- > [掘金翻译计划](https://github.com/xitu/gold-miner) 是一个翻译优质互联网技术文章的社区,文章来源为 [掘金](https://juejin.im) 上的英文分享文章。内容覆盖 [Android](https://github.com/xitu/gold-miner#android)、[iOS](https://github.com/xitu/gold-miner#ios)、[React](https://github.com/xitu/gold-miner#react)、[前端](https://github.com/xitu/gold-miner#前端)、[后端](https://github.com/xitu/gold-miner#后端)、[产品](https://github.com/xitu/gold-miner#产品)、[设计](https://github.com/xitu/gold-miner#设计) 等领域,想要查看更多优质译文请持续关注 [掘金翻译计划](https://github.com/xitu/gold-miner)。 From b682894aef71da63363fe56bd84cbd427d70eefe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A0=B9=E5=8F=B7=E4=B8=89?= Date: Tue, 25 Apr 2017 23:48:52 +0800 Subject: [PATCH 004/253] Fix a typo. --- ...e-programming-android-rxjava2-what-the-hell-is-this-part3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3.md b/TODO/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3.md index e625d1a042c..a548006095a 100644 --- a/TODO/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3.md +++ b/TODO/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3.md @@ -1,4 +1,4 @@ -> * 原文地址:[Reactive Programming [ Android RxJava2 ] ( What the hell is this ) Part3](https://www.teambition.com/project/583d8744180aa4d012496f03/tasks/scrum/583d8744fa1e93bf18a85a7a/task/58d0e5c09e4371c673330e96) +> * 原文地址:[Reactive Programming [ Android RxJava2 ] ( What the hell is this ) Part3](http://www.uwanttolearn.com/android/functional-interfaces-functional-programming-and-lambda-expressions-reactive-programming-android-rxjava2-what-the-hell-is-this-part3/) > * 原文作者:[Hafiz Waleed Hussain](http://www.uwanttolearn.com/author/admin/) > * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner) > * 译者: From 3169c551bc31cf26e6fdd12ecc3e4bfb6c1862a5 Mon Sep 17 00:00:00 2001 From: ylq167 Date: Fri, 28 Apr 2017 15:48:42 +0800 Subject: [PATCH 005/253] =?UTF-8?q?=E5=88=9D=E7=A8=BF=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO/everyone-is-a-designer-get-over-it.md | 35 +++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/TODO/everyone-is-a-designer-get-over-it.md b/TODO/everyone-is-a-designer-get-over-it.md index aee8b2663cd..3d731931f0d 100644 --- a/TODO/everyone-is-a-designer-get-over-it.md +++ b/TODO/everyone-is-a-designer-get-over-it.md @@ -8,78 +8,111 @@ ![](https://cdn-images-1.medium.com/max/2000/1*xIoFsnWI_2-1VOy00a2KrQ.jpeg) Photo by Alice Achterhof [via Unsplash](https://unsplash.com/search/designer-paint?photo=FwF_fKj5tBo) +图片作者 Alice Achterhof [来自于 Unsplash](https://unsplash.com/search/designer-paint?photo=FwF_fKj5tBo) # Everyone is a designer. Get over it. # +# 人人都是设计师。忘了它吧。# Recently, [Jared Spool](https://www.uie.com/about/) caught my attention with [an article](https://articles.uie.com/signup/) about how Netflix’s performance engineers are *actually designers*. It’s a provocative idea, but it makes sense. His argument is that everyone in your organization (including performance engineers) designs the product, not just the people with “design” in their job titles. +最近,[Jared Spool](https://www.uie.com/about/) 通过一篇关于 Netflix 的性能工程师竟然是**设计师**的[文章](https://articles.uie.com/signup/)吸引了我的注意 。这是一个挑衅的想法,但也有一定的道理。他的论点是你团队中的每个人(包括性能工程师)都参与到产品设计,而不仅仅是职位为「设计」的人。 ![](https://cdn-images-1.medium.com/max/800/1*qLoczEHONP188zelJbn-6w@2x.png) From some of the reactions, you might think Jared had kidnapped someone’s baby for ritual sacrifice. What exactly did Jared write? +从一些反应中,你可能会认为 Jared 绑架了一些人的宝贝用来献祭。Jared 到底写了什么呢? > The members of this team are performance engineers. They are architecting, engineering, and maintaining the performance of a very complex system. It occupies all their time and then some. In systems engineering, there are few jobs more technical than these. +> 这个团队的成员都是性能工程师。他们架设,开发,维护一个复杂系统的性能。这占据了他们所有的时间。而且还远不止如此,在系统工程方面,几乎没有比这更技术性的工作。 > And yet, at the very moment that a Netflix viewer’s video stream stops and that spinning animation appears, indicating the player is now awaiting more data, these engineers make a dramatic change. **They become user experience designers.** +> 然而,在 Netflix 观众的视频流停止并出现旋转动画的那一刻,表明播放器正在等待更多的数据,这些工程师发生了戏剧性的转变,**他们变成了用户体验设计师。** I made that last sentence bold — because it’s really important. Some designers are uncomfortable with the idea that an engineer or a salesperson or a CFO could be a *designer*. +我把最后一句话加粗了,因为这真的很重要。一些设计师对工程师或销售人员或财务官可能是「设计师」的想法感到不适。 ![](https://cdn-images-1.medium.com/max/800/1*ErZDaGRy3mJ19jGdWqeJgA@2x.png) Common reactions +常见的反应 Whether you like it or not, whether you approve it or not, people outside of your design team are making significant *design* choices that affect your customers in important ways. They are *designing* your product. They are *designers*. +不管你是不是喜欢,也不管你是不是同意,设计团队以外的人都会以重要的方式通过重大的**设计**决策来影响你的客户。 This shouldn’t be provocative — it’s just a statement of fact. I work with[ dozens of startups](http://www.gv.com/portfolio/) every year, and I see it happen at every one. A CFO makes a pricing decision and changes the product experience. An engineer makes a performance trade-off. A salesperson writes a script for talking to customers. In my view, people who fundamentally change the customer’s experience are *designers*. +这不应该是**挑衅**-这只是一个事实的陈述。我每年与几十家[创业公司](http://www.gv.com/portfolio/)合作,我看到每一家公司都会发生这种情况。首席财务官作出定价决定改变了产品体验。一个工程师做了性能权衡。销售人员写一个与客户交谈的脚本。在我看来,从根本上改变用户体验的人就可以叫做**设计师**。 If this is so self-evident, why do Jared and I press the point? I keep beating the drum because I want designers to change the way they think about their role and become better stewards of good design. +如果这是不言而喻的,那为什么 Jared 和我坚持这一点?我会持续宣传(此处翻译是否合适?),因为我希望设计师改变他们对自身角色的看法,并成为更好的设计师。 For a moment, consider how this shift in perspective could change the way you work. +现在,想想这种观点的改变将如何改变你的工作方式。 #### Everyone needs a design mindset #### +#### 每个人都需要设计思维 #### When you accept the reality that design decisions are coming from outside your group, by people without “design” in their job titles, you approach your co-workers differently . Now they’re not just your co-workers — they’re your design team. +当你接受设计决策来自于你团队之外而且职位不是「设计」的人的现实时,你就会向你的其他同事靠拢。现在他们不仅是你的同事-他们还是你的设计团队。 The companies that produce great design, such as Apple and Airbnb, have learned this. Alex Schleifer, VP of design at Airbnb,[ tells *Wired*](https://www.wired.com/2015/01/airbnbs-new-head-design-believes-design-led-companies-dont-work/) how the company *isn’t* design-led: +创造出顶尖设计的公司,像苹果(Apple)和爱彼迎(Airbnb),都已经意识到了这一点。 爱彼迎(Airbnb)的设计副总裁 Alex Schleifer [告诉**《连线》杂志**](https://www.wired.com/2015/01/airbnbs-new-head-design-believes-design-led-companies-dont-work/)公司如何才能**不由**设计主导。 > *The solution [at Airbnb] actually deemphasizes the designers. The point… isn’t to create a “design-led culture,” because that tends to tell anyone who isn’t a designer that their insights take a backseat. It puts the entire organization in the position of having to react to one privileged point of view. Instead, Schleifer wants more people to appreciate what typically lies only within the realm of designers — the user viewpoint.* +> **爱彼迎(Airbnb)的解决方法实际上不强调设计师,这一点,不是要创造一个「设计主导的文化」,而是因为这往往会告诉任何一个不是设计师的人他们的洞察力是不重要的。它使整个组织能够对一个特别的观点作出反应。(此处该如何翻译?)相反,Schleifer 希望更多的人意识到用户视角通常只在设计师的领域。**(此处该如何翻译?) Does everyone need all the skills of a designer? Of course not. But each person needs to be armed with the tools to understand how their decisions affect the customer experience. +每个人都需要掌握设计师的所有技能吗?当然不是。但是每个人都需要配备工具来理解他们的决定是如何影响用户体验的。 When an engineer takes a shortcut and scrimps on performance, they need to understand how that damages the user experience. Likewise, when a designer pushes an engineer to make a change that affects performance, that engineer should help the designer make the best overall design decision — not just roll over and do what the designer asked. It’s this type of respectful collaboration that makes great design happen. +当一个工程师在性能方面采用敏捷的途径时,他们需要理解这是如何损害用户体验的。同样,当设计师需要推动工程师做影响性能的改变时,这个工程师应该帮助设计师做出最好的整体设计决策,而不仅是否定设计师所需要的。正是这种尊重的合作创造出伟大的设计。 One of the best ways to encourage empathy is to watch customer research studies with co-workers from across your company. When my colleague Michael Margolis runs a study with a GV company, we insist that the real team — not just the designers — watch those interviews and take notes. If it’s not possible for everyone to watch in real time, you can record the sessions and schedule a “viewing party” for later. +激发共鸣的最好方式就是和来自公司的同事一起看用户调研。当我的同事 Michael Margolis 和 GV 公司一起进行研究时,我们坚持认为,真正的团队-不仅仅是设计师-需要看这些访谈并进行记录。如果不可能做到每个人都全部观看,你可以记录会话并在之后安排一个「观看聚会」。 #### Work outside your design team #### +#### 在设计团队之外工作 #### When you accept that design happens almost everywhere in your organization, you have to take responsibility for it. Your app is slow? Go sit with your engineering team. Your marketing team is poorly communicating your product to future customers? You’d better offer to work with them on the problem. +当你接受设计这个行为发生在你的团队中几乎任何地方时,你必须承担责任。你的应用很慢?和你的工程团队坐在一起。你的营销团队很难将你的产品传达给未来的客户?你最好在这个问题上和他们一起工作。 Yes, doing design with everyone at your company is a lot of work. But it’s necessary if you want to be a truly great designer — otherwise, you’re simply papering over bad decisions. For example, imagine that your CEO created a complex pricing structure for your product. You could focus on making the pricing page as clear as possible using your interface and information design skills. But the harder and more important design opportunity is to work with your CEO on repricing your product so it’s clear to customers and compatible with the business goals. +是的,和你公司里的每个人一起做设计的工作量很大。但是,如果你想成为一名真正伟大的设计师,那么这是必要的。否则,你只是在做错误的决定。例如,假设你的 CEO 为你的产品创建了一个复杂的定价结构。你可以专注于使用您的界面和信息设计技巧使定价页面尽可能的清晰。但更难更重要的设计机会是与您的 CEO 一起重新定价你的产品,以便用户清楚,同时符合业务目标。 Focusing on the core business is what differentiates real product design from interface design or even user experience design. Fundamental product design is really hard and requires a lot of legwork, but this is what designers at the highest level do — and it’s why their work is better than yours. +关注核心业务是将是实际产品设计与界面设计甚至用户体验设计区分开来。基本的产品设计真的很难,需要大量的调研工作,但这就是最高级的设计师所做的-这就是为什么他们的工作比你的好。 ![](https://cdn-images-1.medium.com/max/600/1*czW-2nrN_3l50ZzgYQYqlw@2x.png) “The Disciplines of UX Design” by Dan Saffer and Thomas Gläser +Dan Saffer 和 ThomasGläser 的 「用户体验设计学科」 #### Grow your design team to include non-designers #### +#### 扩大您的设计团队,包括非设计师 #### Design is a hard job. You’ll need a wide range of skills (look at all of those circles in the[ diagram of UX Disciplines](https://www.fastcodesign.com/1671735/infographic-the-intricate-anatomy-of-ux-design) by Dan Saffer) and years of practice to truly master design. +设计是一项艰巨的任务,你将需要广泛的技能(请查看由 Dan Saffer(制作的)[UX 学科图](https://www.fastcodesign.com/1671735/infographic-the-intricate-anatomy-of-ux-design)中的所有圈子)和多年的实践才能真正掌握设计。 Maybe that’s why so many designers are offended when non-designers do design work or get called “designers” by Jared and me. You can act offended if you want, but the reality is that other people are making design decisions with or without you. Embrace them . They don’t make your job less valuable. They don’t make your job title less meaningful. +也许这就是为什么当不是设计师的人做设计工作或者被 Jared 和我称作「设计师」时,许多设计师感到生气。只要你愿意你可以表现的很生气,但事实是其他人不管有没有你都一直在做设计决策。拥抱他们吧,他们不会使你的工作变得不那么有价值,也不会使你的职位变得不那么有意义。 Having more people who *do design* is additive, not competitive. These designers make your team and your product stronger, because they’re contributing from their unique perspectives. Help them bolster their skills, and use their expertise to the advantage of your product and company. +对于更多的人来说**做设计**是附加的,并没有竞争力。这些设计是您的团队和您的产品更强大,因为他们从独特的角度做出贡献。帮助他们提高自己的技能,并利用自己的专长来优化您的产品和公司。 ### **Let’s make a better future together** ### +### **让我们一起创造更美好的未来吧** ### A few years ago, I met an executive from a Fortune 500 company. When I told her I’m a designer, her eyes lit up. “Oh, I love design!” she said. “My group is just down the hall from the design team. They do so much creative work in there.” +几年前,我遇到一家财富 500 强公司的 CEO。当我告诉她我是设计师时,她的眼睛亮了起来。「哦,我喜欢设计!」她说,「我的团队就在设计团队的大厅里,他们在那里做了很多创造性的工作。」 My heart sank. The design team was just down the hall from this executive, but they didn’t work together. Instead, they sat behind soundproof glass walls and did special “creative work” in isolation. +我的心冷了下来。设计团队只是在这个行政大厅,但是他们没有一起工作。相反,他们坐在隔音玻璃后面,孤立地做「创造性工作」。 This executive made decisions every day that affected her customers. She bears some of the blame for not reaching out to the designers “in there.” But the design team is primarily at fault — for missing an opportunity to reach out and work together on some of the business’s most important challenges. - +这个行政大厅每天作出影响他的顾客的决定。「在这里」却没有与设计师接触,她需要承担一部分责任。但主要错在设计团队,因为错过了接触和在一些业务中最重要的挑战上共同工作的机会。 Thanks to [Jared M. Spool](https://medium.com/@jmspool) for writing an excellent article, [John Zeratsky](https://medium.com/@jazer) and [Michael Margolis](https://medium.com/@mmargolis) for editing and suggestions, and [Alex Schleifer](https://medium.com/@alexoid) for the excellent *Wired* article. +感谢 [Jared M. Spool](https://medium.com/@jmspool) 拟写优秀的文章, [John Zeratsky](https://medium.com/@jazer) 和 [Michael Margolis](https://medium.com/@mmargolis) 参与编辑和建议, 以及 [Alex Schleifer](https://medium.com/@alexoid) 为优秀的**《连线》**文章(做的努力)。 + --- > [掘金翻译计划](https://github.com/xitu/gold-miner) 是一个翻译优质互联网技术文章的社区,文章来源为 [掘金](https://juejin.im) 上的英文分享文章。内容覆盖 [Android](https://github.com/xitu/gold-miner#android)、[iOS](https://github.com/xitu/gold-miner#ios)、[React](https://github.com/xitu/gold-miner#react)、[前端](https://github.com/xitu/gold-miner#前端)、[后端](https://github.com/xitu/gold-miner#后端)、[产品](https://github.com/xitu/gold-miner#产品)、[设计](https://github.com/xitu/gold-miner#设计) 等领域,想要查看更多优质译文请持续关注 [掘金翻译计划](https://github.com/xitu/gold-miner)。 From 99b6cb77b0b76856ff03bd59e941d3fa8d7a452f Mon Sep 17 00:00:00 2001 From: ylq167 Date: Fri, 28 Apr 2017 15:51:28 +0800 Subject: [PATCH 006/253] =?UTF-8?q?=E5=B0=8F=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO/everyone-is-a-designer-get-over-it.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO/everyone-is-a-designer-get-over-it.md b/TODO/everyone-is-a-designer-get-over-it.md index 3d731931f0d..d2b20d831b0 100644 --- a/TODO/everyone-is-a-designer-get-over-it.md +++ b/TODO/everyone-is-a-designer-get-over-it.md @@ -11,7 +11,7 @@ Photo by Alice Achterhof [via Unsplash](https://unsplash.com/search/designer-pai 图片作者 Alice Achterhof [来自于 Unsplash](https://unsplash.com/search/designer-paint?photo=FwF_fKj5tBo) # Everyone is a designer. Get over it. # -# 人人都是设计师。忘了它吧。# +# 人人都是设计师。结束它吧。# Recently, [Jared Spool](https://www.uie.com/about/) caught my attention with [an article](https://articles.uie.com/signup/) about how Netflix’s performance engineers are *actually designers*. It’s a provocative idea, but it makes sense. His argument is that everyone in your organization (including performance engineers) designs the product, not just the people with “design” in their job titles. 最近,[Jared Spool](https://www.uie.com/about/) 通过一篇关于 Netflix 的性能工程师竟然是**设计师**的[文章](https://articles.uie.com/signup/)吸引了我的注意 。这是一个挑衅的想法,但也有一定的道理。他的论点是你团队中的每个人(包括性能工程师)都参与到产品设计,而不仅仅是职位为「设计」的人。 From 1acb4b09c28c14c639626fb139d2ef003890c8d4 Mon Sep 17 00:00:00 2001 From: Changkun Ou Date: Fri, 28 Apr 2017 14:06:00 +0200 Subject: [PATCH 007/253] =?UTF-8?q?(add):=20=E5=A2=9E=E5=8A=A0=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E5=88=9D=E7=A8=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO/how-to-pretend-youre-a-great-designer.md | 112 +++++++++--------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/TODO/how-to-pretend-youre-a-great-designer.md b/TODO/how-to-pretend-youre-a-great-designer.md index 251eb10769f..753892d29c9 100644 --- a/TODO/how-to-pretend-youre-a-great-designer.md +++ b/TODO/how-to-pretend-youre-a-great-designer.md @@ -1,138 +1,138 @@ > * 原文地址:[How to pretend you’re a great designer](https://thedesignteam.io/how-to-pretend-youre-a-great-designer-3625de90d79f) > * 原文作者:[Pablo Stanley](https://thedesignteam.io/@pablostanley?source=post_header_lockup) > * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner) -> * 译者: +> * 译者:[Changkun Ou](https://changkun.us/) > * 校对者: -# How to pretend you’re a great designer # -## Practical tips and principles to trick people into thinking you’re an industry thought leader. ## +# 设计师装逼指南 # + +## 假装成为行业思想领袖的经验和技巧 ## ![](https://cdn-images-1.medium.com/max/1000/1*8ted6GIeOq2hxnr9cxwtMw.gif) -Gabrielle will use delight until your pupils explode +> Gabrielle 将使用『喜悦』来解释全部的设计,直到你的瞳孔爆炸。 -### **Distract with delight** ### +### **使用『喜悦』来分散注意力** ### -Don’t know how to justify your excessive use of animations, clever copy, or generic *cute* illustrations? Just throw the word “delight” in the mix! Talk about how you understand the user’s psychology–how you’re creating an experience people will love. Who cares if your solution is not functional, expensive to build, or if there’s no data to back up your intuition. Remind everyone that you’re building a lasting and emotional connection with the user. +不知道如何解释你的过度使用动画、巧妙的抄袭,或者通用*可爱*的图案吗?只需要说它们通常伴随着『喜悦』就够了!谈谈你是如何理解用户的心理的 —— 如何打造一个人们会喜欢的体验。没有人关心你的方案是否功能健全、是否成本高昂,或者是否有数据支撑你的直觉。提醒所有人,你正在与用户建立持久的感情联系。 -***PRO TIP:*** *Show everyone a graph of Maslow’s Hierarchy of Needs and point out how the warm-and-fuzzy stuff is on the top.* +***装逼技巧:*** *向所有人展示 Maslow 的需求层次理论图,并指出最上层的『自我实现』是多么高层次的追求。* ![](https://cdn-images-1.medium.com/max/1000/1*U0hzgnxBdy6UWp-9mJsIOQ.gif) -Toby is a walking jargon-encyclopedia. - -### Confuse them using industry language ### +Toby 是一本活脱脱的百科全书. -Never mind that part of your job is making things easy to understand. Use phrases like *“A holistic approach”* or *“brand storytelling”* or other jargon that will keep people scratching their heads, afraid to ask what that even means. The more buzzwords you use, the less you have to explain your actual design thinking. +### 使用行业术语来迷惑他们 ### -If a stakeholder asks about your reasoning for a design, just say something like *“It’s social-minded, guided by our brand values, and built with personality to engage our users through empathy and emotional design”*, even when you’re just designing a coupon input box. +不要在意你的工作是否让事情变得容易理解。使用短语像『*整体分析*』或『*品牌故事*』亦或其他让人即摸不着头脑也不敢问是什么意思的行业术语。你使用的流行语越多,你就越不需要解释你的实际设计思路。 +如果一个利益相关人士询问你的设计理由,只要告诉他们诸如『这种设计以社会为导向,以品牌价值为指导,围绕其特性所建立,从而通过共鸣和情感设计来吸引用户』之类的话就可以了,哪怕你只是在设计一个优惠券的输入框。 ![](https://cdn-images-1.medium.com/max/1000/1*QsVGLGmSStDhlhNY_LKM9w.gif) -Fran advises to be, above all, consistent! +Fran 建议:首先,要保持一致! -### Use Consistency as your ONLY guiding principle ### +### 使用一致性作为你的唯一指导原则 ### -Ignore context––consistency is more important! Your users might have become familiar with iOS, Android, or web patterns but those patterns go against your style guide. You have to be consistent, even if it means the user needs to learn new ways of doing things––they have to check out your unique and sophisticated drop-down menu. +忽略情景 —— 一致性更重要!也许你的用户已经熟悉了 iOS、Android 或 Web 模式,但这些模式与你的设计风格是不一样的。你必须保持设计的一致,即便是需要增加用户学习成本 —— 但他们必须查看你独特且复杂的下拉菜单。 -If your PM asks for a design that is best suited for mobile, just say that you’re striving for consistency. And, can’t the developer just make everything responsive and stuff? Being consistent allows you to not think of different solutions for specific scenarios––you can just copy-paste from the kitchen sink and call it a day! +如果你的产品经理想要一个最适合移动端的设计,只需要说你正在努力让所有平台的设计保持一致。开发者难道不能让所有元素都做到响应式吗?保持一致性可以让你不用考虑特定场景下的不同解决方案 —— 你只用从所有的东西里复制粘贴就算是完成一天的工作了! ![](https://cdn-images-1.medium.com/max/1000/1*hm7Fr-D0-u4Rav6Og-hmLA.gif) -Paul understands aesthetics +Paul 理解美学。 -### **Make aesthetics a priority over functionality** ### +### **美学优于功能** ### -Forget about solving the problem with a flow that actually works. Obviously, you just need to copy all those flashy, unpractical effects you saw on Dribbble and apply them to your design. Who cares if research shows that sole icons are inefficient and hard to memorize or that stock photos rarely add value? Stakeholders will be so wowed by all the bouncy animations, Apple-like white space, and left-aligned Swiss types that no one will question if it even works. +忘记用实际有用的工作流程来解决问题。显然,你只需要复制所有在 Dribbble 上看到那些华而不实的效果,并将其运用到你的设计之中。没有人关心调查显示的单个图标效率很低且很难被记住,以及库存的图片根本没有价值这些结论。所有的利益相关者都会因为那些具有弹性动画、像苹果一样的大量留白,和左对齐的瑞士主义设计风格一样感到震惊,没有人会怀疑它能否奏效。 ![](https://cdn-images-1.medium.com/max/1000/1*BVWmKNOrZ5uVQs9YU2Hw-Q.gif) -Gabrielle uses her magic to turn other products’ solutions into her own! +Gabrielle 用她的魔力将其他产品的解决方案变成了自己的! -### **Learn (copy) from the best** ### +### **学习(照搬)最佳实践** ### -Don’t know how to solve a problem? Just replicate the solution from Amazon, Apple, or Facebook and apply your own style on top of it. When someone challenges you, just say *“that’s how Amazon does it”*. That will teach them to keep questions to themselves next time! If it worked for Amazon, it must work for you, right? Who cares if you’re not even a marketplace or e-commerce product. +不知道如何解决问题?只需要复制亚马逊、苹果或者 Facebook 的解决方案,并运用自己的风格即可。当有人质疑你时,只要说 *『亚马逊就是这么干的』*。这将教会他们将问题保留到下一次再提问!如果它适用于亚马逊,它肯定适合你,对吧?因为根本没有人在乎你搞的是不是一个电商产品。 ![](https://cdn-images-1.medium.com/max/1000/1*_rH6r2v-eKIY9doQOz86jw.gif) -Claude knows how to make a pie chart! +Claude 知道如何制作一个饼状图。 -### **Use research bias** ### +### **使用调查偏差** ### -Do you have to justify that design that you spent time on all week? Just create a beautiful graph with cherry-picked data from a survey or test you conducted. The bigger the numbers, the more you’ll impress people with your interpretation! +你是否必须为你花了一整个星期时间搞出来的设计辩护?只需用你进行过的调查或测试中精心挑选的数据创建一个花哨的图表就可以了。数字越大,你的解释就会让人们的印象越深刻! -If anyone asks to see your methods or sources or wants to see the raw data, just tell them you should take that conversation offline and avoid them for the rest of the month. +假如有人要求查看你的方法或来源或想要查看原始数据,只需告诉他们你们的对话应该结束了,然后在这个月剩下的时间里躲避他们就好。 -***PRO TIP:*** *If you have the skills, make a spurious correlation slide that will have everyone nodding their heads. E.g. “The bounce rate of our landing page correlates with the downloads of Pokemon Go, therefore, we should add Augmented Reality to our page”.* +***装逼技巧:*** *如果你有能力,做一个假的幻灯片,让大家接受你的结论。 比如,『我们的登录页的跳出率与 Pokemon Go 的下载量相关,因此我们应该将增强现实添加到我们的页面』。* ![](https://cdn-images-1.medium.com/max/1000/1*mgeKX-DlW-obHhFUGBB6xA.gif) -Fran looks at her work in deep silence. +Fran 在沉默中看着她的工作。 -### **Make people think you’re busy** ### +### **让人们觉得你很忙** ### -There’s nothing better than having a wall full of other people’s work to impress passers-by. Print screenshots of other products and call it “competitive analysis”. Add all your Pinterest pins from other talented designers and call it “inspiration”. Make collages of all the terrible iterations you explored and call it “ideation”. Go for quantity, not quality. It doesn’t matter if what’s pinned to the wall makes any sense or if there’s any actual substance. The important thing is to make people believe that you have a creative and busy mind. +没有什么比满墙贴满他人的作品更能给路人留下深刻印象的了。打印其他产品的截屏,这叫『竞品分析』;把所有的 Pinterest 上有才华的设计都放上去,这叫『灵感来源』;把所有你探索过的糟糕的迭代过程做成拼图放在一起,这叫『想法形成』。始终追求数量,而不是质量。不管是有意义还是没意义的,钉上在墙后都是有意义的。重要的是要让人们相信你有一个有创造力且忙碌的头脑。 -***PRO TIP:*** *Stare at the wall for hours in silence. Your coworkers will think you’re really contemplative.*[*Draw eyes on your eyelids*](https://www.youtube.com/watch?v=U6qBnykH0DU) *and you can sleep while doing this.* +***装逼技巧:*** *默默地盯着墙看几个小时,你的同事会认为你在沉思。如果你**[在你的眼皮上画上眼睛](https://www.youtube.com/watch?v=U6qBnykH0DU),还能打会盹儿。* ![](https://cdn-images-1.medium.com/max/1000/1*gB-SyYrl3WXBYDW2Up7lWQ.gif) -Petunia is becoming a great designer! +Petunia 马上就要成为一个伟大的设计师了! -### Use ambiguous visuals ### +### **使用模棱两可的视觉表现** ### -Everybody can draw a Venn Diagram, but can they do it with perfect equilateral triangles? +大家都会画韦恩图,但他们能用完美的等边三角形来做吗? -Impress your coworkers with a double ▲▲ or a triple▲▲▲ triangle diagram. It won’t only make everyone nod at your confusing concepts, but it will establish you as a creative mind that uses simplicity to explain complex ideas. +你可以使用双重 ▲▲ 甚至三重 ▲▲▲ 三角形图来打动你的同事。这不仅会让每个人都同意你偷换的概念,还会让他们觉得你你具有创造性思维,并用简单的方式解释复杂的想法。 -***PRO TIP:*** *Always put the word “VALUE” in the overlapping area of the diagram!* +***装逼技巧:*** *总是将『价值』写在图标相交的区域里!* ![](https://cdn-images-1.medium.com/max/1000/1*VImvvTlomv4aX8E_UbUlUQ.gif) -Paul knows how to create a tailor-made product. +Paul 知道如何创建一个量身定做的产品。 -### **Misinterpret Human-Centered Design** ### +### **扭曲用户中心设计** ### -You’re not a modern designer if you don’t use Human-Centered Design (HCD for pros). And when I say “use”, I actually mean “talk about it”. Lecture everyone about how they need to understand the needs and abilities of the users. How building empathy is crucial to creating meaningful products. Who cares if other things have been successfully designed in the past without this approach? Don’t bother if this process might not be the best for you. Never mind if tailoring a product to a certain demographic can alienate others. It doesn’t matter if sometimes it’s in the user’s best interest if you ignore their suggestions. Better to impress everyone with how deeply you *care* about the user. +如果你不用『用户中心设计』(HCD),那么你不够现代。当我们谈论『用』时,我们实际在谈论『讨论它』而已。让每个人都知道他们需要如何理解用户的需求和能力。如何建立共鸣对创造有意义的产品至关重要。如果没有用户中心设计,谁还会在意其他事情是否已经成功地设计好了呢?不用在意这个方法是否适合你,更不用在意如果把产品定制为某种特定的人群是否会疏远他人。如果你忽略了他们的建议,这并不重要。用你是多么地『*关心*』用户来打动大家就可以了。 ![](https://cdn-images-1.medium.com/max/1000/1*J0AFQkt36gUyNqjaFm3lIw.gif) -Paul sure understands his main user. +Paul 确实了解他的主要用户。 -### **Stay focused on your market, which is you** ### +### **专注你的市场** ### -Oh, crap. They actually believed you on the whole human-centered thing and now they want an accessible design? Don’t worry, just point out that making a site accessible can take a long time and money. Say that your target market has state-of-the-art computers and internet connection, and they’re all healthy millennials that never even see the doctor. How do you know? You’re one of them! You’re exactly like your users! +好吧,他们信任你的那套『用户中心设计』了,现在他们想要一个无障碍设计怎么办?不要担心,你只需要指出,对网站进行无障碍需要花很长时间和很多钱。然后假设你的目标市场有着最先进的计算机和互联网连接,而且用户都是健康、甚至都没有见过医生的 00 后就可以了。你怎么知道的?因为你是他们中的一员!你自己就是用户! -And, let’s be honest, accessible design could keep you away from all those marvelous scroll-jacking animations you added to your landing page. +而且,老实说,无障碍设计可能让你永远没法在页面上添加的那些炫酷动画了。 -> Text labels? Ugly! -> High contrast combinations? Awful! -> Clear navigation? Despicable! +> 文本标签?太丑了! +> 高对比度组合?很糟糕! +> 清晰的导航?毫无意义! -Don’t concern yourself with reaching a bigger audience by making your design accessible, or with how it actually improves usability or makes your site SEO friendly. You need those parallax animations and that subtle low-contrast color palette that works only on a thunderbolt display. +不用担心那些为了能获得更多受众而进行的无障碍设计、可用性提升,或者是让网站变得 SEO 友好。你只需要使用视差滚动效果和一台具有精细的低对比度调色板的雷电接口的显示器就足够了。 -### On a serious note ### +### 严肃的说 ### -While all of these “tips” are meant to be tongue-in-cheek, they illustrate sins I myself have committed in the past. And I could say that it’s just a byproduct of how we’re all figuring stuff out as we go. That we’re experimenting with different things, seeing what works and what doesn’t–adapting to the ever-changing user’s needs and technology. And all would be understandable on the surface, but deep down, I have to admit… I sometimes don’t know if what I’m doing is right. +而上面所有这些『技巧』都是不靠谱的,它们其实展示了我自己曾经犯过的错误。可以这么说,这些只是我们所做的一切事情的副作用。我们正在不断尝试不同的事物,看看什么是有效的、什么是不适应不断变化的用户的需求和技术。从表面上看,一切都是可以理解的,但我必须承认,我有时不知道我所做的事情是否正确。 -Do you ever feel like that? Fear of the moment when everyone realizes you’re some kind of fraud? That you’re in the process of faking-it-till-you-make-it? I recently learned they call it the “Impostor Syndrome”. I had never felt this as strongly as when I moved to San Francisco. As soon as I started working at a startup, I realized there was a lot I needed to learn. I found myself feeling insecure and lost–utilizing my charm to get other people’s approval. I didn’t think my design work was enough. +不知道你是否有这样的感觉:当所有人都意识到你是一个骗子的时候,你是否会感到害怕吗?你是否曾今假装自己能做到?我最近听说这叫『骗子综合症』。我从来没有像搬到旧金山之后感受如此强烈。当我开始在一家创业公司工作时,我发现我需要学习很多东西。我感到不安,且失去了利用我的个人魅力来获得别人认可的能力。所以我觉得我的设计工作还做得不够好。 -But anyway, I believe it’s getting better. Or at least I’ve gotten better at pretending. +无论如何,我相信情况正在好转。或者至少我已经变得更加善于伪装了。 -**The Design Team** +**设计团队** -New comic every other Taco Tuesday at[thedesignteam.io](http://thedesignteam.io) -[Subscribe](http://eepurl.com/cbWwtz) to get my spam.I’m [Pablo Stanley](https://twitter.com/pablostanley) . Among many things, I teach [courses on design](https://www.youtube.com/c/sketchtogethertv) , and I work on a healthcare startup called [Carbon Health](https://carbonhealth.com/). +- [thedesignteam.io](http://thedesignteam.io) 上的漫画每周二更新。 +- 我是 [Pablo Stanley](https://twitter.com/pablostanley) 。点击 [订阅](http://eepurl.com/cbWwtz) 可以收到我的『垃圾邮件』。我教授一门 [设计课程](https://www.youtube.com/c/sketchtogethertv),同时我还在一家名为 [Carbon Health](https://carbonhealth.com/) 的医疗保健创业公司工作。 -Thanks to [Courtney M. Sawyer](https://medium.com/@courtneymsawyer) , [Michael Lorton](https://medium.com/@michaellorton) , [Edgar chaparro](https://medium.com/@Echaparro), and [Frances Tung](https://medium.com/@francestung) for all their support. +- 感谢 [Courtney M. Sawyer](https://medium.com/@courtneymsawyer) , [Michael Lorton](https://medium.com/@michaellorton) , [Edgar chaparro](https://medium.com/@Echaparro), 和 [Frances Tung](https://medium.com/@francestung) 的全部支持。 > [Read Previous: The Design Process](https://thedesignteam.io/the-design-process-67df3e8ec68f#.lv47slyvv) > [Another cool one: From a Product Perspective](https://thedesignteam.io/from-a-product-perspective-2f5185a43827) > [The First One: The Onboard-a-Buddy](https://medium.com/the-design-team/the-onboard-a-buddy-71169e460f04#.iru2t3tub) -Thanks to Edgar Chaparro, Michael Lorton, and Courtney Sawyer. +- 感谢 Edgar Chaparro, Michael Lorton 以及 Courtney Sawyer. --- From 9cf7db05e5224b78d44674f1479d822c50911adb Mon Sep 17 00:00:00 2001 From: Romeo Date: Sun, 30 Apr 2017 23:06:04 +0800 Subject: [PATCH 008/253] =?UTF-8?q?=E7=BF=BB=E8=AF=91=E5=88=9D=E7=A8=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO/designing-html-apis.md | 102 +++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/TODO/designing-html-apis.md b/TODO/designing-html-apis.md index b185c4b7c6b..72eda8f5f61 100644 --- a/TODO/designing-html-apis.md +++ b/TODO/designing-html-apis.md @@ -1,23 +1,35 @@ > * 原文地址:[HTML APIs: What They Are And How To Design A Good One](https://www.smashingmagazine.com/2017/02/designing-html-apis/) * 原文作者:[Lea Verou](https://www.smashingmagazine.com/author/lea-verou/) * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner) -* 译者: +* 译者:[王子建](https://github.com/Romeo0906) * 校对者: # HTML APIs: What They Are And How To Design A Good One # +#何为 HTML API,如何设计之?# + As JavaScript developers, we often forget that not everyone has the same knowledge as us. It’s called the [curse of knowledge](https://en.wikipedia.org/wiki/Curse_of_knowledge): When we’re an expert on something, we cannot remember how confused we felt as newbies. We overestimate what people will find easy. Therefore, we think that requiring a bunch of JavaScript to initialize or configure the libraries we write is OK. Meanwhile, some of our users struggle to use them, frantically copying and pasting examples from the documentation, tweaking them at random until they work. +作为 JavaScript 开发者,我们经常忘记并不是所有人都拥有像我们一样的学识。这被称为[知识的诅咒](https://en.wikipedia.org/wiki/Curse_of_knowledge):当我们精通某个内容的时候,我们就不记得自己作为新人的时候有多么困惑。我们总是对人们的能力估计过高。因此,我们认为自己写的那些需要一些 JavaScript 代码去初始化或者配置的类库是完全没问题的。然而,一些用户却在使用中费劲力气,他们疯狂地从文档中复制粘贴例子并随机组合这些代码,直到它们生效。 + You might be wondering, “But all HTML and CSS authors know JavaScript, right?” Wrong. Take a look at the results of [my poll](https://twitter.com/LeaVerou/status/690583334414635009), which is the only data on this I’m aware of. (If you know of any proper studies on this, please mention them in the comments!) +你或许会想,“但是所有写 HTML 和 CSS 的人都懂 JavaScript,对吧?”你错了。来看看我的[测验结果](https://twitter.com/LeaVerou/status/690583334414635009)吧,这是我所知道的唯一数据了。(如果你知道任何适用于这个主题的研究,请在评论中说明!) + ![](https://www.smashingmagazine.com/wp-content/uploads/2017/02/lea-verou-poll-tweet-opt.png) Poll: “How comfortable are you with JavaScript?” ([22 January 2016](https://twitter.com/LeaVerou/status/690583334414635009) +测试:“你对 JavaScript 好感如何?”([2016 年 1 月 22 日](https://twitter.com/LeaVerou/status/690583334414635009)) + One in two people who write HTML and CSS is **not comfortable with JavaScript**. One in two. Let that sink in for a moment. +每两个写 HTML 和 CSS 的人中就有一个**对 JavaScript 并无好感**。每两个中就有一个,让我们感受一下。 + As an example, look at the following code to initialize a jQuery UI autocomplete, taken from [its documentation](https://jqueryui.com/autocomplete/): +举个例子,看一下以下用来初始化一个 jQuery UI 自动完成库的代码,摘自[文档](https://jqueryui.com/autocomplete/)。 + ```
@@ -39,8 +51,12 @@ $( function() { This is easy, even for people who don’t know any JavaScript, right? Wrong. A non-programmer would have all sorts of questions going through their head after seeing this example in the documentation. “Where do I put this code?” “What are these braces, colons and brackets?” “Do I need them?” “What do I do if my element does not have an ID?” And so on. Even this tiny snippet of code requires people to understand object literals, arrays, variables, strings, how to get a reference to a DOM element, events, when the DOM is ready and much more. Things that seem trivial to programmers can be an uphill battle to HTML authors with no JavaScript knowledge. +这很简单,即使对根本不了解 JavaScript 的人来说也是这样,对吧?错。一个非程序员在文档中看到这个例子的时候,脑子里会闪过各种各样的问题。“我该把这段代码放哪儿呢?”“这些花括号、冒号和方括号是些什么鬼?”“我用得着这些吗?”“如果我的元素没有 ID 我该怎么办呢?”等等。即使这个微乎其微的代码段也要求人们了解对象字面量、数组、变量、字符串、如何获取 DOM 元素的引用、事件、 DOM 数何时构建完毕等等更多知识。对于程序员来说微不足道的事情,对没有 JavaScript 知识的 HTML 作者来说都是一场攻坚战。 + Now consider the equivalent declarative code [from HTML5](https://www.w3.org/TR/html5/forms.html#the-datalist-element): +现在来考虑一下 [HTML5](https://www.w3.org/TR/html5/forms.html#the-datalist-element) 中的等效声明性代码: + ```
@@ -57,84 +73,168 @@ Now consider the equivalent declarative code [from HTML5](https://www.w3.org/TR/ Not only is this much clearer to anyone who can write HTML, it is even easier for programmers. We see that everything is set in one place, no need to care about when to initialize, how to get a reference to the element and how to set stuff on it. No need to know which function to call to initialize or which arguments it accepts. And for more advanced use cases, there is also a JavaScript API in place that allows all of these attributes and elements to be created dynamically. It follows one of the most basic API design principles: It makes the simple easy and the complex possible. +这不光对于那些能够写 HTML 的人来说简单了不少,甚至对程序员来说更为简单。我们看到所有的东西都被写在一个地方,不必关心什么时候初始化,如何获取元素的引用和如何设置,无需知道哪个函数是用来初始化或者它需要什么参数。在更高级的使用中,还会在允许动态创建属性和元素的地方添加一个 JavaScript API。这遵循了一条最基本的 API 设计原则:它是的简单的事物变得容易,让复杂的事物变得可能。 + This brings us to **an important lesson about HTML APIs**: They would benefit not only people with limited JavaScript skill. For common tasks, even we, programmers, are often eager to sacrifice the flexibility of programming for the convenience of declarative markup. However, we somehow forget this when writing a library of our own. +这给我们上了一堂**关于 HTML API 的重要课程**:这不光使那些拥有有限的 JavaScript 技能的人受益。对于普通的任务,甚至我们,程序员,也会渴望牺牲程序的灵活性来换取更高的表述性。然而不知怎的,我们在写自己用的类库的时候却总是忘记这些。 + So, what is an HTML API? [According to Wikipedia](https://en.wikipedia.org/wiki/Application_programming_interface), an API (or application programming interface) is “is a set of subroutine definitions, protocols, and tools for building application software.” In an HTML API, the definitions and protocols are in the HTML itself, and the tools look in HTML for the configuration. HTML APIs usually consist of certain class and attribute patterns that can be used on existing HTML. With Web Components, even [custom element names](https://www.w3.org/TR/custom-elements/)are game, and with the [Shadow DOM](https://dom.spec.whatwg.org/#shadow-trees), those can even have an entire internal structure that is hidden from the rest of the page’s JavaScript or CSS. But this is not an article about Web Components; Web Components give more power and options to HTML API designers; but the principles of good (HTML) API design are the same. +那么什么是 HTML API 呢?根据[维基百科](https://en.wikipedia.org/wiki/Application_programming_interface)的定义,API(也就是应用程序接口)是“子程序定义、协议和构建应用软件的工具的合集”。在 HTML API 中,定义和协议都在 HTML 中实现,工具也在 HTML 中配置。HTML API 通常由特定的类和可用于先有的 HTML 的属性模式组成。通过 Web 组件(甚至[自定义元素名称](https://www.w3.org/TR/custom-elements/)都是游戏)和[Shadow DOM](https://dom.spec.whatwg.org/#shadow-trees),HTML API 甚至能拥有完整的内部结构,隐藏在页面其余的 JavaScript 或者 CSS 中。但是这并不是一篇关于 Web 组件的文章,Web 组件给予了 HTML API 设计者更多的能力和选择,但是良好的(HTML)API 设计原则都是相同的。 + HTML APIs improve collaboration between designers and developers, lift some work from the shoulders of the latter, and enable designers to create much higher-fidelity mockups. Including an HTML API in your library does not just make the community more inclusive, it also ultimately comes back to benefit you, the programmer. +HTML API 加强了设计师和工程师之间的合作,减轻工程师肩上的工作负担,还能让设计师创造更具有忠诚度的原型。在类库中引入 HTML API 不仅让社区更具包容性,最终还能反过来让程序员受益。 + **Not every library needs an HTML API.** HTML APIs are mostly useful in libraries that enable UI elements such as galleries, drag-and-drop, accordions, tabs, carousels, etc. As a rule of thumb, if a non-programmer cannot understand what your library does, then your library doesn’t need an HTML API. For example, libraries that simplify or help to organize code do not need an HTML API. What kind of HTML API would an MVC framework or a DOM helper library even have? +**并不是每个类库都需要 HTML API。**HTML API 在使用了 UI 元素的类库中非常有用,比如 galleries、drag-and-drop、accordions、tabs、carousels 等等。第一要务便是,如果一个非程序员不能理解你的类库是干什么的,那么它就不需要 HTML API。比如,那些简化代码或者帮助管理代码的类库就不需要 HTML API。那么 MVC 框架或者 DOM 助手类库应该用什么样的 HTML API 呢? + So far, we have discussed what an HTML API is, why it is useful and when it is needed. The rest of this article is about how to design a good one. +目前为止,我们只讨论了 HTML API 的定义、功能和用处,文章剩下的部分是关于如何设计一个好的 HTML API。 + ### Init Selector ### +### 初始化选择器 ### + With a JavaScript API, initialization is strictly controlled by the library’s user: Because they have to manually call a function or create an object, they control precisely when it runs and on what. With an HTML API, we have to make that choice for them, and make sure not to get in the way of the power users who will still use JavaScript and want full control. +在 JavaScript API 中,初始化是被类库的用户严格控制的:因为他们必须手动调用函数或者创建对象,他们精确地控制着运行的时间和基础。在 HTML API 中,我们必须帮用户做选择并且还要确保不会妨碍那些强势的仍然使用 JacaScript 并且想要得到完全控制权的用户。 + The common way to resolve the tension between these two use cases is to only auto-initialize elements that match a given selector, usually a specific class. [Awesomplete](http://leaverou.github.io/awesomplete) follows this approach, only picking up input elements with `class="awesomplete"`. +最常见的解决两种使用场景的办法就是只有匹配到一个给定的选择器,通常是一个特定的类,的时候才会自动初始化。[Awesomplete](http://leaverou.github.io/awesomplete) 就是采用的这种方法,只选取输入的具有 `class="awesomplete"` 的元素。 + In some cases, making auto-initialization easy is more important than making opt-in explicit. This is common when your library needs to run on a lot of elements, and when avoiding having to manually add a class to every single one is more important than making opt-in explicit. For example, [Prism](http://prismjs.com/) automatically highlights any `` element that contains a `language-xxx` class (which is what the HTML5 specification [recommends for specifying the language of a code snippet](https://www.w3.org/TR/html51/textlevel-semantics.html#the-code-element)) or that is inside an element that does. This is because it could be included in a blog with a ton of code snippets, and having to go back and add a class to every single one of them would be a huge hassle. +有些时候,把自动初始化变得简单比做详尽的选项说明更重要。这是一个很常见的现象,当你的类库需要在非常多的元素上运行的时候,避免手动给每个单独元素添加类比详细的选项说明更加重要。比如,[Prism](http://prismjs.com/) 自动高亮任何包含 `language-xxx` 类的 `` 元素(HTML5 的说明中[建议指定代码段的语言](https://www.w3.org/TR/html51/textlevel-semantics.html#the-code-element))以及其内部的元素。这是因为 Prism 可能会用在一个有着成千上万的代码段的博客系统中,回过头去给每一个元素添加类会是一项非常巨大的工程。 + In cases where the `init` selector is used very liberally, a good practice is to allow customization of it or allow opting-out of auto-initialization altogether. For example, [Stretchy](https://leaverou.github.io/stretchy)[13](#13) autosizes *every*``, `