За последние 24 часа нас посетили 89223 программиста и 5562 робота. Сейчас ищут 1557 программистов ...

AOP - ищу новые идеи

Тема в разделе "Прочие вопросы по PHP", создана пользователем AndreJM, 11 мар 2012.

  1. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.333
    Симпатии:
    1.753
    я про этот пример.
    какой тут механизм?
    Код (PHP):
    1. // test.php
    2. class Test {
    3.      function testfun() {
    4.         /*  тут описана работа метода */
    5.         $test = "Hello";
    6.         /*  тут описана работа метода */
    7.         return $test;
    8.      }
    9. }
    10.  
    11. // aspecttest.php
    12. class AspectTest {
    13.       private $log = new Log();
    14.       function before($class,$method) {
    15.            $this->log->save("Run $method!");
    16.       }
    17.  
    18.      function after($class,$method,$returnvalue) {
    19.           $this->$log->save("End $method!");  
    20.           $this->$log->save("$method return $returnvalue");  
    21.      }
    22. }
    23.  
    24. $aop = new AspectAOP(); 
    25. /* регистрируем наш экземпляр который будет реагировать на вызов метода testfun класса Test;  
    26. Так же можно объявить  array('Test::*')  где будет реагировать на любой вызываемый метод класса Test */
    27. $aop->register(new AspectTest(), array('Test::testfun')); 
    28.  
    29. $test = new Test();
    30. echo $test->testfun();
    31.  
    32.   
     
  2. AndreJM

    AndreJM Активный пользователь

    С нами с:
    25 янв 2012
    Сообщения:
    522
    Симпатии:
    0
    Механизм чего? Тут их много..
    Или тебя интересует картина в целом?
     
  3. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.333
    Симпатии:
    1.753
    реальный партизан =)

    как ты умудряешься перехватить вызовы методов класса Test без перечитки файла?
     
  4. AndreJM

    AndreJM Активный пользователь

    С нами с:
    25 янв 2012
    Сообщения:
    522
    Симпатии:
    0
    Ну про враппер я тебе зачем тут в нескольких постах разъяснял? :)

    Если в целом то:

    $aop = new AspectAOP(); - На этом этапе я создаю объект тип которого был мною предопределен заранее. Он, в свою очередь в конструкторе, определяет собственный враппер для перехвата подключаемых классов (аля require("test.php")).

    $aop->register(new AspectTest(), array('Test::testfun')) - Тут происходит регистрация методов before/after класса AspectTest к методу testfun класса Test.

    $test = new Test(); - в этот момент, как только автоматически подгружается файл класса (средствами spl_autoload_register), враппер класса AspectAOP, токенизит(token_get_all) подгруженный файл, сравнивает с зарегистрированными методами (array('Test::functest')) и вслучае совпадения, переписывает метод functest основываясь на реализацию подсунутую в классе AspectTest. На выхлопе враппера, подгруженный test.php имеет например такую картину:
    Код (PHP):
    1. class Test {
    2.      function testfun() {
    3.          $args = func_get_args();
    4.          return self::__aopCaller(__FUNCTION__, 'aop__testfun', $this, $args);
    5.      }
    6.      private static function __aopCaller($args) {
    7.          /*  тут мы пытаемся выяснить кто нас мог вызывать, 
    8.          то есть получаем доступ к экземпляру класса AspectTest 
    9.          и последовательно выполняем соответствующие методы before/aop__testfun/after
    10.          */
    11.      }
    12.      function aop__testfun() {
    13.         /*  тут описана работа метода */
    14.         $test = "Hello";
    15.         /*  тут описана работа метода */
    16.         return $test;
    17.      }
    18. }
    19.  
    ну как-то так, для наглядности
     
  5. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.333
    Симпатии:
    1.753
    прикольно
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.129
    Симпатии:
    1.225
    Адрес:
    там-сям
    по простому говоря, файл php является "шаблоном", а выполняется какой-то другой, созданный на основе этого плюс код, сгенеренный из аннотаций.
    минусы очевидны, а плюсы как-то нет :D
     
  7. AndreJM

    AndreJM Активный пользователь

    С нами с:
    25 янв 2012
    Сообщения:
    522
    Симпатии:
    0
    Если вы пишите файл php используя в каждом методе заведомо нужный функционал (скажем для логирования), и клонируете его в другие подобные файлы - тоже самое что и генерация кода на основе "шаблона" о котором вы говорите. Плюс второго это наименьшая связанность, мне достаточно переопределить всего лишь методы, а то и просто менять целые классы в качестве AOP для решения задач в "шаблоне", а в случае перового Вам придется переписывать все ваши упоминания во всех ваших файлах =)
    И да, я могу управлять: нужно ли мне менять шаблон или нет, что в случае принудительно написанного функционала приводит к уменьшению покрытия кода из-за отсутствия надобности использования того самого функционала.
     
  8. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    Все не читал, но сильно смахивает на паттерн декоратор. Во всяком случае смысл тот же самый.
     
  9. AndreJM

    AndreJM Активный пользователь

    С нами с:
    25 янв 2012
    Сообщения:
    522
    Симпатии:
    0
    Скорее на фабрику.
    Всё же почитать стоит =)

    Суть не в том, что везде где мне нужно (скажем логировать) надо воткнуть фабрику, декоратор, сервис локатор, да вообще что угодно. Суть в том, что я избавляю себя от написания кода, который может скажем не понадобиться на продакшене, ну допустим:
    Код (PHP):
    1. // Loger должен логировать все в development
    2. function connectToDb($args) {
    3.   Loger::factory('File_Loger')->save("Connect to database", $args);
    4.   ..............
    5.   Loger::factory('File_Loger')->save("Result connect to database", $result);
    6. }
    7. // Но в production должно быть так (без всяких логирований):
    8. function connectToDb($args) {
    9.   ..............
    10. }
    11.  
    Ну а если время от времени я должен использовать фабрику не File_loger, а скажем Dd_Loger, или скажем Mem_loger?
    Получается, я каждый раз должен переписывать все функции где используется другая фабрика.
    Вы конечно скажете, что можно сделать фабрику фабрик -) Однако это тоже не подходит, так-как например я обязан часть функций логировать скажем в File_Loger, а другую часть в Mem_loger, а то и вообще менять местами все это дело.

    Моя же цель, избавить себя от программирования всех этих фабрик, декораторов и прочих петтернов, для того, что бы логгировать, пулять транзакции и много чего еще. То есть не писать данный функционал в рабочих скриптах, а реализовать его отдельно, и в случае надобности, скажем на продакшене, оперативно получить информацию от том, что происходит в тот или иной момент в какой-нить функции(ях).
    То есть код у меня минимальный (только функционал который заложен в функцию, метод и т.п.), и я его могу расширить на лету не меня исходного кода. Включил - глянул, выключил..
     
  10. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.129
    Симпатии:
    1.225
    Адрес:
    там-сям
    Ну не надо преувеличивать сложности. Чтобы заменить класс логгера в общем случае не требуется переписывать место где он используется. IoC существует не только в AOP :) На продакшене можно логгер заменить на заглушку, которая ничего не делает.
    Меня как-то напрягает, что с AOP мы не только не видим внутренности "черного ящика", но даже не знаем есть ли он вообще и как происходит обращение к нему.
     
  11. AndreJM

    AndreJM Активный пользователь

    С нами с:
    25 янв 2012
    Сообщения:
    522
    Симпатии:
    0
    IoC был для примера и не является для АОП панацей.
    Меня напрягают заглушки так-как они не только увеличивают время выполнения алгоритмов, так еще и время написания кода.
    Рабочему коду совершенно не нужно знать о существовании АОП и его реализации, он как работал, так и работает.
    И да, АОП это не каждодневный кодинг, его необходимость используется в частных случаях. Для меня АПО успешно справляется с пересечениями (crosscutting) что представляет для меня большую пользу.
     
  12. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.129
    Симпатии:
    1.225
    Адрес:
    там-сям
    AndreJM, вообще штука интересная. Раз уж ты засветился с аспектами, можно тебя поспрашивать?
    • где еще кроме логирования выгодны аспекты?
    • ты писал, что использовал stream_wrapper для фокуса с аспектами — не могу понять как он может участвовать. автолоадер классов это понятно, а свой протокол зачем???
     
  13. AndreJM

    AndreJM Активный пользователь

    С нами с:
    25 янв 2012
    Сообщения:
    522
    Симпатии:
    0
    • Часто это употреблялось мной еще и в: транзакциях, эксепшенах, ... Иногда даже для реализации некоторых шаблонов, например адаптер, да и вообще наверное для создания комплексной логики в целом.
    • Протокол нужен был для обхода стандартных врапперов, например тот же 'file://'. Ну то есть привычнее работать с собственной обёрткой =) Моя задача подключать (через автолоадер) стандартные(привычные) файлы с расширением.php и в тоже время я должен контролировать их загрузку и в случае определенных условий... короче.. обычная импликация. Навешиваем обертку на загружаемый класс если загружаемый класс подходит под мои условия зарегистрированного ранее аспект-объекта. Ну и на выхлопе уже переработанный класс.
    Надеюсь доходчиво объяснил =)