Аспектно-ориентированное программирование на PHP

ATR

Величайший
PR-group
ПРОВЕРЕННЫЙ ПРОДАВЕЦ
ДРУЗЬЯ ФОРУМА

ATR

Величайший
PR-group
ПРОВЕРЕННЫЙ ПРОДАВЕЦ
ДРУЗЬЯ ФОРУМА
Регистрация
30 Июн 2018
Сообщения
2,003
Реакции
722
Репутация
16
Всем привет!

Закончили в этом месяце первый набор курса

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

и трудоустраиваем их вовсю (ну насколько это возможно в пору отпусков). Курс пополнился ещё одним преподавателем —

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

, которого многие, наверное, знают. Ну, а мы традиционно делимся интересными вещами.

Поехали.

В любом приложении есть части кода, “пересекающие” несколько частей архитектуры одновременно.

Эта проблема не так очевидна при работе с полнофункциональным фреймворком. Скорее всего ваша проблема окажется распространенной, и будет шанс, что фреймворк уже разрешил ее, пожертвовав разделением ответственности или предоставив абстракцию поверх фреймворка. Многие фреймворки используют событийно-ориентированную архитектуру для решения проблем сквозной функциональности. Но всегда наступает момент, когда фреймворк не способен предоставить нужный уровень контроля над конкретным фрагментом логики. Это особенно актуально при использовании микрофреймворков или разработке со специализированными библиотеками. Чем больше ваше приложение учитывает принципы разделения ответственности, тем больше будет роль сквозной функциональности в вашей архитектуре.


Аспектно-ориентированное программирование на PHP

Аспектно-ориентированное программирование (АОП) — парадигма программирования, сфокусированная на организации и модульности сквозной функциональности. Кейсы применения — ACL, логирование, обработка ошибок, кэширование.

Встроенный (внутренние) предположения PHP (когда вы определяете функцию/константу/класс, она остается определенной навсегда) делают парадигму АОП сложной для имплементации.


Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

был первым, решившим проблему сквозной функциональности с помощью механизма фильтрации, позволяющего фильтровать логику метода через замыкания. Чтобы сделать метод фильтруемым, имплементация Li3 требует мануального добавления шаблонного кода. С такими ограничениями, техники АОП ограничиваются методами фильтрации.

Другие хорошо известные реализации АОП на PHP:

Расширение PECL AOP — интересный, но в то же время рискованный подход, так как поддержка PECL расширений не распространена. Другой вариант — библиотеки Go!, представляющие собой реализацию АОП, исправляющей PHP код на лету, что делает возможным использование методов АОП.

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

Новый парень на районе

Автоматическая генерация кода давно есть в PHP и используется во многих библиотеках, например

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

А благодаря принятию Composer,

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

показывает, что правка кода на лету возможна.

Если генерацию кода еще можно посчитать простой, то исправление кода несколько сложнее. Во-первых, в PHP нет встроенного парсера кода, а во-вторых, очень мало библиотек, решающих проблемы парсинга PHP кода. Самая известная — библиотека

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

. PHP-Parser — отличный инструмент, но даже он игнорирует форматирование пробелов в сгенерированных абстрактных синтаксических деревьях. Что затрудняет исправление кода. Действительно, код, который нужно исправить, является настоящим исполняемым кодом. Поэтому, если хотите, чтобы обратная трассировка была точна при ошибках, нужно учитывать номера строк в исправленном файле.

Для этой задачи мы используем патчер JIT кода

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

. Kahlan — новый тестовый фреймворк Unit & BDD, благодаря JIT техникам правок, позволяющий stub’ить и monkey patch’ить код прямо в Ruby или JavaScript. Под капотом обнаружим, что данная библиотека основана на рудиментарном парсере PHP. Но, тем не менее, он достаточно быстрый и стабильный, чтобы нам подойти.

Библиотека фильтров доступна на

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

и может быть использована следующим образом.

Во-первых, патчер JIT кода должен быть инициализирован как можно быстрее (например, сразу после включения композера autoloade):

Screenshot_1.png
Заметим, что правка кода возможна только для классов, загруженных autoload’ером Composer. Если класс добавлен при помощи require или include выражения, он уже загружен перед вызовом Filters::patch(true), и поэтому не будет исправлен.

По умолчанию, весь исправленный код будет храниться по адресу /tmp/jit, но вы всегда можно изменить его на свой:

Screenshot_2.png
Кэшированные файлы будут восстановливаться автоматически каждый раз при изменении PHP файла.

Внимание! Filters::patch(true) — самый простой способ настройки патчера, имейте в виду, что весь ваш код будет исправлен. Чтобы завернуть все методы вашей базы кода в фильтр-замыкание, может потребоваться много времени.

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

Screenshot_1.png
Таким образом, вы можете выбрать исправление всех методов определенного класса, только одного метода или нескольких из них.

API Фильтр

Теперь, когда JIT патчер включен, создадим фильтр логирования:

Screenshot_2.png
В приведенном выше примере создается фильтр регистрации SQL запросов для библиотеки базы данных Chaos. Больше информации о API фильтре можно узнать на

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.

Заключение

АОП, по моему мнению, настоящий ответ для сквозного функционала. Все прочие абстракции одинаково излишни и в большинстве случае ограничены определенными рамками. Я не теряю надежду, что однажды PHP предоставит встроенный API для аспектно-ориентированного программирования. Но сейчас, я думаю, патчинг JIT кода — лучший вариант, где преимущества значительно перевешивают оверхэд CPU, которым можно практически пренебречь, когда патчинг JIT кода не применяется глобально.

THE END

MaxRokatansky​
 
Сверху