⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.cn/post/6844903886264729607 「唐子玄」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

你一定在内心、对其他同事或程序员朋友吐槽过别人的代码太烂:没注释、逻辑混乱、到处都是 magic number、实现方案过时、耦合严重、一改就出 bug。

此时心中的怒火油然而生,仿佛自己是正义的化身,要代表月亮消灭这样的代码,甚至拼写错误也可以成为你 diss 的点。稍等片刻,先抑制一下燃烧的小宇宙,你有没有认真想过到底什么样的代码才算的上优秀?

在看了 Gerald M. Weinberg 的《The Psychology of Computer Programming》(书籍中文名《程序开发心理学》)后让我有了不一样的认识。不过我觉得这是一个开放问题,不同情况下会有不同答案,欢迎讨论。

我曾经给好代码下的结论是:

❝

你这个周写的代码比上个周有进步,你这个月写的代码比上月有进步,你今年写的代码比去年有进步。

我认为,你应该就写出了基于当时来说,最好的代码。

今天,我们一起来看看国外大佬的对好代码的一些看法。

可行性

作者给出的第一个标准是“程序的可行性”,它是指对于任何一种约定的输入,程序都能给出期望的输出。毕竟可行的程序总比不可行的要好。在不满足可行性前提下的优越性能,高可扩展性都不值一提。

但不可否认的是,我们脑子里成天考虑的是这些次要问题。甚至会形成“不优雅就是垃圾”的价值观,好像只有这样才可以在内心自恃高人一等。获得这种莫须有的优越感的代价可能是写出了不可行的代码,捡了芝麻丢了西瓜。

引用一段原文:

❝

如果程序根本无法正常运转,对其效率、适应性及生产成本的评估就毫无意义。无论如何,我们需要务实一些,需要承认:也许根本没有哪个完美的程序曾经被写出来过。每一个真正大型和重要的程序都必然包含很多个纰漏。所以对程序进行评估时,必须考虑到其不完美的一面。

按时性

作者给出的第二个标准是“按时性”。

即使不考虑可行性的问题,效率的问题仍然不是最重要的。程序开发中经常遇到一个问题是要符合开发的日程计划,推迟完成的程序常常没有意义。

我们不得不比较一下,到底是一个可能在未来完成的高效程序带来的潜在节省更大,还是没有一个程序损失更大。现实中,往往是后者的损失更大。

真正困扰人们的并非是预先估计的平均开发时间,而是实际消耗时间的标准偏差。就好比大多数人宁可每天早上花固定的10分钟等公交车,也不愿意每周有4天只等1分钟,而最后一天等26分钟,尽管就平均等待时间而言,后一种方案只需要6分钟,但由于某次无法预测的长时间等待就会打乱计划,这点好处无法弥补其损失。所以宁可承诺一个更留有余地的排期,然后按时完成。而不是承诺一个满打满算的排期,然后delay。

开发过程中遭遇的各种意外导致实际消耗时间和预估时间形成方差,这一问题是值得我们深入思考的。如何提前感知不确定性,如何快速解决意外,是一项需要不断提升的能力以减小方差。

适应性 & 效率

作者给出的第三个标准是“适应性”,即程序的可扩展性。紧跟其后的标准是“效率”,即程序运行的性能。

总算轮到了本以为重要的标准,作者的一席话描述地入木三分:

❝

在软件生命周期内,多数程序都会被修改,无论其经验的多少,绝少有哪位程序员能反驳这一论断。既然如此,为什么在必须修改以前的程序时,我们总是觉得这项任务如此艰巨,以至于往往决定弃之不用,干脆自己从头写起呢?只要阅读过程序,我们就会透过这些程序发现:实际上,很少有哪位原作者会考虑可能的后续修改。

作者还提了两个问题来表达程序员的矛盾之处:

❝

在编写程序时,你曾经有多少次想到过它在未来可能被别人修改?反过来,在修改别人程序时,你又曾经咒骂够几回?

之所以把适应性和效率放在一起讨论,是因为它们俩会此消彼长,作者用 Fisher 定理来证明这个观点:

❝

Fisher定理:一个系统对某一特定环境适应性越强,它适应新环境的能力也就越弱。

❝

如果强调的是程序的效率,那么我们往往会追求紧密式的代码,而如果在未来要对这些代码进行修改,那将会非常棘手。如果使用的是更高层的语言,那么为了使程序更高效,我们往往需要深入到机器语言层。这种做法至少抵消了原本用更高层语言编程的一个好处 —— 在不同机器之间的可移植性。其实际效果是,我们将被局限于特定的某台计算机或特定的某个实现。

回想设计模式,无一例外是通过增加一层抽象以达到可扩展的目的,这样的设计增加了类的数量,类的构建和类方法调用的都会消耗空间和时间的性能,降低了效率。而且它让功能的实现变得更加间接,也增加了理解成本,降低了沟通效率。

但作者认为性能问题不是问题:

❝

运行效率正在成为计算中一个日益不明朗的问题,随着单位计算能力成本的逐年下降,以及单位程序开发成本的不断提高,在程序开发方面比在产品方面投资更多的典型做法,早已不合时宜。因此我们期望,随着岁月的推移,我们听到的关于效率的言论将会越来越少。

紧接着依然是两个耐人寻味的问题:

❝

你是否曾经因为追求效率而延误了工作进度?反过来,是否曾经因为要赶时间完成而没有做到尽善尽美?

但有趣的是,面试时,极少有公司是按照上述的优先级来考察候选人的,通常的考察优先级正好相反,即使有算法笔试也是把重点放在实现方案的内存性能或时间性能上,并不会对程序的正确性进一步追究。

下面是 GPT 认为的好代码:

  1. 可读性:代码应该易于理解,命名规范,结构清晰,有适当的注释。
  2. 简洁性:代码简洁,没有冗余的部分,避免过度复杂的逻辑。
  3. 可维护性:代码结构合理,模块化,便于后续的维护和升级。
  4. 可扩展性:代码设计灵活,能够容易地添加新功能或修改现有功能。
  5. 健壮性:代码能够处理异常情况,有错误处理机制,不会因为意外输入而崩溃。
  6. 性能:代码运行效率高,优化了性能瓶颈,不会无谓地消耗系统资源。
  7. 安全性:代码考虑了安全性,没有安全漏洞,如SQL注入、跨站脚本攻击等。
  8. 遵循规范:代码遵循了编程语言和项目特定的编码规范和最佳实践。
  9. 文档齐全:有完整的文档,包括代码注释、API文档、用户手册等。
  10. 测试覆盖:有充分的单元测试和集成测试,确保代码的正确性和稳定性。
  11. 可重用性:代码中的函数或类具有良好的封装性,便于在其他项目中重用。
  12. 版本控制:代码使用版本控制系统进行管理,如Git,便于追踪变更和协作。
  13. 持续集成/持续部署:代码集成了CI/CD流程,可以自动化测试和部署。
  14. 用户友好:如果代码是用户交互软件的一部分,那么它应该提供良好的用户体验。
  15. 可移植性:代码能够在不同的环境或平台上运行,没有硬编码的依赖。
  16. 注释质量:代码注释应该清晰、准确,能够解释代码的意图和复杂逻辑。
  17. 适当的复杂度:代码的复杂度应该适中,既不过于简单也不过于复杂,符合问题域的需要。
  18. 依赖管理:代码的外部依赖应该被明确管理,并且保持更新,避免安全漏洞。
  19. 资源管理:代码应该正确管理资源,如内存、文件句柄、数据库连接等,避免泄露。
  20. 代码审查:代码经过同行审查,以发现并修复潜在的问题。

好代码的定义可能会根据项目、团队和上下文的不同而有所变化,但上述特点提供了一个通用的指导原则。

文章目录
  1. 1. 可行性
  2. 2. 按时性
  3. 3. 适应性 & 效率