Антон Шевчук // Web-разработчик

Рефакторинг который мы не делаем // PHP

Не так давно я описывал процесс рефакторинга одного проекта зашедшего в отдел, мы вместе посмеялись да поплакали, но ведать мораль оттуда не вынесли. И в этой истории мы не «белые и пушистые»…

История начиналась банально — проект загибается, заказчик ищет новую команду разработки и находит нас. Мы такие все из себя, на белом коне въезжаем в проект, а там ничего страшного, просто функциональный plain PHP код, т.е. классов нет, функций практически тоже (один файл functions.php, а в нем dbconnect(), userlogin() да функция-шаблонизатор, и что-то еще по мелочи). Смотрим — а проблема то в нагрузке — до 10 000 онлайн пользователей и в это время на сайт и зайти нельзя. Хорошо, задача ясна, садим в проект разработчика, который знаком с оптимизацией, ну и он начал работать. И да, после двух недель работы (а может и больше, уже не помню) сайт ожил, чуть-чуть индексов, чуть-чуть кеширования, еще немного оптимизации SQL запросов и нагрузка на сервера спала.

Заказчик доволен, и уже у него появляются «хотелки» на новый фичи, да немного еще старых багов подкидывает на фикс. В этот момент эффективность нашего разработчика сильно падает — он то любит заниматься оптимизацией, а вот эти CSS да JavaScript ну ой как туго идут…

Спустя некоторое время, мы заменяем разработчика в проекте, новому человеку больше по душе приходятся фичи и ченжи заказчика, и наша эффективность опять идет вверх, заказчик удовлетворен, мы считаем деньги. Все хорошо и ничто не предвещало случившегося.

В проекте всё меньше и меньше работы, задачи скатываются до уровня trivial, и мы принимаем решение посадить в него «зелёного» бойца, дабы опробовать его, да и заказчик дал на это добро. Старт был гладким, а потом начались проблемы, то вылезли за сроки, которые сами и оговорили, то на сервер залили не совсем рабочий код. И как итог — «Спасибо, что помогли, вы меня действительно выручили, но дальше я обойдусь без вас»

Начинаем разбор полётов, решаем, что новенького мы зря посадили в проект, но я к тому моменту залез в изучение кода по уши, и поэтому сейчас опишу то, чего я там не увидел.

Шаблонизатор

В системе был создан элементарный шаблонизатор с нативным синтаксисом (что скорее плюс), но в шаблонах постоянно встречались обращения к БД, и при изменении структуры приходилось перелапачивать не только код страниц, но и все шаблоны. Таким образом необходимо было разделить логику от представления раз и навсегда.

Если говорить о функции-шаблонизаторе, то вот элементарный пример:

/**
 * @param string
 * @param array
 */ 
function template($path, $vars = array()) {
    extract($vars);
    include $path;
}

template("templates/index.phtml", array(
    "foo" => "bar",
    "user" => $user
));

Остальное остается на совести разработчика, собственно даже в тот же Smarty можно впихнуть логику при должном желании.

Сущности

Процесс разработки так же затруднялся тем, что очень много копипаста было в проекте, и вносить изменения сразу и везде было проблематично (поиск и замена по папке это не тру). А необходимо было выделить сущности, и методы для работы с ними свести в один класс (или хотя бы файл). Таким образом мы бы смогли уменьшить повторение кода (и повторения ошибок).

Контроллеры

Тут просто напрашивался этот пункт, поэтому я его добавил, и хотел сказать следующее — если у вас в корне проекта лежит пару десятков файлов, то не стоит заморачиваться, и переписывать их все, чтобы у вас получилась папочка controllers и единая точка входа, ведь эти файлы с поставленной задачей вполне справляются. Как вывод — не стоит гнаться за идеальным кодом, такие вложения труда могут не окупиться.

Работа с БД

Как я описывал выше, SQL запросы встречались в проекте везде и всюду, и даже процесс экранирования входных данных в них был разный. Привести к единому стилю, создать нормальный врапер для БД, или хотя бы заменить использование расширения mysql на что-либо более современное.

Можно было бы написать простой врапер для врапера PDO за 20 минут, конечно он не будет универсален, но облегчит труд рефакторинга:

  • легко логировать используя одну точку входа
  • можно быстро добавить кеширование для всех запросов

Кеширование

Тут стоит упомянуть, кеширование прикрутили, НО лишь там где указал заказчик, а хотелось бы, чтобы был кеш везде где это имеет смысл, а не исходя из заключения «вроде тут», т.е. надо было в каждый файл заглянуть, логи проанализировать, да и время кеширования можно было потюнить в рейлтайме, но сдвиг часового пояса нам наверное сильно помешал, и никто не захотел ради этого из дома мониторить сервер, или хотя бы попросить об этом наших же админов (а мы такие услуги предоставляем ;).

Работа над ошибками

Тут все легко, если вы открываете PHP файл, а вам IDE подсказывает кричит о ошибках в коде, то уделите пять минут времени и исправьте их:

И еще — в обязательном порядке включите отображение ошибок, и запомните — «подавленный» Notice крадет время:

error_reporting(E_ALL);
ini_set('display_errors', '1');

Тестирование

— Unit тестирование? О чем речь, у нас тут запара, надо выкатывать на лив!
Ну-ну…

Клиентская оптимизация

Этого пункта не коснулся ни один из разработчиков, участвовавших в проекте, и это действительно огорчает. Конечно, главная страничка проекта не слишком и тяжела — всего 300кб, но на них приходится 15 JS файлов, 18 картинок в CSS (спрайты спасут сервер), так же стоило потереть старые хуки для браузеров (IE5.5 и IE6), облегчить верстку, ведь 8,7kb это не так уж и мало (слишком много таблиц).

Собственно, сайт по оценке YSlow получает оценку C (70), что я считаю недопустимым, для сравнения мой блог с кучей картинок — A (90). Как улучшить эти показания очень хорошо рассказывает сайт webo.in, и я думаю ему стоит уделить место в закладках.

«Не наш» проект

Еще я бы хотел рассказать о том, что очень часто программисты не переживают и не живут проектом, а это очень негативно сказывается на взаимоотношения с заказчиком и на развитие проекта. Проект должен стать чем-то неотъемлемым от вас, если сайт загибается под наплывом пользователей — вам тоже должно быть не по себе, ведь это ваше творение страдает, и ему нужна ваша помощь. Вы как специалист должны советовать заказчику, как развивать проект, ведь именно вы знаете о всех ноу-хау в web-разработке, и не стоит ждать, что с предложением о улучшении выступит он, сделать первый шаг должны именно вы и именно сейчас. Не стоит в проекте жить одним днем, надо смотреть вперед и возможно рефакторинг проекта стоило начать еще вчера.

P.S

Если в вашем проект все идет гладко, то присмотритесь, возможно под столь сладким обликом притаился рак вашего безразличия к жизни проекта.

P.P.S

Если вы уже загорелись начать рефакторинг, то я вас еще чуть-чуть еще отвлеку — стоит рефакторинг правильно «продать» заказчику, который любит и умеет считать деньги, с ним стоит разговаривать именно в этом ключе. Удачи вам.

© Антон Шевчук 2007-2016