您应该牺牲代码的可读性和效率如何吗?[关闭]


37

您应该牺牲代码的可读性和效率如何吗?

例如,将3行代码转换为1行。

我在Pete Goodliffe的Code Craft中读到,可读性是关键。

你的想法?


13
为什么您认为行数更少的代码可能更有效?尽管现代语言可能已应用于8位BASIC解释器,但这种情况很少出现。
David Thornley,

69
可读性和性能都无法在线衡量。

在极少数情况下,我会为了速度而牺牲可读性,但很少。运行高速机械的嵌入式代码就是一种情况。对于大多数软件而言,可读性更为重要。
Jim C


在性能出现问题之前,我将始终倾向于可读性。然后我会开始担心它。
皮特

Answers:


62

“更少的行”并不总是与“更有效的”相同。我以为您的意思是“应该缩短程序的长度以牺牲可读性为代价”。

必须编写程序供人们阅读,并且只能偶然地使机器执行。

-Abelson和Sussman,计算机程序的结构和解释

总的来说,我认为简单易懂的程序比简短的程序更重要。不过,我应该指出的是,使程序更短通常也会使其更具可读性(当代码开始看起来像行杂讯时,您会有一个明显的门槛,但到那时为止,表达得更简洁似乎更清楚了)。

有一些特定的例外(例如您的个人shell脚本或一种数据清除代码),不需要任何人来维护,只有您才需要阅读。在这种情况下,为方便起见而牺牲一些可读性可能是可以的,只要您仍然能够理解它即可。


3
+1收益递减,但我也发现,简短的程序通常比冗长的程序容易阅读。
Michael K

23
不幸的是,我发现一次性的数据处理代码没有立即删除就变成了长期代码,这太频繁了。除非删除代码,否则总是希望事情会发生变化,重复使用和扩展。
Vatine 2011年

1
我同意维汀。曾经回过头来尝试弄清楚什么时候您曾经认为“完全清晰”的东西吗?
2011年

SICP +1。很棒的书。
Jason Yeo 2013年

30

有时候是。

可读性是要争取的一件好事。为典型的业务线应用程序编写的大多数代码都将具有足够的性能,并且注重可读性很重要。在性能要求更高的领域(例如视频游戏编程或繁重的计算),重要的是要放弃可读性,转而使用令人难以理解但性能惊人的特定语言功能。

有关后者的示例,请参阅Wikipedia上的Fast Inverse Square Root

我一般认为,最好先使某些内容易于阅读,然后再担心性能,但前提是要采取常识性的预防措施,例如不要选择O(n ^ 2)算法而不是O(n)。在我看来,仅出于简洁起见而牺牲可读性是错误的。


4
我认为“可读代码”和“了解算法”之间可能会有区别。我想,如果您不了解算法,那么任何代码都会或多或少难以阅读和理解。例如,在提到的FISR情况下,普通代码实际上可读性很强,但是未记录该算法。如果您知道FISR算法,则可以编写多少可读性的代码?密切相关的问题可能是:何时选择精美的算法?
Maglob

@Maglob我专门指的是使用0x5f3759df。在不考虑性能的情况下,您可以使用定期除法来实现ISR算法,这对不太了解计算机内部知识的人来说可能更易读。
亚当李尔

3
这也许可以表示为“用以15行注释和5行代码表达的复杂算法替换用5行注释和20行代码表达的天真算法有时是正确的”。
彼得·泰勒

1
还请记住,对一个域中的开发人员进行令人费解的混淆可能是另一域中的开发人员完全可以接受的习惯用法。虽然ISR算法中的魔术常数似乎确实推动了边界的发展,但我猜想当时对于浮点近似的这种位级黑客攻击在当时的游戏开发中非常普遍。同样,在嵌入式系统中工作时,有很多习惯用法,但对于应用程序开发人员来说似乎太过时了。
Cercerilla

互联网的奇迹之一->在实现复杂算法时(例如:levenshtein距离与对角线优化...我正在研究它;)),可以引用一篇文章,甚至可以将其复制到文档中该项目,并在代码中添加参考。这样一来,了解算法的人们就可以按照解释特定测试/优化的注释进行操作,而初学者则必须首先阅读有关算法的信息,然后再回到实现中。
Matthieu M.

22

我唯一会牺牲可读性的时候是代码被证明是性能瓶颈,而重写会解决该问题。在这种情况下,应充分记录代码的意图,以便在存在错误时可以更轻松地对其进行跟踪。

当然,这并不是说重写必须是不可读的。



9

您应该牺牲代码的可读性和效率如何吗?

就代码而言,自我记录总是很不错的。但是有时候那是不可能的。有时您确实需要进行优化,而有时该代码本身并不易读。

这就是发明注释的目的。使用它们。甚至汇编都有评论。如果您编写了大量代码,但看不到注释,我很担心。注释不会影响运行时性能,但是有关正在进行的事情的一些说明总是有帮助的。

在我看来,绝对没有任何不提出一些基本意见的借口。显然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
    ; ...

是很有帮助的。


6

您应该牺牲代码的可读性和效率如何吗?

如果效率是您当前的目标(例如在优化阶段)并且您知道-您拥有指标,不是吗?-该行代码是当前的瓶颈,然后是。

否则,否:可读性将使您(或另一人)以后可以更改此代码,以使其更有效,因为它更易于理解。


4

没有人赢得Code Golf

例如3行代码变成1行

一个特别可怕的想法。

打代码高尔夫的成本-非常高。

维护无法读取的程序的成本-天文数字。

这种最小化代码的值-零。它仍然有效,但没有任何“更好”的效果。

明智选择的效率

选择正确算法和数据结构的成本-适中。

维护正确算法和数据结构的成本-低。

正确的算法和数据结构的价值-高。资源使用率低。

愚蠢的(“微观优化”)效率

进行微优化的成本很高。

维护无法读取的,经过微优化的代码的成本–非常高。

微优化的价值-变化。当这里的值非零时,成本仍然超过它。


2

取决于我们是在代码执行速度方面还是在开发人员可以编写代码速度方面谈论效率。如果您牺牲了代码的可读性而支持能够非常快速地键入代码,那么您可能会发现自己在调试方面花了很多时间。

但是,如果我们谈论的是在代码执行的速度方面牺牲代码的可读性,那么只要代码必须以有效的方式执行,这就有可能是可以接受的折衷方案。仅仅因为您可以而编写尽可能快地运行的内容,并不是因为它像快速反平方根之类的东西,而性能是关键。诀窍是在平衡代码和确保即使很难理解源代码的同时,描述源代码的注释也可以解释所发生的情况。



2

我不接受“可读性高于性能”的说法。 让我给您一个不同的答案。

一些背景:你知道什么让我恶心吗?当我双击“我的电脑”时,我实际上必须等待它填充。如果那花费的时间超过5秒,我会感到非常沮丧。愚蠢的事情是,并且不仅是怪微软,在某些情况下,之所以花费如此长时间是因为需要决定要显示的图标!那就对了。因此,我坐在这里,只对转到C:驱动器感兴趣,我必须等待驱动程序访问CD-ROM并从那里读取图标(假设驱动器中有CD)。

好。因此,请想象一下我之间的所有层,双击“我的电脑”,它实际上是通过驱动程序与CD-ROM通信。现在想象每一层都...更快...

您会看到,在所有这些背后,都有成千上万的快乐程序员,因为他们的代码“更具可读性”。那很棒。我为你感到高兴。但是从用户的角度来看,这很烂(技术术语)。因此,您在晚上睡个好觉,通过确保代码更具可读性但又慢下来,告诉自己您做对了。甚至比它可能慢一些。因此,成千上万的开发人员都这样做了,我们最终因为您而等待着我们的PC。我认为你不值得。我并不是说您的第一行应该是最好的。

这是我的方法: 首先,使其工作,然后使其更快。 始终以编写高效的代码为目标,如果您不得不牺牲可读性,请添加注释。我不会牺牲效率,以使一些普通的程序员可以维持它。但是,我将解释我的代码,但是,如果这还不够的话,对不起,您根本无能在这里工作。因为在这里,我们编写的代码既快速又易读,尽管有一定的平衡,但是可以解释可读的代码,而效率低下是不可接受的。


“好吧,让我想象一下我之间的所有层,双击“我的电脑”,它实际上是通过驱动程序与CD-ROM进行通信。现在想象每一层都...更快...”,我立即有了2张DVD驱动器
Rangoric

一个词:升级
jmort253 2011年

2
伙计们,在这里和我一起工作,这是一个例子……
Maltrap

@Rangoric就是我所说的技术进步,而不是礼物。如果您可以说服用户更频繁地打开他们的钱包,则对行业来说效果很好。
乔纳森·诺伊菲尔德

我认为膨胀的代码对能量的影响需要更多的审查和严格的措施。这里缺乏环境管理。考虑到我们现在正在考虑全球温度升高4度,为什么计算复杂性会退居次席?
乔纳森·诺伊菲尔德

2

在办公室讨论采访时,这个问题经常浮现在脑海。很多年前,当我毕业时,有人问我“您认为代码是自我记录的吗?”。现在,我将以程序员身份回答这个问题,就面试官而言,这是一个黑白问题,因此没有中间立场。这个过程应该比个人活得更久,因为人们将变得更加热闹非凡,并且您希望尽快准备好新的开始,并且代码越容易阅读,就越能理解正在发生的事情。

不久前,我读了一本相当不错的书,叫做《领域驱动开发:领域驱动的设计:解决软件心脏中的复杂性》,一开始虽然读起来有些枯燥,但是材料讲得很好。这显示了一个很好的方法,可以使系统很好地自我记录。语言是传达您的解决方案的媒介,因此,如果性能确实成为一个重要因素,则解决方案的表达越清晰,就越容易适应。这是我的信念,对我来说似乎效果很好。


1

使代码以更快的速度运行以牺牲可读性为代价的投资回报率很少是值得的。现代计算机的运行速度如此之快,以至于我怀疑是否会出现这种情况。如果计算机正在运行该代码,则需要维护该代码。

为此,我发现可读性非常重要。当然,正如无数次提到的那样,仅仅因为代码可读性并不一定意味着它会更慢。

一个很好的例子是变量名: $a

什么是$a?? 这是上下文之外的,因此您无法回答,但是您是否曾经在实际代码中遇到过这种情况?现在假设有人写了$file_handle-那是什么?即使没有上下文,也很明显。变量名的长度对计算机没有太大的影响。

我认为这里有常识。

某些应用程序可能会保证并非所有人都能理解的位移捷径,但我认为在某些方面回报会减少,因此很难找到方案。

*这确实取决于行业和其他此类事情。我正在从业务软件开发人员(业务信息系统)的角度来看这件事。


为了从另一个角度看这个问题(而不是为了漫游),我在一家从事SAAS的公司工作。当某个站点出现故障时,我们必须非常非常快地对其进行修复-通常是其他人正在修复其他开发人员的代码。

,而别人做一些事情的效率非常低,但比可读性,使其看上和“快”。我们的Web服务器处于最前沿,不需要在百万分之一秒之内交付请求。我们没有负载问题。

因此,在实践中,我认为您更有可能伤害自己或他人……(我希望周末回来。)


1

对于大多数情况,答案是“请编译器执行其工作”,并编写可读的代码。这意味着代码具有逻辑结构(即没有意大利面条)和自我记录(即变量,函数等的足够清晰的名称)。没有自我记录的补充代码,带有有意义的注释。不要为了评论而发表评论,即

x++; // Add one to x

而是在6个月或12个月或其他足够长的时间内为您(读者)发表评论。通过并遵守编码标准。


为“信任您的编译器完成工作”而为+1。这是我对Skype的新评论。
jmort253 2011年

0

干净的代码是快速代码。清晰易写,易于维护的代码往往会更快,因为它表明程序员可以理解手头的任务,并将代码重构为核心目的。

此外,现代编译器非常有效地优化了指令。您键入要执行某项操作的代码行数以及编译器根据指令创建的内容不一定相关。阅读有关编译器的内容,以了解为什么会这样。

当我处理基于图形的性能时,当我处理最深层的嵌套算法时,有时会牺牲可读性/可维护性,而当我处理图像处理之类的东西时,小的优化可能会产生重大影响。即便如此,我还是在进行性能分析后才这样做,以确保所做的更改实际上可以加快速度。我无法告诉您多少次我尝试了手工编码的“优化”,却发现它实际上由于编译器优化手工键入代码的方式而导致应用程序运行速度减慢。


-1

可读性是无能和懒惰的程序员的借口(实际上,当它被用作捍卫糟糕的算法/设计的论据时,“简单性”也是如此)!

对于每个给定的问题,您都应努力寻求最佳解决方案!今天的计算机速度快这一事实不能成为浪费CPU周期的借口。唯一的限制应该是“交货时间”。请注意,此处的“最佳解决方案”是指您可以提出的解决方案(我们不能全都提出最佳解决方案;或者具有实施这些解决方案的技能/知识)。

正如其他人提到的那样,如果解决方案存在“难以理解”的方面,那么这就是评论的目的。其他人提到的“正确,可读,快速”(或类似的命令)顺序只是浪费时间。

我真的很难相信那里有程序员,当他们遇到问题时,他们会直言不讳地认为:“ ...必须这样做,但我会这样做,但效率较低,但更具可读性/可维护的和其他类似的废话...”。这样做的谬误是,下一个开发人员(见到效率低下)很可能会修改代码,而下一个开发人员会修改代码,依此类推...最终结果是,经过几个版本之后,代码将变成原始代码开发人员应该在第一位写。原始开发人员的唯一借口是a。他/她没有想到(足够公平)并且(如上所述)b。时间和资源的限制。


-2

如果降低可读性有助于代码性能/优化(如swfobject和其他js库中的代码),那么这就是为什么要继续编写格式正确且可读性强的代码,并将其转换为不可读/优化的原因,这是“编译” /发布过程的一部分。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.