Conversation
|
|
yufangong
left a comment
There was a problem hiding this comment.
Hey, thank you so much for doing this! This is awesome! I'm halfway through this PR and left some comments here. I'll finish reading soon.
| 这是一篇“活的”文档,我们会更新它,以反映我们当前的最佳实践,但核心的思想不太可能会变: 永远重视可读性;写泛化的代码但不要牺牲清晰度; | ||
| 利用简单的语言特性的威力,但避免晦涩难懂(尤其是类型系统)。最重要的,总要意识到你所做的取舍。一门成熟的(sophisticated)语言需要复杂的实现,复杂性又产生了复杂性:之于推理,之于语义,之于特性之间的交互,以及与你合作者之间的理解。因此复杂性是为成熟所交的税——你必须确保效用超过它的成本。 | ||
| 这是一篇“活的”文档,我们会更新它,以反映我们当前的最佳实践,但核心的思想不太可能会变:永远重视可读性;在不损失清晰度的前提下,编写通用的代码(generic code); | ||
| 使用简单却威力强大的语言特性,但避免使用晦涩难懂(尤其是类型系统)的特性。最重要的是对自己所做的取舍心中有数。精巧的语言需要复杂的实现,复杂性又产生了复杂性:之于推理,之于语义,之于特性之间的交互,以及与你合作者之间的理解。因此复杂性是为精巧的代价——你必须确保它带来的好处高于它的成本。 |
There was a problem hiding this comment.
s/但避免使用晦涩难懂(尤其是类型系统)的特性/但避免使其晦涩难懂(尤其是类型系统
| <dd> <code>i</code>s, <code>j</code>s 和 <code>k</code>s等可出现在循环中。</dd> | ||
| <dt>对作用域较长的变量使用长名字:</dt> | ||
| <dd>外部APIs应该用长的,不需加以说明便可理解的名字。例如:<code>Future.collect</code> 而非 <code>Future.all</code> | ||
| <dd>外部 APIs 应该用长的,不需加以说明便可理解的名字。例如:<code>Future.collect</code> 而非 <code>Future.all</code> |
| } | ||
|
|
||
| .LP 它很清晰的表达了 list中的元素都被映射,间接的方式让人不容易明白。 | ||
| .LP 它很清晰的表达了list中的元素都被映射处理,间接的方式让人不容易明白。 |
| 我们对类型系统的使用应当反映这一目标,但我们必须考虑到读者(译注:读你代码的人):明智地使用类型可以增加代码清晰度,而过份聪明只会让代码更加混乱。 | ||
|
|
||
| Scala的强大类型系统是学术探索和实践共同来源(例如[Type level programming in Scala](http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/)) 。但这是一个迷人的学术话题,这些技术很少在应用和正式产品代码中使用。它们应该被避免。 | ||
| Scala 强大的类型系统是学术探索和实践共同来源(例如[Type level programming in Scala](http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/)) 。虽然这是一个迷人的学术话题,但这些技术很少用于生产代码。应该避免使用它们。 |
There was a problem hiding this comment.
我认为 production code 在这里指产品代码,
“但这些技术很少应用于产品代码“ 如何?
| ### 返回类型注解(annotation) | ||
|
|
||
| 尽管Scala允许返回类型是可以省略的,加上它们提供了很好的文档:这对public方法特别重要。而当一个方法不需要对外暴露,并且它的返回值类型是显而易见的时候,则可以直接省略。 | ||
| 尽管 Scala 允许省略返回类型,但它们提供了很好的文档:这对 public 方法尤其重要。当方法不对外暴露,且其返回值类型显而易见时,可直接省略返回值类型。 |
| } | ||
|
|
||
| .LP 上面的make<em>不需要</em>定义返回类型为Service;编译器会创建一个加工过的类型: Object with Service{def getId:Int}(译注:with是Scala里的mixin的语法)。若用一个显式的注释: | ||
| .LP make 的返回类型<em>根本不是</em><code>Service</code>;编译器会为其创建一个加工过的类型:<code>Object with Service{def getId:Int}</code>。此时需要显式地添加返回类型: |
| mammals.add(new Cat{}) | ||
|
|
||
| .LP 这将不再是一个只存储狗(dog)的HashSet! | ||
| .LP 这将不再是一个 HashSet[Dog]!(译者注:在HashSet[Dog]中出现了Cat,失去了类型安全) |
| ### Future | ||
|
|
||
| 使用Future管理并发。它们将并发操作从资源管理里解耦出来:例如,Finagle(译注:twitter的一个RFC框架)以有效的方式在少量线程上实现并发操作的复用。Scala有一个轻量级的闭包字面语法(literal syntax),所以Futures引入了很少的语法开销,它们成为很多程序员的第二本能。 | ||
| 使用 Future 管理并发。它们将并发操作从资源管理里解耦出来:例如,Finagle(译注:twitter 的一个 RFC 框架)以有效的方式在少量线程上实现并发操作的复用。Scala 有一个轻量级的闭包字面语法,所以 Futures 引入了很少的语法开销,它们成为很多程序员的第二本能。 |
There was a problem hiding this comment.
Can you add the link here? [Finagle](https://github.com/twitter/finagle)
And I think it intended to say RPC 框架 here.
| *Future组合子(combinators)的使用*。当操作多个futures时,Future.select,Future.join和Future.collect应该被组合编写出通用模式。 | ||
| *使用 Future 组合子(combinators)*。当组合多个 futures 时,Future.select、Future.join 和 Future.collect 内置了许多常见模式。 | ||
|
|
||
| *不要在返回 Future 的方法中抛出自定义的异常*。Future 可同时表示成功或失败的计算,因此最好将计算中出现的错误封装在返回的 Future 中,具体而言,返回 Future.exception 而非将直接抛出异常: |
| 并发集合的主题充满着意见、微妙、教条、恐惧/不确定/怀疑(FUD)。在大多实际场景它们都不是问题:总是先用最简单、最无聊、最标准的集合解决问题。在没有确定同步集合不能满足需求前不要用并发集合:JVM 有着老练的手段来使得同步开销更小,所以它的效率能让你惊讶。 | ||
|
|
||
| 如果一个不可变(immutable)集合可行,就尽可能用不可变集合——它们是指称透明的(referentially transparent),所以在并发上下文推断它们是简单的。不可变集合的改变通常用更新引用到当前值(一个var单元或一个AtomicReference)。必须小心正确地应用:原子型的(atomics)必须重试(retried),变量(var类型的)必须声明为volatile以保证它们发布(published)到它们的线程。 | ||
| 如果可以用不可变(immutable)集合,就尽量用它——它们是引用透明的(referentially transparent),所以更容易在并发上下文中推断它们。不可变集合中的修改通常通过更新引用到当前值(一个var单元或一个AtomicReference)实现。必须小心正确地应用:原子型的(atomics)必须重试(retried),变量(var类型的)必须声明为 volatile 以防止它们发布(published)到其他线程。 |
It's been more than one year since the last updates of the Chinese version, now I make the following changes: