Приёмка чужого проекта - инвентарь, правки ядра, карта рисков
Принимаем проект, который писали до нас: стенд, инвентарь, правки ядра, обработчики и карта рисков вместо приговора.
Механика
Приёмку делают на копии, а не на боевом сайте. Первое действие - поднять стенд, второе - собрать инвентарь, и только третье - что-то менять; порядок здесь важнее скорости, потому что чужой проект всегда сложнее, чем выглядит.
Свой код проекта живёт в четырёх местах сразу. Каталог для своего кода, старая папка обработчиков ядра, шаблоны и компоненты - причём и в правильном каталоге, и в каталоге платформы, куда их клали раньше.
Правки ядра - главный риск любого чужого проекта. Обновление затирает их молча, и сайт ломается ровно в тот момент, когда его нельзя ломать: обычно на обновлении ради безопасности или новой версии языка.
Вмешательства в поведение платформы видны списками, а не чтением кода. Обработчики событий и задания по расписанию перечисляются запросами, и это быстрее, чем читать чужой код в поисках подписок.
Прямые запросы к таблицам и логика в шаблонах - не преступление сами по себе. Это места, которые ломаются при обновлении структуры и при переносе, поэтому их выписывают, а не переписывают сразу.
Итог приёмки - не приговор «плохой код», а карта рисков с ценой. Что чинить до первого обновления, что переписать при следующей задаче в этой области и чего не трогать вовсе, пока оно работает.
Отдельная часть приёмки - доступы и внешние связи. Cron, почта, обмен с учётной системой, платёжные системы и внешние ключи живут вне репозитория, и без них картина проекта неполная.
Шаги
- Поднять стенд из копии и отрезать на нём боевые интеграции и почту.
- Снять инвентарь: редакция, версии модулей, сторонние решения, версия языка.
- Найти правки ядра сравнением с эталоном той же версии и записать их списком.
- Выписать обработчики событий и задания по расписанию вместе с источниками.
- Найти прямые запросы к базе, записи из шаблонов и код вне своего каталога.
- Собрать карту рисков и согласовать с заказчиком очередь работ по ней.
Код
Снимаем инвентарь модулей:
use Bitrix\Main\ModuleManager;
foreach (ModuleManager::getInstalledModules() as $module) { printf("%-28s %s\n", $module['ID'], ModuleManager::getVersion($module['ID']));}// сторонние решения видно по точке в имени: vendor.solution// версия модуля ядра показывает, насколько давно проект обновлялиИнвентарь отвечает на первый вопрос заказчика: можно ли обновляться. Разброс версий модулей и старое ядро означают, что обновление станет отдельным проектом, а не задачей на полчаса.
Ищем правки ядра:
# эталон той же версии: распаковать чистый дистрибутив рядом и сравнитьdiff -rq /tmp/bitrix-clean/bitrix/modules/main bitrix/modules/main | head -20# ту же задачу решает контроль целостности файлов в проактивной защитеПравленое ядро находят до первого обновления, а не после. Список таких файлов - самая ценная часть приёмки: каждый из них однажды исчезнет вместе с логикой, которую в него добавили.
Выписываем обработчики событий:
$manager = \Bitrix\Main\EventManager::getInstance();foreach (['OnBeforeProlog', 'OnPageStart', 'OnEndBufferContent'] as $event) { foreach ($manager->findEventHandlers('main', $event) as $handler) { printf("%-18s %s\n", $event, $handler['TO_NAME'] ?? $handler['TO_MODULE_ID']); }}// то же самое смотрят по событиям инфоблоков, заказов и пользователейОбработчик на событии, случающемся на каждой странице, объясняет половину странностей проекта. Он же чаще всего оказывается причиной медленной работы, о которой заказчик рассказывает как о свойстве платформы.
Смотрим задания по расписанию:
$rs = CAgent::GetList(['NEXT_EXEC' => 'ASC'], ['ACTIVE' => 'Y']);while ($agent = $rs->Fetch()) { printf("%-12s %-52s %s\n", $agent['MODULE_ID'], $agent['NAME'], $agent['NEXT_EXEC']);}// агент, падающий каждую минуту, - обычная находка приёмкиИщем код вне своего каталога:
ls bitrix/php_interface/ 2>/dev/null # старое место обработчиков проектаls bitrix/templates/ | grep -v '^\.' # шаблоны сайта в каталоге платформыls bitrix/components/ | grep -v bitrix # свои компоненты рядом с чужими# всё, что лежит здесь, обновление затирает без предупрежденияКаталог для своего кода появился не сразу, и на старых проектах его нет вовсе. Перенос туда - отдельная задача с проверкой каждого пути, а не операция копирования, поэтому её планируют, а не делают в первый день.
Находим прямые запросы и записи из шаблонов:
grep -rn '\$DB->Query\|mysqli_query' local/ bitrix/templates/ | wc -lgrep -rln 'CIBlockElement::Add\|->save()' bitrix/templates/ local/templates/ | head# запись данных прямо из шаблона переносят в свой код при первой же правкеЧитаем журнал ошибок до того, как читать код:
tail -50 bitrix/modules/error.log # журнал платформы, если он включёнgrep -c "" bitrix/modules/error.log # объём: тысячи строк говорят сами за себяЖурнал показывает живые проблемы, а не потенциальные. Проект, который сыплет ошибками каждую минуту, лечат до любых улучшений: пока журнал шумит, новые ошибки в нём не видны.
Собираем карту рисков:
| Находка | Риск | Когда чинить ||---|---|---|| Правки в модуле инфоблоков | обновление затрёт логику | до первого обновления || Записи из шаблона каталога | ломается при переносе | при следующей правке витрины || Агент решения падает | забивает журнал | на этой неделе |Карта рисков - это разговор с заказчиком на его языке. Она отвечает не на вопрос «хорош ли код», а на вопрос «что случится и когда», и именно поэтому по ней принимают решения о деньгах и сроках.
Ограничения
Приёмка даёт карту, но не диагноз по каждой задаче. Она показывает, где проект рискует сломаться, а разбираться в конкретной логике всё равно придётся при первой же задаче в этой области.
Сравнение с эталонным дистрибутивом даёт ложные срабатывания на файлах кэша и на загрузках. Часть отличий - следы штатных обновлений и кэш, поэтому сравнивают каталоги модулей, а не весь проект, и проверяют находки глазами.
Тяжёлые проверки целостности не запускают на боевом сайте в рабочее время. Контроль целостности файлов и монитор качества нагружают сервер заметно, и на живом магазине их включают в спокойное время или не включают вовсе.
Часть сторонних решений держится на активной подписке и без неё не обновляется. Истёкшая лицензия решения означает отсутствие обновлений и поддержки, и это отдельная строка в карте рисков, а не техническая мелочь.
Без доступа к боевому серверу картина проекта останется заведомо неполной и приблизительной. Задания по расписанию, настройки почты, конфигурация веб-сервера и внешние ключи живут вне репозитория, и их приходится запрашивать отдельно.
Переписывать весь чужой проект сразу нельзя практически ни при каких обстоятельствах и сроках. Проект приносит деньги в текущем виде, поэтому работы ставят в очередь по риску и по стоимости, а не по личному отношению к чужому коду.
Типичные проблемы
После обновления платформы пропала часть логики.
Логика была дописана прямо в файлы ядра, и обновление их перезаписало. Правки ядра выписывают при приёмке и переносят в свой код.
Правки в шаблонах исчезают после обновления.
Шаблоны и компоненты лежат в каталоге платформы, а не в каталоге проекта. Их переносят с проверкой путей, а не копированием.
Сайт медленный без видимой причины.
На событии, случающемся на каждой странице, висит тяжёлый обработчик чужого решения. Списки обработчиков событий смотрят раньше, чем берутся за профилирование страниц и запросов.
Журнал ошибок растёт на мегабайты в сутки.
Задание по расписанию падает при каждом запуске и пишет ошибку в журнал. Его находят в списке заданий по времени следующего запуска.
После обновления структуры перестали работать отчёты.
Отчёты собраны прямыми запросами к таблицам платформы, в обход её штатных интерфейсов и правил. Такие места выписывают при приёмке и переводят на API постепенно.
Часть сайта не находится поиском и не видна в меню.
Страницы лежат статическими файлами вне структуры разделов, вне меню и вне поиска сайта. Их либо заводят в структуру, либо переносят в инфоблок.
Частые вопросы
С чего начать приёмку чужого проекта?
С копии на стенде и инвентаря: редакция, версии модулей, сторонние решения, версия языка. Правки начинают только после того, как картина собрана, иначе первая же правка ломает то, о чём никто не знал.
Как найти изменённые файлы ядра?
Сравнить каталог модулей с чистым дистрибутивом той же версии либо запустить контроль целостности файлов в проактивной защите. Ложные срабатывания на кэше и загрузках проверяют глазами.
Что делать, если папки для своего кода в проекте нет?
Планировать перенос отдельной задачей с проверкой каждого пути, а не копировать каталоги в первый день. До переноса любое обновление платформы способно затереть чужие правки.
Стоит ли переписывать проект целиком?
Почти никогда: проект приносит деньги в текущем виде, а переписывание останавливает развитие на месяцы. Работы ставят в очередь по риску, начиная с того, что сломается при ближайшем обновлении.
Что показать заказчику по итогам приёмки?
Карту рисков: находка, что случится, когда чинить и сколько это стоит. Список замечаний к качеству кода без последствий и сроков заказчику ни о чём не говорит.
Смежное
- Стенд разработчика - оглавление подтемы
- Легаси-код в проекте: как читать, править и переводить на D7 - что делать с найденным старым кодом
- Стенд из копии боевого: подъём, обезличивание, отрезанные связи - с чего начинается приёмка
- Копия сайта не открывается на стенде: разбор причин - разбор мёртвой копии чужого сайта
- Готовое решение в проекте: установка, вмешательство, удаление - что делать с найденными решениями
- Обновление продукта: подготовка, порядок, откат - первое, что упрётся в правки ядра
- Обновления не устанавливаются: ключ, срок, доступ, права - если обновление не запускается вовсе
- Миграции структуры: перенос инфоблоков и настроек между стендами - как перестать править структуру руками
- Стандарты кода - к чему приводить найденный чужой код
- Архитектура проекта - что где лежит в проекте на платформе