Рефакторинг массивной функции во многие файлы - PullRequest
1 голос
/ 05 декабря 2008

Я пытался реорганизовать «бит» кода, который я ранее разработал. По сути, проект был моим ответом на то, что я не знал, как эффективно использовать XSLT, поэтому я разработал систему преобразования XML в PHP. Программа читает теги 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-файлы, которые хранятся - это не делается на лету), у вас есть какой-нибудь совет для меня здесь?

Ответы [ 3 ]

3 голосов
/ 05 декабря 2008

предостережение: я не знаю PHP, но я могу google , и мне нравятся указатели функций лучше, чем огромные операторы switch, так что если вы не можете просто использовать XSLT ...

... одним из вариантов будет принятие соглашения об именах для ваших «рабочих» функций, которые включают имя тега html-узла, например, _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 голос
/ 05 декабря 2008

Не вдаваясь в сам XSLT и не сосредотачиваясь на вопросе рефакторинга: вы уже рассмотрели немало различных стратегий. Я предложу совет по оптимизации для одного из подходов, с которым вы уже экспериментировали, и еще один подход, который может работать для вас.

Когда вы сказали, что при использовании многих файлов снижение производительности составило 50%. Я так понимаю, у вас не включен кэш PHP-кода. Вы делаете это, и эти 50% проигрыша должны исчезнуть.

С другой стороны, я бы предложил создать базовый класс NodeProcessor или около того. А затем создайте новый класс для каждого узла ANodeProcessor, RefNodeProcessor, ... и т. Д.

Кроме того, вы можете создать только один класс NodeProcessor, который содержит методы в виде: processTag. Тогда:

  1. Вы можете позвонить $this->processNode($tag);
  2. В этом методе: $name = 'process'. $tag;
  3. Тогда: return $this->nodeProcessor->{$name};
  4. NodeProcessor должен иметь метод __call() для выполнения "вещи по умолчанию" для тегов, для которых не определен метод processTag.

Опять же, не забудьте добавить кеширование кода операции.

1 голос
/ 05 декабря 2008

Попробуйте что-то вроде этого:

//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 , если считаете, что это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...