Как стать автором
Обновить

Комментарии 41

> Судя по популярности в Java, парадигма довольно интересная и имеет право на жизнь в PHP.

Эту фразу можно сказать о чём угодно, и получится неверно.
Судя по популярности в Java, парадигма довольно популярна в Java.
А интересная парадигма или нет, и имеет ли она право на жизнь в PHP, никак с популярностью в Java не связано. Может быть, интересная, может быть, нет, может быть, имеет право на жизнь, может быть, нет. Но об этом нужно отдельно рассуждать.
Иногда полезно перенимать опыт.
Была давненько статья с презентацией библиотеки, реализующей эту парадигму в php. Это работало как постобработка кода, то есть вы пишете пишете используете красивые конструкции которых нет в языке, потом прогоняете код парсером и все работает, но код — лапша.
Парадигма интересная, но лично мне страшно что-то такое использовать в production. Было бы хотя бы расширение или смутные намеки, что это запилят в x.x версии языка.
Расширение то есть(описаное в статье), но оно конечно пока сырое, до продакшена еще далеко.
2005 последнее обновление. Вы же понимаете, что это мертвый код.
Это Intercept обновлялось в 2005, на базе него я разработал свое(MethodIntercept), которое обновлялось позавчера). Если окажется кому-то нужным, могу занятся разработкой и поддержкой.
Интересно, конечно. В первую очередь документацией, тестами производительности и success story применения в рабочем проекте.
доклад АОП в PHP, который был аж на PHPConf2007 (слайды доступны тут wiki.agiledev.ru/doku.php?id=conferences), мне кажется более полно раскрывает + данного подхода.
из рассмотренных тогда способов реализации wiki.agiledev.ru/doku.php?id=aop:aop_php#средства_аоп_для_php сейчас не работает ни один.

третий способ реализации на php — парсерить php код и генерировать на его основе другой php код, который выполняет обёртки
Кажется именно про эти слайды я тут писал.
Вы не в курсе, разработка идет? Три с лишним года прошло.
вроде все проекты сдохли, code.google.com/p/php-aop/source/list датируется 2008 годом последний коммит. видимо на определённом этапе интерес пропадает :)
> вроде все проекты сдохли

Вот здесь посмотрите еще — wiki.agiledev.ru/doku.php?id=aop:aop_php — некоторые проекты вроде еще живы.
Кроме runkit все либо очень старое, либо умерло.
Я эти аспекты заменил евентами, на каждый пук фреймверк посылает евент, остальные, кому надо на них подписываются, yii и ZendFramework 2 так же работают, и это, как по мне, удобней и проще.
Аспекты немного шире, и затрагивают как ваш код «вне» фреймворка так и потенциально внешние библиотеки без исходных кодов.
«Судя по популярности.....»
Насколько я знаю, AOP в «традиционных» языках имеет весьма ограниченное применение в силу того, что очень легко так, что код один, а происходит совсем другое. В Java — это отчасти компенсируется IDE которая подсказывает, что вот «здесь» ещё и аспекты вызываются. На даже не смотря на поддержку IDE — применение аспектов обычно ограничивается: логированием, декларативным управлением транзакциями, кешированием.
Но юмор ситуации в том, что если мы в архитектуре опираемся на SOLID, то декларативное управление транзакциями, кеширование и отчасти логгирование — мы можем легко и явно (или чуть менее явно — внутри IOC-контейнера) реализовать и без аспектов. Так так ли нужны аспекты в php?
Тут скорее стоит задать вопрос так — «Нужны ли аспекты вообще?», потому что php язык себе как язык.
Мне лично понравилась статья от IBM — www.ibm.com/developerworks/ru/library/j-aopwork15/
Они как раз утверждают что «применение аспектов обычно ограничивается» ваше неверно.
> Они как раз утверждают что «применение аспектов обычно ограничивается» ваше неверно.
Пробежался по статье по диагонали. Нашёл много текста говорящего о том, что «мол да — не ограничивается, что для аспектов есть много других хороших применений», но не нашёл ни одного убедительного примера. В случае с фильтром попытка показать преимущества аспектной реализации перед реализацией интерфейса выглядит надуманной.
Если у вас есть материалы об успешном использовании аспектов — будет интересно узнать (только просьба — больше не кидать ссылки на документы подобные тому с ibm)

Причём — если в java реализация динамических прокси выглядит обычно пугающе, то в php подобная техника является обычным делом благодаря magic-методам.

А питоновские декораторы служат для этой же цели или это другая парадигма?
Они в том числе могут служить для этой цели, но есть также множество других применений. Декораторы в питоне — лишь инструмент языка, а то, какую парадигму/методику программирования вы будете с помощью них реализовывать — ваше дело.
А почему не сделать, чтобы в совет объект и параметры метода, приходили как два разных параметра, а не один массив?
Для единообразия.
В пхп уже принято так передавать методы в качестве параметра.
А где это написано как а пхп принято?
Например в магическом методе

public function __call($method, array $args) {}

название метода и список аргументов разделены на два разных параметра, разве это не пример того как принято?

И мне непонятна эта строчка github.com/kooler/PAF/blob/master/Framework/paf/joinpoint.php#L97

public function fire($arguments) {
$funcCreation = '$ob=new '.$this->getCallClassName().'();$ob->'.$this->getCallMethodName().'($arguments);';
eval($funcCreation);
}


В чем смысл использовать eval, когда можно написать
public function fire($arguments) {
$objClass = $this->getCallClassName();
$obj = new $objClass;
call_user_func_array(array($obj, $this->getCallMethodName()), $arguments);
}

Когда в ход идел eval() — дело пахнет жареным.

И наконец вместо написания комментария
/*
* Base aspect class. Must be extended in all aspects
* IMPORTANT: Each aspect should have constructor without arguments
*/
abstract class Aspect {};


Если можно просто финализировать конструктор:
/*
* Base aspect class. Must be extended in all aspects
* IMPORTANT: Each aspect should have constructor without arguments
*/
abstract class Aspect {
final public function __construct() {}
};
Спасибо за замечания касательно eval и финализации конструктора, исправлю.

Насчет параметров совета — планирую в следующей версии модуля сделать аналогично методу __call.
Сначала планировал передавать больше информации в совет, поэтому и сделал в виде массива, чтобы проще было расширить. Но немного поработав с модулем вижу, что кроме обьекта и аргументов ничего не нужно, поэтому решил переделать, пока он еще на ранней стадии и никем не используется.
Ванга видит как охуенно такой код дебажить.
мне не нравится парадигма АОП, так как основное требование к большинству проектов — это скорость выполнения.
Внедрять парадигму АОП надо как-то на уровне Zend Egine, как точно я пока не знаю.
Расширения Intercept и MethodIntercept так и делают. Они заменяют функцию вызывающую методы\функции оберткой, соответственно вызов советов выполняется на уровне Zend Engine.
Хм, как мне кажется основное требование давно скорость разработки и, главное, простота (включая скорость) поддержки и развития. И если со скоростью разработки явных преимуществ не видно, то если вот, например, внезапно для проектировщика добавить то же логирование каждого чиха — преимущества АОП, имхо, очевидны, если каких-то хуков и евентов архитектурой не предусмотрено.
Не всегда. В высоконагруженных проектах, оплата за процессорное время может запросто обогнать затраты на разработку. Я работал в проекте, где 10% снижение нагрузки означало экономию в 50 000$
«Основное требование к большинству проектов — это скорость выполнения.»

По-моему, высоконагруженных проектов явно не большинство, даже если отбросить явных «хомячков», но оставить «визитки», за создание которых кому-то хоть что-то заплатили.
Не люблю АОП — слишком много магии в коде. Вот вроде класс как класс, ан нет — там еще 100500 функций вызывается неизвестно где
А нет ли желания добавить поддержку annotations так, как это сделано в C#?
А в чём качественное отличие? Просто в PHP есть уже устоявшиеся, имхо, традиции.
Насколько помню, в C# можно создавать пользовательские типы аннотаций.
Мне кажется, что для программиста задавать точки соединения при помощи регулярных выражений удобней всего.
Что бы посоветовали добавить?
более-менее какая-то имплементация для Symfony2 уже есть. и довольно даже работает :)
Полноценная реализация AOP с упором на DDD, TDD и вообще лучшие практики объектного программирования уже есть в свежем релизе фреймворка FLOW3. В нашем интернете о нём мало что известно, меж тем, на нём построена новая версия движке TYPO3.
Когда-то бы статья, быть может даже здесь на Хабре. Элегантная иньекция сквозной функциональности. Возможно если поработать с кодом, можно выйти на фреймворк, если вдруг никто этого еще не сделал.

class Event extends ArrayObject {
public function __invoke() {
foreach($this as $callback)
call_user_func_array($callback, func_get_args());
}
}
$test = new Event();

/* Setting up callbacks */
$test[] = function($msg, $txt) {
echo "This is the event!
";
};

$test[] = function($msg, $txt) {
echo "Message: $msg. Text: $txt
";
};

$test[] = function($msg, $txt) {
echo "Works great!
";
};

/* call */
$test("Some message", "Some text");
Я не понял главного. Как осуществляется связь обслуживаемый метод -> аспект? Ну то есть, каким образом синтаксически задаётся, что для метода Backet::order() нужно вызывать конкретный аспект после выполнения метода?

У меня три предположения. Вот ваш код:

/*
* @After(Backet->order)
*/
public function backetOrderMessage($params) {
echo ‘Backed has been ordered’;
}


Вариант 1. Связь задаётся через комментарий. Ваша библиотека ищет комментарий вида "@After(Backet->order)" и благодаря ему знает, что код ниже должен срабатывать после метода Backet::order().

Вариант 2. Связь задаётся через имя метода backetOrderMessage. Первое слово — класс (backet), второе слово — метод (order), третье слово — тип аспекта (message), видимо message — это тип пост-аспекта, т.е. который срабатывает после метода.

Вариант 3. Вы забыли показать кусок кода, в котором происходит связь метод->аспект.

Пожалуйста, проясните данный вопрос.
Связь задается при помощи аннотаций — определенного формата комментариев.
Таким образом аннотация вида:
/*
 * @After(Backet->order)
 */
public function backetOrderMessage($params) {
 echo ‘Backed has been ordered’;
}

значит, что совет backetOrderMessage нужно вызвать после выполнения метода order обьектов класса Backet.
Более детально о возможных аннотациях можно почитать в документации на Гитхабе: github.com/kooler/PAF/wiki/PAF-Join-points
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.