Keras之父写给年轻程序员的33条忠告
英文:https://medium.com/s/story/notes-to-myself-on-software-engineering-c890f16f4e4d
中文:https://mp.weixin.qq.com/s/6n07LwUk5YW6q0y53BMRRg
我本来想节选部分的,但是的确是字字珠玑,所以还是全文粘贴过来吧!
关于开发过程
- 代码不仅仅是用来运行的。代码也是跨团队交流的一种方式,是向他人描述问题解决方案的一种方式。良好的代码可读性不是那么容易做到的,但它是编写代码最基础的部分之一。良好的代码可读性包括清晰地分解代码,选择恰当的自解释变量名,添加注释来描述所有隐含的内容。
- 不要渴望你的 pull request 能为你赢得多少名声,而要多关注你的 pull request 能为你的用户和社区做些什么。要不惜一切代价避免“功利性的贡献”。如果你提交的功能对于这个产品想要达到的目的没有明显的帮助,就不要添加任何功能。
- 品味也适用于代码。品味是一种受约束的满足过程,这种满足是由对简单的渴望所约束的。保持对简单性的偏爱。
- 要学会说“不”——仅仅因为有人要求做某个特性,并不意味着你就应该这么做。每个特性都有一个超出初始实现的成本:维护成本、文档成本和用户的认知成本。我们要时刻提醒自己:我们真的应该这样做吗? 通常,答案是否定的。
- 当你准备答应实现一个新的使用场景时,请记住,仅从字面意思理解实现用户的需求通常不是最佳选择。用户关注的仅仅是他们自己的特定使用场景,你必须从整个项目的角度出发,兼顾整体性和原则性。通常,正确的做法是在现有特性的基础上做扩展。
- 不断进行持续集成,并以完整的单元测试覆盖为目标。确保你处在一个可以自信地编写代码的环境中;如果不是这样,那么你需要从构建正确的基础设施开始。
- 可以不事先计划好一切。先试一下,看看结果如何。尽早对错误的选择进行回退。当然,前提是确保你的开发环境可以做到这一点。
- 好的软件使困难的事情变得简单。问题一开始看起来很困难,并不意味着解决方案必须很复杂或者很难操作。在很多情况下,工程师给出的解决方案都是未经思考的,这就可能在有更简单的解决方案(虽然可能不那么明显)的情况下,带来不必要的复杂性(我们可以使用 ML!我们可以尝试构建一个应用程序!我们可以使用区块链!)。在编写任何代码之前,请确保你所选择的解决方案已经简单到不能再简单。做任何事情都要有本源思维。
- 避免隐式规则。应该明确说明你自己开发的隐式规则,并与他人共享。当你发现自己提出了一个重复的、准算法的工作流时,你应该设法将它标准化到一个文档中,以便其他团队成员能够从此经验中获益。此外,你应该在软件中尝试自动化任何可以自动化的工作流 (例如,正确性检查)。
- 在设计过程中应该考虑你选择方案的总体影响,而不仅仅是你希望关注的那些方面——比如收入或增长。除了你正在监控的那些指标之外,你的软件对其用户、对整个世界还会带来哪些影响? 是否存在超过价值主张的不良副作用? 在保持软件可用性的同时,你能做些什么来解决这些问题呢?
设计伦理,把你的价值观融入你的作品中。
API 的设计
- 你的 API 是有用户的,因此它事关用户体验。在你做的每一个决定中,都要考虑到用户。要站在用户的角度思考问题,无论他们是初学者还是有经验的开发人员。
- 总是想着让你的用户在使用 API 的过程中尽量减少认知负荷。自动化可以自动化的东西,最小化用户需要做的操作和选择,不显示不重要的选项,设计简单一致的工作流,反映简单一致的思维模型。
- 简单的事情要简单处理,复杂的事情应该尽量简单化。不要为了少量特殊的使用场景而增加普通使用场景的认知负荷,即使是最低限度的。
- 如果工作流的认知负荷足够低,那么用户在使用一到两次之后,应该可以凭记忆完成工作了 (无需查找教程或文档)。
- 寻求与领域专家和实践者的心智模型相匹配的 API。有领域经验但没有 API 经验的人应该能够使用最少的文档直观地理解你的 API,主要是通过查看一些代码示例,看看哪些对象可用,以及它们的特征是什么。
- 一个参数的含义应该是容易理解的,而不需要任何关于底层实现的上下文。必须由用户指定的参数应该与用户关于问题的心理模型相关,而不是与代码中的实现细节相关。API 只与它所要解决的问题有关,与软件在后台如何工作无关。
- 最强大的心智模型是模块化和层次化的:在高层次上很简单,但在细节上很精确。同样地,一个好的 API 也应该是模块化和层次化的:易于使用,但具有表现力。在更少的对象上有复杂的特性和具有更简单特性的对象之间有一个平衡。一个好的 API 要有合理数量的对象,并具有相当简单的特性。
- 你的 API 不可避免地反映了你选择的实现方式,特别是你选择的数据结构。要实现直观的 API,你必须选择自然适合其领域的数据结构——与领域专家的心智模型相匹配。
- 有意识地设计端到端工作流,而不是一组原子特性。大多数开发人员在设计 API 时都会问:我们应该提供哪些功能? 让我们为这些功能提供配置选项吧。恰恰相反,开发人员应该这样问:这个工具有哪些使用场景? 对于每个使用场景,用户操作的最佳顺序是什么? 支持这个工作流的最简单的 API 是什么? 你的 API 中的原子选项应该能够满足在高级工作流中出现的明显需求——不要“因为有人可能需要它”而添加某个功能。
- 错误消息,以及在与 API 交互过程中向用户提供的任何反馈,都是 API 的一部分。交互性和反馈是用户体验的一部分。需要谨慎的设计 API 的错误消息。
- 因为代码是一种交流方式,所以命名很重要——无论是命名项目还是变量。名字反映了你对问题的看法。避免使用过于通用的名称( x, variable, parameter),避免使用过于冗长和特定的命名模式,避免使用可能造成不必要误解的术语 (主、从),并确保你的命名选择方式是一致的。命名一致性意味着内部命名一致性 (不要在其他地方将“dim”称为“axis”) 和与问题域的既定约定的一致性。在确定名称之前,请确保查找领域专家 (或其他 API) 使用的现有名称。
- 文档是影响 API 用户体验的关键。它不是一个附加产品。着力产出高质量的文档,你将看到比开发更多功能带来的更高回报。
- Show, don 't tell:你的文档不应该讨论软件是如何工作的,它应该展示如何使用这个软件。显示端到端工作流的代码示例;为 API 的每个常见使用场景和关键特性展示代码示例。
生产力可以归结为快速决策和偏好行动。
软件职业生涯
- 事业的进步不在于你管理了多少人,而在于你产生了多大的影响:一个有你的工作的世界和一个没有你的工作的世界之间的差别。
- 软件开发是团队合作 ; 它不仅关乎技术能力,也关乎人际关系。做一个好队友。当你开始做事情的时候,要和别人保持沟通。
- 技术从来都不是中立的。如果你的工作可能对世界产生任何影响,那么这种影响是有道德导向的。我们在软件产品中做出的看似无害的技术选择有可能会影响获得技术的条件、使用动机、谁将受益、谁将受害。技术选择也是伦理选择。因此,对于你希望自己的选择支持的价值,一定要慎重和明确。基于道德准则来做设计,把你的价值观融入你的作品中。永远不要想,我只是在开发一种能力,这个能力本身是中性的。并不是因为你的开发方式决定了它将如何被使用。
- 自我指导——掌控你的工作和环境——是获得生活满足感的关键。确保你给你周围的人足够的自我导向,确保你的职业选择为你自己带来更大的回报。
- 创造世界所需要的,而不仅仅是你希望拥有的。技术人员往往过着精细化的生活,专注于满足自己特定需求的产品。寻找机会拓宽你的生活经验,这将使你更好地看到世界需要什么。
- 当做出任何具有长期影响的选择时,将你的价值观置于短期的自我利益和短暂的情绪之上——比如贪婪或恐惧。知道你的价值观是什么,让它们来引导你。
- 当我们发现自己陷入矛盾中时,应该停下来寻找我们共同的价值观和共同的目标,并提醒自己,我们几乎肯定站在同一条战线上。
- 生产力可以归结为快速决策和偏好行动。这需要 a) 来自经验的良好直觉,以便在给出部分信息的情况下做出普遍正确的决定 ; b) 对何时要小心地前进或等待更多信息要有敏锐的意识,因为一个错误的决定的代价将大于等待的代价。 在不同的环境中,最佳速度 / 质量决策权衡可能会有很大的差异。
- 快速做决定意味着在你的职业生涯中你能做出更多的决定,这会让你对哪一个备选项才是正确的选择产生更强的直觉。经验是生产力的关键,更高的生产力将为你提供更多的经验:这是一个良性循环。
- 在你意识到自己缺乏直觉的情况下,坚持抽象原则。在你的职业生涯中建立一个可靠的原则清单。原则是形式化的直觉,比原始模式识别适用于更广泛的情况 (这需要对类似情况有直接且广泛的经验)。