专栏名称: 伯乐在线
关注职业资讯;学习各类职业感悟、心得和经验分享,扩大职业视野;体会求职、工作和创业的历程 - 就在JobBole.com 伯乐在线
目录
相关文章推荐
程序员的那些事  ·  湖南大学的 DeepSeek ... ·  2 天前  
程序员的那些事  ·  突发!4 个程序员被抓,维护赌博网站每月赚 ... ·  2 天前  
OSC开源社区  ·  深度实测Manus,我依然认为这就是AI ... ·  4 天前  
OSC开源社区  ·  30个小确幸(程序员版) ·  3 天前  
51好读  ›  专栏  ›  伯乐在线

软件开发和测试的 30 个最佳实践

伯乐在线  · 公众号  · 程序员  · 2019-11-13 20:30

正文

(给 伯乐在线 加星标,看经典文章

编译:伯乐在线/maifans

这些软件开发和测试的最佳实践,可以帮你节省时间和避免问题。

加入一个企业文化和编程实践已经定型的新公司,可能会是一种令人沮丧的经历。当我加入 Ansible 团队后,我决定整理我多年以来所学并为之奋斗的软件工程实践和准则。这是一个不明确的也不够详尽的准则列表,使用它们时需要智慧和灵活性。

我对测试充满热情,因为我相信良好的测试实践既能确保满足最低质量标准(可悲的是许多软件产品做不到),并能指导和塑造开发本身。本文提到的这些准则,很多是与测试实践和理念相关的。其中一些准则针对 Python 的,但大多数不是。(对于 Python 开发者,PEP 8 应该是编程风格和指南的首先。)

开发和测试的最佳实践

1. YAGNI 原则:“You Aint Gonna Need It”。不要写你认为将来可能需要但现在不需要的代码。 这是为 假想的未来用例 编码,这些代码将不可避免地变成死代码,或需要重写,因为未来结果 总是 与想象的稍有不同。

如果你写代码用于将来的用例,我将在代码评审中对其质疑。(你可能而且必须设计 API,并 确保 未来的用例可用,但这是不同的问题。)

这条原则也适用于被注释掉的代码;如果一个被注释掉代码块即将进入一个发布版本,那么它就不应该存在。如果代码可能要还原,请为代码删除创建一个问题单并引用提交对象的哈希字符串。YAGNI 原则是敏捷编程的核心要素,这个话题最好的参考书是 Kent Beck 写的《解析极限编程》(《Extreme Programming Explained》)。

2 . 测试不需要测试。 用于测试需要的基础设施、框架和库需要测试。除非你 真的需要 不要测试浏览器或外部库。测试你写的代码,而不是别人的代码。

3.当第三次编写相同的代码时,也是将其提取成通用的辅助函数(并为其编写测试)的正确时机。 测试中的辅助函数不需要测试;但当你将它们剔除出去然后再重用它们时,它们需要测试。到你第三次编写类似代码的时候,你通常会清楚地认识到你正在解决的通用问题的模型是什么。

4. 现在来谈谈 API 设计(面向外部的对象API): 把简单的事情做简单了,复杂的事情自然成为可能 。首先设计简单的用例,如果有可能最好是零配置或参数化。为更复杂和灵活的用例(如需要)增加 选项 或额外的 API 方法。

5. 快速失败。 检查输入,如果遇到无意义输入或非法状态则尽早失败,最好是通过异常或错误响应使问题对调用者变得清晰。允许你的代码处理“有创意”的用例(例如,除非真的需要,否则在做输入验证的时候不要做类型检查)。

6.单元测试测的是行为单元,而不是实现单元。 我们的目标是在改动实现的情况下不改动行为,也不必更新测试,尽管这个目标不总是能实现。因此在可能的情况下将测试对象视为黑盒,通过公共 API 测试,而不调用私有方法或玩弄状态位。

在一些复杂的情况可能做不到,如在特定的复杂状态下测试行为,以找到一个偶发的错误。这一点对于写测试非常有帮助,因为它迫使你在写测试代码之前思考你代码的行为以及你将如何测试它。测试首先鼓励更小,更模块化的代码单元,这通常意味着好代码。关于“测试优先”方法有一本很好的入门参考书,就是 Kent Beck 写的《测试驱动开发》(《Test Driven Development by Example》)

7. 对于单元测试(包括测试基础设施测试),所有代码路径都应该被测到。 100% 覆盖是一个好的开始。你不能覆盖所有可能状态的排列/组合(组合性爆炸),因此这个问题需要考虑。只有当有很好理由的情况下才允许有代码路径未经测试。没有时间 不是 一个好理由,最终会花费更多的时间。可能的好理由包括:真正的不可测(以任何有意义的方式),现实中不可能发生,或被其它测试覆盖。没有测试的代码是一种债。测量覆盖率和拒绝减少覆盖率 PR(拉取请求) 是确保你在正确的方向演进的一种方式。

8. 代码是敌人:它可能出错,并且需要维护。 少写代码,删除代码,不要写你不需要的代码。

9. 随着时间的推移,代码注释不可避免地成为谎言。 在现实中,很少有人在事情变化的时候更新注释。通过良好的命名法和已知的编程风格,努力使你的代码可读和自文档化。

对于那些晦涩的代码, 一定 要写注释,例如偶发错误或意外情况的变通方案,或者必要的优化。解释代码的 意图 和及其原因,而不是解释代码在做什么。(顺便说一句,有些观点认为注释变谎言是有争议的。我仍然认为这是正确的,《程序设计实践》(《The Practice of Programming》)的作者 Kernighan 和 Pike 同意我的观点。)

10. 防守思维。 总是考虑什么会出错,无效的输入会引发什么,什么可能会失败,这将有助于你在许多错误发生之前发现他们。

11.无状态和无副作用的单元测试,其逻辑应简单 。将逻辑分解成单独的函数,而不是将逻辑混合到有状态和充满副作用代码中。将有状态代码和有副作用代码,分为较小的更容易模拟的函数和无副作用地单元测试。(测试的开销越小意味着更快的测试)副作用 确实 需要测试,但是测试一次然后处处模拟它们通常是一个好的模式。

12. 全局变量不好。 函数优于类型。对象可能比复杂的数据结构更好。

13.使用 Python 内置类型及其方法将比自己编写的类型运行快(除非你用C语言编写) 。如果性能是一个考虑因素,请尝试弄懂如何使用标准的内置类型,而不是自定义对象。

14. 依赖注入是一个实用的编程模式,明确你的依赖是什么和它们来自哪里。(对象,方法等以参数的形式接收它们的依赖,而不是实例化新对象本身。)这确实让 API 签名更复杂,所以这里需要权衡。如果一个方法最后为所有的依赖设置了10个参数,那这是一个不错的信号,不管为什么你的代码做得太多。关于依赖注入的权威文章是 Martin Fowler 的《控制反转容器&依赖注入模式》(《Inversion of Control Containers and the Dependency Injection Pattern》)。

15. 需要模拟测试的代码越多,你的代码就越糟糕。 为了测试一个特定的行为,需要实例化和牵扯的代码越多,代码越糟糕。我们的目标是小型可测试的单元,以及更高级别的集成和功能测试,以测试各单元是否配合正确。







请到「今天看啥」查看全文