Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ _book
# other
.DS_Store

.idea
10 changes: 10 additions & 0 deletions zh/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
每个程序员都应该知道的97件事
======

*来自领先从业者的程序员智慧结晶。*

这是['每个程序员都应该知道的97件事'项目](http://programmer.97things.oreilly.com/wiki/index.php/97_Things_Every_Programmer_Should_Know)的[GitBook](https://www.gitbook.io)版本。

所有内容均根据[Creative Commons Attribution-NonCommercial-ShareAlike 3.0许可证](http://creativecommons.org/licenses/by-nc-sa/3.0/)授权。书籍的印刷版可在[Amazon.com](http://www.amazon.com/Things-Every-Programmer-Should-Know/dp/0596809484)上购买。

如果您发现任何错误或有任何建议,可以在[仓库](https://github.com/97-things/97-things-every-programmer-should-know)中[创建问题](https://github.com/97-things/97-things-every-programmer-should-know/issues)或[提交拉取请求](https://github.com/97-things/97-things-every-programmer-should-know/pulls)。
100 changes: 100 additions & 0 deletions zh/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# 摘要

* [介绍](README.md)
1. [谨慎行事](thing_01/README.md)
1. [应用函数式编程原则](thing_02/README.md)
1. [问“用户会怎么做?”(你不是用户)](thing_03/README.md)
1. [自动化你的编码标准](thing_04/README.md)
1. [美在于简洁](thing_05/README.md)
1. [重构之前](thing_06/README.md)
1. [小心共享](thing_07/README.md)
1. [童子军规则](thing_08/README.md)
1. [在责怪他人之前先检查你的代码](thing_09/README.md)
1. [谨慎选择工具](thing_10/README.md)
1. [用领域语言编写代码](thing_11/README.md)
1. [代码即设计](thing_12/README.md)
1. [代码布局很重要](thing_13/README.md)
1. [代码审查](thing_14/README.md)
1. [理性编码](thing_15/README.md)
1. [关于注释的评论](thing_16/README.md)
1. [只注释代码无法表达的内容](thing_17/README.md)
1. [持续学习](thing_18/README.md)
1. [便利性不是一种能力](thing_19/README.md)
1. [尽早且频繁地部署](thing_20/README.md)
1. [区分业务异常和技术异常](thing_21/README.md)
1. [进行大量刻意练习](thing_22/README.md)
1. [领域特定语言](thing_23/README.md)
1. [不要害怕破坏东西](thing_24/README.md)
1. [不要用测试数据耍小聪明](thing_25/README.md)
1. [不要忽略那个错误!](thing_26/README.md)
1. [不要只学习语言,理解其文化](thing_27/README.md)
1. [不要把你的程序钉死在直立位置](thing_28/README.md)
1. [不要依赖“魔法发生在这里”](thing_29/README.md)
1. [不要重复自己](thing_30/README.md)
1. [不要碰那段代码!](thing_31/README.md)
1. [封装行为,而不仅仅是状态](thing_32/README.md)
1. [浮点数不是实数](thing_33/README.md)
1. [通过开源实现你的抱负](thing_34/README.md)
1. [API设计的黄金法则](thing_35/README.md)
1. [大师神话](thing_36/README.md)
1. [努力工作不会带来回报](thing_37/README.md)
1. [如何使用缺陷跟踪器](thing_38/README.md)
1. [通过删除代码来改进代码](thing_39/README.md)
1. [安装我](thing_40/README.md)
1. [进程间通信影响应用程序响应时间](thing_41/README.md)
1. [保持构建干净](thing_42/README.md)
1. [知道如何使用命令行工具](thing_43/README.md)
1. [精通两种以上的编程语言](thing_44/README.md)
1. [了解你的IDE](thing_45/README.md)
1. [了解你的极限](thing_46/README.md)
1. [知道你的下一次提交](thing_47/README.md)
1. [大型互连数据属于数据库](thing_48/README.md)
1. [学习外语](thing_49/README.md)
1. [学会估算](thing_50/README.md)
1. [学会说“Hello, World”](thing_51/README.md)
1. [让你的项目为自己说话](thing_52/README.md)
1. [链接器不是一个神奇的程序](thing_53/README.md)
1. [临时解决方案的长寿](thing_54/README.md)
1. [使接口易于正确使用,难以错误使用](thing_55/README.md)
1. [让不可见的更可见](thing_56/README.md)
1. [消息传递在并行系统中带来更好的可扩展性](thing_57/README.md)
1. [给未来的信息](thing_58/README.md)
1. [多态性的缺失机会](thing_59/README.md)
1. [怪异新闻:测试人员是你的朋友](thing_60/README.md)
1. [一个二进制文件](thing_61/README.md)
1. [只有代码能说明真相](thing_62/README.md)
1. [拥有(并重构)构建](thing_63/README.md)
1. [结对编程并感受流程](thing_64/README.md)
1. [优先使用领域特定类型而非原始类型](thing_65/README.md)
1. [预防错误](thing_66/README.md)
1. [专业程序员](thing_67/README.md)
1. [将所有内容置于版本控制之下](thing_68/README.md)
1. [放下鼠标,远离键盘](thing_69/README.md)
1. [阅读代码](thing_70/README.md)
1. [阅读人文学科](thing_71/README.md)
1. [经常重新发明轮子](thing_72/README.md)
1. [抵制单例模式的诱惑](thing_73/README.md)
1. [通往性能的道路上布满了肮脏的代码炸弹](thing_74/README.md)
1. [简洁来自于减少](thing_75/README.md)
1. [单一职责原则](thing_76/README.md)
1. [从“是”开始](thing_77/README.md)
1. [退后一步,自动化,自动化,自动化](thing_78/README.md)
1. [利用代码分析工具](thing_79/README.md)
1. [测试所需行为,而非偶然行为](thing_80/README.md)
1. [精确而具体地测试](thing_81/README.md)
1. [在你睡觉时(和周末)测试](thing_82/README.md)
1. [测试是软件开发的工程严谨性](thing_83/README.md)
1. [状态思维](thing_84/README.md)
1. [两个脑袋通常比一个好](thing_85/README.md)
1. [两个错误可以变成一个正确(且难以修复)](thing_86/README.md)
1. [为你的朋友编写Ubuntu代码](thing_87/README.md)
1. [Unix工具是你的朋友](thing_88/README.md)
1. [使用正确的算法和数据结构](thing_89/README.md)
1. [冗长的日志会打扰你的睡眠](thing_90/README.md)
1. [WET稀释性能瓶颈](thing_91/README.md)
1. [当程序员和测试人员合作时](thing_92/README.md)
1. [编写代码时,假设你需要终身支持它](thing_93/README.md)
1. [使用示例编写小函数](thing_94/README.md)
1. [为人们编写测试](thing_95/README.md)
1. [你必须关心代码](thing_96/README.md)
1. [你的客户并不总是言出必行](thing_97/README.md)
15 changes: 15 additions & 0 deletions zh/thing_01/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 谨慎行事

> *“无论你承担什么任务,都要谨慎行事并考虑后果。” —— 无名氏*

无论一个迭代开始时的时间表看起来多么舒适,你都无法避免在某些时候处于压力之下。如果你发现自己必须在“正确完成”和“快速完成”之间做出选择,通常“快速完成”会更吸引人,因为你理解可以在以后回来修复它。当你对自己、团队和客户做出这个承诺时,你是认真的。但往往在下一个迭代中,新的问题会出现,你会把注意力集中在它们身上。这种被推迟的工作被称为技术债务,它并不是你的朋友。具体来说,Martin Fowler 在他的[技术债务分类](http://martinfowler.com/bliki/TechnicalDebtQuadrant.html)中将其称为故意技术债务,不应与无意技术债务混淆。

技术债务就像一笔贷款:你在短期内从中受益,但在完全还清之前,你必须支付利息。代码中的捷径使得添加功能或重构代码变得更加困难。它们是缺陷和脆弱测试用例的温床。你拖延得越久,情况就会变得越糟。当你终于开始处理最初的修复时,可能已经有一堆不太正确的设计选择叠加在原始问题之上,使得代码更难重构和修正。事实上,通常只有当事情变得非常糟糕以至于你必须修复时,你才会真正回去修复它。而到那时,修复往往变得非常困难,以至于你根本无法承担所需的时间或风险。

有时你必须为了赶在截止日期前完成任务或实现某个功能的薄切片而承担技术债务。尽量避免这种情况,但如果情况确实需要,那就去做吧。但是(这是一个很大的“但是”),你必须跟踪技术债务并尽快偿还,否则情况会迅速恶化。一旦你决定妥协,立即写一张任务卡片或在问题跟踪系统中记录下来,以确保它不会被遗忘。

如果你在下一个迭代中安排偿还债务,成本将是最小的。未偿还的债务会积累利息,这些利息应该被跟踪,以使成本可见。这将强调技术债务对项目业务价值的影响,并使偿还的优先级得到适当的安排。如何计算和跟踪利息的选择将取决于具体的项目,但你必须跟踪它。

尽快偿还技术债务。否则就是不谨慎的。

作者:[Seb Rose](http://programmer.97things.oreilly.com/wiki/index.php/Seb_Rose)
19 changes: 19 additions & 0 deletions zh/thing_02/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 应用函数式编程原则

函数式编程最近在主流编程社区中重新引起了兴趣。部分原因是因为函数式范式的*涌现特性*非常适合应对我们行业向多核转变所带来的挑战。然而,尽管这无疑是一个重要的应用场景,但这并不是本文劝诫你*了解函数式编程*的原因。

掌握函数式编程范式可以极大地提高你在其他上下文中编写的代码质量。如果你深入理解并应用函数式范式,你的设计将展现出更高程度的*引用透明性*。

引用透明性是一个非常理想的特性:它意味着函数在给定相同输入的情况下始终产生相同的结果,无论它们在何时何地被调用。也就是说,函数的求值过程较少依赖于可变状态的副作用——理想情况下,完全不依赖。

命令式代码中缺陷的一个主要原因是可变变量。阅读本文的每个人都曾调查过为什么在某些情况下某个值不符合预期。可见性语义可以帮助缓解这些潜在的缺陷,或者至少大大缩小它们的位置范围,但真正的罪魁祸首实际上可能是设计中过度使用可变性。

在这方面,我们当然没有得到行业的太多帮助。面向对象编程的入门教程默许了这种设计,因为它们通常展示的示例是由相对长寿命的对象图组成的,这些对象愉快地互相调用可变方法,这可能是危险的。然而,通过精明的测试驱动设计,特别是确保“模拟角色,而不是对象”,可以设计出不必要的可变性。

最终的结果是一个通常具有更好责任分配的设计,其中包含更多的小函数,这些函数作用于传递给它们的参数,而不是引用可变的成员变量。缺陷会更少,而且通常更容易调试,因为在这些设计中更容易定位到引入错误值的位置,而不是推断出导致错误赋值的特定上下文。这大大提高了引用透明性,而学习一门函数式编程语言是让这些理念深入骨髓的最佳方式,因为在这种计算模型中,引用透明性是常态。

当然,这种方法并非在所有情况下都是最优的。例如,在面向对象系统中,这种风格通常在领域模型开发(即协作有助于分解业务规则的复杂性)中比在用户界面开发中产生更好的结果。

掌握函数式编程范式,以便你能够明智地将所学到的经验应用到其他领域。你的对象系统(至少)将因引用透明性的优点而受益,并且比许多人让你相信的更接近函数式编程的对应物。事实上,有些人甚至断言函数式编程和面向对象编程的巅峰*仅仅是彼此的反映*,一种计算中的阴阳形式。

作者:[Edward Garson](http://programmer.97things.oreilly.com/wiki/index.php/Edward_Garson)
16 changes: 16 additions & 0 deletions zh/thing_03/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 询问“用户会怎么做?”(你不是用户)

我们往往倾向于认为其他人的思维方式与我们相同。但事实并非如此。心理学家将这种现象称为“虚假共识偏差”。当人们的想法或行为与我们不同时,我们很可能会(潜意识地)给他们贴上某种“缺陷”的标签。

这种偏差解释了为什么程序员很难站在用户的角度思考问题。用户的思维方式与程序员不同。首先,他们使用计算机的时间要少得多。他们既不了解也不关心计算机的工作原理。这意味着他们无法利用程序员所熟悉的各种解决问题的技巧。他们无法识别程序员在界面中使用的模式与线索。

了解用户思维方式的最佳方法是观察他们。让用户使用与你正在开发的软件类似的软件来完成一项任务。确保任务是一个真实的任务:“将一列数字相加”是可以的;“计算你上个月的开支”则更好。避免过于具体的任务,比如“你能选择这些电子表格单元格并在下面输入一个 *SUM* 公式吗?”——这个问题中已经给出了很大的提示。让用户一边操作一边讲述他们的进展。不要打断他们,也不要试图提供帮助。不断问自己:“他为什么要这样做?”以及“她为什么不那样做?”

你首先会注意到的是,用户在某些核心行为上是相似的。他们会以相同的顺序尝试完成任务——并且在相同的地方犯相同的错误。你应该围绕这些核心行为进行设计。这与设计会议不同,在设计会议上,人们往往会因为提出“如果用户想要……怎么办?”而受到关注。这会导致复杂的功能和对用户需求的混淆。观察用户可以消除这种混淆。

你会看到用户卡住。当你卡住时,你会四处寻找解决方案。而当用户卡住时,他们会缩小注意力范围。这使得他们更难看到屏幕上其他地方提供的解决方案。这也是为什么帮助文本对于糟糕的用户界面设计来说是一个糟糕的解决方案的原因之一。如果你必须提供说明或帮助文本,请确保将其放置在问题区域的旁边。用户注意力范围的狭窄性解释了为什么工具提示比帮助菜单更有用。

用户往往会凑合着用。他们会找到一种有效的方法,并坚持使用它,无论这种方法多么复杂。提供一个非常明显的操作方式,比提供两三个快捷方式更好。
你还会发现,用户所说的需求与他们实际的行为之间存在差距。这令人担忧,因为收集用户需求的常规方法是询问他们。这就是为什么捕捉需求的最佳方法是观察用户。花一个小时观察用户,比花一天时间猜测他们的需求更有价值。

作者:[Giles Colborne](http://programmer.97things.oreilly.com/wiki/index.php/Giles_Colborne)
20 changes: 20 additions & 0 deletions zh/thing_04/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 自动化你的编码标准

你可能也经历过这种情况。在项目开始时,每个人都有很多美好的愿望——可以称之为“新项目的决心”。通常,这些决心中的许多都会被记录在文档中。关于代码的部分最终会写入项目的编码标准中。在项目启动会议上,首席开发人员会逐条讲解文档,最好的情况下,大家都会同意尽力遵守这些标准。然而,一旦项目进入正轨,这些美好的愿望就会一个接一个地被抛弃。当项目最终交付时,代码看起来一团糟,似乎没有人知道为什么会变成这样。

问题出在哪里?很可能在项目启动会议上就已经埋下了隐患。一些项目成员没有认真听,另一些没有理解其中的要点。更糟糕的是,有些人不同意这些标准,并且已经在计划如何反抗这些编码标准。最后,有些人理解了并同意了这些标准,但当项目压力过大时,他们不得不放弃一些东西。格式良好的代码并不会让客户给你加分,尤其是当客户更关注功能时。此外,如果没有自动化,遵循编码标准可能是一项相当枯燥的任务。你可以试着手动为一个混乱的类进行缩进,自己体会一下。

但如果这是一个如此大的问题,为什么我们一开始还要制定编码标准呢?统一代码格式的一个原因是,没有人可以通过以自己私有的方式格式化代码来“拥有”某段代码。我们可能希望防止开发者使用某些反模式,以避免一些常见的错误。总的来说,编码标准应该让项目中的工作更加轻松,并保持开发速度从始至终。因此,每个人都应该同意编码标准——如果一个开发者使用三个空格缩进代码,而另一个使用四个空格,这并没有什么帮助。

有许多工具可以用来生成代码质量报告,并记录和维护编码标准,但这并不是完整的解决方案。应该尽可能地自动化并强制执行这些标准。以下是一些例子:

- 确保代码格式化是构建过程的一部分,这样每个人在编译代码时都会自动运行它。
- 使用静态代码分析工具扫描代码,查找不需要的反模式。如果发现任何问题,中断构建。
- 学会配置这些工具,以便你可以扫描项目中特定的反模式。
- 不仅要测量测试覆盖率,还要自动检查结果。如果测试覆盖率太低,再次中断构建。

尽量为你认为重要的所有事情都这样做。你无法自动化所有你真正关心的事情。对于那些你无法自动标记或修复的事情,可以将它们视为编码标准的补充指南,但要接受你和你的同事可能不会那么严格地遵循它们。

最后,编码标准应该是动态的,而不是静态的。随着项目的发展,项目的需求会发生变化,一开始看起来明智的做法,几个月后可能就不再明智了。

作者:[Filip van Laenen](http://programmer.97things.oreilly.com/wiki/index.php/Filip_van_Laenen)
28 changes: 28 additions & 0 deletions zh/thing_05/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 美在于简洁

有一句名言,我认为对所有软件开发人员来说都特别值得铭记于心:

> *风格之美、和谐、优雅和良好的节奏都依赖于简洁。* —— 柏拉图

我认为这句话总结了我们作为软件开发人员应该追求的价值。

在我们的代码中,我们追求许多东西:

- 可读性
- 可维护性
- 开发速度
- 难以捉摸的美感

柏拉图告诉我们,所有这些品质的促成因素都是简洁。

什么是美丽的代码?这可能是一个非常主观的问题。对美的感知在很大程度上取决于个人的背景,就像我们对任何事物的感知都取决于我们的背景一样。接受过艺术教育的人与接受过科学教育的人对美的感知(或至少是方法)是不同的。艺术专业的学生倾向于通过将软件与艺术作品进行比较来探讨软件中的美,而科学专业的学生则倾向于谈论对称性和黄金比例,试图将事物简化为公式。根据我的经验,简洁是双方大多数论点的基础。

回想一下你研究过的源代码。如果你没有花时间研究别人的代码,现在就停止阅读这篇文章,去找一些开源代码来研究。说真的!我是认真的!去网上搜索一些用你选择的语言编写的代码,这些代码是由一些公认的专家编写的。

你回来了吗?很好。我们说到哪儿了?啊,对了……我发现那些与我产生共鸣并且我认为美丽的代码有一些共同的特点。其中最主要的是简洁。我发现,无论整个应用程序或系统有多复杂,各个部分都必须保持简单。简单的对象只承担单一职责,包含同样简单、专注且具有描述性名称的方法。有些人认为五到十行代码的短方法是极端的,有些语言很难做到这一点,但我认为这种简洁仍然是一个值得追求的目标。

归根结底,美丽的代码就是简洁的代码。每个单独的部分都保持简单,职责简单,与系统其他部分的关系也简单。通过这种方式,我们可以保持系统的可维护性,使用干净、简单、可测试的代码,在整个系统的生命周期中保持较高的开发速度。

美生于简洁,也存在于简洁之中。

作者:Jørn Ølmheim
Loading