[英]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
左右。 然后為每個節點ANodeProcessor
, RefNodeProcessor
等創建一個新類。
或者,您只能創建一個類NodeProcessor
,其中包含以下形式的方法: processTag
。 然后:
$this->processNode($tag);
$name = 'process'. $tag;
$name = 'process'. $tag;
return $this->nodeProcessor->{$name};
NodeProcessor
應該具有__call()
方法來對未定義processTag
方法的標簽執行“默認操作”。 同樣,不要忘記添加操作碼緩存。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.