1

以前に開発したコードの「ビット」をリファクタリングしようとしています。基本的に、このプロジェクトは、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 になり、1 回のスイッチ ブロックのコードが 1000 行を超えたことを除いて、すべてうまくいきました。言うまでもなく、メンテナンスが少し難しくなりました。

私が今行ったことは、各ブランチのコードを独自のファイル (「a.php」、「box.php」、「ref.php」... という名前) とincludeそのファイルに毎回プルすることです。

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

繰り返しますが、これは機能しますが、ベンチマークでは、処理時間が 50% 遅くなることが示されています。これは、現在最大 4000includeの処理が行われているためだと思います。

私が考えていたのは、各テンプレートのコードを関数に入れ、関数が宣言されていない場合はファイルをインクルードしてから関数を実行することでした-それに関する唯一の問題は、既存のコードが.$thisなどを使用して、元の関数の範囲。

このコードがリアルタイムで実行されないことを考えると (たとえば、XML を保存されている静的な HTML ファイルに処理するだけであり、その場で実行されるわけではありません)、何かアドバイスはありますか?

4

3 に答える 3

3

警告: 私は PHP を知りませんが、Googleで検索することはできますし、巨大な switch ステートメントよりも関数ポインターの方が好きなので、XSLT だけを使用できない場合は...

... 1 つのオプションは、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)
    }
}
于 2008-12-05T04:01:47.350 に答える
1

次のようなことを試してください:

//utils.php
関数 handle_box($ノード)
{
//...
}

関数 handle_link($node)
{
//....
}
?\>

それから:

require_once 'templates/utils.php';


関数 getTemplate()
{
  スイッチ($ノード)
  {
      ケース "a" :
        handle_link($node,$otherParams);
      壊す;
  }
}

}

基本的に、これは各ノードのすべての機能を独自の機能にリファクタリングします。ここから、より一般化されたソリューションに取り組むことができます。これは元のものと非常に似ていますが、switch/case ステートメントは、内部に大量のコードがなくてもはるかに扱いやすくなります。その後、必要に応じてStratgy デザイン パターンを実装する可能性を検討できます。

于 2008-12-05T04:43:50.273 に答える
1

XSLT 自体に触れたり、リファクタリングの問題に焦点を当てたりしなくても、すでにかなりの数のさまざまな戦略を検討しています。あなたがすでに試したアプローチの 1 つと、あなたに役立つ可能性のある別のアプローチについて、最適化のヒントを提供します。

多くのファイルに依存すると、パフォーマンスが 50% 低下するとおっしゃいました。PHP オペコード キャッシュが有効になっていないと思います。そうすれば、その 50% の損失はなくなるはずです。

他のアプローチでは、基本クラスなどを作成することをお勧めしNodeProcessorます。そして、すべてのノードに対して新しいクラスを作成しますANodeProcessor, RefNodeProcessor, ...など.

NodeProcessorまたは、次の形式のメソッドを含むクラスを 1 つだけ作成することもできますprocessTag。それで:

  1. あなたは呼び出すことができます$this->processNode($tag);
  2. その方法で:$name = 'process'. $tag;
  3. それで:return $this->nodeProcessor->{$name};
  4. NodeProcessorメソッドが定義され__call()ていないタグの「デフォルトのこと」を行うメソッドが必要です。processTag

繰り返しますが、オペコード キャッシングを追加することを忘れないでください。

于 2008-12-05T12:04:12.617 に答える