簡體   English   中英

將大量功能重構為許多文件

[英]Refactoring a massive function into many files

我一直在嘗試重構以前開發的代碼的“一部分”。 基本上,該項目是我對不知道如何有效使用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” ...)中,並每次都include該文件:

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

再次,這是可行的,但對其進行基准測試表明,它已將處理時間減慢了50%。 我假設這是因為現在最多可以完成4000個include

我正在考慮的是將每個模板的代碼放入一個函數中,如果尚未聲明該函數,則包括該文件,然后運行該函數-唯一的問題是現有代碼已寫入其中原始功能的范圍,使用$this等。

鑒於此代碼不是實時運行的(例如:它僅將XML處理為存儲的靜態HTML文件-並非即時完成),您在這里對我有什么建議嗎?

警告:我不了解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)
    }
}

嘗試這樣的事情:

//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設計模式

在不涉及XSLT本身而只關注重構問題的情況下:您已經考慮了很多不同的策略。 我將提供關於您已經嘗試過的一種方法的優化技巧,以及另一種可能對您有用的方法。

當您說依賴許多文件時,性能下降了50%。 我認為您沒有啟用PHP操作碼緩存。 您這樣做了,那50%的損失應該消失了。

在另一種方法上,我建議創建一個基類NodeProcessor左右。 然后為每個節點ANodeProcessorRefNodeProcessor等創建一個新類。

或者,您只能創建一個類NodeProcessor ,其中包含以下形式的方法: processTag 然后:

  1. 您可以調用$this->processNode($tag);
  2. 該方法中的一個: $name = 'process'. $tag; $name = 'process'. $tag;
  3. 然后: return $this->nodeProcessor->{$name};
  4. NodeProcessor應該具有__call()方法來對未定義processTag方法的標簽執行“默認操作”。

同樣,不要忘記添加操作碼緩存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM