25 сентября 2011 г.

Расширение функциональности с использованием метаданных и аспектно-ориентированного программирования

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

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

Q: Почему вы использовали Unity?

A: Дело в том, что Unity реализует механизм подачи аспектов через перехватчики. Аналогичную концепцию реализует Spring.NET в части AOP, поэтому для демонстрации это было не принципиально. Отвечая на данный вопрос, было бы правильней ответить, почему была выбрана концепция подачи аспектов через перехватчики в качестве основной. Дело в том, что при таком подходе класс, перехват методов которого мы осуществляем, и аспект никак не связаны друг с другом, поскольку связь между ними устанавливается на этапе инициализации приложения в одном месте. Как следствие – можно достаточно просто включить или отключить интересующее нас поведение. Если говорить о Unity, то данную связь можно установить в конфигурационном файле, не меняя код самого приложения. Поэтому данный подход достаточно просто реализовать в проектах, в которых используется какая-либо DI-инфраструктура, в частности, различного рода контейнеры зависимостей. В противовес первому подходу существует другой подход – подача через атрибуты, когда классы или методы помечаются атрибутами, которые инкапсулируют логику некоторого аспектов. Впоследствии эти атрибуты анализируются некоторым инфраструктурным сервисом, который производит вызов аспектов в нужное время и нужном месте. Основным минусом такого решения является жесткая связность между классом и аспектом, который в него внедряется. Другим малоприятным фактом является то, что при таком подходе мы не можем добавить или удалить поведение “просто”, то есть не меняя кода программы, а если таких мест в приложении достаточно много, то это может занять очень много времени. Концепции подачи через атрибуты придерживаются разработчики PostSharp, Aspect.NET, а также некоторых других библиотек. Однако, в защиту последнего следует сделать важное замечание. Каждый инструмент ориентирован на решение своего круга задач, поэтому в вопросах выбора инструмента не нужно быть слишком категоричным. Если в вашем случае решение с использованием атрибутов наиболее эффективно, то почему бы и нет. Более того, зачатую оказывается эффективным “микс” из нескольких концепций (конечно, все в рамках разумного).

Q: Увеличивается ли время выполнения при использовании АОП?

A: Время выполнения увеличивается ровно на столько, сколько будут выполняться все аспекты в целом, связанные с данной точкой слияния. При прочих равных условиях это время будет незначительно отличаться от того, если бы мы поместили код аспекта непосредственно в тело перехватываемого метода. Между тем, время выполнения можно уменьшить, используя асинхронные аспекты. Об этом не было сказано в рамках моего доклада и за данную идею отдельное спасибо Сергею Звездину. Суть асинхронных аспектов заключается в том, что они выполняются асинхронно, после того, как пользователь получит результат. Однако в таком решении имеются “подводные камни”. Если перехватываемый метод вызывается довольно интенсивно, это может привести к большой загруженности сервера. Тем не менее, данную проблему также можно решить, ограничив используемые ресурсы.

 

 

Если будут еще вопросы, пишите :)

3 коммент.:

Sergey Zwezdin комментирует...

Доклад понравился. Спасибо.

xoposhiy комментирует...

Спасибо за ответы :)

1. Почему Unity. Я, конечно, хохмил, когда в твиттер писал :) Так-то понятно, почему Unity.

2. А про время выполнения вопрос возник на слайде, на котором аспект проверял имя метода, сравнивая со строкой. Я не знаток unity, но полагаю такой код без Reflection работать не может, а значит, как обычно с Reflection, будут тормоза.

Александр Межов комментирует...

@xoposhiy

Критика всегда полезна :) Да, имеются некоторые накладные расходы на reflection, генерацию proxy и т.д. Однако нужно сказать, что они не такие большие. Если счет пойдет на миллисекунды, то ни о каком АОП речи быть не может :)

Отправить комментарий