点击上方“CSDN”,选择“置顶公众号”
关键时刻,第一时间送达!
我们最近编译并分析了一些最广泛使用的软件度量标准(你可以在此下载我们的报告https://www.codacy.com/ebooks/guide-to-code-reviews?ref=hackernoon)。作为工作的一部分,我们询问了我们的用户他们采取了什么捷径,哪些是后悔采用的。
1.复制代码
“我认为最有价值的规则是避免重复。有且仅有一次是极限编程里的说法。- Martin Fowler
这很容易成为头号规则。如果你想要你的代码坚如磐石,永世长存,那么重复的代码是破坏你目标的最好的方法。那是因为如果你在一个副本中发现一个错误,你必须在所有其他副本中修复它。这里假设你首先能找到他们,或者你甚至知道他们。这使得测试和调试的时间和成本都增加了。
注意事项:
目标是在产品环境中的零重复代码。你可能不会达到100%,但这是一个有价值的目标。
分解,分解和再分解代码。
测试,测试和再测试你的代码。
进阶思考:
重构,Martin Fowler。
https://martinfowler.com/books/refactoring.html
“在代码复制上实现闭环”。
http://blog.robertelder.org/coming-full-circle-on-code-duplication/
何时代码重复是可接受的(Fagner Brack,2016)。
https://hackernoon.com/when-code-duplication-is-acceptable-51ce33ecd0f5
2. 没有测量或管理--代码复杂度
"复杂度杀手。复杂度不断吞噬着开发者的生命,它使得产品很难做计划,很难构建和测试,同时它也引入了安全性威胁,并且让用户和管理者感到沮丧。" -- Ray Ozzie
代码复杂度的一个衡量方式是循环复杂度。它是指代码可以通过的逻辑分支的数量。实际中,它经常近似于 IF、WHILE、FOR、FOREACH 等类似表达式的数量。
想一下就知道一个方法中控制状态越多,它就越复杂,别人也就很难读懂和明白,因此事与愿违的风险也就越高。
注意事项:
紧盯循环复杂度。就像任何软件度量,他们虽不是那么完美,但至少标识出了潜在危险区域并有可能引发合理的重构。
一定要记住:一个方法或类从来都不会太小。
尽可能地,遵从单一任务原则(single responsibility principle:https://en.wikipedia.org/wiki/Single_responsibility_principle)。
进阶思考:
路径测试:独立路径,Jeff Nyman。
http://testerstories.com/2014/06/path-testing-independent-paths/
复杂度测量,Thomas J. McCabe. IEEE Transactions on Software Engineering, Vol. SE-2, No 4, December 1976.
http://www.literateprogramming.com/mccabe.pdf
3. 忘记代码设计
"构建软件设计有两种方法:一种是使它尽可能简单以至于没有明显的缺陷,另一种是使它尽可能复杂以至于看不出明显的缺陷。第一种方法更难以实现。" -- C.A.R Hoare
故事就像这样发生了:Bob X 编辑包 A , 包 A 依赖于包 B。Jonh Y 编辑包 B,然而包 B 又反过来依赖于包A。
好戏开始了...No,最好不要这样做。
代码设计是不同的包、模块、类和方法被互相连接在一起的方式。
要对此有一些思考:一个区域的代码如何被连接到其它区域的代码但却可以有效减少陷入叠积木游戏的几率。
注意事项:
没有银弹(silver bullet)。代码评审, 测试和少量代码度量(输入输出耦合, 到主序列距离等)的合理搭配可能会更有帮助。
进阶思考:
单一任务原则,Wikipedia.
https://en.wikipedia.org/wiki/Single_responsibility_principle
面向对象设计指标作为质量指示的验证,Basili et al. 1995.
https://pdfs.semanticscholar.org/77dd/b5c10e69b4e4104deb20e9d6888b31187c55.pdf
软件包装度量,Wikipedia article.
https://en.wikipedia.org/wiki/Software_package_metrics
迪米特法则,Wikipedia article.
https://en.wikipedia.org/wiki/Law_of_Demeter
设计原则和设计模式. Object Mentor. Robert C. Martin (2000).
http://www.cvc.uab.es/shared/teach/a21291/temes/object_oriented_design/materials_adicionals/principles_and_patterns.pdf
面向对象设计质量度量. 相关性分析. Robert C. Martin (1994).
https://linux.ime.usp.br/~joaomm/mac499/arquivos/referencias/oodmetrics.pdf
4. 没有测试,没有代码覆盖率
"程序测试能被用来发现 bug 的存在, 但从来不能证明不存在 bug 。" -- Edsger Dijkstra
检验测试并测试你的代码,单元测试、功能测试、回归测试,时刻关注代码覆盖率。
代码覆盖率的好坏取决于支撑它的测试代码,但它却是一个形成持续测试文化的好方法。同时也有其它一些好处:它提供了对代码一定级别的置信度,它也在开发周期帮助识别出需要更进一步测试的代码区域。
注意事项:
代码覆盖率的目标大约是 80% ,但是请记住:代码覆盖率的好坏取决于驱动它的测试代码的质量。
更高的代码覆盖率并不保证更高的代码质量,但是低代码覆盖率应该使你停下来想一下为什么。
开发者应该花大约 10% 的时间在单元测试上,直到达到目标代码覆盖率。
进阶思考:
测试有意思?真的吗!?(结论是:写测试代码可能并不是那么有意思,但最终会让你的开发过程受益)
https://www.ibm.com/developerworks/library/j-test/
代码覆盖率,Wikipedia.
https://en.wikipedia.org/wiki/Code_coverage
测试和代码覆盖率,Paul Johnson.
http://pjcj.net/testing_and_code_coverage/paper.html
5. 没有编码规范
我们从很明显的地方开始:好的代码是工作良好且容易维护、扩展和调试的代码。为了使代码容易维护、扩展或调试,那么代码必须易于阅读和理解。
如果有编码规范就容易写出像上述那样的代码,这就是为什么像谷歌这样的公司都采用在编码规范上有很大的投入。首先,通过限制选择,它消除了不必要的分心来源。开发人员可以专注于功能,而不是命名约定。它也让开发者们共享代码变得更容易。最后,编码规范提供了一定程度的可预测性:如果你的所有功能使用驼峰命名,那么任何人阅读你的代码都能知道` SendMessage `是一个函数,而不是参数或变量。
注意事项:
采用编码规范这个建议有时候有些争议,争议的双方都有有效的依据。一方认为编码规范的好处正如前文所述的那样。另一方则强调编码规范就像直夹克,对最终的产品没有影响。这两个论点都有其优点,因此在下一节中,我们将列出两个具有相反观点的文章。
进阶思考:
Coding standards horror story(标准编码的恐怖故事).
http://www.lhotka.net/weblog/CodingStandardsHorrorStory.aspx
Why I Have Given Up on Coding Standards(为什么我放弃了编码规范). Richard Rodger.
http://www.richardrodger.com/2012/11/03/why-i-have-given-up-on-coding-standards/
6. 注释太多,或者完全没有注释
“如果没人向你解说,所有的事情都是复杂的。” - Fredrik Backman
如果编写新代码是有趣的话,代码注释是我们大多数人宁可不做的一件繁琐的事情。在理想情况下,代码是非常明了的,不需要任何注释。但是,有时你需要澄清该代码的目的是什么。它使代码维护更容易,并促进项目上的协作。不管你怎么看,好的代码也意味着好的注释。因此,注释代码所需的时间应计入总开发时间。
注意事项:
太多的注释是适得其反的,这使得代码难以阅读和维护。
不要为每条注释的代码行数设置严格的指导原则,而应遵循一些常识规则,比如关于命名变量和方法的好的代码风格,自解释代码,以及偶尔的用于解释为什么这段代码要这么做的注释。
进阶思考:
注释的艺术 Bernhard Spuida, 2002.
http://www.icsharpcode.net/TechNotes/Commenting20020413.pdf
代码即文档。Martin Fowler. 2005.
https://martinfowler.com/bliki/CodeAsDocumentation.html
7. 没有代码评审或者代码评审时间过长
如果你阅读此条目,你可能知道代码评审有以下几个目的:
它们是确保代码质量的最佳实践。
他们促进团队协作
他们帮助应用代码标准
他们帮助在开发过程的早期识别错误。
他们帮助开发人员入职和学习。
但是,让我们从 McConnell 的《代码大全》一书中拿出一些坚实的、客观的数据点来说明下:
“… 单靠软件测试的效率是有限的 - 单元测试的平均缺陷检测率仅为 25% ,函数测试的平均缺陷检测率为 35% ,集成测试的平均缺陷检测率为 45% 。相比之下,设计和代码评审的平均效率分别是 55% 和 60% 。评审结果的案例研究令人印象深刻:
在一个软件维护机构中,在引入代码评审之前,55% 的单行维护变更是错误的。评审后,只有 2% 的变化是错误的。如果考虑到所有的变化,评审后第一次 95% 是正确的。在引入评审之前,第一次是低于 20% 是正确的。
在由同一群人开发的11个项目组中,前5个项目是在没有评审的情况下开发的。剩下的6个是通过评审的。在所有程序发布到产品之后,前5个平均每100行代码有4.5个错误。已经评审的6个平均每100行只有0.82个错误。评审把错误减少了 80% 以上。
Aetna 保险公司通过审查发现了项目中 82% 的错误,并能够将其开发资源减少 20% 。
IBM 的 50万行的 Orbit 项目使用了 11 个级别的审查。它是提前交付的,仅有约百分之一的正常预期的错误。
对 AT&T 中一个有200多人的组织进行的一项研究报告称,该组织在引入评审后,生产力提高了14%,缺陷减少了90%。
喷气推进实验室(Jet Propulsion Laboratories)估计,通过在早期发现和修复缺陷,每次审查可节省大约25,000美元。“
注意事项:
系统地应用代码评审,例如在每次提交时。另外,考虑在你的 Scrum 看板上添加一个评审专栏,并确保每个人都坚持下去,包括团队领导。
不同的人带来不同的观点,因此确保评审代码的人不总是相同的。
把代码评审分解成小的日常会议,并保持短期每周4-5小时是正确的。
进阶思考:
结对评审的七个真相 (Karl E. Wiegers).
http://www.processimpact.com/articles/seven_truths.html
代码大全 Code complete. (Steve McConnell).
https://www.amazon.co.uk/Code-Complete-Practical-Handbook-Construction/dp/0735619670
编码黑洞 Code Reviews: Just Do It. Link. Coding Horror.
https://blog.codinghorror.com/code-reviews-just-do-it/