7. Почему не проще?
• Код, в принципе, решает свои задачи
• На него потрачено немало человеко-часов
• Ресурсы ограничены и много текущих задач
• Есть другой подход - evolution
8. Как будем улучшать?
• Будем использовать composer
• Придерживаться стандартов PSR
• Поэтапно рефакторить
• Отлаживать только с Xdebug
• Профилировать код (в том числе и в бою)
9. Наследство
• проект живет с 17 июля 2011
• построен на Zend 1 (Zend 2 уже больше двух лет*)
• My_Super_Awesome_Class (пространству имен уже два года*)
• отсутствие единого стандарта (до PSR еще долгих два года*)
• отсутствие цельной архитектуры (толстые контроллеры; мешанина
из php и sql; массивы адской структуры)
• сторонние библиотеки в library (composer только на подходе*)
• код опирается на PHP 5.2 (PHP 5.3 уже два года*)
* на момент старта разработки
11. • Проще управлять зависимостями
• Проще обновлять сторонние библиотеки
• Очень гибкий инструмент:
• version: ~x.y, > x.z; x.y.z; x.*
• private: Satis или Toran Proxy
• non-composer: директива repositories
• Автозагрузка PSR-0, PSR-4 и не только
• Разработчики не лезут в исходный код сторонних библиотек!
Какие преимущества?
13. Составьте roadmap по
рефакторингу
• Придерживайтесь стандарту PSR-4 для улучшения
структуры проекта
• Пишите unit-тесты
• Покрывайте критичный функционал приемочными
тестами
• Придерживайтесь принципов SOLID, DRY, KISS и YAGNI
• Анализируйте логи
14. Анализ логов для
рефакторинга
• Настроили rsyslog и logrotate для сбора логов со
всех боевых машин
• cat %project%-pool-ro.log | grep -Eo "PHP.*[0-9]" | sort
| uniq -c
• Количество вхождений - вес; в каждый следующий
релиз обязательно включаем парочку ошибок с
наибольшим весом
15. 52 PHP Fatal error: Call to a member function getId() on a non-object in %file% on line 1233
1871 PHP Fatal error: Call to a member function setPrice() on a non-object in %file% on line 125
217392 PHP Warning: array_key_exists() expects parameter 2 to be array, null given in %file% on line 826
29676 PHP Strict Standards: Only variables should be passed by reference in %file% on line 1269
217392 PHP Warning: array_key_exists() expects parameter 2 to be array, null given in %file% on line 826
147344 PHP Warning: Invalid argument supplied for foreach() in %file% on line 2522
и еще сотни строк
* количество записей в день
Что получили в начале
16. 7 PHP Warning: array_key_exists() expects parameter 2 to be array, null given in %file% on line 333
75 PHP Warning: array_key_exists() expects parameter 2 to be array, null given in %file% on line 336
60 PHP Warning: Creating default object from empty value in %file% on line 60
1 PHP Warning: Invalid argument supplied for foreach() in %file% on line 215
86 PHP Warning: Invalid argument supplied for foreach() in %file% on line 2198
64 PHP Warning: Invalid argument supplied for foreach() in %file% on line 407
75 PHP Warning: Invalid argument supplied for foreach() in %file% on line 55
Что имеем сейчас
17. Что дальше
Собираем slowlog с помощью fabric
@task(default=True)
def alalyze_slow_logs():
execute(get_slow_log_ro)
execute(agregate_slow_log_ro)
execute(alalyze_slow_log_ro)
@task
@parallel
@roles('dbro')
def get_slow_log_ro():
get(
env.log_remote_path + 'slow.log',
env.log_local_path + 'slow_ro.%s.log' % (env.host)
)
@task
def agregate_slow_log_ro():
local('cat %s/slow_ro.*.log > %s/slow_ro.log' % (
env.log_local_path,
env.log_local_path
))
@task
def alalyze_slow_log_ro():
local('mysqldumpslow %s/slow_ro.log > %s/total_slow_ro.log' % (
env.log_local_path,
env.log_local_path
))
- просто `$ fab` для старта
- параллельно собираем slow.log со всех тачек
- собираем в один файл для обработки
- прогоняем его через mysqldumpslow
21. Почему сразу не использовать
Xdebug?!
• Сложно настроить удаленную отладку
• ssh -R 9191:127.0.0.1:9000 sandbox
• Сложно настроить отладку через шлюз
• ProxyCommand или ssh -L 9191:sandbox:9191 -R
9191:127.0.0.1:9000 gateway
• var_dump(…); die(); быстрее
• на самом деле это наиболее затратный по времени способ
отладки
23. Пользуйтесь профилировщиком
для поиска узких мест
• В качестве профилировщика взяли Pinba
• В качестве «клиента» взяли Intaro Pinboard
• Для включения профилировщика используем
подход Progressive Enhancement (состояние
окружения)
28. Спасибо за внимание!
Есть вопросы?
Камиль Самигуллин
какой-то разработчик
kamil@samigullin.info
@ikamilsk
github.com/kamilsk
linkedin.com/in/kamilsk