Вы когда-нибудь слышали об аспектно-ориентированном программировании (AOP) раньше? Это широко используемая концепция при разработке систем корпоративного уровня, хотя она не получила большого применения в PHP. Я собираюсь использовать эту статью как возможность познакомить PHP разработчиков с AOP.
Этот урок будет доставлен вам в виде серии из трех частей. В этой части я объясню концепции АОП. Во второй части я покажу вам практическое использование AOP и создание структуры правил AOP. Наконец, я покажу вам, как интегрировать функциональность AOP с использованием CodeIgniter в части 3.
Что такое АОП?
При разработке приложений мы часто находим требуемые функциональные возможности, которые должны использоваться в нескольких частях нашего кода, но которые на самом деле не связаны с бизнес-логикой. Хорошим примером является проверка подлинности, чтобы убедиться, что пользователь вошел в систему перед выполнением определенной задачи. Такие задачи называются сквозными задачами. Давайте посмотрим на определение сквозных проблем, данное в Википедии :
В информатике сквозные проблемы — это аспекты программы, которые затрагивают другие проблемы. Эти проблемы часто невозможно четко разложить на остальную часть системы как при проектировании, так и при реализации, и могут привести к разбросу (дублирование кода), запутыванию (значительные зависимости между системами) или к тому и другому.
Теперь, когда у вас есть общее представление о сквозных проблемах, давайте посмотрим, как они выглядят в коде.
Рассмотрим ситуацию, когда вы являетесь редактором блога, такого как SitePoint. Вам необходимо войти в систему, чтобы создавать сообщения, утверждать сообщения, редактировать сообщения и т. Д. Если вы не вошли в систему, вы должны быть перенаправлены на экран входа в систему. Чтобы обеспечить такое поведение, код должен проверять подлинность перед каждой из задач, упомянутых выше.
<?php
class BlogPost extends CI_Controller
{
public function createPost() {
if (!Authentication::checkAuthentication()) {
// redirect to login
}
else {
// proceed
Messages::notifyAdmin();
}
}
public function approvePost() {
if (!Authentication::checkAuthentication()) {
// redirect to login
}
else {
// proceed
}
}
public function editPost() {
if (!Authentication::checkAuthentication()) {
// redirect to login
}
else {
// proceed
}
}
public function viewPost() {
// ...
}
}
Посмотрите на приведенный выше код, и вы увидите, что checkAuthentication()
notifyAdmin()
Это не только дублированный код, но и класс BlogPost
Аутентификация и уведомления должны быть сделаны отдельно. Мы нарушили принцип единой ответственности :
Принцип единой ответственности гласит, что каждый класс должен нести одну ответственность, и эта ответственность должна быть полностью заключена в класс. Все его услуги должны быть тесно связаны с этой ответственностью.
Итак, теперь мы пришли к месту, где мы можем понять значение АОП. Межотраслевые задачи могут быть сгруппированы в объекты, называемые «аспектами», а процесс отделения сквозных задач от нашего основного кода называется Аспектно-ориентированным программированием.
АОП Терминология
Есть несколько конкретных терминов, используемых в АОП для объяснения его особенностей. Понимание этих терминов, вероятно, станет ключом к успешной интеграции AOP в ваши проекты PHP.
- аспект
- Совет
- Joinpoint
- Pointcut
Мы только что узнали, что такое аспект, поэтому теперь давайте посмотрим, что означают остальные три термина.
Совет
Функциональность аспекта называется советом. Как следует из названия, советы определяют, что делать в определенных ситуациях и когда это делать. В нашем предыдущем примере проверка аутентификации (что) — это совет, и его следует применять перед выполнением кода (когда) внутри определенных методов.
Joinpoint
Точки соединения — это места в приложении, где мы можем создавать советы. Оглядываясь назад на пример кода, вы можете найти несколько мест, где я назвал функциональность, которая не имеет прямого отношения к бизнес-логике. Например, в createPost()
Это обе возможные точки соединения.
Соединительные точки могут быть определены в любом месте кода вашего приложения, но применение советов будет доступно только в определенных точках в соответствии с вашими особенностями инфраструктуры AOP и будет обсуждаться позже в этом руководстве.
Pointcut
Pointcut определяет способ сопоставления советов с определенными точками соединения. Хотя в нашем примере у нас есть пара точек соединения, в вашем приложении могут быть тысячи точек соединения, и вам может не потребоваться применять рекомендации ко всем из них. В таких ситуациях мы можем сопоставить подмножество точек соединения, которое называется указателями, и применять рекомендации только к выбранным элементам.
Предположим, что мы хотим посоветовать createPost()
approvePost()
editPost()
viewPost()
Мы должны как-то подобрать эти 3 метода и применить советы. Позже мы будем создавать XML-файл с подробностями аспектов, который будет содержать регулярные выражения для сопоставления точек соединения.
Итак, подведем итог: когда в приложении возникает сквозная проблема, мы создаем аспект, который учитывает функциональность приложения в определенных точках соединения, выбранных с помощью pointcut.
Типы рекомендаций АОП
Есть несколько способов, которыми мы можем посоветовать наш код. Как я упоминал ранее, доступность этих типов рекомендаций зависит от типа используемой платформы AOP, но некоторые типы, с которыми вам следует ознакомиться:
- Перед советом
- После возвращения совета
- После броска совета
- Вокруг совета
Перед советом
Перед тем, как совет будет применен перед определенной точкой в вашем коде, обычно вызовом метода.
До сих пор я использовал советы внутри методов, чтобы упростить концепцию и помочь вам быстрее понять ее. Но в реальном мире советы обычно не входят в методы. Должен быть отдельный глобальный контроллер, в который должен входить каждый метод, и внутри метода мы можем обернуть функциональность AOP. Этот глобальный контроллер работает внутри системы и невидим для нас.
<?php
class PathController
{
function controlPaths($className, $funcName) {
Authentication::checkAuthentication();
$classObj = new $className();
$classObj->$funcName();
}
}
Здесь я создал фиктивный класс, чтобы показать вам, как это происходит на самом деле. Предположим, что метод controlPaths()
В приведенном выше коде мы применили рекомендацию checkAuthentication()
Это называется перед советом.
После возвращения
Этот совет будет применен после того, как определенная функциональность будет полностью выполнена и возвращена вызывающей точке. Рассмотрим следующий код:
<?php
class PathController
{
function controlPaths($className, $funcName) {
$classObj = new $className();
$classObj->$funcName();
Database::closeConnection();
}
}
Смотрите здесь, что после завершения метода мы очищаем ресурсы базы данных. Это называется после возвращения совета.
После броска
Если функция выбрасывает исключение в процессе выполнения, может быть применен совет После выбрасывания. Здесь, после броска совет — сообщение об ошибке.
<?php
class PathController
{
function controlPaths($className, $funcName) {
try {
$classObj = new $className();
$classObj->$funcName();
}
catch (Exception $e) {
Error::reportError();
}
}
}
Вокруг Советов
Четвертый тип совета — это совет, который представляет собой комбинацию как до, так и после возвращения совета.
<?php
class PathController
{
function controlPaths($className, $funcName) {
Logger::startLog();
$classObj = new $className();
$classObj->$funcName();
Logger::endLog();
}
}
Резюме
В этой статье я познакомил вас с AOP. Вы должны иметь общее представление о том, чего пытается достичь АОП, и быть знакомыми с некоторыми основными терминами АОП. В следующей части этой серии я покажу вам, где требуется AOP в реальных проектах и как мы можем использовать хуки CodeIgniter для создания функциональности AOP. Будьте на связи!
Изображение через Fotolia