Answers:
“更少的行”并不总是与“更有效的”相同。我以为您的意思是“应该缩短程序的长度以牺牲可读性为代价”。
必须编写程序供人们阅读,并且只能偶然地使机器执行。
-Abelson和Sussman,计算机程序的结构和解释
总的来说,我认为简单易懂的程序比简短的程序更重要。不过,我应该指出的是,使程序更短通常也会使其更具可读性(当代码开始看起来像行杂讯时,您会有一个明显的门槛,但到那时为止,表达得更简洁似乎更清楚了)。
有一些特定的例外(例如您的个人shell脚本或一种数据清除代码),不需要任何人来维护,只有您才需要阅读。在这种情况下,为方便起见而牺牲一些可读性可能是可以的,只要您仍然能够理解它即可。
有时候是。
可读性是要争取的一件好事。为典型的业务线应用程序编写的大多数代码都将具有足够的性能,并且注重可读性很重要。在性能要求更高的领域(例如视频游戏编程或繁重的计算),重要的是要放弃可读性,转而使用令人难以理解但性能惊人的特定语言功能。
有关后者的示例,请参阅Wikipedia上的Fast Inverse Square Root。
我一般认为,最好先使某些内容易于阅读,然后再担心性能,但前提是要采取常识性的预防措施,例如不要选择O(n ^ 2)算法而不是O(n)。在我看来,仅出于简洁起见而牺牲可读性是错误的。
您应该牺牲代码的可读性和效率如何吗?
就代码而言,自我记录总是很不错的。但是有时候那是不可能的。有时您确实需要进行优化,而有时该代码本身并不易读。
这就是发明注释的目的。使用它们。甚至汇编都有评论。如果您编写了大量代码,但看不到注释,我很担心。注释不会影响运行时性能,但是有关正在进行的事情的一些说明总是有帮助的。
在我看来,绝对没有任何不提出一些基本意见的借口。显然if ( x == 0 ) /* check if x is 0 */
完全没有用;您不应该在代码中添加不必要的噪音,而是类似以下内容:
; this is a fast implementation of gcd
; in C, call as int gcd(int a, int b)
; args go in rdi, rsi, rcx, r8, r9
gcd:
push rdp
; ...
是很有帮助的。
不再需要使用许多技巧,这些技巧可以使代码更快,但往往会使代码的可读性降低,因为要么编译器变得非常聪明(甚至比大多数开发人员都聪明),要么机器变得荒谬。
我不接受“可读性高于性能”的说法。 让我给您一个不同的答案。
一些背景:你知道什么让我恶心吗?当我双击“我的电脑”时,我实际上必须等待它填充。如果那花费的时间超过5秒,我会感到非常沮丧。愚蠢的事情是,并且不仅是怪微软,在某些情况下,之所以花费如此长时间是因为需要决定要显示的图标!那就对了。因此,我坐在这里,只对转到C:驱动器感兴趣,我必须等待驱动程序访问CD-ROM并从那里读取图标(假设驱动器中有CD)。
好。因此,请想象一下我之间的所有层,双击“我的电脑”,它实际上是通过驱动程序与CD-ROM通信。现在想象每一层都...更快...
您会看到,在所有这些背后,都有成千上万的快乐程序员,因为他们的代码“更具可读性”。那很棒。我为你感到高兴。但是从用户的角度来看,这很烂(技术术语)。因此,您在晚上睡个好觉,通过确保代码更具可读性但又慢下来,告诉自己您做对了。甚至比它可能慢一些。因此,成千上万的开发人员都这样做了,我们最终因为您而等待着我们的PC。我认为你不值得。我并不是说您的第一行应该是最好的。
这是我的方法: 首先,使其工作,然后使其更快。 始终以编写高效的代码为目标,如果您不得不牺牲可读性,请添加注释。我不会牺牲效率,以使一些普通的程序员可以维持它。但是,我将解释我的代码,但是,如果这还不够的话,对不起,您根本无能在这里工作。因为在这里,我们编写的代码既快速又易读,尽管有一定的平衡,但是可以解释可读的代码,而效率低下是不可接受的。
在办公室讨论采访时,这个问题经常浮现在脑海。很多年前,当我毕业时,有人问我“您认为代码是自我记录的吗?”。现在,我将以程序员身份回答这个问题,就面试官而言,这是一个黑白问题,因此没有中间立场。这个过程应该比个人活得更久,因为人们将变得更加热闹非凡,并且您希望尽快准备好新的开始,并且代码越容易阅读,就越能理解正在发生的事情。
不久前,我读了一本相当不错的书,叫做《领域驱动开发:领域驱动的设计:解决软件心脏中的复杂性》,一开始虽然读起来有些枯燥,但是材料讲得很好。这显示了一个很好的方法,可以使系统很好地自我记录。语言是传达您的解决方案的媒介,因此,如果性能确实成为一个重要因素,则解决方案的表达越清晰,就越容易适应。这是我的信念,对我来说似乎效果很好。
使代码以更快的速度运行以牺牲可读性为代价的投资回报率很少是值得的。现代计算机的运行速度如此之快,以至于我怀疑是否会出现这种情况。如果计算机正在运行该代码,则需要维护该代码。
为此,我发现可读性非常重要。当然,正如无数次提到的那样,仅仅因为代码可读性并不一定意味着它会更慢。
一个很好的例子是变量名: $a
什么是$a
?? 这是上下文之外的,因此您无法回答,但是您是否曾经在实际代码中遇到过这种情况?现在假设有人写了$file_handle
-那是什么?即使没有上下文,也很明显。变量名的长度对计算机没有太大的影响。
我认为这里有常识。
某些应用程序可能会保证并非所有人都能理解的位移捷径,但我认为在某些方面回报会减少,因此很难找到方案。
*这确实取决于行业和其他此类事情。我正在从业务软件开发人员(业务信息系统)的角度来看这件事。
为了从另一个角度看这个问题(而不是为了漫游),我在一家从事SAAS的公司工作。当某个站点出现故障时,我们必须非常非常快地对其进行修复-通常是其他人正在修复其他开发人员的代码。
我多,而别人做一些事情的效率非常低,但比可读性,使其看上和“快”。我们的Web服务器处于最前沿,不需要在百万分之一秒之内交付请求。我们没有负载问题。
因此,在实践中,我认为您更有可能伤害自己或他人……(我希望周末回来。)
对于大多数情况,答案是“请编译器执行其工作”,并编写可读的代码。这意味着代码具有逻辑结构(即没有意大利面条)和自我记录(即变量,函数等的足够清晰的名称)。没有自我记录的补充代码,带有有意义的注释。不要为了评论而发表评论,即
x++; // Add one to x
而是在6个月或12个月或其他足够长的时间内为您(读者)发表评论。通过并遵守编码标准。
干净的代码是快速代码。清晰易写,易于维护的代码往往会更快,因为它表明程序员可以理解手头的任务,并将代码重构为核心目的。
此外,现代编译器非常有效地优化了指令。您键入要执行某项操作的代码行数以及编译器根据指令创建的内容不一定相关。阅读有关编译器的内容,以了解为什么会这样。
当我处理基于图形的性能时,当我处理最深层的嵌套算法时,有时会牺牲可读性/可维护性,而当我处理图像处理之类的东西时,小的优化可能会产生重大影响。即便如此,我还是在进行性能分析后才这样做,以确保所做的更改实际上可以加快速度。我无法告诉您多少次我尝试了手工编码的“优化”,却发现它实际上由于编译器优化手工键入代码的方式而导致应用程序运行速度减慢。
可读性是无能和懒惰的程序员的借口(实际上,当它被用作捍卫糟糕的算法/设计的论据时,“简单性”也是如此)!
对于每个给定的问题,您都应努力寻求最佳解决方案!今天的计算机速度快这一事实不能成为浪费CPU周期的借口。唯一的限制应该是“交货时间”。请注意,此处的“最佳解决方案”是指您可以提出的解决方案(我们不能全都提出最佳解决方案;或者具有实施这些解决方案的技能/知识)。
正如其他人提到的那样,如果解决方案存在“难以理解”的方面,那么这就是评论的目的。其他人提到的“正确,可读,快速”(或类似的命令)顺序只是浪费时间。
我真的很难相信那里有程序员,当他们遇到问题时,他们会直言不讳地认为:“ ...必须这样做,但我会这样做,但效率较低,但更具可读性/可维护的和其他类似的废话...”。这样做的谬误是,下一个开发人员(见到效率低下)很可能会修改代码,而下一个开发人员会修改代码,依此类推...最终结果是,经过几个版本之后,代码将变成原始代码开发人员应该在第一位写。原始开发人员的唯一借口是a。他/她没有想到(足够公平)并且(如上所述)b。时间和资源的限制。