你必定在心里吐槽过他的代码太烂:没注释、逻辑混乱、处处都是 magic number、实现方案过期、耦合严重、一改就出 bug。程序员
此时心中的怒火油然而生,仿佛本身是正义的化身,要表明月亮消灭这样的代码,甚至拼写错误也能够成为你 diss 的点。稍等片刻,先抑制一下燃烧的小宇宙,你有没有认真想过“到底什么样的代码才算的上优秀?”面试
在看了 Gerald M. Weinberg 的《The Psychology of Computer Programming》后让我有了不同的认识。不过我以为这是一个开放问题,不一样状况下会有不一样答案,欢迎讨论。算法
这是代码人生系列的第一篇,文章目录以下:编程
做者给出的第一个标准是“程序的可行性”,它是指对于任何一种约定的输入,程序都能给出指望的输出。毕竟可行的程序总比不可行的要好。在不知足可行性前提下的优越性能,高可扩展性都不值一提。设计模式
但不能否认的是,咱们脑子里整天考虑的是这些次要问题。甚至会造成“不优雅就是垃圾”的价值观,好像只有这样才能够在心里自恃高人一等。得到这种莫须有的优越感的代价多是写出了不可行的代码,捡了芝麻丢了西瓜。post
引用一段原文:性能
若是程序根本没法正常运转,对其效率、适应性及生产成本的评估就毫无心义。不管如何,咱们须要务实一些,须要认可:也许根本没有哪一个完美的程序曾经被写出来过。每个真正大型和重要的程序都必然包含不少个纰漏。因此对程序进行评估时,必须考虑到其不完美的一面。设计
做者给出的第二个标准是“按时性”。生命周期
即便不考虑可行性的问题,效率的问题仍然不是最重要的。程序开发中常常遇到一个问题是要符合开发的日程计划,推迟完成的程序经常没有意义。内存
咱们不得不比较一下,究竟是一个可能在将来完成的高效程序带来的潜在节省更大,仍是没有一个程序损失更大。现实中,每每是后者的损失更大。
真正困扰人们的并不是是预先估计的平均开发时间,而是实际消耗时间的标准误差。就比如大多数人宁肯天天早上花固定的10分钟等公交车,也不肯意每周有4天只等1分钟,而最后一天等26分钟,尽管就平均等待时间而言,后一种方案只须要6分钟,但因为某次没法预测的长时间等待就会打乱计划,这点好处没法弥补其损失。因此宁肯承诺一个更留有余地的排期,而后按时完成。而不是承诺一个满打满算的排期,而后delay。
开发过程当中遭遇的各类意外致使实际消耗时间和预估时间造成方差,这一问题是值得咱们深刻思考的。如何提早感知不肯定性,如何快速解决意外,是一项须要不断提高的能力以减少方差。
做者给出的第三个标准是“适应性”,即程序的可扩展性。紧跟其后的标准是“效率”,即程序运行的性能。
总算轮到了本觉得重要的标准,做者的一席话描述地入木三分:
在软件生命周期内,多数程序都会被修改,不管其经验的多少,绝少有哪位程序员能反驳这一论断。既然如此,为何在必须修改之前的程序时,咱们老是以为这项任务如此艰巨,以致于每每决定弃之不用,干脆本身从头写起呢?只要阅读过程序,咱们就会透过这些程序发现:实际上,不多有哪位原做者会考虑可能的后续修改。
做者还提了两个问题来表达程序员的矛盾之处:
在编写程序时,你曾经有多少次想到过它在将来可能被别人修改?反过来,在修改别人程序时,你又曾经咒骂够几次?
之因此把适应性和效率放在一块儿讨论,是由于它们俩会此消彼长,做者用 Fisher 定理来证实这个观点:
Fisher定理:一个系统对某一特定环境适应性越强,它适应新环境的能力也就越弱。
若是强调的是程序的效率,那么咱们每每会追求紧密式的代码,而若是在将来要对这些代码进行修改,那将会很是棘手。若是使用的是更高层的语言,那么为了使程序更高效,咱们每每须要深刻到机器语言层。这种作法至少抵消了本来用更高层语言编程的一个好处 —— 在不一样机器之间的可移植性。其实际效果是,咱们将被局限于特定的某台计算机或特定的某个实现。
回想设计模式,无一例外是经过增长一层抽象以达到可扩展的目的,这样的设计增长了类的数量,类的构建和类方法调用的都会消耗空间和时间的性能,下降了效率。并且它让功能的实现变得更加间接,也增长了理解成本,下降了沟通效率。
但做者认为性能问题不是问题:
运行效率正在成为计算中一个日益不明朗的问题,随着单位计算能力成本的逐年降低,以及单位程序开发成本的不断提升,在程序开发方面比在产品方面投资更多的典型作法,早已不合时宜。所以咱们指望,随着岁月的推移,咱们听到的关于效率的言论将会愈来愈少。
紧接着依然是两个回味无穷的问题:
你是否曾经由于追求效率而延误了工做进度?反过来,是否曾经由于要赶时间完成而没有作到尽善尽美?
但有趣的是,面试时,极少有公司是按照上述的优先级来考察候选人的,一般的考察优先级正好相反,即便有算法笔试也是把重点放在实现方案的内存性能或时间性能上,并不会对程序的正确性进一步追究。