关于程序员的产出效率以及代码的执行性能(思考题)

2014-07-17 00:38:55 +08:00
 vjnjc
我的问题是:程序员的开发、维护效率重要还是代码的执行性能重要?

不知道类似的想法有没有在v2ex上提及,事情的缘由是昨天我去SAP面试,和面试官观念冲突。

面试官:(这道算法题)为什么要用递归?
我:(我当然知道递归调用会消耗调用函数的栈,)我希望(别人)阅读、维护这段代码能够更轻松一点。
面试官:你的代码就是写出来看的?
我:。。。(别人看不懂怎么维护啊)
面试官:有其他的解法么?
我:有的,用个while套起来。

十分种后,我的比较优美的代码变成了我都不想承认的代码。
PS:括号里的是我结合语境杜撰出来的,当时对话并没有这些部分。

我的看法:由于鄙人是《人月神话》的忠实粉丝,所以当然是人力比较重要!!写出一段阅读性好,可维护的代码是程序员的职责,而写出奇葩、差劲的代码都是被(进度或者是性能要求)胁迫的。

不吐不快啊,欢迎各位exer表达自己的看法。
由于我能力有限,如有不对之处也欢迎板砖。
5506 次点击
所在节点    程序员
48 条回复
hyq
2014-07-17 10:44:53 +08:00
@huangyan9188 c++也支持尾递归,c++也哭了
pp3182429
2014-07-17 11:09:53 +08:00
以前感觉写递归很cool,后来面试了几次。发现基础打扎实了才是对的,其实基础扎实了,即使有的递归不能转换为循环,照样能自己用栈实现,将函数栈转换为数据栈,会好很多。看起来也不复杂。重在熟练吧。。
frankzeng
2014-07-17 13:22:52 +08:00
面试的时候经常有问到递归,但实际工作中又很少用到,这算不算是一个奇技淫巧。
multiple1902
2014-07-17 13:24:53 +08:00
写驱动确实用递归比较少。
nsa
2014-07-17 14:02:39 +08:00
看了楼上的评论,写汇编的瘫了
abscon
2014-07-17 14:27:02 +08:00
@pp3182429 我在前面的说法正好针对你的这种情况:“照样能自己用栈实现,将函数栈转换为数据栈,会好很多”。请给出证明为什么**要好很多**?

找照这种逻辑来说的话:
1. c语言就不应该支持函数的递归调用,反正程序员能用数据栈手工模拟函数栈
2. c++就不应该支持面向对象编程,反正C程序员能手工模拟面向对象
3. 各种支持namespace的语言是吃饱了撑的,反正程序员能用命名规范来模拟名字空间
4. c语言就不该支持else,while,for这几个关键字,反正程序员能用if和goto来模拟

我的主张是,不要刻意的去用递归,也不要刻意的不去用递归

应该是仔细分析要解决的问题,写完代码后一看,恩,原来是个递归(或者,恩,原来没有用到递归)。
loryyang
2014-07-17 14:48:21 +08:00
递归这个东西一般不太用,因为现实环境,搞不好会爆栈。。如果用个while能够搞定,我一般不会去用递归。。。
pp3182429
2014-07-17 14:56:50 +08:00
@abscon ==#我只是觉得,本来栈里要放函数及各种形参临时变量,现在只要放要操作的数据或者只需要每一层栈记录一个状态了,这样省地方。。

对于下面这么多问题,无非是哪个适合用哪个么。哪个适合自己用哪个,有什么可争的么?每个人选择不一样而已。
abscon
2014-07-17 15:52:04 +08:00
@pp3182429 “数据栈”这种东西在堆里分配,效率比函数栈可是要差的。
要是按照楼主的面试官的喜好,为了效率高而舍弃递归,那么反而会选出一个效率差的方案(和他的直觉相反了,哈哈)。

你只用数据栈,不可避免的要比那些“各种形参临时变量”多写一些代码。要定义struct/class吧?要分配内存吧?如果没有垃圾收集还要销毁内存吧?不管是代码还是实际占用内存,都不会“省地方”的。

只用数据栈有几个用处:
1. 显示水平高,咱不需要用递归的语法也能完成哦!
2. 避免堆栈溢出。
3. 可以用于不支持递归语法的语言。

在我看来,只有2和3才是有意义的做法。

你说的“个人选择不同”,我很赞同,我只补充一点,任何时候,如果程序员在“使用语言直接支持的语法”和“用其他方法模拟”中选择了后者,那这个选择极有可能是错误的。
tabris17
2014-07-17 16:38:41 +08:00
看应用场景了,如果递归深度是可以预见的,那用递归也无妨
tabris17
2014-07-17 16:41:38 +08:00
递归并非是人力和效率的问题,而是代码可靠性的问题,用递归就需要考虑栈内存耗尽的问题,call和ret的性能损耗倒是其次。

题外话,编译器优化的时候不会能把某些形式的inline函数的递归自动转为循环的么
lightening
2014-07-17 20:40:39 +08:00
代码写出来,当然要首先适宜人类阅读,其次才是执行能高效了。不然为什么我们不都用汇编?
vjnjc
2014-07-17 21:38:00 +08:00
不要究诘于递归了,我只是举了一个看上去很不恰当的例子。。。。
我就是想听听别人对于 代码维护性vs代码性能 的看法~
vjnjc
2014-07-17 21:40:41 +08:00
@JustFuckingDoIt 我感觉真的很有用啊。不知道做产品的怎么样,我是做项目的,有一个Java文件光是import语句 都有100行,我感觉很复杂,特别像《人月神话》描述的焦油坑,一不小心就会陷进回归测试出BUG的大沼泽。
vjnjc
2014-07-17 21:42:07 +08:00
@frankzeng 我猜测是因为业务上面的算法会比较少,写业务很多都是增删改查,这种递归不起来。
vjnjc
2014-07-17 21:45:52 +08:00
@huangyan9188 递归与循环复杂度一样的吧。因为代码里面用到的循环和变量才记入复杂度,而函数调用的额外耗费不计复杂度(个人看法,欢迎指正)
vjnjc
2014-07-17 21:47:20 +08:00
@akfish 说得挺对,现在想起来究诘于面试的时候跟面试官争论是最无意义的。
AlanZhang
2014-07-17 21:50:10 +08:00
维护第一,性能第二。现在人比机器贵的多。
vjnjc
2014-07-17 21:51:48 +08:00
@abscon 多谢提醒,第一次听到尾递归优化为循环的细节,很开眼界。有没有推荐的书啊,关于编程的,任何方向的
vjnjc
2014-07-17 21:58:28 +08:00
@tabris17 Hello,你提到‘call和ret的性能损耗倒是其次。’ 以我的知识只知道‘递归会同时多消耗栈和cpu跳转时间’,请问你的结论是怎么得出的?是工作经验还是某方面的书籍?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/123037

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX