逐步提升框架的性能(转载网络)

2009-02-03 15:46:45 php Views(556)

一、当前框架存在什么问题

目前主流的框架Zend Framework、Cakephp等都采用了MVC模式,同时实现了URL的路由分配。比如说http://www.xxx.com/user /login就会映射到userController对象中的loginAction方法,http://www.xxx.com/user /register对应为userController对象中的registerAction方法。这样对应的userController对象就很可能 是这样的。

<?
class userController extends controller{

function

loginAction(){
//login
}

function

registerAction(){

}

}

?>

那么这存在什么样的问题呢?很明显:包含了不必要的代码!比如说你访问/user/login完全没必要包含 registerAction()方法里面的内容。上面的代码只是简单的例子,一般来说controller对应的是一个小功能模块,它会有比较多的功能 操作的,尤其在比较大的项目中。这样,如果一个controller里面有十几个方法,那么每请求就包含了很多冗余的代码。而在PHP性能提升中很重要的 一点:尽量避免包含不相关代码
在我最近的小项目中,我采用自己的phpbean框架(框架类似Zend Framework),在后来的开发发现的确每个controller包含太多action了,后来不得不考虑分流。但很不理想。项目地 址:http://www.songjin.net:8080。

二、问题不是因为面对对象的错
很多人认为包含多余的冗余代码是面对对象的错误,我不同意。正如我上篇说的:面对对象能实现面对过程的所有功能,并且做的更好!关键是采用面对对象的思维来使用面对对象,而不是用面对过程的思维来写面对对象的程序。

三、如何解决这个问题呢?
解决的关键就是把action分离开来。如何分离呢?首先要清楚controller的作用。controller是控制器,主要是做请求的转发,把 http请求转发到具体的action上。注意:在struts中是没有存在controller文件的(注意不是说没有控制器),它是直接映射到 action文件。所以我们完全可以把controller直接放到路由转发中,而真正的流程控制、逻辑处理等放到action中。

比如说上面的例子,我们就可以分离成两个文件:
loginAction.php


<?
class loginAction extends Action{

function

run(){

}

}

?>

和registerAction.php

<?
class registerAction extends Action{

function

run(){

}

}

?>
<?
class user extends Action(){

function

__contruct(){
//比如说权限检查
}
}
?>

这样就实现了action的分离。当你访问/user/login请求的时候就不会包含registerAction的代码。
但这样又存在两个问题:
第一、实际项目中action文件会非常多,如何有效的管理是个关键。
第二、同一功能模块中的操作可能有共同的代码,如何共享?

第一个问题比较好解决。把同一个模块的action放到一个子文件夹中,也就是说允许多级目录。比如说我们上面的代码中就可以把 loginAction.php和registerAction.php放到user目录中。但注意这样会增加路由分配的麻烦度,如何实现就看读者自己去 思考了。

第二个问题的解决也不难,关键是具有面向对象的思维。这里,我们就可以采用对象的继承来实现。比如说上面的例子,我们可以先定义一个user抽象类。

然后让loginAction 和RegisterAction都继承与user。这样就可以很好解决了。

west Says:

2007/05/23 06:35

和我自己用的mf框架解决方案类似..连run()方法名都一样.汗
就我自己的体会说两句:
的确性能瓶颈不在于包含文件大小,如果纯粹为了追求包含文件大小来使用这样的方案是没有必要的.但是这样的方案有其他的好处,包含文件缩小只是附带的.就我体会来说,好处至少有两个:
1. 单个action文件的代码更加清晰.在af的方案下,如果一个module下面有很多action,那么action文件是什么样?如果各个 action都比较复杂,又会如何?更进一步,因为action的execute过程比较复杂而在action内拆分出方法是很常见的(相当于opp时的 函数),那么如果一个module下的多个action都各自定义了几个方法之后action类又会变成什么样?在这些情况下,action类可谓混乱不 堪.拆分之后就会清晰很多.
2.action的层次定义可以更加灵活.简单的说,在zf的方案下一个具体的action分派同时涉及到 action类的文件(包含路径)与类之内的具体方法名,而文中的方法则只涉及到action类的文件.具体的灵活度涉及到url_rewrite与 dispatch规则,但是就我的体会来说是更加灵活了,尤其是适当定义的话重组层次会特别容易(只涉及文件复制/移动,不涉及文件内的代码复制/剪切 /粘贴).
另外,对于文中提到的"同一功能模块中的操作可能有共同的代码,如何共享?"这个问题,就我的体会,一个设计良好的功能结构中 action应当是不会出现action之间互相继承扩展的需求的,如果必须出现这种情况一般意味有一些内容可以重构移动到model层去.这里需要注意 一点,action本身并不代表任何客观实体,理想状态下action类本身只是作为一种包装容器存在,因此原则上不应当出现关联于特定action的方 法/属性,都可以通过恰当重构来归入正确的实体类下(例如某个model类)

首先,我纠正一下:ZF是支持这种模式的,但需要自己去定义下。

至于这种当时的好处,是有几方面的(我在文中只说到一方面)
一、提升了性能。我用ZF和我自己的PHPBEAN开发了两个中型项目。其中发现功能多的时候,controller文件不小,这对性能一定是有影响的。关于有没有必要,我觉得这和代码优化一样,如果你觉得把count移到for循环之外没有好处,那我就没话说了。
第二、结构更加合理。ZF中默认其实是module->controller->action的。其实本生MVC中真正负责处理的是action,我在这里把action单独出来,更加符合MVC设计的原理。
第三、更加有利于分工合作。使用controller分工的级别是在功能块上的,而使用action分工到具体的某个大动作上。使用action就可以做一个一个人实现user中的loginAction,其他人实现registerAction.

对于框架我的开发是效率+灵活(分工合作)。

对 于west说的“一个设计良好的功能结构中action应当是不会出现action之间互相继承扩展的需求的,如果必须出现这种情况一般意味有一些内容可 以重构移动到model层去”,这个我不认同。action之间共享的未必是数据的操作。对于action的继承。主要是为了实现一些公共的逻辑流程功 能,比如说ACL、注册公共变量等等。

Tags:   php  zend  framework  mvc  oo

Comments

rui

我的一般情况是: 一个控制器放置 3~5 个动作,代码控制在 500 行以内 ...

2009-02-03 21:39:35

Leave a Comment

Name
Content
Verification Type the characters you see in the picture below