Facing refucktoring



    История одного рефакторинга, или о сказ о том как не надо разрабатывать на PHP…

    Началось все как всегда, откуда-то появляется заказчик весь в слезах и трансе, орет не своим голосом: «Спасите, помогите, мой проект тормозит, от меня пользователи бегут. У вас неделя...»

    Развернули проект на нашем сервере — н-да уж… Дальше был анализ сего творения фирмы «Q» (кто следит за мной, знает о какой украинской фирме речь), смех сквозь слезы, и истерика в течении недели. Ну для начала был взят XDEBUG и посмотрели профайлером что там и как (кликабельно):


    Такую клевую штуку рисует Webgrind, удобно и наглядно


    Т.е. у нас страница, которая выводит приветствие + выбор языка + выбор категории для просмотра (захардкоденных кстати) генерировалась за 4,6 секунды на сервере с Core2 Quad CPU Q6600@2.40GHz/16Gb (истерика и лучи ненависти конторе «Q»).

    Куда более жутка картина ожидала нас на главной странице:


    До применения Zend Framework'a нас отделяло еще несколько недель оптимизации г… кода…

    FastTemplate такой «Fast»



    Если присмотреться, то на предыдущем скрине видно, что очень дорого нам обходится некая функция parse_body:



    Внутри нас ждет:

    • вызов strtoupper — 56560 раз
    • вызов str_replace — 56560 раз


    Смотрим на код:
    // $content - шаблон
    // $rec - переменные
    $content = preg_replace("/\\$([A-Z][A-Z0-9_]+)/", "@\\1@", $content);
    if (is_array($rec)) {
        foreach ($rec as $key => $value) {
            $name = strtoupper($key);
            $content = str_replace("@$name@", "$value", "$content");
        }
    }
    return $content;


    Т.е. в самом начале мы ищем в шаблонах что-то вроде $HTTP_PATH, заменяем это на @HTTP_PATH@, потом перебором пытаемся заменить все известные переменные. Есть одна проблема — шаблонов у нас много, в них используется совсем чуть-чуть из пары сотен переменных. Простая замена str_replace на preg_replace_callback дала прирост в пару секунд (т.е. около 10%).

    Примеры кода


    Слабонервным лучше пропустить данный абзац.

    Классика плохого PHP кода, встречается у индусов и наших студентов:
    function n() {
       global $db, $CONSTANTS, $user, ...; // много одним словом
     
       echo $CONSTANTS[HOMEPAGE_BANNER1_ID];  // думаете это константа?
       echo $CONSTANTS[HOMEPAGE_BANNER2_ID];  // а знаете, что внутри?
       echo $CONSTANTS[HOMEPAGE_BANNER3_ID];  // 1, 2, 3, которые меняются совсем не там где объявляются О_о
    }


    Использование файловой системы вместо системы контроля версий:
    tpl
    |-- index.tpl
    |-- index2.tpl
    |-- index3.tpl
    |-- index__.tpl
    `-- index.44.tpl
    


    С базой данных тот же номер — таблицы categories_old, items_1 и т.д.

    Если мальчик любит труд
    тычет в книжку пальчик,
    про такого пишут тут:
    он хороший мальчик.


    Это, как вы понимаете, не про наших «мальчиков», у наших 9 000 notices на главной. Да и manual'ами пользуются только слабаки:
    // мы не читаем мануалов
    while ($row = mysql_fetch_array($res)) {
          if ($row) {
                foreach ($row AS $key => $field) {
                    if (ereg("^[0-9]+", $key)) {
                        unset($row[$key]);
                    }
                }
          }
          $rows[] = $row;
    }
    // если чуть-чуть допилить
    // мелочь, конечно, но прирост ~0,1 сек т.к. имеет место 23162 вызовов
    while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) {
          $rows[] = $row;
    }


    Далее просто гениальное решение, тайный смысл этого творения я не осилил:
    $sqls[] = $sql;
    if (is_array($sqls)) {
        foreach ($sqls AS $ssql) {
            if ($ssql) {
                $res = mysql_db_query($db['name'], $ssql, $db['id']);
                if (!$res) {
                    return 0;
                }
            }
        }
    } else {
        return 0;
    }


    Подсчет результатов поиска, что может быть проще:
    // перед выполнением запроса можно подсчитать кол-во результатов
    // воспользовавшись функцией db_count (вызывается в 96 разных местах)
    function db_count($sql) {
        global $db;
        $res = mysql_db_query($db['name'], $sql, $db['id']);
        $result = mysql_num_rows($res);
        return $result;
    }


    Постраничная навигация, и это тоже можем:
    // пошел запрос к БД
    $res = mysql_db_query($db['name'], $sql, $db['id']);
    // подсчитали итого (хотя до этого уже был вызван db_count)
    $row_count = mysql_num_rows($res);
    // подсчитали сколько у нас страниц получается
    $page_count = floor($row_count / $pager['per_page'] + 1);
     
    // это offset
    $bi = ($pos - 1) * $pager['per_page'];
     
    // теперь выбираем только нужные записи
    for ($i = $bi; $i < $bi + $pager["per_page"]; $i++) {
        if ($i >= $row_count) {
            break;
        }
     
        if (!mysql_data_seek($res, $i)) {
            break;
        }
     
        if (!($row = mysql_fetch_assoc($res))) {
            break;
        }
        // складируем результат
        $new_rows[] = $row;
    }


    Повторение строк — мы не ищем легких путей (str_repeat):
    // в файле categories.sql.php
    // функция которая строит select для HTML
    $offset_string  = '';
    for ($i = 1; $i < $rec['level']; $i++) {
        $offset_string .= '&nbsp;&nbsp;&nbsp;&nbsp;';
    }


    Если нам надо обрезать строку на 100 символов, и при этом не кромсать слова то вот оно решение:
    $data['row']['description'] = substr($description, 0, 100);
     
    $i = 100;
    while (!($description[$i] == " " || $description[$i] == "_") && $i < strlen($description)):
        $data['row']['description'] .= $description[$i];
        $i++;
    endwhile;
     
    if ($i < strlen($description)) {
        $data['row']['description'] .= "...";
    }


    У нас так много глобальных переменных, там есть конечно $db, и она же передается во все функции которые работают с БД:
    function db_query($db, $sql) {}
    function db_sql_query($db, $sql) {}
    function db_count($db, $sql) {}
    // и т.д.
    // но почему не так, ведь у нас одна БД
    function db_query($sql) {
        global $db;
    }


    Пусть на море качка, но мы всегда прибережем обходные пути:
    $sql = "SELECT id, name, pasw from users where name = '$_POST[username]'";


    Про агрегирование в SQL мы не знаем:
    // $rows - записи из БД
    foreach ($rows as $value) {
          $total += $value["price"];
    }


    Необходимо SEO URL? Не проблема:
    switch ($params[1]):
           case "usageagreement": 
                $page_id = 13;
           break; 
           case "privacypolicy": 
                $page_id = 14;
           break; 
           case "termsandconditions": 
                $page_id = 15;
           break; 
           case "affiliates": 
                $page_id = 22;
           break; 
           case "aboutus": 
                $page_id = 19; 
           break; 
    endswitch;


    Ладно с PHP, но HTML то можно было подучить:
    <!-- id такой id -->
    <div id="banner">...</div>
    <div id="banner">...</div>
    <div id="banner">...</div>
    <div id="banner">...</div>
     
    <!-- class это почти style -->
    <li class="padding-left:15px;">...</li>
     
    <!-- табличная верстка -->
    <!-- хотя не стоит 10 вложенных таблиц расписывать -->
     
    <!-- margin, что такое margin? -->
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;


    Применение Zend_Cache


    Кеш спасет мир, подумали мы и прикрутили его для всех SQL запросов (благо кто-то догадался написать единую функцию db_sql_query) и всех вызовов parse_body. Для начала попробовали кешировать в файлы, на тестовом сервере это помогло, на живом — нет. Причина — у нас так много мелких шаблонов (~200 для главной), что операции с файловой системой свели на нет прирост кеширования.

    Вторая попытка оказалась более удачной, решили применить memcache — прирост скорости ~180%. Какой клевый показатель, но верен лишь в 100% попадании в кеш, таким образом перед нами вырисовывалась перспектива полного рефакторинга системы.

    Немного клиентской оптимизации


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

    FileETag MTime Size

    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/x-javascript

    <ifModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 seconds"
    ExpiresByType text/html "access plus 1 seconds"
    ExpiresByType image/x-icon "access plus 2592000 seconds"
    ExpiresByType image/gif "access plus 2592000 seconds"
    ExpiresByType image/jpeg "access plus 2592000 seconds"
    ExpiresByType image/png "access plus 2592000 seconds"
    ExpiresByType text/css "access plus 604800 seconds"
    ExpiresByType text/javascript "access plus 216000 seconds"
    ExpiresByType application/x-javascript "access plus 216000 seconds"


    А далее все по порядку:
    • Оптимизация изображений для web (есть такой пункт в Photoshop) — 40% на всех JPEG фалах
    • Спрайты — кропотливая работа, десятки обращений к серверу можно свести к единицам
    • Жмем JavaScript и CSS — ~50%
    • И последним пунктом — nginx для всего этого добра


    Zend Framework


    А теперь расскажу о том, как проект медленно переезжает на Zend Framework. Начинается всё с простой проверки в index.php (о да в нашей системе одна точка входа):

    // список модулей, которые уже отрефакторили
    $modules = array (
        '/search/',
        '/about/'
    );
     
    $path = $_SERVER['REQUEST_URI'];
     
    // нас устроила такая простая проверка, 
    // но запрос вида /search/?... уже не будет обрабатываться
    if(in_array($path, $modules)) {
        // подключаем ZF (внутри стандартный код из сгенерированного public/index.php)
        require 'loader.php';
        exit();
    }
     
    // а эта будет
    foreach ($modules as $module) {
        if (strpos($path, $module) === 0) {
            require 'loader.php';
            exit();
        }
    }


    Если у нас не одна точка входа, то в каждом файле, которые были затронуты делаем простую вставку:
    $_SERVER['REQUEST_URI'] = str_replace($_SERVER['PHP_SELF'], '/admin/', $_SERVER['REQUEST_URI']);
    require 'loader.php';
    exit();


    Что-бы забыть «глобальный» ужас, жизненно-необходимые переменный были закинуты в Zend_Registry (а в дальнейшем закинуты в конфигурационный файл application.ini, где им самое место).

    Так же Zend_Translate была скормлена таблица с переводами (см. адаптер array)

    Результат


    Сложно судить о результате, проект находится в разработке, но вот несколько сравнительных замеров:

    Время генерации Время генерации (re) Время генерации (ZF) Объем страницы Объем страницы (ZF)
    Главная страница 4 663ms 2 759ms 699.5Kb 288.0Kb
    Статические страницы 3 115ms 2 008ms  295ms 263.3Kb 166.2Kb
    Cтраница айтема 3 082ms 1 745ms  180ms 589.1Kb 260.8Kb


    Еще наглядный скриншот среднего/максимального времени генерации страниц по датам: http://screencast.com/t/NDY1NGE5

    UPDATE: Извините за тон статьи, но как-то накипело-то. Если кому-то кажется, что цель статьи показать кто тут белый и пушистый, а кто иной — то нет, основная задумка — поделиться опытом, показать примеры «плохого» кода, и не имеет значения кто его написал, главное чтобы каждый извлек для себя урок, и подобного кода становилось меньше…
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 159
    • 0
      Разница впечатляет, но даже достигнутый результат (ИМХО) слабоват. 2 секунды. Хабр вот меньше чем пол секунды грузится.
      • 0
        Да тут спасет только полные переезд, похоже. Код явно писался году так в 2004 (:
        • 0
          да и сейчас такие перлы встречаются.
          • +1
            Сейчас и не такие перлы встречаются. Виделся с одним перлом в огромном интернет-магазине на чистом php
            • 0
              Можно порадоваться за исполнителя, нашедшего такого богатого заказчика.
              • 0
                Да, как-то на хабре кто-то публиковал: в самом старте скрипта делался запрос к базе и вытаскивались ВСЕ позиции товаров в массив.
                • 0
                  ага помню GLOBAL_ARRAY=все и вся)
              • +2
                В данном контексте интересно звучит слово "перлы" :))
            • 0
              Время генерации (ZF) 295ms и т.п., тобеж только полный переезд поможет
              • 0
                Ать я дуплан, не туда посмотрел.
                Ну так 295 мс ето супер!
              • +1
                Работы много, практически надо написать проект с нуля, при этом поддерживая старый код, и обеспечивая совместимость, хочешь по… ся поразвлекаться?

                Как писал выше — отрефакториные (читай — с нуля написанные) страницы генерируются достаточно быстро (даже с учетом того, что старый код не отключен полностью)…
                • –7
                  >>Хабр вот меньше чем пол секунды грузится.
                  xa-xa. для москвы, может быть.
                  кроме медленной загрузки (секунд десять где-то) Хабр ужасно тормозит на страницах с большим количеством комментариев.
                  • +3
                    Да лана, я из Харькова.

                    И да, мы тут меряем время генерации а не время загрузки контента самого сайта.
                    Время загрузки действительно зависит от того где ты находишься и какой у тебя канал. Время генерации зависит от того как написан код.
                    • +2
                      Зря минусуете, человек абсолютно прав. Для медленных соединений хабр просто неподъёмен. Как-то пришлось через gprs заходить. Не самая большая тема (~ 100 комментов) грузилась минуты 2-3.
                      • +3
                        Может, для gprs стоить использовать m.habrahabr.ru? :)
                        • 0
                          В тот раз я про него забыл. Не так часто приходится ходить на хабр мобильно.
                          • 0
                            m.habrahabr.ru — какой-то недоделанный:
                            1. если комментариев много или статья большая — страница не бьется на части
                            2. ссылки внутри статей на другие хабра-посты уводят с мобильной версии хабра на полноценную
                            3. картинки в статьях хорошо поднимают трафик
                          • +1
                            Тормоза — я имел в виду Javascript, а не время загрузки.
                            Хотя грузятся камменты тоже медленно.

                            Мобильный интернет (около мегабита), шестимегабитный DSL или хз какой широкий канал на работе — разницы не вижу, грузится у меня Хабр (субъективно) одинаково медленно.
                            На данный момент около 5 секунд (очень хорошо!), пару часов назад — секунд 20 и больше было. Измеряю файрбагом время оnload.
                            microsoft.com < 1.5s
                            lenta.ru < 2s
                            • +1
                              если объяснишь как связано время загрузки страницы на плохом коннекте с временем генерации страницы на сервере, то да — зря минусуем.
                              • 0
                                Причём здесь GPRS и время интерпретации?
                                • 0
                                  При том, что время интерпретации — это ещё не всё. Конечному-то пользователю, по большому счёту, всё равно, почему у него страница грузится долго.
                          • +9
                            Мораль

                            «Q» — быдлокодеры, а вы — красавцы.
                            • +1
                              В защиту конторы «Q» могу сказать, что БД разрабатывал вполне адекватный чел, все по уму, запросы к БД не тормозят, просто если их выполнять по 200 раз за раз, то будет ощущаться проблема с производительностью (эка, я так мягко сказал)
                              • +8
                                Может, БД была на аутсорсе? :)
                                • 0
                                  Как это запросы к бд не тормозят? А как жет функции «db_count», коленочная аггрегация и странная разбивка на страницы? Это не выглядит как «адекватные» запросы, не тормозящие… Или Вы о чем-то другом сейчас говорили?
                                  • 0
                                    Это уже косяк логики приложения, а не неправильной структуры БД
                                  • 0
                                    БД разрабатывал вполне адекватный чел
                                    С базой данных тот же номер — таблицы categories_old, items_1 и т.д.
                                    т.е. название items_1 вполне себе?
                                    • 0
                                      изначально ее же наверное не было, разрабатывать и постоянно следить/поддерживать — это разные вещи…
                                • +3
                                  Ох знали бы вы сколько на фрилансе такого кода предлагают допиливать… а когда человеку говоришь, что только переписывать с 0, или сажать на опенсорс движок — сразу пропадают.
                                  Был у меня недавно проект. Портал. Там сайт при нагрузке в 40 онлайна начинал тормозить катастрофически.
                                  Около 100 запросов на главной… и никакого кеширования. И код внавалку… и ошибки отключены, чтобы нотисы, которых по 300 штук на каждой странице, не заменяли собой сайт.
                                  • +2
                                    Ну так ни на одном нормальном проекте на продакшене не будет display_errors == 1 :)
                                    • +2
                                      Не будет. но любой нормальный проект либо запишет в лог возникшие ошибки, либо озаботится их перехватом.
                                      И на любом нормальном проекте не будет по 300 нотисов на страницах
                                      • +1
                                        это само собой :) это я к тому написал, что хорошо хоть display_errors отключили. Сейчас хватает разных сайтов с вываливающимися notice/warning
                                        • +6
                                          если бы не отключили, то посетитель думал бы заходя на сайт, что он посвящен всевозможным нотисам в PHP — там страницы на 3-4 пролистываний их было :)
                                          • +2
                                            Он подумал бы, что взломал сайт взглядом. И пароли где то тут
                                      • 0
                                        Зато на нормальном дев сервере всегда будет ;)
                                        У нас, правда, в этом проекте пришлось отключить, т.к. даже на уменьшение кол-во notices от 9 000 к 1 000 ушел день…
                                        • 0
                                          Да, такого я не видел. Зато встречал заботливо расставленные повсеместно @ вместо нормальной обработки (:
                                          • 0
                                            Вообще не понимаю, зачем @ нужно в php. Я быдлокодер?
                                            • 0
                                              Один из вариантов — вызов DOMDocument::loadHTML*
                                        • +6
                                          У меня на половине боевых проектов ini_set('display_errors',1); error_reporting(E_ALL);
                                          Знаете как помогает всегда быть аккуратным и учитывать любые варианты работы? ;-) Ух, рекомендую!
                                          • 0
                                            но когда отваливается бд и вываливается too many connections, то все равно как-то не весело. Ну или какие-нибудь warning/notice от memcache.
                                            • 0
                                              Это совсем не весело! =) И все получаю получают такой разнос что после устранения проблемы и доработки сайт до следующего падения работает в 2 раза дольше! =)
                                        • +2
                                          Да что фриланс :) Есть такое поделие, Invision Powerboard. 30 запросов в секунду к базе на средней руки сайте — это нормально :)
                                          • –1
                                            Не понимаю чем вы недовольны — IPB3 достаточно грамотно спроектирован (на главной, кстати, всего 11 запросов, без хуков).
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                          • 0
                                            Интересный вопрос, а принадлежит ли заказчику код который у него был но которого нет теперь? Ну например тот что я удалил как «г» во время рефакторинга :)
                                            • +4
                                              а если человек не копировал код, а набивал его в ручную и — Все персонажи вымышлены, все совпадения случайны? :)
                                            • +11
                                              дело даже не в пхп, а в больном мозгу, который породил это мертворожденное творение на этот свет.
                                              • +2
                                                А никто и не говорил, что дело в php
                                                • +3
                                                  Да нет, у php такая слава именно благодаря таким кодерам. Ну и Бобуку, да, хотя тот тоже наверное просто такого кода насмотрелся.
                                              • +8
                                                Прочитал как Fucking refucktoring
                                                • +2
                                                  Я думаю смысл не потерялся :)
                                                • 0
                                                  Антон, проект залей сразу на govnokod.ru/
                                                  • +11
                                                    спасибо за webgrind
                                                    • +5
                                                      Честно в шоке. Не думал, что они ещё «творят». Только на прошлой неделе закончил приводить в чувство очередное детище этой же конторы. Контора «Q» популярнее чем я думал)
                                                      Кэш в базе данных, загрузка страницы за пол-минуты, злостное нежелание изспользовать кавычки для ключей массивов, register_globals=On и это только малая часть веселья.
                                                      Постарался избавиться от явного говнокода, уменьшить количество ошибок, установил memcache + nginx. Теперь страницы гузится в с реднем в пределах полу-секунды.
                                                      Кстати, по контракту мне пришлось ещё и продолжать развитие проекта, добавлять новые страницы, фичи и т.д. Чувствую себя изнасилованным)
                                                      истерика и лучи ненависти конторе «Q»
                                                      — именно так.
                                                      База данных, кстати, по уровню действительно выше кода.
                                                      • +1
                                                        Пока есть такие конторы, мы без работы не останемся…
                                                        • +3
                                                          Ага, самые заметные результаты рефакторинга дают подключение memcache и перенос на nginx… Я всё понимаю, мы сами так делаем в первую очередь. Но к рефакторингу это не относится (замечание и к автору статьи).
                                                        • 0
                                                          >Такую клевую штуку рисует Webgrind, удобно и наглядно
                                                          Если есть linux то советую KCachegrind для профилирования
                                                          • +6
                                                            А это не Битрикс? А то похоже.
                                                            • +1
                                                              Спасибо, здоровый смех с утра — что может быть лучше!
                                                              Сразу вспоминаются посты про NetCat, Bitrix и иже с ними.
                                                              • 0
                                                                Так вот он каков, суровый краматорский код!

                                                                Или, аки «поляк — это не национальность, поляк — это профессия» (из постперестроечных времен, если кто помнит, что творили поляки) — «индус — это не национальность...» :)
                                                                • 0
                                                                  Вспомнил, как я один раз вносил изменения в код, где почти весь функционал был запихан в один файл с гигантским switch на 1000 строк и не было ни одного отступа. А AJAX был реализован самодельной фигней на iframe.
                                                                  Рефакторить такое я не решился.
                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                    • 0
                                                                      AJAX — это не строго XmlHttpRequest. Это и iframe и динамические <script>
                                                                      • 0
                                                                        Я об этом знаю.
                                                                        Но зачем это писать самому, если есть куча готовых библиотек?
                                                                        • 0
                                                                          Это риторический вопрос для изобретателей велосипедов.
                                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                                            • +1
                                                                              COMET? У вас слишком богатая фантазия :)
                                                                              Там этот велосипед с iframe использовался, чтобы при выборе в форме пункта в выпадающем списке подгружать содержимое другого списка.
                                                                              • +1
                                                                                Скорее всего, это просто старый код. До AJAX так и делали.
                                                                      • 0
                                                                        1 000 строк, это просто благодать, видали мы проекты на 10 000 (давно правда)…
                                                                        • +2
                                                                          Хе, 10000 строк…
                                                                          2 недели назад меня угораздило взяться за приведение в божеский вид интернет магазина, разработанного довольно известной вэбстудией (ну, в нашем городе конечно ;).

                                                                          Монстр в 470000 строк кода. 1852 .php файла.
                                                                          В основе — лежит osCommerce.
                                                                          Горы спагетти-говнокода. Никакой документации. Минимум комментариев. Единого стиля — нет. В БД — 185 таблиц. Куча ненужных индексов и нет необходимых. Денормализация — ну мне не с чем даже сравнить.

                                                                          Главная весит 800Кб(включая картинки), генерится 4-10 секунд. Алфавитный каталог по любой букве — до 20 секунд.

                                                                          С какой ноги я встал когда согласился взяться за ЭТО — я не знаю, наверное по голове чем нибудь вдарили.
                                                                          • +1
                                                                            Ну вот, примерчик.
                                                                            Табличка с эээ… подвалами заказов.

                                                                            orders_total_id | orders_id | title | text | value | class | sort_order
                                                                            1 | 1 | Стоимость товара: | 0.00р. | 0.0000 | ot_subtotal | 1
                                                                            2 | 1 | Всего: | 0.00р. | 0.0000 | ot_total | 10

                                                                            На каждый заказ — две строчки.
                                                                            Суммы — везде = 0, пересчитываются при выводе, жабоскриптом.
                                                                            • +1
                                                                              Тэги съелись:

                                                                              orders_total_id | orders_id | title | text | value | class | sort_order
                                                                              1 | 1 | <span class=«text»>Стоимость товара:</span> | <span class=«text»>0.00р.</span> | 0.0000 | ot_subtotal | 1
                                                                              2 | 1 | <span class=«text»>Всего:</span> | <span class=«text»>0.00р.</span> | 0.0000 | ot_total | 10
                                                                            • 0
                                                                              Упреждая закономерные вопросы. «Приведение в божеский вид» — подразумевает под собой меры которые позволят более — менее дожить до нового, переписанного с нуля варианта.
                                                                              • 0
                                                                                Ничего более нет постоянней чем временное решение.
                                                                                • 0
                                                                                  Вполне реальный исход, т.к. владелец бизнеса в любой момент может передумать и нового варианта не будет.
                                                                              • 0
                                                                                > Горы спагетти-говнокода. Никакой документации. Минимум комментариев. Единого
                                                                                > стиля — нет. В БД — 185 таблиц. Куча ненужных индексов и нет необходимых.
                                                                                > Денормализация — ну мне не с чем даже сравнить.

                                                                                Я так понимаю, большая часть из перечисленного относится и к osCommerce?
                                                                                Интересен этот вопрос, потому что это вроде как один из самых популярных опенсорц-продуктов для интернет-магазинов.
                                                                                • 0
                                                                                  osCommerce, который лежит в основе — весьма творчески доработан. Да и версия использована аж 2003 года.
                                                                                  Свежий osCommerce я не анализировал, сказать ничего конкретного не могу.
                                                                                  • 0
                                                                                    Сам интернет-магазин был сделан в 2006. Несколько раз допиливался сначала собственно студией его породившей, потом штатным программером.
                                                                              • 0
                                                                                ну десять не десять но нам дали на поддержку код на 5-6к строк, причем 4,5к — один метод
                                                                                тока маленькое но! это к тому же был asp.net / c# =))
                                                                              • 0
                                                                                Я тоже как-то видел switch на 1000 строк.
                                                                                Правда, это был эмулятор процессора и на си =)
                                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                                • 0
                                                                                  Перед заменой проверял — полей вида "^[0-9]+" в БД нет, и в запросах тоже не используются цифры как алиасы…
                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                                • +6
                                                                                  Если всё настолько печально, то почему не отказаться от заказа?

                                                                                  Анализ актуальный, но тон статьи неприятный.
                                                                                  • 0
                                                                                    Меркантильный вопрос, он такой меркантильный…

                                                                                    За тон уж извините, но действительно это была истерика в течении первых двух недель, и вот осадочек остался…
                                                                                    • 0
                                                                                      Скажите, а вы не повышаете цены на такие заказы? Если я вижу что в исходном — говнокод, то цена раза в полтора должна быть выше за нервы, или вам пофигу или даже в кайф?)
                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                    • –2
                                                                                      Тоже считаю, что свичи с кейзами очень даже не плохи. Это не тысяча ифов, а вполне понятный код.
                                                                                      Я конечно не стал бы такой роутер городить, привык в базе хранить такие вещи.
                                                                                      • +2
                                                                                        поздравляю вы говнокодер, пораждающий унылые много страничные сфитчи вместо трех строк код, которые к тому же нельзя генерить из внешнего источника данных.
                                                                                        • +3
                                                                                          Дело не в switch, а в том, что id страниц сделаны хардкодом.
                                                                                          Такие вещи надо хранить в базе с правильными связями и возможностью менять в админке.
                                                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                                                            • +2
                                                                                              доо) на сайт из 5-10 страниц обязательно базу, и в ней табличку )))
                                                                                              • +1
                                                                                                хардкод — наше все? :)
                                                                                                • –1
                                                                                                  Для сайтов-визиток где разделы меняются раз в год в лучшем случае? Да )
                                                                                                  • 0
                                                                                                    И для изменения разделов нужен программист? Часто с этим секретари справляются, если есть нормальная админка ;)
                                                                                                    • –1
                                                                                                      Давайте так. Там, где нужно менять контент чаще чем никогда, я лично сделаю интеграцию с MS Word через Metaweblog, а не вынесу в админку редактор — это чушь требовать от секретаря знания HTML, тот HTML который они родят в WYSIWYG редакторе, лучше убивать до рождения.
                                                                                                      Но есть огромное количество компаний, которым не нужны регулярные, и даже в обозримом будущем, изменения на сайте.
                                                                                                      Например производитель кабеля. Он 10 лет назад производил кабель, одних и тех же марок, сейчас производит тот же кабель, и еще 10 лет будет его производить. Все что ему надо — один раз написать какой это кабель, и загружать по фтп новый прайс-лист
                                                                                                      • 0
                                                                                                        Возможно и есть такие заказчики, кому в обозримом будущем изменения на сайте не нужны. Мне не встречались
                                                                                                    • 0
                                                                                                      Понимаете, хардкод — это дурная привычка. Сегодня захардкодишь 2 значения и подумаешь «А что в этом такого?!», завтра — 3 и подумаешь «Ну вот вчера захардкодил 2 и ниче страшного». А через месяц это будет везде. Я сам тех лид и на код ревью регулярно встречаюсь с таким и пресекаю.
                                                                                                      • 0
                                                                                                        Может подскажете, в какую сторону копать, чтобы «засофткодить» на PHP реакцию на изменение поля типа «статус_ид» для записи в БД, когда список статусов зафиксирован (простая таблица ид+имя, в которой пользователям делать нечего) и на каждый статус нужна своя реакция (например счета и их статусы — черновик, выставлен, оплачен, отгружен)? Каждый раз когда пишу подобный код приходится хардкодить скрипя зубами, а красивой «софтовой» реализации никак в голову не приходит
                                                                                                        • 0
                                                                                                          Битрикс хранит в базе названия функций-обработчиков для каждого статуса, втч могут быть нестандартные
                                                                                                          • 0
                                                                                                            Пока коммент предыдущий писал тоже такая идея возникла :) Хорошо это или плохо, что я думаю как в Битриксе :-/
                                                                                                            • 0
                                                                                                              классическая формула для бизнеса: функциональность >> производительности
                                                                                                              )
                                                                                                              зависит от задачи )
                                                                                                              Битрикс — ну очень тяжелая система, но и очень гибкая и функциональная )
                                                                                                          • 0
                                                                                                            коль таков вопрос, то хотя бы от magic numbers надо избавиться, но пример в статье уж точно требует другой реализации (было добавлено поле slug по которому и вытаскиваются статьи)
                                                                                              • 0
                                                                                                Дальше был анализ сего творения фирмы «Q» (кто следит за мной, знает о какой украинской фирме речь)


                                                                                                Ладно, если бы это был какой-нибудь студентик-пацанчик-горе-пхп-фриласнер. Но нет! Тут целая фирма!

                                                                                                Такую клевую штуку рисует Webgrind, удобно и наглядно


                                                                                                Спасибо, интересный инструмент. Не знал о нём.
                                                                                                • +1
                                                                                                  А что мешает объединиться студентикам-пацанчикам-горе-пхп-фрилансерам под одной крышей? :)
                                                                                                  • 0
                                                                                                    Ну, как мне кажется, человек, который их объединяет не должен допускать такого.
                                                                                                    • 0
                                                                                                      Я думаю в городе с населением в 170 тыс человек, где еще молодых не очень-то много (все стараются остаться в крупном городе после ВУЗов) выбор кадров невелик.
                                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                  • 0
                                                                                                    Интересно было читать! Сам хотел бы попробовать рефакторинг какого-нибудь проекта, но пока не было такой задачи. И еще попробую попользоваться Webgrind — стало интересно, что это =)
                                                                                                    • +4
                                                                                                      Да любую ЦМСку возьмите, которая писалась лет 5 и отрефакторите =) Опыту наберётесь мама не горюй)
                                                                                                      Рефакторить можно всё что угодно до безумия. Сам этим грешу, но нашёл способ останавливаться во время.

                                                                                                      Если вижу не понятный мне код, но знаю как он должен работать. Переписываю (не тратя много драгоценного времени) и прошу другого программиста рассказать, что мой код делает. Не смог — значит я плохо написал и забиваю с этой идеей.
                                                                                                      • 0
                                                                                                        Да, надо бы заняться этим — интерес есть, только руки как-то не доходили =)
                                                                                                        • 0
                                                                                                          Главное, чтобы тот, кто рефакторит не оказался таким же быдлокодером :)
                                                                                                          • 0
                                                                                                            Тогда это и будет называться реFUCKторинг.
                                                                                                    • –1
                                                                                                      Понравилось про медленный переезд на ZF.
                                                                                                      Остальное, что описано в статье ужасная работа, с таким кодом работать не хочется совсем.
                                                                                                      • +1
                                                                                                        Узнал про фронтенд для xdebug, спасибо
                                                                                                        • +2
                                                                                                          Как по мне и ~0.3c многовато… Надо стремиться к 0.1, а для статических страниц вообще 0.01 должно быть.

                                                                                                          P.S. сколько времени уходит на все инклуды сейчас?
                                                                                                          P.P.S. APC пробовали?
                                                                                                          • –1
                                                                                                            Данный замеры без кеширования, и без акселераторов, до финишной прямой нам еще бежать и бежать…
                                                                                                        • +3
                                                                                                          Какое-то странно ощущение вызывается эта статья. Вроде автор не глупый. Но у меня сложилось впечатления, взяли древнию технологию( Fast Templates использовались на заре моей карьеры, и то я их так и не успел выучить только — появлось Smarty и заняло всю нишу).
                                                                                                          И показали как её можно допилить использую новые тхнологии. При этом показав, какой я герой — я почистил авгиевы конюшни. А тех кто это писла гавнюки полные.

                                                                                                          Вот интересно как бы автор реализовал это всё в году так 2003-2004.
                                                                                                          • 0
                                                                                                            Оптимизация Fast Template — это лишь временное решение (кстати в проекте нашлось 3 шаблонизатора — FastTemplate, XTemplate и свой велосипед выдранный из обоих шаблонов), проект медленно мигрирует на ZF, но старый код надо хоть как то поддерживать на плаву…

                                                                                                            В 2003-2004 я не занимался профессиональной разработкой, а начинал в 2005 уже со Smarty (от которого отказались уже давно в пользу нативного Zend_View)…

                                                                                                            P.S. Статью воспринимайте как вредные советы, хотя искорки идей присутствуют (webgrind, к примеру)…
                                                                                                            • +2
                                                                                                              Мне очень не понравился тон статьи.
                                                                                                              Вот гавнокод — а вот мы умнички. Умеем этим и этим пользоваться.
                                                                                                              Только никто не сделал взгялд назад и не посмотрел, что проект-то годов так 2003-2005. Когда магазин стартанул?
                                                                                                              • 0
                                                                                                                Вот тут-то собака и зарыта — старт проекта 2007 год…
                                                                                                        • +3
                                                                                                          Зачем ставить mod_expires для статики если потом все это перекрывать nginx'ом?
                                                                                                          • –2
                                                                                                            Одного меня не радуют картинки 100летней давности на главной? М?http://www.tineye.com/search/e6ebea1b733b347dc44d7114952541bac2befd9d/
                                                                                                            • +14
                                                                                                              Антон, вы такой умный, аж страшно…
                                                                                                              • 0
                                                                                                                У нас еще удаленные программисты использую переменные и имена файлов вида glange.php и прочую ерунду с упячки. А процесс отладки cron скриптов на php вообще был восхитителен, оказалось что ни memcached, ни mysql, ни прав доступа на запись нет, а скрипт продолжал выводить что все хорошо.
                                                                                                                • +1
                                                                                                                  налепили поверх более новых заплаток )))
                                                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                      • +1
                                                                                                                        Есть такая штука типа «они козлы, мы лучше»

                                                                                                                        Интересно, что ваши программеры испытают, заглянув в свой код 2004 года :)
                                                                                                                        Меня воротит, хотя таких штук там нет… Но епрш… mysql_fetch_array… Закат солнца вручную.
                                                                                                                        • 0
                                                                                                                          Никто не говорит про 2004-ый год, тут как бы проект стартовал в 2007-м, к тому моменту все велосипеды были уже написаны…
                                                                                                                          • –1
                                                                                                                            Сколько стоит час вашей работы?
                                                                                                                            • –1
                                                                                                                              Когда балуюсь фрилансем — $15
                                                                                                                              • –1
                                                                                                                                И сколько часов ушло на вашу оптимизацию описанного проекта?
                                                                                                                                • 0
                                                                                                                                  Это не в рамках проект-то, если интересны расценки компании, то милости прошу по официальным каналам sales@nixsolutions.com…
                                                                                                                                  • –1
                                                                                                                                    «на уменьшение кол-во notices от 9 000 к 1 000 ушел день»

                                                                                                                                    получается что клиент заплатил за эту работу $120 (8часов х $15)
                                                                                                                                    можно предположить, что на всю «оптимизацию» ушло недели 2 вашей работы… получается сумма $1200
                                                                                                                                    за такую сумму, можно написать магазин с нуля хоть на ZF, хоть на чем угодно и портировать данные со старого проекта (даже сохранив URL страниц)
                                                                                                                                    причем исполнителей, который выполнят такую работу, огромное количество… та же «фирма Q» без проблем выполнила бы такую работу
                                                                                                                                    • 0
                                                                                                                                      Автор написал же, что это был проект в рамках компании, не фриланс
                                                                                                                        • –1
                                                                                                                          Зашел на их сайт, видать себе тоже гавнокодили. Даже не утрудились логотип ссылкой сделать :)
                                                                                                                          • 0
                                                                                                                            Кю… © «Кин-дза-дза»
                                                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                              • 0
                                                                                                                                На dailywtf.com, однозначно…
                                                                                                                                • +2
                                                                                                                                  Да ладно, в интернете много подобно написанных сайтов. Я работаю фрилансером и у многих проектов видел код. Есть и более худшие варианты. И ничего, многие работают и денег приносят. Хотя дорабатывать их, конечно, практически нереально. Только поправить мелкие косяки. Нормальный вывод ошибок и включать порой не хочется.
                                                                                                                                  • +1
                                                                                                                                    И опять речь о том как не делать, когда же уже кто нибудь напишет о том как надо?
                                                                                                                                    • 0
                                                                                                                                      А как вы себе это представляете?
                                                                                                                                      • 0
                                                                                                                                        Если бы знал как, написал бы сам =)
                                                                                                                                        • 0
                                                                                                                                          Я к тому, что нет универсального алгоритма, что для одной задачи будет решением близким к идеальному, для другой будет смотреться смешно
                                                                                                                                          • 0
                                                                                                                                            Но приятнее всё-же читать статьи про то как «я в таком-то конкретном случае сделал так» и коментарии типа «да согласен хорошо» или «мне не нравится, а я бы сделал эдак» (причём с подробностями и объяснениями, почему так а не иначе)

                                                                                                                                            А статьи типа «посмотрите какой быдлокод» может написать даже новичок.
                                                                                                                                            • –1
                                                                                                                                              Возьмите любую задачу, решите её и напишите пост о решение (причём с подробностями и объяснениями, почему так а не иначе) — получите море комментов ;)
                                                                                                                                              • –1
                                                                                                                                                ага. о том, какой автор быдло-говно-кодер. Т.к. одно дело решать задачу, другое дело попивая пивко говорить, что код пахнет. Он всегда пахнет на реальных проектах. В ядре можно все чистенько сделать, а на той части, что все время подпиливается под заказчика будет грязненько.

                                                                                                                                                Грязненький устоявшийся код можно потом и подчистить, но появится новый грязненький кусок.
                                                                                                                                    • 0
                                                                                                                                      Между прочим, термином refucktoring обозначают постепенный «рефакторинг» особо увлеченными сотрудниками, в ходе которого чистый гладкий код превращается в неузнаваемое квазимодо. Так что к вашему случаю это вряд ли применимо.
                                                                                                                                      • +1
                                                                                                                                        refucktoring
                                                                                                                                        :)
                                                                                                                                        • 0
                                                                                                                                          Ну да, так и написал.

                                                                                                                                          На самом деле моё определение, конечно, одно из возможных, ибо этот сленг ещё не устоялся. Взял его из www.globalnerdy.com/2010/05/09/new-programming-jargon/ (клевая статья).

                                                                                                                                          Ещё, пока искал, нашел русское переложение термина: «ретрахинг» :)
                                                                                                                                          • –1
                                                                                                                                            Заголовок статьи как бы намекает на аналогичную шутливую надпись «sick my duck»
                                                                                                                                      • –1
                                                                                                                                        Нда…
                                                                                                                                        «просто гениальное решение, тайный смысл» которого автор не осилил означает, по всей видимости выполнение ряда SQL запросов. А если будет несовместимая с жизнью ошибка (когда массив окажется не массивом или один из перечисленных элементов массива исчезнет во время выполнения сего действа...) — результат будет равен 0, что скорее всего где-то там далее вызовет на экране ошибку, что-то типа BSOD, только менее понятного.
                                                                                                                                        • 0
                                                                                                                                          приведеный пример AS IS — и никаках предыдущих присвоений $sqls нету (даже нету объявления)
                                                                                                                                          • 0
                                                                                                                                            что же вы об этом сразу не написали… тогда, конечно, соглашусь с вашим выводом.
                                                                                                                                        • +1
                                                                                                                                          шаблоны надо было лечить не preg_replace_callback, а компиляцией. открыл шаблон, заменил @var@ на ну и соответственно инклудишь его внутри класса, а-ля Zend_View. делал уже такое. последнее время обожаю рефакторить такой код, хорошая разминка для мозгов, после унылой разработки на фреймворке.

                                                                                                                                          p.s. А статья очень полезная и нужная, ведь большинство кода пишется вот такими «мастерами», которые даже не подозревают о наличии «светлой» стороны.

                                                                                                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.