将大量函数重构为许多文件

时间:2008-12-05 03:50:09

标签: php xml refactoring include

我一直在尝试重构我之前开发的一些“代码”代码。基本上,该项目是我不知道如何有效使用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文件 - 它不是即时完成的),你对我有什么建议吗?

3 个答案:

答案 0 :(得分:3)

警告:我不知道PHP,但我可以google并且我比大型switch语句更喜欢函数指针,所以如果你不能只使用XSLT ......

...一个选项是为你的'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左右。然后为每个节点ANodeProcessorRefNodeProcessor,...等创建一个新类。

或者,您只能创建一个类NodeProcessor,其中包含以下形式的方法:processTag。然后:

  1. 您可以致电$this->processNode($tag);
  2. 使用该方法:$name = 'process'. $tag;
  3. 然后:return $this->nodeProcessor->{$name};
  4. NodeProcessor应该使用__call()方法为未定义processTag方法的代码执行“默认操作”。
  5. 同样,不要忘记添加操作码缓存。