你会拆分这样的函数么?

2014-12-05 16:16:51 +08:00
 spacewander
有一个函数,是这样子的:
(仅仅用作表示,真实函数肯定不叫doSomething)

doSomething(a, b, c)
{
// prepare
...
// do A
...
// do B
...
// do C
...
}

前提:
1. do A/B/C中的内容不会被其他函数复用,仅仅在doSomething中被用到
2. 这是C++写的
3. 该函数不是“厨房下水道”函数,其长度是300多行

有人认为,应该把do A/B/C部分,分别拆开成单独的函数,然后让doSomething调用它们。
理由:
1. 这样做大大减少了doSomething函数的大小,使得整个函数更加一目了然
2. 无需再添加一行注释表示该部分代码是做什么的,用函数名就能清晰表示它们的职责
3. 将部分逻辑置于独立的函数之中,便于调试

不过楼主不认同这个观点,反而认为维持现状即可。
理由:
1. 这些部分不会被复用,即使独立成单独的函数,意义不大,不应该过度设计。
2. 独立成单独的函数后,需要将函数的输入/输出参数重复一遍,而且万一以后发生变动,不得不修改多个函数之间的传递的类型信息。
3. 独立出更多的函数后,看上去程序更好理解了,但实际是把单个函数的维护成本分摊到多个子函数上了。如果这样做了,要想明白doSomething的实现细节,你就不得不去阅读4个函数:doSomething,doA,doB和doC。
4. 一旦doSomething的逻辑发生较大变化,原本只需修改doSomething一个函数,现在则需要修改三个子函数。分拆函数就是为了把逻辑独立出去,但是这三个函数在逻辑上不一定能够独立开来,分拆它们会把事情变得更复杂。

各位怎么看?
6098 次点击
所在节点    程序员
44 条回复
jox
2014-12-05 16:25:14 +08:00
如果A,B,C只在dosomething里会用到,没必要拆分,在 不同的功能块前面使用注释区分也一样,性能上也有一点点优势,免去了函数调用的开销,如果dosomething很长,无所谓,现在的IDE都带代码折叠功能,不需要编辑的区块折叠起来就行

不过不需要拆分的情况不多见,一般函数之间都是互相调来调去的,都需要把重复的代码弄成个函数
akira
2014-12-05 16:25:55 +08:00
1. 一个函数尽量只做一个事
2.一个函数的长度要适中。

至于你的理由,
1/2可以把函数做成局部函数,
3 doA/doB/doC 可以视为大纲,是有助于代码阅读的。
4 确实是有可能会有这种情况,要具体案例具体分析了
binux
2014-12-05 16:26:47 +08:00
首先2不成立,函数输入输出的重新设计,正是梳理函数功能的过程,让函数只能看到它需要的变量。
3也不成立,函数单独拆出的原则是函数是能独立工作的,而经过2,使得接口更清晰,会让它更容易理解。而且拆出去之后loc不变,实际阅读量不变。
4函数拆分的原则就是功能是独立的,拆出去的函数如果功能不独立,请考虑你拆分方式是否有问题?!

由2-4点得,独立成函数不是意义不大的,不是过度设计。
yeqiu
2014-12-05 16:30:51 +08:00
别的语言我不懂啊,对于oo的语言,例如c#,如果拆分的话,因为方法树的存在会增加内存消耗。
chmlai
2014-12-05 16:30:59 +08:00
这样拆分一下谈不上什么"过度设计"
chmlai
2014-12-05 16:31:57 +08:00
另外只是那点函数调用就别谈什么性能不性能了吧, 又不是递归
hh3755
2014-12-05 16:32:00 +08:00
虽然我也是个菜鸟,我觉得还是应该拆出来,因为函数太大,实在不好维护的,别人理解起来也会有点费劲。
理由:
1. 对于参数的问题。参数可以全部封装到一个对象中去,或者直接丢到一个KEY,VALUE的结构中。改变参数也不会改变代码,关于参数本身的校验全部耦合到参数对象中去。
2. 独立后的每个子函数职责就更清晰,可以在函数命名时就明确其作用,比如doCheck,doProcess,releaseResouce.
3. 当然不太清楚你的场景啊,瞎猜,有的时候拆着拆着,就会发现,原来有些东西可以放在一起,哈哈。
JonyOang
2014-12-05 16:37:21 +08:00
逻辑分割,单一目的,长度适中,支持分割,哈
staticor
2014-12-05 16:40:21 +08:00
可拆,或者说如果能拆就方便拆。
主要是方便以后的扩展设计,对一个函数的调用修改可在调用时再装饰
repus911
2014-12-05 16:44:18 +08:00
应该按照实际情况来考虑,一个爬虫和一个系统毕竟不一样,但是……

1. 过度设计你妹啊 300行的函数完全不能忍啊
2. 你改原函数也要做的事情,而且300行代码还可能带暗雷
3. 你看一个函数的名字,参数,输出,就可以明明白这个函数的功能了
2/4 万一,一旦 你这算不算过度设计
4. 拆开主要是帮你理清逻辑的,你会发现自己改的更快了

300行的代码老兄你真的能忍 我是写python的
88250
2014-12-05 16:44:27 +08:00
等纠结完这些,别人同样特性的产品已经上线了....
jiang42
2014-12-05 16:51:08 +08:00
肯定拆

理由1:你不会知道以后会不会在其它地方用到A,B,C的。。。
理由2:IDE自带重构-。-
理由3:如果需要读A,B,C只能说你A,B,C有问题,A,B,C的名字就应该描述其作用
理由4:不能拆开你提什么分拆函数?实际上一般逻辑都是能拆开的,拆不开说明水平不够。至于修改doSomething,考虑一下,如果只有A出现问题,则去A子函数修改就好了,不拆分的话你需要理清楚修改A是否会影响B,C


@yeqiu 99%的性能问题都是程序员的意淫。与其死扣细节,不如学好算法和数据结构。
jerry2014
2014-12-05 16:51:39 +08:00
先订好一套规则,大家都根据这个规则来写。
standin000
2014-12-05 16:56:27 +08:00
无参数调用,可以试试inline。
有参数调用首先要考虑参数本身的意义。如果参数固定,就建议用子函数,要改什么就在子函数里改就可以了。
lincanbin
2014-12-05 17:01:27 +08:00
我不会,我只封装会重复使用的代码。
现在只用一次,以后用不用,那是以后的事,现在就封装就是过度设计了。
matrix67
2014-12-05 17:01:51 +08:00
楼主头像和我我好像像
bzmario
2014-12-05 17:09:06 +08:00
sampeng
2014-12-05 17:09:28 +08:00
我会,理由。。
3个月后,300行的代码,以我的记忆而言,肯定忘得干干净净。。写注释,怎么也不会比小函数简单明了。
sampeng
2014-12-05 17:12:16 +08:00
补充一句,超过200行代码,不管多简单明了,不管是不是我写的,我都会直接上手自己重构一下。。因为没耐心去看
ipconfiger
2014-12-05 17:13:21 +08:00
如果第一条成立就没有必要拆分。拆分狂魔恨不得一个函数只有一行代码,BT得过分

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

https://www.v2ex.com/t/151763

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

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

© 2021 V2EX