我一直在尝试重构我之前开发的一些“代码”代码。基本上,该项目是我不知道如何有效使用XSLT的回应,所以我开发了一个PHP的XML转换系统。该程序读取XML文件的标记,并沿着这些行执行某些操作以将其转换为HTML:
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”......)和{{1}每次都是那个文件:
include
同样,这有效,但基准测试表明它已将处理时间减慢了50%。我假设这是因为现在已经完成了4000 if (file_exists("templates/$nodeName.php")) {
include "templates/$nodeName.php";
} else {
// do the default thing
}
。
我在考虑的是将每个模板的代码放入一个函数中,如果该函数尚未声明,则包含该文件,然后运行该函数 - 唯一的问题是现有代码具有已使用include
等编写在原始函数的范围内
鉴于此代码不是实时运行的(例如:它只是将XML处理成存储的静态HTML文件 - 它不是即时完成的),你对我有什么建议吗?
答案 0 :(得分:3)
...一个选项是为你的'worker'函数采用一个命名约定,该命令约定包含html节点的标记名称,例如: < tagname> _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)
}
}
答案 1 :(得分:1)
尝试这样的事情:
//utils.php function handle_box($node) { //... } function handle_link($node) { //.... } ?\>
然后:
require_once 'templates/utils.php'; function getTemplate() { switch($node) { case "a" : handle_link($node,$otherParams); break; } } }
基本上,这会将每个节点的所有功能重构为自己的功能。从这里开始,您可以使用更通用的解决方案。它与你原来的非常相似,但是如果没有大量代码,switch / case语句将更易于管理。如果您觉得有必要,可以考虑潜在地实施Stratgy design pattern。
答案 2 :(得分:1)
没有进入XSLT本身并专注于重构问题:您已经考虑了相当多的不同策略。我将针对您已经尝试过的方法之一提供优化提示,以及另一种可能适合您的方法。
当你说依赖很多文件时性能下降了50%。我认为你没有启用PHP操作码缓存。你这样做,50%的损失应该消失。
在另一种方法中,我建议创建一个基类NodeProcessor
左右。然后为每个节点ANodeProcessor
,RefNodeProcessor
,...等创建一个新类。
或者,您只能创建一个类NodeProcessor
,其中包含以下形式的方法:processTag
。然后:
$this->processNode($tag);
$name = 'process'. $tag;
return $this->nodeProcessor->{$name};
NodeProcessor
应该使用__call()
方法为未定义processTag
方法的代码执行“默认操作”。同样,不要忘记添加操作码缓存。