尹念念的博客

给年轻程序员的33条忠告

发布时间:2018-10-08 10:36:30阅读: 102024 评论数:

关于开发过程
  1. 代码不仅仅是用来运行的。代码也是跨团队交流的一种方式,是向他人描述问题解决方案的一种方式。良好的代码可读性不是那么容易做到的,但它是编写代码的基本部分。这涉及到清晰地分解代码,选择恰当的自解释变量名,插入注释来描述任何隐含的内容。

  2. 不要渴望你的 pull request 能为你赢得多少名声,而要多关注你的 pull request 能为你的用户和社区做些什么。要不惜一切代价避免“功利性的贡献”。如果你提交的功能对产品的意图没有明显的帮助,就不要添加任何功能。

  3. 品味也适用于代码。品味是一种受约束的满足过程,这种满足是由对简单的渴望所约束的。保持对简单性的偏爱。

  4. 要学会说“不”——仅仅因为有人要求做某个特性,并不意味着你就应该这么做。每个特性都有一个超出初始实现的成本:维护成本、文档成本和用户的认知成本。我们要时刻提醒自己:我们真的应该这样做吗? 通常,答案是否定的。

  5. 当你准备答应实现一个新用例时,请记住,仅从字面意思理解实现用户的需求通常不是最佳选择。用户关注的仅仅是他们自己的特定用例,你必须从整个项目的角度出发,兼顾整体性和原则性。通常,正确的做法是扩展现有的特性。

  6. 不断进行持续集成,并以完整的单元测试覆盖为目标。确保你处在一个可以自信地编写代码的环境中;如果不是这样,那么你需要从构建正确的基础设施开始。

  7. 事先不做好计划也是可以的。尝试一下,看看结果如何。尽早恢复错误的选择。当然前提是确保你的环境可以达到这样的目的。

  8. 好的软件使困难的事情变得简单。问题一开始看起来很困难,并不意味着解决方案必须很复杂或者很难操作。工程师经常使用反射式的解决方案,这会在有更简单解决方案 (虽然可能不太明显) 的情况下,带来不必要的复杂性 (我们可以使用 ML! 我们可以尝试构建一个应用程序! 我们可以使用区块链!)。在编写任何代码之前,请确保你所选择的解决方案不能变得更简单。做任何事情都要有本源思维。

  9. 避免隐式规则。应该明确说明你自己开发的隐式规则,并与他人共享。当你发现自己提出了一个重复的、准算法的工作流时,你应该设法将它标准化到一个文档中,以便其他团队成员能够从此经验中获益。此外,你应该在软件中尝试自动化任何可以自动化的工作流 (例如,正确性检查)。

  10. 在设计过程中应该考虑你选择方案的总体影响,而不仅仅是你希望关注的那些方面——比如收入或成长性。除了你正在监视的度量之外,你的软件对其用户、对世界的总体影响是什么? 是否存在超过价值主张的不良副作用? 在保持软件可用性的同时,你能做些什么来解决这些问题呢?

设计伦理,把你的价值观融入你的作品中。

API 的设计

  1. 你的 API 是有用户的,因此它有用户体验。在你做的每一个决定中,都要考虑到用户。要站在用户的角度思考问题,无论他们是初学者还是有经验的开发人员。

  2. 要保持让你用户使用 API 的过程中尽量减少认知负荷。自动化可以自动化的东西,最小化用户需要的操作和选择,不要显示不重要的选项,设计简单一致的工作流,反映简单一致的思维模型。

  3. 简单的事情要简单的处理,复杂的事情应该尽量简单化。不要为了小范围的用例而增加普通用例的认知负荷,即使是最低限度的。

  4. 如果工作流的认知负载足够低,那么用户在完成一到两次工作之后,应该可以靠记忆完成工作了 (无需查找教程或文档)。

  5. 寻求与领域专家和实践者的心智模型相匹配的 API。有领域经验但没有 API 经验的人应该能够使用最少的文档直观地理解你的 API,主要是通过查看一些代码示例,看看哪些对象可用,以及它们的特征是什么。

  6. 一个参数的含义应该是容易理解的,而不需要任何关于底层实现的上下文。必须由用户指定的参数应该与用户关于问题的心理模型相关,而不是与代码中的实现细节相关。一个 API 是关于它解决的问题,而不是关于软件在后台如何工作。

  7. 最强大的心智模型是模块化和层次化的: 在高层次上很简单,但在细节上很精确。同样地,一个好的 API 是模块化和层次化的: 易于使用,但具有表现力。在更少的对象上有复杂的特性和具有更简单特性的对象之间有一个平衡。一个好的 API 有合理数量的对象,具有相当简单的特性。

  8. 你的 API 不可避免地反映了你的实现选择,特别是你对数据结构的选择。要实现直观的 API,你必须选择自然适合其领域的数据结构——与领域专家的心智模型相匹配。

  9. 特意设计端到端工作流,而不是一组原子特性。大多数开发人员在进行 API 设计时都会问: 应该提供哪些功能? 让我们为它们提供配置选项。恰恰相反,他们应该这样问: 这个工具的用例是什么? 对于每个用例,用户操作的最佳顺序是什么? 支持这个工作流的最简单的 API 是什么? 你的 API 中的原子选项应该能够满足在高级工作流中出现的明显需求——它们不应该被添加,“因为有人可能需要它”。

  10. 错误消息,以及在与 API 交互过程中向用户提供的任何反馈,都是 API 的一部分。交互性和反馈是用户体验的一部分。需要谨慎的设计 API 的错误消息。

  11. 因为代码是一种交流方式,所以命名很重要——无论是命名项目还是变量。名字反映了你对问题的看法。避免使用过于通用的名称 (x、变量、参数),避免使用过于冗长和特定的命名模式,避免使用可能造成不必要误解的术语 (主、从),并确保你的命名选择方式是一致的。命名一致性意味着内部命名一致性 (不要在其他地方将“dim”称为“axis”) 和与问题域的既定约定的一致性。在确定名称之前,请确保查找领域专家 (或其他 API) 使用的现有名称。

  12. 文档是 API 用户体验的中心。它不是一个附加组件。着力产出高质量的文档;你将看到比开发更多的功能更高的回报。

  13. Show, don 't tell:你的文档不应该讨论软件是如何工作的,它应该展示如何使用它。显示端到端工作流的代码示例;为你的 API 的每个常见用例和关键特性展示代码示例。

生产力可以归结为快速决策和偏好行动。

软件职业生涯

  1. 事业的进步不在于你管理了多少人,而在于你产生了多大的影响:一个有没有你的工作的世界的差别。

  2. 软件开发是团队合作 ; 它不仅关乎技术能力,也关乎人际关系。做一个好的队友。当你开始做事情的时候,要和别人保持沟通。

  3. 技术从来都不是中立的。如果你的工作对世界有任何影响,那么这种影响是有道德导向的。我们在软件产品中做出的看似无害的技术选择调整了获得技术的条件、使用动机、谁将受益、谁将受害。技术选择也是伦理选择。因此,对于你希望你的选择支持的价值,一定要慎重和明确。设计伦理。把你的价值观融入你的作品中。永远不要想,我只是在建立能力 ; 它本身是中性的。这并不是因为你构建它的方式决定了它将如何被使用。

  4. 自我指导——掌控你的工作和环境——是获得生活满足感的关键。确保你给你周围的人足够的自我导向,确保你的职业选择为你自己带来更大的回报。

  5. 创造世界所需要的,而不仅仅是你希望拥有的。技术人员往往过着精细化的生活,专注于满足自己特定需求的产品。寻找机会拓宽你的生活经验,这将使你更好地看到世界需要什么。

  6. 当做出任何具有长期影响的选择时,将你的价值观置于短期的自我利益和短暂的情绪之上——比如贪婪或恐惧。知道你的价值观是什么,让它们来引导你。

  7. 当我们发现自己陷入矛盾中时,应该停下来寻找我们共同的价值观和共同的目标,并提醒自己,我们几乎肯定站在同一条战线上。

  8. 生产力可以归结为快速决策和偏好行动。这需要 a) 来自经验的良好直觉,以便在给出部分信息的情况下做出普遍正确的决定 ; b) 对何时要小心地前进或等待更多信息要有敏锐的意识,因为一个错误的决定的代价将大于等待的代价。 在不同的环境中,最佳速度 / 质量决策权衡可能会有很大的差异。

  9. 快速的做决定意味着在你的职业生涯中你会做出更多的决定,这会让你对可用选择的正确性有更强的直觉。经验是生产力的关键,更高的生产力将为你提供更多的经验: 一个良性循环。

  10. 在你意识到自己缺乏直觉的情况下,坚持抽象的原则。在你的职业生涯中建立一个可靠的原则清单。原则是形式化的直觉,比原始模式识别适用于更广泛的情况 (这需要对类似情况有直接且广泛的经验)。