PHPCleanArchitecture — Что нового?
Этот пост является дополнением предыдущего. В нём я расскажу о новых возможностях инструмента (с блэкджеком и шлюпками с примерами и картинками).
Предисловие
Привет! Рад что ты читаешь это, а еще больше я буду рад, если этот пост окажется для тебя интересным и полезным.
В своём предыдущем посте я представил сообществу инструмент для визуализации и анализа архитектуры php-приложений и автоматизации процесса контроля её качества.
С тех пор прошло не мало времени и мне есть чем поделиться.
Сегодня поговорим о новых возможностях, без которых использование php-clean-architecture в реальных проектах было сильно затруднено (или вообще невозможно).
Содержание
Если бы мне кто-то сказал, что в проекте над которым он трудится продолжительное время (с командой или в одиночку, наверное не важно), нет архитектурных проблем — я бы не поверил. И дело здесь совсем не в компетенции команды или конкретных её членов, а в человеческом факторе.
Человек без ошибки — ошибка природы. (Когда-то давно, в моём детстве, так мне говорил отец).
Мы люди, а людям свойствено ошибаться: разработчик допустил ошибку, ревьюер недоглядел и пропустил запрос на слияние, и вот проблема уже в мастере.
А ты ведь знаешь — архитектурные ошибки коварны. Они могут очень долгое время оставаться незамеченными, а проявляются (по собственному опыту) в самый неподходящий момент.
Автоматизация — самый действенный способ решения многих проблем. Мне кажется, если процесс контроля качества кода/архитектуры в проекте не автоматизирован (средствами различных инструментов, вроде стат. анализаторов и их подобным), в нём просто не может не быть проблем.
Об автоматизации процесса контроля качества архитектуры php-проектов я рассказывал во второй части предыдущего поста. Наглядно и с примерами я показывал, как подключить и начать использовать разработанный мною инструмент php-clean-architecture (далее по статье — phpca). С его помощью можно визуализировать граф зависимости компонентов проекта и контролировать значения метрик качества, описанных Робертом Мартиным в его книге «Чистая архитектура».
Разрешенное состояние проекта
Как оказалось, тогда phpca был хорош при подключении к проектам на начальном этапе. В таких проектах еще нет большого тех. долга, а значит все обнаруженные проблемы можно махом исправить, и дальше уже сам phpca будет бить разработчиков по рукам. Но вот при подключении его к боевому проекту выяснилось, что гибкости для работы с большими проектами, в которых уже накоплен внушительный тех. долг, что разом исправить его за сколь-либо адекватный срок невозможно, сильно не хватает.
Пример: предположим есть проект состоящий из следующих компонентов:
domain (сущности, интерфейсы их репозиториев, …)
infrastructure (какие-то инфраструктурные классы, типа email и sms сендеров, реализации репозиториев, …)
use cases (различные возможные сценарии использования)
entry-points (классы запросов и ответов, контроллеры, форматеры и прочее)
Каждый из компонентов содержит 100+ файлов.
Настраивая phpca мы задаём правила:
domain не должен иметь исходящих зависимостей
use cases может знать только про domain
entry-points может знать только про use-cases и domain
infrastructure может знать только про domain и use cases
В действительности же:
20 классов из domain каким-либо образом зависят от 17 классов из use cases
32 класса из use case используют 28 сервисов из infrastructure
18 контроллеров из entry-points используют 12 классов из infrastructure
и даже сервисы из infrastructure зависят от request-классов из entry-points
(не спрашивай почему так, пример надуманный, но даёт возможность предметно рассмотреть проблему и ее решение)
Что получается? С одной стороны мы не можем быстро решить все обнаруженные проблемы, их слишком много. С другой стороны, если сейчас не задать запрещающие правила для направлений в графе зависимости компонентов, то через время проблем будет еще больше.
Для решения этой проблемы в инструмент была добавлена команда сохранения текущего состояния проекта (настройка доступна в конфигурационном файле phpca-config.php)
// Исключения
'exclusions' => [
'allowed_state' => [
'enabled' => true,
'storage' => __DIR__ . '/phpca-allowed-state.php',
],
],
В процессе выполнения, команда vendor/bin/phpca-allow-current-state {?path/to/phpca-config.php}
строит и сохраняет нынешний граф зависимости компонентов и их составляющих между собой для его дальнейшего использования.
При истинном значении флага exclusions.allowed_state.enabled, в момент выполнения команд phpca-build-report и phpca-check, ранее сохраненное разрешенное состояние проекта будет учитываться анализатором, и ранее существовавшие несоответствия в графе зависимости компонентов будут игнорироваться.
Таким образом, мы можем взять абсолютно любой проект, с любым количеством проблем, подключить и настроить в нем phpca как нам хочется, выгрузить текущее состояние и сразу запускать его в эксплуатацию. Старые проблемы будут игнорироваться, но новые phpca уже не пропустит. А далее, по мере решения старых проблем, усиливать проверки.
Рекоммендация: Файл для сохранения разрешенного состояния проекта должен быть под управлением системы контроля версий (для того, чтоб у всех членов команды он был един, а еще для возможности частичного построения отчетов или запуска проверок по списку разрешенных путей, но об этом в следующем пункте).
Ограничение работы списком разрешенных путей
В какой-то из дней, сидя на работе и отсматривая одну жирную MR коллеги, я задался вопросом. Запрос на слияние был действительно большим и мне хотелось взглянуть на изменения сверху, без лишних деталей. Тогда я уже использовал phpca в нескольких проектах, но он мог работать только со всей кодовой базой, а я хотел визуализировать лишь ее новую/измененную часть. Ведь это было бы очень удобно, иметь возможность еще на этапе код-ревью, за пару секунд сформировать по измененным файлам отчет без воды и лишних деталей, с визуализацией графа зависимости компонентов и таблиц зависимости их составляющих, и понять какие из этих изменений и чем нарушают установленные правила.
Еще хотелось сделать эту возможность гибкой, чтоб списки разрешенных путей можно было формировать и передавать в команду динамически. Конфигурационный файл для этих целей не подходил чуть больше чем совсем. Так phpca научился работать с переменными окружения.
Рассмотрим пример: ниже расположен общий граф зависимости компонентов php-clean-architecture, построенный командойvendor/bin/phpca-build-reports {?path/to/phpca-config.php}
по всей кодовой базе проекта
граф зависимости компонентов php-clean-architecture
Далее рассмотрим детали со страницы отчета по компоненту entry-points
граф зависимости компонента entry-points
(я специально выбрал в качестве примера небольшой компонент небольшого проекта, чтоб всё было максимально наглядно и не возникло путаницы)
На скриншоте видно, что изначально 1класс из entry-points зависит от 4х классов из model.
Далее я внесу некоторые бессмысленные изменения в entry-points и сформирую отчет на основании этих изменений.
не пытайся найти смысл в этих изменениях, ничего не выйдет
export PHPCA_ALLOWED_PATHS=`git diff master --name-only` PHPCA_REPORTS_DIR='phpca-reports-by-git-diff'; bin/phpca-build-reports
Общий граф зависимости компонентов и граф зависимостей entry-points теперь выглядят одинаково. (Это происходит из-за того, что текущий отчет отображает данные только из единственного измененного файла, лишние компоненты из основного графа убраны)
граф зависимости компонента entry-points (на основе изменений)внесенные ранее изменения отражены в таблице
На скриншоте видно, что в таблице зависимости составляющих компонента, помимо ранее существовавших теперь стали отражены и вновь внесенные изменения, а лишние компоненты и их составляющие из отчета убраны.
Так было уже почти хорошо, но мне все еще хотелось больше гибкости. Хотелось отбросить больше лишнего и оставить только самое важное. Ведь видеть полный отчет только по измененным файлам — это круто, но иногда было бы полезно видеть по измененным файлам НЕ полный отчет. Зачем мне смотреть список всех зависимостей, пусть даже и только измененных файлов, если я хочу узнать какие зависимости были добавлены в текущей ветке?
Это можно было реализовать дополнив фильтрацию графа по списку разрешенных путей, проверками наличия зависимостей в разрешенном состоянии проекта (из предыдущего пункта статьи).
Ниже я включу в файле конфигурации флаг exclusions.allowed_state.enabled и повторно сформирую отчет на основании git diff текущей ветки с master.
граф зависимостей внесенных в измененных файлах
Теперь граф и таблица зависимостей отображают только те изменения, которые действительно были внесены в измененных файлах. Все остальное из отчета убрано и это как-раз тот результат который мне хотелось получить.
Заключение
Используя описанные выше возможности ты можешь сильно упростить процесс подключения phpca к своему проекту, даже если он активно разрабатывается большой командой и в нем есть много легаси, а также начать использовать инструмент при проведении код-ревью сессий, и таким образом благодаря наглядности облегчить анализ больших запросов на слияние и поиск в них потенциальных архитектурных проблем.
Я искренне рад, что ты дочитал пост до этого места. Спасибо тебе за потраченное время, и я надеюсь что возможность использования phpca и знания приобретенные из этой статьи в дальнейшем сэкономят тебе намного больше времени.
А еще я буду очень рад получить твою обратную связь в ЛС или коментариях.
Доброго времени суток и чистой архитектуры!