【问题标题】:Refactoring a massive function into many files将海量函数重构为多个文件
【发布时间】:2008-12-05 03:50:08
【问题描述】:

我一直在尝试重构我之前开发的“一点”代码。基本上,该项目是我对不知道如何有效使用 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
    }
}

这一切都很好,除了最后我的 switch 有 26 个分支,而且曾经的 switch 块有超过 1000 行代码。不用说,它使维护变得更加困难。

我现在所做的是将每个分支的代码提取到它自己的文件中(名为“a.php”、“box.php”、“ref.php”...)和include每次归档:

if (file_exists("templates/$nodeName.php")) {
    include "templates/$nodeName.php";
} else {
    // do the default thing
}

同样,这很有效,但基准测试表明它已将处理时间减慢了 50%。我假设这是因为现在有多达 4000 个includes 正在完成。

我正在考虑将每个模板的代码放入一个函数中,如果尚未声明该函数,则包含该文件,然后运行该函数 - 唯一的问题是现有代码已经写在原函数的范围内,使用$this

鉴于此代码不是实时运行的(例如:它只是将 XML 处理为存储的静态 HTML 文件 - 它不是即时完成的),您对我有什么建议吗?

【问题讨论】:

    标签: php xml refactoring include


    【解决方案1】:

    警告:我不懂 PHP,但我可以google,而且我更喜欢函数指针而不是巨大的 switch 语句,所以如果你不能只使用 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)
        }
    }
    

    【讨论】:

      【解决方案2】:

      试试这样的:

      //utils.php 函数句柄框($节点) { //... } 函数句柄链接($节点) { //.... } ?\>

      然后:

      require_once '模板/utils.php'; 函数获取模板() { 开关($节点) { 案例“一”: handle_link($node,$otherParams); 休息; } } }

      基本上,这会将每个节点的所有功能重构为自己的功能。从这里您可以研究更通用的解决方案。它与您原来的非常相似,但 switch/case 语句将更易于管理,而其中没有大量代码。然后,如果您认为有必要,您可以考虑实施Stratgy design pattern

      【讨论】:

      • 我认为这实际上是他的原始代码,或者更糟。对你来说幸运的是,我的投票差了 9 分;)
      • 不,我实际上只是将我的原始代码剪切并粘贴到外部文件中 - 根本没有对其进行任何更改(例如:将每个代码包装到一个函数中)
      • 如果这是他的原始代码,将26个case语句变成1000行,那将是相当惊人的......
      【解决方案3】:

      无需深入研究 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 方法的标签执行“默认操作”。

      同样,不要忘记添加操作码缓存。

      【讨论】:

        猜你喜欢
        • 2014-11-30
        • 2020-01-22
        • 2018-04-23
        • 1970-01-01
        • 1970-01-01
        • 2018-02-28
        • 1970-01-01
        • 2021-12-22
        • 1970-01-01
        相关资源
        最近更新 更多