我正在研究可以帮助我编写更小但更复杂的代码的算法。我可以设计一个20行的算法,而不是编写150行if-else语句。问题是很多这些算法都很复杂,需要大量的数学才能理解它们。我也是这里唯一了解他们的人。
为了代码的可维护性,像其他人一样编写代码会更好,还是使用算法更好?
答案 0 :(得分:54)
让一切尽可能简单,但并不简单。
它适用于代码和物理。
使用您的判断 - 是否会更容易维护?通常通过将较大的if / else混淆减少为较小的东西,可以移除不需要存在的角落情况,从而防止将来可能出现的错误。当然,通过将一组明确的条件简化为一个只是恰好起作用的布尔逻辑的模糊扭曲,当事情发生变化时,你可能会使事情变得更加困难。
编辑:
根据你引用的案例,如果公式可行,那么它可能是更好的选择 - 你甚至可以引用来源的评论。尽管如此,完全可能的是,该公式之前存在,但是被删除以允许特定情况得到解决。这是您的版本控制库中的注释应该有用的东西。
由于还没有人发布链接,here's a description of the PID algorithm他指的是。
答案 1 :(得分:28)
代码写入一次,读取10次。因此,您应尽量使其易于理解。
此外,调试比编写代码要困难得多。那么,当你已经把所有的脑力投入编写复杂的代码时,你怎么能调试你的代码呢?
试着关注The Three Laws of Software Development:
答案 2 :(得分:23)
(来源:osnews.com)
答案 3 :(得分:13)
请记住,代码应该主要由人类理解......编译器负责使计算机理解。
答案 4 :(得分:11)
“复杂”的水平在这里可能有点冒险,但只要算法不需要数学博士来解决,
我会说继续使用这些算法。确保提供关于算法名称的相当级别的文档,可能是它的工作原理的简短描述或对文档的引用。
它将保持代码量的下降,希望为应用程序提供一些额外的性能,并且它有望鼓励你周围的一些程序员学习一些新的东西来添加到他们的保留节目中。此外,确实知道这些事情的程序员有可能不会在以后进入。
答案 5 :(得分:9)
好老报......
任何傻瓜都可以编写一个代码 电脑可以理解。好 程序员编写人类可以编写的代码 理解
答案 6 :(得分:8)
我无法相信任何人都认为150行的任何东西都比20行更简单。
使用20行,并按如下方式保护您的同事:
记录每个数据结构不变量和每个非平凡循环不变量。记录这些不是在注释中,而是在检查不变量的实际代码中。生产期间可以关闭支票。
如果您在代码中使用数学公式或派生代码,则在评论(或静态字符串)中包含引用。理想情况下包括两个参考:一个可能在几秒钟内可用的Web引用和一个很有可能在很长一段时间内保存并且可以在大学图书馆中找到的备受好评的教科书。
如果理解你的代码需要特殊的专业知识(理解偏微分方程,物理学位,伽罗瓦理论,你的名字),那么为了保护自己,你可能希望去管理层说“我有这个特殊的专业知识这使得我可以编写更小的代码(因此更快,更可靠,更易于维护),但是当你必须替换我时,你将不得不雇用具有类似专业知识的人。你想要我什么?去做?”如果您能告诉您的管理层如何轻松获得这些专业知识,将会很有帮助。例如,很多具有工程学位的人可以学习偏微分方程,但伽罗瓦理论家在地面上相当薄。
P.S。这是一个来自业余爱好项目的示例注释,因此我可以稍后调试自己的代码:
/*
* Compute the position of a point partially along the geodesic from
* pt1.lat,pt1.lon to pt2.lat,pt2.lon
*
* Ref: http://mathworld.wolfram.com/RotationFormula.html
*/
答案 7 :(得分:6)
尽可能复杂,不再存在。
答案 8 :(得分:6)
这实际上取决于复杂的手段。如果你的“简单”算法是150行几乎相同的代码,我的眼睛会釉面,我将无法理解它。如果你把这些条件放在一个矩阵或者什么东西中,然后你的代码就是一个读取矩阵并做出决定的循环,我会更好地理解它,即使循环可能不像“if / else语句那么简单”。 / p>
如果基本上你在谈论一个Perl程序,你可以在一行中大量使用默认变量$ _,我会坚持使用更长的更冗长的版本。
如果有可接受的公式来做某事,那么您可以使用公认的公式。如果有一个简单的代数公式需要3或4行并且有一个复杂的微分方程需要一条线,那么你应该使用简单的代数公式。在评论中提到的情况下,我认为PID算法比150行if / else代码“更简单”。我不认为你使用算法来模糊任何东西,而是你在问题领域使用标准技术。只需确保对其进行评论,甚至可以包含指向公式的网页链接。
答案 9 :(得分:5)
找出通过100行if / else语句的方式通常(在我看来)维护人员的耐力比在同一时间理解更好的算法(应该在评论中解释或链接)并且最后只是验证实现的20行确实执行了那一行。它还具有在工作中受教育的好处,这使得它更有趣(在积极意义上),并且通常还有更好的执行概况(更少使用资源)。
你应该避免的聪明是以“聪明的黑客”的形式滥用语言而没有实际的好处。你应该拥抱的聪明才智总是使用最好的算法。
编辑:关于PID示例:我发现很难想象PID的功能可以被一堆if-else语句巧妙地替代。 if-else解决方案总是会工作得更糟(转换不太平滑),很难维护,而且很难调整(调整PID部分对于获得所需的行为非常重要)。我想补充说理解PID并不太难,即使你不知道数学,也可以很容易地查找。
答案 10 :(得分:4)
以最易于维护和理解的方式编写代码,以供处理代码的普通程序员使用。
答案 11 :(得分:4)
Zen of Python可以很好地解决这个问题:
...
简单比复杂更好。
复杂比复杂更好。
...
如果实施难以解释,那就是一个坏主意
...
换句话说(正如其他人所说的),最简单的算法将在强加的约束(时间,内存等)下完成工作是最好的算法。显然,一个不能完成工作的简单算法就不够好了。如果您的代码较短,因为它使用了复杂的想法,那么它很复杂。如果没有其他人能理解你的代码,那就太复杂了,如果你很难向他们解释(即使他们会用数学博士来理解它),这是一个坏主意。
...
特殊情况不足以打破规则。
虽然实用性胜过纯洁。
...
在它的生命周期中,通常会有许多特殊的案例代码进入最初的“纯”代码。你应该对抗这种建筑的复杂性,但在必要时接受它。
答案 12 :(得分:4)
有趣的是,代码复杂性最常见的衡量标准之一是嵌套深度。您的“If-then-else”解决方案可能被自动代码分析器归类为 more 复杂,而不是您的公式化。
但是,我已经看过“WTF”了吗?您描述的编码,我通常会采用if-then-else方法。但考虑一下;是否可以使用更复杂的公式化方法,但是将特别困难的组件拆分为命名良好的方法?如果你可以这样做(甚至可能重构以消除冗余),你可以避免算法中最糟糕的方面,同时避免使用多级if-then-else结构。
答案 13 :(得分:4)
更简单通常更好。请记住,有一天其他人可能不得不维护它。
答案 14 :(得分:3)
不需要的复杂性总是很糟糕。是的,编写一个能够完成200行功能的精彩内衬可能会很有趣。但请记住,您应该维护代码。简短的复杂代码是难以维护的。
答案 15 :(得分:2)
使代码更简单的另一个风险是你会被集中到一堆普通的编码器中。您正在寻找的行是可读/不可读的代码。如果你能在一周内回来并且仍然能够轻松阅读代码,那么我会说它很简单。
答案 16 :(得分:2)
我看到非常优化的代码运行速度非常慢,未经优化的代码运行得很快,这是因为编译器知道计算机是如何工作的,编译器编写者首先关注易于优化的代码。
可能是您的150行算法编译成运行时比20行版本快得多的东西。你的20行算法最终会变慢,因为编译器不知道如何优化它。
我还建议您可能希望将if-else版本放在20行算法版本之上的注释块中(反之亦然),以便维护人员能够理解您的复杂版本正在尝试做什么。将它们放在代码中也可以很容易地对两者进行性能测试(一旦你输入它们,就没有理由删除另一个)。这也将允许轻松迁移到其他语言/平台/编译器。您可能没想到它,但如果代码有效,它可能会持续数十年并且可以看到许多不同的编译器和平台。
答案 17 :(得分:2)
在您撰写文章几周后,尝试让其他人审核您的“更复杂”版本。判断您阅读并向他人解释的难度以及他们对代码的反应的复杂程度。
答案 18 :(得分:1)
我认为问题是 - 复杂的代码是否更好?它更快,更可靠吗?目标是编写最好的程序,如果复杂的代码是最好的解决方案,那么你只需编写更好的注释,以便你的继任者可以在将来管理代码。原则上,代码应该在任何给定的情况下尽可能简单。
答案 19 :(得分:1)
使其变得复杂的风险是没有其他人会理解它。在这种情况下,请清楚地对其进行评论,并引用一些有助于其他人学习并弄明白的消息来源。
让事情变得简单的风险在于,有人不愿意理解它,因为它很长。
答案 20 :(得分:1)
如果你可以在20行上做,然后正确评论这些行,我会说它去。您不仅可以通过减少维护代码来使维护更容易,而且还有助于让您的程序员更聪明。
预优化和聪明的黑客攻击是一回事,但智能算法一直都是公平的游戏。
但请将这些算法保留在自己的函数中,并记住解释输入和输出变量!
强制性报价:
“控制复杂性至关重要 计算机编程。“(Brian Kernigan)
答案 21 :(得分:1)
我认为将域复杂性与底层技术复杂性分开是很重要的。
您希望使用计算机的某些特定于域的功能本质上很复杂,有些则不然。例如,会计问题充满了奇怪的规则,但大多数计算都相当简单。另一方面,根据类型评估金融证券可能包括非常复杂的数学公式和大量的模拟。大多数计算机系统实际上只是收集大量数据,但其中许多都有一些基础复杂的算法。
另一方面,技术往往会带来复杂性。用C ++编写一个用于PC的大程序可能是一个挑战。为互联网编写基于Web的应用程序可能会更糟糕。尝试确保容错,性能或安全性通常会导致大量增加的复杂性。每种不同的技术都有助于或阻碍系统。我们真正想做的是,以最简单的形式表达代码,这种形式最接近其固有领域或技术规范。如果您正在编写操作系统,那么C是一种更容易使用的语言。如果您正在研究复杂的保险风险概率,那么像APL这样的矩阵导向语言可能更合适。如果您只是创建大量报告,那么使用简单的语法指向报告是最好的选择。
因此,如果你的150行if / else东西“匹配”表达问题的方式远远好于20条聪明的行,那么这是一个更易于维护和消耗的代码。如果从长远的角度来看,编写运行代码很容易,那就是保持这种真正的挑战......
保罗。
答案 22 :(得分:0)
嗯,如果代码变得足够大(参见大多数Java代码),代码就会因为数量庞大而难以理解和维护。如果所有其他的(性能等)相等,并且简单算法和复杂算法之间的长度差异非常大,那么我总是采用复杂但简洁而优雅的算法而不是简单而冗长的算法。假设两种算法都被证明是正确的,那么if语句较少且代码总体较少的算法不太可能产生细微的实现错误,因此不太可能需要维护。如果我是一名维护者,我宁愿花时间学习一种新算法,也不愿学习某人如何实施一些冗长而又无聊的算法。
答案 23 :(得分:0)
取决于。我不希望维护150行if-then-else语句组成一个函数,特别是如果决策树是密集的。 20行复杂的数学可能会或可能不会更好。理解可能需要一段时间,但更长的解决方案可能需要更长时间才能验证。
理想情况下,你会找到一种方法,可以用更少和更简单的行来完成它,但并非所有函数都以这种方式工作。
如果您确实使用了20行,请使用注释中保存的130行中的一些来解释您正在使用的算法。如果你不能很好地解释它,请使用150行解决方案。
答案 24 :(得分:0)
它必须尽可能复杂。它不可能是复杂的,差异很大。
答案 25 :(得分:0)
复杂并不一定意味着更多或更少的代码行。
完美的系统永远不会第一次建成。 你所能做的就是尽量不做太多复杂的决定,让你以单向的方式做事。
出于这个原因,我喜欢在任何项目的初始版本中保持低复杂性。你构建某些东西(新的灵活性)的原因受到严重影响。如果你让它尽可能复杂,那么开始时就会有更少的人理解它。这可能是好事也可能是坏事。
如果你过于简单(代码增加50%到70%),可能会出现性能问题。
随着系统的老化和成熟,复杂性似乎通过重新分解来实现。到那时,你可以达到某些代码可能永远不会被触及的程度,如果你曾经这样做,理解复杂性的成本会因为触摸它的频率较低而降低。
我喜欢用简单的步骤来解决复杂的问题。在不可能的地方,复杂性相应增加。另一个问题是关于知道何时“足够好”。有时,更多的代码(5-20%)可以显着地抵消复杂性,这可能会使某人重新学习或理解更加昂贵。
需要一个更好的算法通常是一个很好的问题,因为它意味着你的东西被使用,并且需要处理新的需求。
这与我适用于数据库抽象的复杂性相同,您必须知道何时使其更加灵活,何时保持简单,并通过构建它最好地学习,并在之前废弃它你写了一行任何东西。
答案 26 :(得分:0)
复杂算法只有在实际需要速度或空间提升时才有用。不要费心写出在O(1)中运行的花哨因子算法,因为基本上永远不会使用大约25的因子。但是,如果代码位于最里面的循环中,并且此代码中的25%的加速将使整个应用程序的性能提高20%,那就去吧。
答案 27 :(得分:0)
我承认知道并喜欢数学和算法,但对我来说,150行if / else乱码比任何可以在20行中清晰表达的东西更复杂和难以维护。正确记录代码并提交论文,书籍或维基百科。