代码应该多复杂?

我正在研究可以帮助我编写更小但更复杂的代码的algorithm。 我没有写150行if-else语句,而是devise了一个20行的algorithm。 问题是很多这些algorithm可能很复杂,需要大量的math来理解它们。 我也是唯一一个了解他们的人。

为了代码的可维护性,像其他人一样编写代码会更好吗?还是使用algorithm更好?

正如爱因斯坦所说:

尽可能简单,但并不简单。

它适用于代码以及物理。

使用你的判断 – 它会变得更容易维护? 通常通过将较大的if / else大小减小到更小的大小,可以移除不需要在那里的angular落案例,从而防止将来可能popup的错误。 当然,通过将一系列明确的条件减less为一种布尔逻辑的晦涩难懂的转变,而这种逻辑只会发生作用,当某些事情发生变化时,可能会使事情变得更加困难。

编辑:
就你提到的情况来说,如果公式能够起作用,那么这可能是更好的select – 你甚至可以引用来源的评论。 尽pipe这是完全可能的,但是这个公式之前已经存在了,但是却被放弃以允许一个特定的情况被解决。 这是在你的版本库中的评论应该帮助的东西。

由于没有人发布链接,下面是他所指的PIDalgorithm的描述 。

代码被写入一次,并读取10次。 所以你应该尽可能地使它容易理解。

而且,debugging比编写代码更困难。 那么当你已经把所有的智力写入复杂的代码时,你怎么能debugging你的代码呢?

试着按照软件开发的三个定律 :

  1. 开发者必须编写创造价值的代码。
  2. 开发人员必须使代码易于维护,除非这些开支与第一法相冲突。
  3. 一个开发者必须尽可能地减less他们的代码,只要这样的减less与前两个法律不冲突。

罗伯特·C·马丁(Robert C. Martin)用这本漫画作为他的着作的简介。

代码质量的唯一有效测量:WTF /分钟http://www.osnews.comhttp://img.dovov.comcomics/wtfm.jpg

请记住,代码应该主要由人类来理解……编译器负责使计算机理解。

在这里“复杂”的级别可能有点冒险,但只要algorithm不需要math中的博士来解决,

我会说,继续前进,并使用algorithm。 请确保提供有关algorithm名称的相当级别的文档,也可以简要说明它是如何工作的或对文档的引用。

它将保持代码量不变,希望给应用程序带来一点额外的性能,并且希望可以鼓励你周围的一些程序员学习一些新的东西来添加到他们的工具中。 另外,有一个程序员知道这些事情的机会总是不会在以后出现的。

好老引用….

任何傻瓜都可以编写计算机可以理解的代码。 好的程序员编写人类可以理解的代码

  • 马丁福勒

我不敢相信任何人认为150条线比20条线更简单。

去20线,保护你的同事如下:

  • logging每一个数据结构不变和每一个非平凡的循环不变。 logging这些不是在注释中,而是在检查不variables的实际代码中。 检查可以在生产过程中closures。

  • 如果在代码中使用math公式或者在代码中派生,请在注释(或静态string)中包含引用 。 理想情况下,包括两个参考文献:可能在几秒钟内提供的Web参考,以及可能在很长一段时间内保持打印并在大学图书馆中find的备受好评的教科书。

如果理解你的代码需要特殊的专业知识(理解偏微分方程,物理学学位,伽罗瓦理论,你的名字),那么为了保护自己,你可能希望去你的pipe理,并说:“我有这个特殊的专业知识,使得它我可以编写更小的代码(因此速度更快,更可靠,更容易维护),但是当你必须replace我时,你将不得不聘请一个具有类似专业知识的人,你想让我做什么? “ 如果您可以告诉您的pipe理层如何轻松获得这些专业知识将是有帮助的。 例如,许多具有工程学位的人可以学习偏微分方程,但伽罗瓦理论家在地面上相当薄弱。

PS这里是一个业余爱好项目的例子,所以我可以稍后debugging我自己的代码:

/* * 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 */ 

像它一样复杂,不再是。

这真的取决于复杂的手段。 如果你的“简单”algorithm是150行几乎相同的代码,我的眼睛会釉下去,我将无法理解它。 如果你把这些条件放在一个matrix中,那么你的代码是一个循环来读取matrix并作出决定,即使循环可能不那么“简单”,那么一堆if / else语句也可以更好地理解。

如果基本上你是在谈论一个Perl程序,你在一行中做了大量的默认variables$ _我会说坚持更长的更详细的版本。

如果有一个公认的做法,那么你可以使用公认的公式。 如果有一个简单的代数公式需要3或4行,并且有一个复数微分方程需要一行,那么应该使用简单的代数公式。 在评论中提到的情况下,我认为PIDalgorithm比150行的if / else代码更“简单”。 我不认为你正在使用algorithm来掩盖任何事情,而是你在问题的领域使用标准技术。 只要确保评论它,甚至可能包括一个网页的链接描述公式。

通过100行if / else语句来查找方法通常(在我看来)比维护者的耐力更难,而不是花费同样的时间来理解更好的algorithm(应该在评论中解释或链接),最后只是validation实现的20行确实执行那一个。 它还具有工作上的教育的好处,这使得它更有趣(积极意义上的),并且通常也具有更好的执行概况(较less使用资源)。

你应该避免的聪明是以“聪明的黑客”的forms滥用语言没有实际的好处。 你应该拥抱的聪明才智总是使用最好的algorithm来完成工作。

编辑:关于PID的例子:我觉得很难想象PID的function可以被一堆if-else语句所理解。 if-else解决scheme总是会变得更糟(不太平滑的过渡),很难维护,而且很难调整(调整PID部分对于获得所需的行为非常重要)。 我想补充一点,理解PID不是太难,即使你不知道math,可以很容易地查找。

简单通常更好。 请记住,其他人可能有一天会维护它。

用最容易维护和理解代码的普通程序员的方式编写代码。

有趣的是,最常见的代码复杂度之一是嵌套深度。 你的“If-then-else”解决scheme很可能被自动化代码分析器比你的公式复杂。

但是,我已经看到了足够的“跆拳道?” 编码,你描述了我通常会去if-then-else的方法。 但考虑一下 是可以使用你的更复杂的,公式化的方法,但分裂出特别困难的组件成为命名的方法? 如果可以这样做(甚至可能重构以消除冗余),则可以避免algorithm的最坏方面,同时避免多级if-then-else结构。

Python的Zen在解决这个问题方面做得相当不错:

简单胜于复杂。

复杂比复杂好。

如果实施很难解释,这是一个坏主意

换句话说(就像其他人所说的那样),在最大限制(时间,内存等)下完成工作的最简单的algorithm是最好的。 显然,一个简单的algorithm不能完成工作是不够的。 如果你的代码因为使用复杂的想法而缩短,那就很复杂。 如果没有其他人能够理解你的代码,那么这很复杂,如果你很难向他们解释(即使他们能用math博士来理解), 也不是一个好主意

特例不足以打破规则。

虽然实用性胜过纯净。

通常有很多特殊情况代码在其生命周期中悄然进入“纯粹”代码。 你应该对抗这个build筑的复杂性,但是在必要的时候接受它。

不必要的复杂性总是不好的。 是的,写出一个能够完成200线function工作的明亮的class轮可能很有趣。 但请记住,你应该保持代码。 而短复杂的代码是地狱来维护。

使代码更简单的另一个风险是,你会被集中到一堆普通的编码器中。 您正在寻找的行是可读/不可读的代码。 如果你能在一个星期内回来,仍然可以轻松阅读代码,那么我会说这很简单。

我看到非常优化的代码运行非常缓慢,未优化的代码运行得很快,这是因为编译器知道计算机如何工作,编译器编写者首先关注易于优化的代码。

这可能是你的150行algorithm编译成运行时比20行版本快得多的东西。 你的20行algorithm最终会变慢,因为编译器不知道如何优化它。

我还build议你可能想把if-else版本放在20行algorithm版本的注释块中(反之亦然),这样维护人员就能理解你的复杂版本正在做什么。 在代码中使用它们可以很容易地对性能进行testing(一旦你input了它们,没有理由删除其他的)。 这也可以方便地向其他语言/平台/编译器转移。 你可能不会期望它,但是如果代码有效,它可能会持续数十年,并且看到许多不同的编译器和平台。

在你写了几个星期后,试着让你的“更复杂”的版本被其他人审阅。 要判断你阅读和解释给别人的难度以及他们对代码的反应的复杂性。

使其变得复杂的风险是没有人会理解它。 在这种情况下,请清楚地评论一下,并引用一些可以帮助别人学习和弄清楚的来源。

简单的风险是有人不愿意理解,因为它太长了。

我认为问题是 – 复杂的代码是否更好? 它更快,更可靠吗? 我们的目标是编写最好的程序,如果复杂的代码是最好的解决scheme,那么你只需写出更好的评论,以便你的后继者可以在将来pipe理代码。 原则上,在任何情况下,守则应尽可能简单。

如果你可以做20行,然后正确地评论这些行,我会说去。 您不仅可以通过减less维护代码来简化维护工作,还可以让您的程序员变得更加智能。

预优化和聪明的黑客是一回事,但聪明的algorithm一直是公平的游戏。

但是要保持这些algorithm独立于自己的function,并记住解释input和输出variables!

强制性的报价:

“控制复杂性是计算机编程的本质”(Brian Kernigan)

我认为将域复杂性与底层技术复杂性分开是非常重要的。

您想要使用计算机的某些特定于域的function本质上是复杂的,有些则不是。 例如,会计问题充满了奇怪的规则,但大部分计算都相当简单。 另一方面,根据types来评估金融证券,可以包括非常复杂的math公式和大量的模拟。 大多数计算机系统实际上只是收集大量的数据,但其中很多都有一些底层的复杂algorithm。

另一方面,技术经常会增加其复杂性。 使用C ++编写一个大型程序可能是一个挑战。 为互联网编写一个基于Web的应用程序可能会更糟。 试图确保容错,性能或安全性通常会带来很多额外的复杂性。 每种不同的技术都可以帮助或阻碍系统。

我们真正想要做的是用最接近其固有领域或技术规范的最简单的forms表示代码。 如果你正在编写一个操作系统,那么C就是一个更简单的语言。 如果你正在为保险制定复杂的风险概率,那么像APL这样的基于matrix的语言可能会更合适。 如果您只是创build大量的报告,那么比面向报告的简单语法是最好的select。

所以,如果你的150行if / else的东西“匹配”的方式表示远远胜过20个聪明的行,这是一个更易于维护和消耗的代码。 如果你从长远的angular度来看,编写运行代码很容易,它保持这种方式,这是真正的挑战….

保罗。

必要时需要尽可能复杂。 不可能是复杂的,差别很大。

那么,如果代码足够大(见大部分的Java代码),那么代码就会变得很难理解和维护。 如果所有其他(性能等)相等,并且简单algorithm和复杂algorithm之间的长度差异是非常激烈的,那么我总是会用简单而冗长的复杂而简洁优雅的algorithm。 假设两种algorithm都被certificate是正确的,那么如果语句less,代码less,则不太可能存在细微的实现错误,因此不太可能需要维护。 如果我是一个维护者,我宁愿花时间学习一个新的algorithm,而不是学习一个人如何实现一些荒谬漫长但无聊的algorithm。

依靠。 我不想保留150行if-then-else语句组成一个函数,特别是在决策树很密集的情况下。 20行复杂的math可能会或可能不会更好。 理解可能需要时间,但更长的解决scheme可能需要更长的时间来validation。

理想情况下,你会find一种方法来做更less,更简单的线条,但并不是所有的function都是这样工作的。

如果您使用20行,请使用注释中保存的130行中的一些来解释您正在使用的algorithm。 如果你不能很好的解释,那就去150线解决scheme吧。

复杂并不一定意味着更多或更less的代码行。

完美的系统从来没有第一次build成。 你所能做的就是尽量避免做出太多复杂的决定,让你以某种方式做事。

出于这个原因,我喜欢在任何项目的初始版本中保持低复杂性。 你build立的东西(新的灵活性)的原因是严重影响。 如果让它尽可能地复杂,那么一开始就会有更less的人了解它。 这可能是好事或坏事。

如果你把它做得太简单了(还有50到70%的代码),它可能会有性能问题。

随着系统的老化和成熟,复杂性似乎通过重新分解来实现。 到那时,你可以达到一些代码可能永远不会再被触摸的地步,如果你这样做的话,由于触摸它的频率较低,理解复杂性的成本将会降低。

我喜欢用简单的步骤解决复杂的问题。 在不可能的情况下,复杂性相应增加。 在另一个问题上有一个关于知道什么时候它“够好”的问题。 有时多一点的代码(5-20​​%)可以显着地抵消复杂性,这对于重新学习或者被某人理解可能是更昂贵的。

需要一个更好的algorithm通常是一个很好的问题,因为这意味着你的东西正在被使用,并有新的需求被处理。

这与我对数据库抽象的复杂性是一样的,你必须知道什么时候使它更灵活,什么时候保持简单,如何通过构build它来获得最好的学习,并且在你编写单线的任何东西。

只有在实际需要速度或空间提升的情况下,复杂的algorithm才是有效的。 不要费神写一个运行在O(1)中的花式因子algorithm,因为约25的因子基本上不会被使用。 但是,如果代码位于最内层循环中,并且此代码中的25%的加速将使整个应用程序的性能提高20%,那就去做吧。

我承认知道并喜欢math和algorithm,但对于我来说,一行150行的if / else混乱比任何可以用20行清晰expression的任何东西都要复杂得多。 正确地logging代码并将其引用到论文,书籍或维基百科中。