Php 将大型函数重构为多个文件
我一直在尝试重构我以前开发的一些代码。基本上,这个项目是我对不知道如何有效使用XSLT的回应,所以我用PHP开发了一个XML转换系统。程序读取XML文件的标记,并按照以下方式将其转换为HTML:Php 将大型函数重构为多个文件,php,xml,refactoring,include,Php,Xml,Refactoring,Include,我一直在尝试重构我以前开发的一些代码。基本上,这个项目是我对不知道如何有效使用XSLT的回应,所以我用PHP开发了一个XML转换系统。程序读取XML文件的标记,并按照以下方式将其转换为HTML: private function getTemplate(...) { switch ($nodeName) { case "a" : // code here to generate a link tag break;
private function getTemplate(...) {
switch ($nodeName) {
case "a" :
// code here to generate a link tag
break;
case "box" :
// code here to generate the divs and whatnot to create a box
break;
case "ref" :
// look up an external reference file and include a bibliography
break;
default :
// do the default thing
}
}
这一切都很好,除了我的交换机有26个分支,而且曾经的交换机块有1000多行代码。不用说,这使得维护稍微困难一些
我现在所做的是将每个分支的代码拉到它自己的名为a.php、box.php、ref.php的文件中。。。并且每次都包括该文件:
if (file_exists("templates/$nodeName.php")) {
include "templates/$nodeName.php";
} else {
// do the default thing
}
同样,这是可行的,但基准测试表明它将处理时间降低了50%。我假设这是因为现在有多达4000个包含正在进行
我考虑的是将每个模板的代码放入一个函数中,如果函数尚未声明,则包含该文件,然后运行该函数-唯一的问题是,现有代码已在原始函数的范围内编写,使用$this,等等
考虑到这段代码不是实时运行的,例如:它只是将XML处理成静态HTML文件并存储起来——这不是即时完成的,您有什么建议吗?警告:我不懂PHP,但我可以而且我更喜欢函数指针而不是巨大的开关语句,所以如果您不能只使用XSLT …一种选择是为包含html节点标记名的“worker”函数采用命名约定,例如_converter,包括所有函数,并用以下内容替换switch语句:
private function getTemplate(...)
{
$func = $nodeName + "_converter";
if (function_exists($func)) //see if function is defined, somehow...
{
$func(); //call conversion function (pass whatever is needed)
}
}
警告:我不懂PHP,但我可以而且我更喜欢函数指针,而不是大型开关语句,所以如果您不能只使用XSLT …一种选择是为包含html节点标记名的“worker”函数采用命名约定,例如_converter,包括所有函数,并用以下内容替换switch语句:
private function getTemplate(...)
{
$func = $nodeName + "_converter";
if (function_exists($func)) //see if function is defined, somehow...
{
$func(); //call conversion function (pass whatever is needed)
}
}
试着这样做: //utils.php function handle_box($node) { //... } function handle_link($node) { //.... } ?\> 然后:
基本上,这会将每个节点的所有功能重构为自己的功能。从这里你可以得到一个更普遍的解决方案。它与您最初使用的非常相似,但是switch/case语句在没有大量代码的情况下将更易于管理。然后,如果您觉得有必要,可以考虑潜在地实施。尝试以下方法: //utils.php function handle_box($node) { //... } function handle_link($node) { //.... } ?\> 然后:
基本上,这会将每个节点的所有功能重构为自己的功能。从这里你可以得到一个更普遍的解决方案。它与您最初使用的非常相似,但是switch/case语句在没有大量代码的情况下将更易于管理。然后,如果您觉得有必要,您可以考虑潜在地实现。而不必深入XSLT本身并关注重构问题:您已经考虑了大量不同的策略。我将提供一个优化技巧,介绍您已经尝试过的一种方法,以及另一种可能适合您的方法 当您说依赖多个文件时,性能会下降50%。我认为您没有启用PHP操作代码缓存。你这么做了,那50%的损失应该消失了 在另一种方法中,我建议创建一个基类NodeProcessor左右。然后为每个节点创建一个新类ANodeProcessor、RefNodeProcessor等等 或者,您只能创建一个类NodeProcessor,其中包含:processTag形式的方法。然后: 您可以调用$this->processNode$tag; 该方法中的一个参数:$name='process'$标签 然后:返回$this->nodeProcessor->{$name}; NodeProcessor应该有一个_调用方法来为没有定义processTag方法的标记执行默认操作。
同样,不要忘了添加操作码缓存。不必深入XSLT本身并关注重构问题:您已经考虑了大量不同的策略。我将提供一个优化技巧,介绍您已经尝试过的一种方法,以及另一种可能适合您的方法 当您说依赖多个文件时,性能会下降50%。我认为您没有启用PHP操作代码缓存。你这么做了,那50%的损失应该消失了 在另一种方法中,我建议创建一个基类NodeProcessor左右。然后为每个节点创建一个新类ANodeProcessor、RefNodeProcessor等等 或者,您只能创建一个类NodeProcessor,其中包含:processTag形式的方法。然后: 您可以调用$this->processNode$tag; 该方法中的一个参数:$name='process'$标签 然后:返回$this->nodeProcessor->{$name}; 节点处理器应该有一个_调用方法来执行de 未定义processTag方法的标记的错误。
同样,不要忘了添加操作码缓存。我认为这就是他的原始代码,或者更糟的话。对你来说幸运的是,我还差9分投了反对票;不,我实际上只是将我的原始代码剪切粘贴到外部文件中——根本没有对其进行任何更改。例如:将每个代码包装成一个函数如果这是他的原始代码,将26个case语句转换成1000行将是非常惊人的……我想这就是他的原始代码,或者更糟的话。对你来说幸运的是,我还差9分投了反对票;不,我实际上只是将我的原始代码剪切粘贴到外部文件中-根本没有对其进行任何更改例如:将每个代码包装成一个函数如果这是他的原始代码,将26个case语句转换为1000行将是非常惊人的。。。