首页 > 代码库 > 不要把时间浪费在写出完美的代码
不要把时间浪费在写出完美的代码
一个系统可能会持续工作5年,10年,20年甚至更长的时间。但是具体到这个系统中的某一行代码,即使是关于设计的部分,这一行代码存在的时间却会很短:几个月或者几天,甚至是几分钟。
一些代码比其他代码更重要
通过研究代码是怎么随时间改变的,Michael Feathers定义了一条代码变动曲线。每个系统都有很多写完之后就不再改变的代码。与此同时,也存在少量这样的代码,这些代码是整个系统最重要也是最有用的代码,它们会随时间一次又一次地改变、重构,或者被删除,重新来过,如是反复几次。
随着你对一个系统越来越熟悉,或者你具备的领域知识越来越丰富,再或者你对架构方法了解更多,你就能很容易地预测哪些代码会经常变动,而哪些代码基本上不会改变:也就是说,哪些代码重要,哪些代码不重要。
我们应该尝试去写完美的代码吗?
我们知道应该书写整洁的代码,写出来的代码应该具备一致性、简洁性,并且尽可能的简单。
一些人在写代码方面追求极致,他们尽自己最大的努力写出来和完美代码尽可能接近的、漂亮、优雅的代码,他们过度重构自己的代码,并且对每一个不完美的细节都感到痛苦。
但是如果代码一旦写出来之后就不会再改变,或者走向另一个极端,写出来的代码需要经常改变,在这两种情况下,我们是不是可以认为尝试去写出完美的代码是在浪费时间,并且是没有必要的,就像尝试写出一个完美的需求分析或者试图写出一个完美的预期分析一样。
你不能写出完美的软件。看到这句话有什么感受?不管你有什么感受,也不管你是怎么认为,事实就是这样——你不能写出完美的软件。你能做的就是接受这个事实,并且将它奉为一个生活的真理。拥抱这个现实吧,因为完美的软件根本就不存在。在计算机短暂的发展历史中,还没有人写出过哪怕是一个完美的软件。你成为第一个的概率也是微乎其微。除非你接受这个现实,否则你就会把你的时间和精力浪费在追逐一个不可能实现的梦想上面。 Andrew Hunt,The Pragmatic Programmer: from Journeyman to Master(《程序员修炼之道:从入门到精通》)。
那些一次性书写完毕就不需要修改的程序不必漂亮优雅,这类程序只要能正确运行,并且易于理解——因为这类程序在整个系统的生命周期内可能会被多次阅读。这类程序也不需要具备紧凑性,整洁即可。适当的复制、粘贴操作是可以接受的。一旦书写完毕,这类代码不会被清除,也不需要重构,甚至它们周围的代码发生变化的时候也是这样,所以,没必要把额外的时间花在修改这类代码上。
如果代码是经常变动的呢?在这种情况下,试图寻找最优雅的解决方案也是在浪费时间,因为这类代码总是在变,甚至是重写。过度重构会变动的代码和重构不会变动的代码都是在浪费时间。代码总是能被修改得更好,但那不是最重要的。
真正重要的是:代码是按照你所想的方式在工作吗——代码是不是高效可用的?代码能否处理错误和坏数据而不崩溃——至少要能做到安全的失效?代码容易调试吗?改动代码是不是容易?是不是安全?这些都和美无关,但是这些都是决定软件能否成功的实用准则。
务实地编码和重构
精益开发的核心思想是:不把把时间浪费在不重要的事情上。这条核心思想应该指导我们怎么编码,怎么重构,怎么检查,怎么测试。
只重构需要重构的代码——Martin Fowler把这称之为机会重构,或者预备重构。使用这条准则,代码的修改会更加容易和安全。如果代码根本就不需要改变,它看起来美不美真的不重要。
在检查代码的时候,只关注真正重要东西。代码是不是正确?是不是具备防御性?是不是安全?是不是易读?是不是能被安全地修改?
除非代码的风格能影响到它的可读性,否则不必在风格上纠结。把这种事情交给IDE去处理。没有人会在意代码能否更加面向对象。只要代码本身有意义,那么它是按照哪种模式写的并不重要,你是不是喜欢它也不重要。除非你是在教新手,并且需要做一些代码审查的工作,否则你是否能写出更漂亮的代码是不重要的。
写测试很重要。测试包括了主要的执行路径和重要的异常案例。测试用最少的工作量反馈给你最大的信息量,并且给你极大的信心。不管你是做大而广的测试,还是小而集中的测试,不重要;也不管你是在编码前还是编码后进行测试,也不重要,重要的是你的测试用例要是有效的。
无关编码
建筑和工程上的比喻不适合软件。我们不是在设计建造桥梁或者摩天大楼,这些东西一旦建好之后,几年或者几代都不会发生改变。我们在做的东西是软件,它更加塑料化,更加抽象,也更加短暂。代码写出来就是为了修改的,要不然怎么叫“软”件呢?
经过五年的使用和修改,一个成功软件的源码和它最初的形式几乎完全不同,但是对一个成功的建筑来说,几乎没有改变。 Kevin Tate, Sustainable Software Development(《可持续软件开发》)。我们需要把代码看成是我们工作的一个临时作品:
我们要写好的代码:代码是可理解的,正确的,安全的。我们也需要重构和检查代码,要写好的、有用的测试,但是我们要知道有些代码很快就会被丢弃,或者不会有人再去看它,或者压根就没有使用过。我们要认识到我们必然会做一些无用功。做真正需要做的事情。不要浪费时间尝试去写完美的代码。 有时在一些更重要的事情面前,我们迷恋代码。我们经常陷入到这样的假象中去:促进产品成功的最重要的原因是代码,实际上,可能是对问题的一个理解,对一个设计难题的改进,甚至是用户的反馈。 Dan Grover, Code and Creative Destruction(《代码与创造性破坏》)。迭代开发教会我们怎么实验并检测我们的工作结果,我们是不是解决了问题?如果没有,我们学到了什么?可以怎样改进?我们正在开发的软件从来没有完成这一说。尽管设计是对的,代码也没有问题,但是它们可能只是在这段时间内是正确的。等到新的需求出现,这些代码被修改或者被替代,然后继续正确地工作。
我们要写好代码:代码是可理解的,正确的,安全的。我们也需要重构和检查代码,要写好的、有用的测试,但是我们要知道有些代码很快就会被丢弃,或者不会有人再去看它,或者压根就没有使用过。我们要认识到我们必然会做一些无用功。做真正需要做的事情。不要浪费时间尝试去写出完美的代码。
不要把时间浪费在写出完美的代码