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

伯乐在线 / 2018年10月04日 13:23

品牌

编译:伯乐在线/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. 需求模仿测验的代码越多,你的代码就越糟糕。为了测验一个特定的行为,需求实例化和牵扯的代码越多,代码越糟糕。咱们的方针是小型可测验的单元,以及更高等级的集成和功用测验,以测验各单元是否合作正确。

16. 面向外部的 API 是“预先规划”——一起要考虑未来的用例——真实重要的当地。改动 API 对咱们和用户来说是一种苦楚,形成向后不兼容是可怕的(虽然有时无法避免的)。规划面向外部的 API 要仔细,依然要坚持“把简略的作业做简略”的原则。

17.假如函数或办法超越 30 行代码,考虑分化它。一个杰出的模块最大约 500 行。测验文件往往比这个要大。

18 .不要在方针结构函数中作业,这儿很难测验并且常常发作意外。不要在__init__ .py中增加代码(导入命名空间在外)。__init__ .py不是程序员一般希望找代码的当地,所以它是个“惊喜”。

19. DRY(不要重复自己)在测验中没有在出产代码中要紧。单个测验文件的可读性比可保护性更重要(跳出模块复用的约束)。这是由于测验是独自被履行和阅览的,并且它们自己不是大体系的一部分。虽然在许多重复的时分创立可重用的组件更便利,但相较于产品代码,测验代码较少考虑。

20.每逢你看到有需求有时机就重构。编程是关于笼统的,你的笼统映射越挨近问题域,代码就越简略了解和保护。跟着体系的有机增加,需求改动结构以扩展它们的用例。体系越来越多的笼统和结构,假如不改动它们就成为技能性的债款。它会是愈加苦楚的作业(更慢,越来越多的过错)。在特性开发估量中请考虑铲除技能债款(重构)的本钱。你留传债款的时刻越长,堆集的利息就越高。关于重构和和测验的一本很棒的书是 Michael Feathers 的《修正代码的艺术》(《Working Effectively with Legacy Code》)。

21. 代码正确为第一位,速度快第二位。在处理功用问题时,在修正过错之前先要做功用分析。一般瓶颈不是你以为的那样。假如写不流畅的代码的仅有价值就是更快并且你现已做过功用分析并证明了,那么它实践就是值得的。编写测验守时检测你要做功用分析的代码,这样能够很简略让你知道你什么时分测验过。测验能够留在测验套件中,以避免功用退化。(一般状况下,增加守时代码总会改动代码的功用特性,使功用作业成为令人懊丧的使命之一。)

22. 当更小、规模有限的单元测验失利的时分,能够给出更多有价值的信息,通知你详细是什么过错。假如一个测验牵涉了半个体系来测验行为,那么它需求更多的查询以断定什么是过错的。一般来说,运转超越 0.1 秒的测验不是单元测验。没有所谓的慢单元测验。用限制规模的单元测验测验行为,你的测验行为扮演了事实上的代码标准。抱负状况下假如有人想了解你的代码,他们应该能够把测验套件转换为行为的“文档”。Gary Bernhardt 的《快测,慢测》(《Fast Test, Slow Test》)是关于单元测验实践的一篇很棒的讲演。

23. ”非我所创“不像人们说的那么坏。假如代码是咱们写的,那么咱们知道它是什么,咱们知道怎么保护它,在咱们能够在恰当的时分自由地扩展和修正它。这遵从了 YAGNI 原则:咱们用那些合适咱们需求用例的特定代码,而不必咱们不需求的能够做杂乱作业的通用代码。另一方面,代码是敌人,具有必要的代码比具有更多的代码更好。引进新的依靠联系时要权衡。

24. 同享代码一切权是咱们方针;缄默沉静的常识不是好常识。这意味着最低极限要评论或记载规划决议计划和重要的施行决议计划。代码评定(Code Review)是开端评论规划决议计划的最坏时刻,由于在代码编写后,很难完全更改。(当然在评守时指出并修正规划过错比没有好。)

25. 生成器很棒!它们一般比迭代或重复履行的状况方针更短更简略了解。David Beazley的《体系程序员的生成器窍门》(《Generator Tricks for Systems Programmers》)是关于生成器一个很好的介绍。

26.让咱们成为工程师!让咱们考虑规划、构建强健并完成杰出的体系,而不是做胀大的有机怪物。但是编程是一种平衡。咱们并不总是缔造火箭。过度规划(洋葱架构)同规划不完善的代码相同,处理起来十分苦楚。Robert Martin 的著作简直都值得一读,《架构之洁:一个工匠的软件结构和规划攻略》(《Clean Architecture: A Craftsman’s Guide to Software Structure and Design》)是这个论题一个很好的资源。《规划方法》(《Design Patterns》)是每一位工程师都应该阅览的经典编程书。

27. 间歇失利的测验会腐蚀测验套件的价值,以至于终究每个人都疏忽测验运转成果,由于总有一些失利的作业。修正或删去间歇性失利测验是苦楚的,但这些尽力是值得的。

28. 一般来说,特别是在测验中,在需求等候一个特定的改动时分不要选用休眠随机时刻的办法。Voodoo(Python 库) 的 sleeps 很难了解并且使你的测验套件变慢。

29. 至少让你的测验失利一次。成心参加一个过错,并保证它失利,或在测验的行为不完整的状况下运转测验。不然你不知道你真的在测验什么。瞎写的测验实践上不能测验任何东西或它很可能永久不会失利。

30. 终究一点:只重视特性改进是开发软件的一种可怕办法。假如开发者的作业不能保证最好的成果,那么不要让他们为自己的作业感到骄傲。不处理技能债款会使开发变慢并终究导致产品更糟,问题更多。

感谢 Ansible 团队,尤其是 Wayne Witzel,为改进这个列表中的原则而提出的定见和主张。

1. 中国品牌新闻网遵循行业规范,任何转载的稿件都会明确标注作者和来源;2. 中国品牌新闻网的原创文章,请转载时务必注明文章作者和"来源: 中国品牌新闻网",不尊重原创的行为 中国品牌新闻网或将追究责任;3.作者投稿可能会经 中国品牌新闻网编辑修改或补充。