如何说服同行算法很重要?

3
我的同事正在制作一份报告,展示我们小型咨询公司每个员工的每周(从周日到周六)进展情况。他编写了一段代码,显示与目标周中的天对应的列。他的算法如下:
  1. 获取月份第一天是星期几。如果是星期日,则将标志设置为零;否则,将其设置为一。
  2. 遍历整个月的所有日期。如果是星期日,则增加标志。然后,如果标志的值等于要显示的周数,请显示对应于当前日期的列;否则,隐藏该列。
当然,标志表示当前是第几周。
我建议使用另一个算法:
  1. 获取指定周的月份第一天(F)和最后一天(L)。例如,2009年10月的第一周从星期二1日开始,到星期六3日结束。
  2. 遍历与第1天到第F-1天相对应的列,并将它们隐藏。
  3. 遍历与第F天到第L天相对应的列,并显示它们。
  4. 遍历与第L+1天到月末相对应的列,并将它们隐藏。
我的算法中“困难”的部分是第1步。我的意思是“难以理解”,因为执行它的算法复杂度是恒定的。我的算法具有更紧密的循环优势,而同事的循环则针对每个月的每一天进行比较。
这只是一个小例子,你可能会说在这里过度优化有点过分谨慎。但当我们编写实际性能关键代码时,他的编程风格没有丝毫改变。
他的代码还充满了这些测试:
/* doSomething() doesn't change the state of the relevant variables. */
if (condition)
{
    flag++;
    if (flag > test)
        doSomething();
}
else
    if (flag >= test)
        doSomething();

当然,它可以这样完成:
if (flag >= test);
    doSomething();
if (condition)
    flag++;

我该怎么办?!?!

编辑:我已经更正了代码示例中的比较。


7
不要做任何事情,专注于让自己的工作变得更好。永远会有像这样的人,不要让他们影响你。 - rfunduk
这是一个很好的邪恶可变状态的例子。当我倡导函数式编程风格时,我得记住它 :) - em70
我明确表示doSomething()不会修改程序的状态。 - isekaijin
8个回答

10

我认为你的朋友是正确的。选择明显正确的算法,而不是需要一个小时才能解释清楚的算法,尤其是没有特定性能目标的时候。

如果你有具体的性能要求,比如“代码需要在机器X上为未来十年的所有月份在200毫秒内得出正确的结果”,并且简单的代码无法满足要求,那么你可能需要考虑使用你的版本。

(你发布的代码示例确实在你的方式下更好,因为它更简洁。)


我所做的是:首先,我会想出一个效率低下的程序版本,然后尽可能将许多比较或内部循环移出主循环。 - isekaijin
1
我投票支持这个回答(以及其他一些反对过早优化的答案),但我认为我们也需要承认,有时确实存在一个明显更好的选择,而不需要花费一个小时来解释,原帖的同行们可能只是没有想到。那么这些情况怎么办?是否有人能够给原帖者以疑问,并就此提供建议?也许不会,因为这是一个社会问题,但我很想听听大家的看法。 - Jeff Sternal

5
根据您的描述,我不确定我是否不同意您的同事。关键问题在于这段代码是否是性能瓶颈。
为了说服我转换到您的算法,您需要对相关应用程序进行分析,并向我展示这段代码的性能关键性。然后进行更改并再次进行分析。这样,您就有了一个客观的比较基础。
如果两个算法之间存在有意义的差异,那么您们可以讨论是否值得进行转换。
如果您担心Web应用程序的页面加载时间,请记住《高性能网站》Yahoo性能指南的教训 - 如何处理CSS、JavaScript和缓存将比优化服务器上运行的算法产生更大的影响。
主张优化而没有测量与忽视天真算法的性能影响一样危险。

哦,好吧...在这种情况下,我最好使用我首先想到的任何算法。我编写PeopleCode,并且在PeopleSoft的架构中有一个处理JavaScript、CSS等内容的组件。 - isekaijin

4

显然你错了,不应该干涉...这两段代码并不等价。只需将条件condition=1,flag=0和test=1代入测试即可。


哦,现在这真是经典 :) 真糟糕,要按我说的做...而不是按我做的去做。 - Tim Post

3

这个任务是你的还是他的?如果是他的,就让他去做。我是一个追求效率的人,在某些事情看来低效并且不受我的掌控时,我会非常沮丧。

在Stack Overflow上有超过200位用户能够比我的“高效”想法、算法和代码更胜一筹。实际上可能更多,因为仅凭声望无法衡量。即便是Linus Torvalds本人注册了账号,他也要像我们其他人一样从1开始。

你需要考虑到人们需要能够维护他们自己编写的代码。这意味着他们必须像自己孕育出来的一样理解它。 即使有人演示了比我自己更有效的另一个算法,除非我感到舒适,否则我不会使用它。

如果这是一个联合项目,你可以按照你的方式编写它,展示加速效果,然后花费一些非常非常耐心的时间与您的同伴一起,帮助他真正理解它。

回顾你5年前写的东西,每个人都必须通过实践学习,而且每个人的学习速度都不一样。


"...他们必须理解它,就好像它是他们亲生的一样。" 我认识很多女性都不理解自己的孩子... - Dave Sherohman
@Dave Sherohman:瞧,比喻的安全性!我们不是在谈论女性,而是在谈论算法。如果女性那么容易理解,就会有专利存在了。“……方法”让我们保持话题一致? - Tim Post

3

你好,

我建议你应该优先选择算法简单并且能够在你的限制条件内运行的算法,而不是过于复杂、没有实际收益的聪明算法。根据我的经验,这些过于聪明的技巧往往会成为未来维护的噩梦!

以下引用更好地表达了这个想法:

"有能力的程序员完全意识到他自己头脑的严格局限性;因此,他充满谦卑地对待编程任务,在其他事情中,他像瘟疫一样避免聪明的技巧。" - Edsger Dijkstra在他1972年的ACM图灵讲座“The Humble Programmer”中说道。

顺便提一下,那篇论文是非常棒的阅读材料!他的许多其他论文也可以在E.W.Dijkstra Archive上在线获取。

希望对你有所帮助!

祝好,


2
我看不出这里有什么问题...虽然他的版本在达到目标的方式上有一些绕弯子,但他确实达到了目标。
我即将发表的声明不应该被断章取义:但总会有像他那样做事情的人——这并不是错的,相反...他可能不知道如何用更好的方法完成某件事,但他知道如何得到结果,不管他的方法有多丑陋。 当没有人知道某个东西的正确算法时,这可能是真正的救命稻草...很有可能他会以某种方式“duct tape”它。

1
我个人不太喜欢“鸭子胶带编程”。 - isekaijin
@Eduardo Leon:如何编程鸭子胶带?我多年来一直在努力防止它们在我撕下大块时粘在一起。我想Idigas的意思是_每个人都在学习_. 你最后一次维护自己五年前写的代码是什么时候?这是一个过程... - Tim Post
我曾经在大学时编写过一个离散模拟引擎,其中一些代码实际上非常牵强。一个月前,我在其中最牵强的部分发现了一个错误,并且很容易地进行了修正。当然,这是因为源代码有足够的注释以便于理解。 - isekaijin
我认为这里应该是指“胶带编程”,不要与“鸭子类型”混淆。 - Michael Easter
1
我知道什么是“胶带编程”,但我并不太喜欢它。 - isekaijin

2

我同意这里普遍的观点:如果性能提升会使代码变得更难读,那么必须有充分的理由来进行改变。

另一方面,这并不意味着我们应该总是满足于“脑海中首先想到的东西”。有时候,有明显优越的替代方案,它们同样易读或几乎同样易读。

如果你想说服你的同事认真考虑他选择的算法,你应该谨慎选择你的战斗。不要试图颠覆他的世界,并在每一个你发现的情况下强制执行。开始时只在你能想到一个明显优越且清晰的替代算法时提出建议,并准备好在他抵制时后退。

如果你感到狡猾,甚至可以给他提示,问导向性问题,或者用任何其他技巧来帮助他自己找到答案。


1
我理解你的感受。程序员天性中非常固执己见。每个人都有自己构建程序的原则和规则。如果其他观点与其中一些相冲突,改变程序员的看法就像移动摩天大楼的基础支柱一样困难。 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接