PHP的Class与function之争

曾建凯 发布于 2013/03/27 21:06
阅读 7K+
收藏 10
PHP

昨日在博客发表了一篇文章(点击进入查看),网友@ichenshy 提出了一片质疑之声,论及:框架存在的价值,Class和function在PHP运行时的性能问题等,这不会改变我的看法和观点,但是我真心觉得他说得很好,为什么这么说呢?我先把他的观点挪过来,大家看看。

第一次回复

1、弱类型有弱类型的优点,强类型有强类型的好处,在哪些地方非得进行类型判断呢?
2、实在不明白为什么对于PHP这样的解释性语言非得在框架里堆砌一大堆的class,有些事明明一个function就能搞定的;
3、框架是为了规范写代码的人,还是帮助写代码的人自动完成一些重复性的工作?

4、框架弄得太复杂了,给人使用的时候学要多长的学习成本?后续维护的人接手的时候需要多长的时间完全弄懂?

第二次回复

你题目的重点“运行效率”,我说的2点也是说这个!在PHP这种解释性语言中,fn无论是在内存占用还是性能上面都要比cls要好很多,不管在哪个版本中都一样。既然“cls、obj是一种代码管理和组织形式”,那为了“代码管理和组织形式”牺牲“运行效率”值得么?特别是“运行效率”无法在代码方面解决的时候只能再掏真金白银来买硬件。我并不是反对面向对象,只是反对一味的面向对象,明明一个fn就能解决的问题,非得弄个cls,特别是一大堆cls的时候,就丢失了PHP的优势,还不如去用JAVA!“面向接口设计,为软件设计,架构设计提供稳定性和可靠性”——面向过程或者两者混合难道就不能“为软件设计,架构设计提供稳定性和可靠性”?用C写的哪些大型项目不是也有很多吗?“对象实例,比起值类型判断要简洁明快”——内存占用也会多很多,运行效率也会差很多!“参数类型说明,直接避免了不可靠的参数进入”——如果是外部直接提交的参数怎么说倒是可以理解,如果是怕写代码的人犯这样的错,那你要防范的事情就太多了!

首先交代清楚我的立场,我不想在我的博客里面和别人吵了乱七八糟的,因为博客的评论很乱。论坛讨论区的功能非常适合争论,所以楼主按理说应该是 @ichenshy 我只是将他的内容收集,并转移过来,我的回复、我的观点,会在这个贴的回复里面交代,那时我会作为反立场。

同时解释一下为什么说我觉得他说得好!质疑,是说明人在思考,有自己的思想。Class和function之争,PHP里由来已久,包括框架该不该存在等,都是经典之争。我会尝试表达出我的看法与见解,不过我不会立足于争论!

加载中
1
曾建凯
曾建凯

好,现在开始说明我的观点,先简单阐述一下,我这一年里在升级过程中所做过几次大规模的调整。

其中有一个阶段,大概去年9月到11月之间,我就为了到底应该基于function还是基于Class去组织框架核心的代码,进行过大量的测试和性能比较,最终选择的方案是基于Class,其中得出了一些测试的数据。

call function 10000次,设定运行时间为x(同一台机器上)

call Class::function 10000次,其运行时间约为x * (1.05 ~ 1.1),1.05 ~ 1.1表示为一个取值的范围。

call new Class 10000次,运行时间约等于x,小于x * 1.05。

当然,这里三种模式,执行的操作是相同的,这结果也包含了空函数的测试。

不过问题不仅仅在于调用一个函数所消耗的时间成本。使用function或Class模式,是两种迥然不同的风格,其中需要调整最多的,主要是全局环境的变量存放载体,和这些变量的闭合性处理的问题。说得通俗点就是,函数在运行过程中(以一个项目整体而言),产生大量的中间变量,这些中间变量指的是可用于其他函数运算时使用的,这些变量存放在哪里,是使用function或Class后,第二个争论点所在,包括如何调用。

也正是基于这第二个争论点,我最终选择了基于全局静态Class(就是Class::function)的模式,内部使用实例化的模式(new Class)来组织核心代码,重要的函数使用function形式,作为函数库的形式存在。

使用function的话,项目配置,供其他函数使用的中间变量,基本上要存放在$GLOBALS的空间里,事实上,在PHP 5.3以前的版本时,这是最稳妥的做法,因为当时PHP的GC有个bug,如果把Class实例作为类属性存放,需要手动注销,当然5.3以后就解决了这个bug。

题外话:不过PHP 5.2的这个bug,其实蛮严重的,框架2.0的时候,没注意到这个问题(PHP最初也没有公布这个bug),所以在项目面临高并发的情况下,都会发生内存溢出的问题,不得不强迫重启Apache,后来针对这种情况还特别做出调整,将所有的中间Class实例存放到$GLOBALS变量里,以解决了这个问题。

存放在$GLOBALS空间里,最大的好处是调用方便,写入直接,完全不需要考虑通过接口实现,完全是0成本。不过也碰到最大的问题,就是这些变量的闭合性的问题,有些中间变量,是不希望被直接修改的,尤其可能涉及项目运行模式的那部分,还是希望有一个接口来控制。

除了$GLOBALS空间以外,还有就是局部static变量,这东西真是……他和Class的static是一样的实现思路,初始化赋值不允许运算,只能赋静态常量和语法结构。

static弥补了纯粹存放在$GLOBALS空间的问题,的确做到了将中间变量隐藏在这个函数内部可见,不过同时又存在开放性的问题。A函数内部的static是不能和其他函数共享访问的,那意味着,如果你想访问这个static,你的函数必须设计的非常……

当然,还有老传统,就是传引用,这个东西总能在关键时刻,给你很重要的帮助。不过他的缺点也很明显,可控性太低。关于传引用的问题,有很多资料,我就不罗嗦了。

可以得见,当使用function时,闭合性方面是没有很好的解决方案的。就算能勉强实现,支撑起一个局面,可是越到深处,会发现,需要隐蔽起来的变量,会越来越多,同时这些隐蔽的变量,又需要公共接口访问。使用公共接口访问的好处是,得意在接口处,你还可以做一层处理,提供更大的编程可能性。而就算是用函数局部的static,又需要把函数的参数设计的异常诡异。而我个人认为,一个能易于被学习、被使用的函数,他的参数应该是少量,且合理的,而不是多变的,不可预测的——所谓可预测,是一个十分重要的特性,一个函数,调用1、2次,基本上就能推测出起参数传递方式,便于被记住,这样这种函数被使用的几率也最大,如果一个函数一会一种情况,要怎么用,还得看看说明文档,这是很糟糕的函数设计。

使用$GLOBALS实际上还存在另外一个问题,立于PHP这个语言来说,直接读取$GLOBALS应该最快的做法,不过事实上HashKey查找的成本,你没有计算进去。为此前几天,我还为此专门拿node.js和PHP做了一个比较,比较的就是HashTable的性能问题。结论是明显的,node.js的object结构({})性能远远高于PHP的array。其实看他实现出来的东西你就知道了,v8引擎里object是无序的,而PHP的array,即便你把他当hashtable来使用,他本身还是有序的。

相反之下,使用Class的结构去组织代码,全部的变量可以很好的隐藏在类属性中,如果你认为必要,完全可以转用public公布这个属性,如需要,又能很好的将其隐蔽,然后设计接口,提供写入的方法。所以,经过这个层次的对比,Class和function之争,很快有了答案。

当然,这个答案是对我而言,我想,每个人有自己的看法,没来得半分强求吧。我不求辩其长,只求论其明。

0
Narky
Narky

按照这个观点,很多解释型的语言完全可以一个function打天下了,要class干啥

框架是框架的问题,class是class的问题,这个需要搞搞区分

class是为了更好的代码组织和复用,而不是为了有个class就用class

全部都是function的一个典型的反面例子就是 ECShop

x
xx-xx-xx
回复 @Narky : 你没有看懂我的观点,又说“按照这个观点”来如何如何,那我还是有必要争论一下的吧?不然我在说东,你却反对我说西,这样还怎么讨论呢?
曾建凯
曾建凯
回复 @Tuesday : 其实从wp3.x以后的表现来说,他还是想走oop的,只是前面的东西改动大了,估计很多人不乐意了。关键是wp 到今天才形成CMS的口碑。
曾建凯
曾建凯
回复 @Tuesday : wordpress的源代码我从2.x一直跟到3.x了,后台部分的很多代码,还是走oop设计思路的,后台界面有一个核心的class,然后不同的模块重载具体的列表,编辑的接口。后台代码更新之频密真是十分讨厌,意味着很多开发好的插件要跟进调整。
Narky
Narky
回复 @ichenshy : 没有跟你解释的必要。讨论问题就讨论问题,没必要做无谓的争论
Narky
Narky
回复 @Tuesday : phpmyadmin和wp轮不到我来黑。我是被ecshop折腾过了,所以要黑一下,哈哈。其实也不是黑,只是说一个例子
下一页
0
Tuesday
Tuesday

function 就失去了重载的功能, 这点对于架构会造成严重的影响.

事实上写函数到达一定境界, 是在写类方法. 比如get_cat(); 函数, 取得所有的栏目数组, 我们平时写, 也许就查询一下, 然后return结果即可. 接着又将查询数据库缓存, 接着又会去思考防止函数被调用二次, 函数调用二次不会报错, 却会引发开发者去思考, 这真心是低智商的bug. 所以你又会产生静态数组方式.

楼主, 不要批判class, 可以批判框架.

0
曾建凯
曾建凯
先吃点东西,回头来发下篇。
0
pantrick
pantrick
楼主最好发博客吧,那样留存也久,容易查找
曾建凯
曾建凯
但是博客的评论没讨论区的好用,真是头疼啊,最后结贴的时候,我再转移回博客好了。
0
傅小黑
傅小黑
回头到博客贴一边吧。。。开发过程的思考都写出来
0
南湖船老大
南湖船老大
人家都在搞设计模式、函数式编程、多范式了,可怜的PHPer还在Class与function之争
0
dy810810
dy810810
php的效率瓶颈根本不在class或function上。扯来扯去净整些没用的。再纠结的话,整java的去整java,整c的就去整c。
0
yak
yak

为此前几天,我还为此专门拿node.js和PHP做了一个比较,比较的就是HashTable的性能问题。结论是明显的,node.js的object结构({})性能远远高于PHP的array。

 具体测试结果是多少





曾建凯
曾建凯
远高于!我测试的时候,纯粹是php xxx.php和node test.js。以运行一个相同效果的函数执行x万次。
0
Narky
Narky

引用来自“阿尔法兽”的答案

人家都在搞设计模式、函数式编程、多范式了,可怜的PHPer还在Class与function之争

上层概念和底层的东西不好拿来比较吧。

phper也是码农

返回顶部
顶部