Аспектно-орієнтоване програмування (АОП) для чого його краще використовувати

Аспектно-орієнтоване програмування (АОП) для чого його краще використовувати
Нещодавно мені запропонували провести обговорення аспектно-орієнтованого програмування (АОП) з дослідницькою групою програмної інженерії (SERG). За кілька годин до зустрічі один зі студентів запитав мене: «Ну і чим хороші аспекти? Тільки не треба наводити приклад реєстрації. Схоже, це єдине застосування аспектів, про який я знаю ».

Це питання змусило мене задуматися про ефективні способи застосування АОП в деяких програмних системах, з якими я працював. Я також зрозумів, що необхідно подумати про те, як і коли слід починати використовувати нові методи, особливо, якщо для них потрібні нові способи мислення. АОП, про який згадувалося вище в цій статті, як раз і представляє новий підхід. Хотілося б трохи поговорити про способи ефективного, на мій погляд, використання АОП. Також розглянемо деякі останні досягнення в АОП, здатні полегшити його розуміння.

Як приклади буде використовуватися аспектно-орієнтована мова Java. В даний час є кілька мов програмування з аспектно-орієнтованої реалізацією. Серед них AspectC ++ і навіть AspectL, тобто аспектно-орієнтована реалізація Lisp. 1

Огляд концепцій АОП

Щоб зрозуміти дане обговорення АОП, необхідно знати кілька концепцій. Основна концепція - точка з'єднання (join point). Ця концепція, з якої знайомі всі програмісти, і для якої немає назви. Точка з'єднання являє собою «точно певну точку в процесі виконання програми». 3 Є багато типів точок з'єднання, наприклад, виклик або повернення методу, який може бути звичайним поверненням або генерацією винятку.

В АОП необхідно знайти спосіб ідентифікації точок з'єднання в програмі. У AspectJ для опису однієї або декількох точок з'єднання використовується pointcut (зріз точки). Pointcut є вираз, що описує набір точок з'єднання. Pointcut можна розглядати як запит до коду, який повертає набір точок з'єднань.

При виборі набору точок з'єднань для них надається механізм advice (рекомендація). Advice є виконуваним кодом, який запускається при досягненні точки з'єднання в процесі виконання програми. Точки з'єднання, pointcuts і advice призначені для реалізації динамічних властивостей ПО. Механізм advice змінює характеристики виконуваного коду програми.

приклади АОП

Тепер розглянемо приклади, де можна використовувати АОП і де воно використовується. Деякі приклади взяті з виробничих систем, інші - з процесу експлуатації і розробки. Почнемо з пари прикладів для розробників.

трасування виконання

Дивно, як багато розробників вставляє в код різновиди операторів print для налагодження або трасування виконання програми. Для отладчиков ця інформація дійсна важлива. Але дане обговорення не пов'язане з вивченням отладчиков. Природно, існують вагомі аргументи для створення текстової трасування програми. У поточному наборі засобів розробки AspectJ (AJDT) в Eclipse є чудовим прикладом аспекту, що реалізує трасування виконання програм. Приклад докладно описаний в довідковій системі Eclipse. Його також можна знайти в «Керівництві з програмування AspectJ».

У прикладі є невелика Java-додаток з класами, що представляють двомірні фігури, наприклад, кола і квадрати. У додатку також є метод, який створює два кола і квадрат і виводить їх властивості, наприклад, площа, периметр і відстань між центрами. Після запуску програми виведення даних повинен відповідати малюнку 1.

Малюнок 1. Дані програми форми

Розглянути фактичну послідовність виклику методів можна двома способами. У першому підході можна в початок кожного методу вставити код, що виводить повідомлення з ім'ям методу і класу, а також факту виклику цього методу. Це необхідно зробити для кожного методу. Другий підхід полягає в створенні аспекту, що виконує ту ж саму операцію. У цьому підході змінювати код програми не потрібно.

Приклад трасування складається з декількох версій програми для трасування з використанням аспектів. Розглянемо останню версію. Опис інших версій див. У «Керівництві з програмування AspectJ».

Рішення для надійного механізму трасування складається з двох файлів. Перший файл - абстрактний аспект. Цей аспект схожий на абстрактний клас, де деяка частина коду залишена програмістам для реалізації в похідному класі, або, в даному випадку, в похідному аспекті. Абстрактний аспект, званий Trace, має кілька стандартних методів для виведення повідомлень про вхід і вихід з методу або конструктора і для форматування вихідних даних. Якщо аспекти не використовуються, ці методи знаходяться в класі helper і використовуються для виведення інформації про трасування. Трасування також дозволяє програмістам задавати тип трасування за допомогою завдання властивості TRACELEVEL. Існує три рівні: немає повідомлень, повідомлення, які не структуруються, і повідомлення, структуровані для відображення вкладених викликів.

Трасування визначає три pointcut: два конкретних і один абстрактний (див. Рис. 2). Будь аспект, який розширює аспект Trace, повинен надати абстрактний pointcut, myClass. Призначення pointcut полягає у виборі класів для об'єктів, що містять точки з'єднань, які будуть рекомендовані. Це дозволяє розробникам вирішити, які класи слід включити в вивідні дані трасування.

Малюнок 2. Pointcut в аспекті трасування

Pointcut myConstructor вибирає точки з'єднання на початку будь-якого конструктора для об'єкта в класі, обраного myClass. Точка з'єднання фактично є тілом конструктора. myMethod подібний myConstructor, але вибирає виконання будь-якого методу в обраному класі. Зверніть увагу, що виконання методу toString пропускається, так як він використовується в коді advice.

Наданий аспектом код advice досить простий. Є код advice (рекомендації), що вставляється перед кожною точкою з'єднання, і advice, що виконується після точки з'єднання. Це показано на малюнку 3.

Малюнок 3. Pointcut в аспекті трасування

Для використання аспекту Trace його необхідно розширити і надати точну реалізацію для абстрактного pointcut. На малюнку 4 показано тіло прикладу програми з аспектом TraceMyClasses. Pointcut використовується для вибору тільки тих об'єктів, які є екземплярами класів TwoDShape, Circle або Square. Основний метод задає TRACELEVEL, инициализирует трасування виконання програми і запускає основний метод прикладу.

Малюнок 4. Певний аспект трасування

На малюнку 5 показана частина вихідних даних для даного прикладу. Зверніть увагу, що виводиться інформація про всі об'єкти. Це частина методу toString кожного об'єкта. Рointcut (зріз точки) myClasses публікує об'єкт в advice (рекомендація), яка дозволяє легко додавати інформацію про об'єкт.

Малюнок 5. Приклад вихідних даних трасування

Які переваги АОП підходу до трасуванні в порівнянні з ручною вставкою коду трасування в потрібних місцях? Таких переваг декілька.

  • Весь вихідний код, пов'язаний зі ставленням трасування, зберігається в одному місці (два аспекти);
  • Код трасування легко вставляти та видаляти. Для цього з конфігурації конструкції видаляються аспекти;
  • Код трасування можна додати в будь-яке місце, навіть при додаванні до цільових класів нових методів. Це дозволяє усунути помилки програміста. При видаленні аспекту з конфігурації конструкції можна бути впевненим, що весь код трасування вилучений і нічого не пропущено;
  • Отримуємо повторно використовуваний аспект, який можна застосовувати і покращувати.

Контрактне або безпечне програмування

При створенні бібліотек широкого використання не можна бути впевненим у достовірності аргументів, переданих в методи. Необхідно перевірити аргументи до їх обробки логікою кожного методу. Це приклад безпечного програмування. Передбачається, що всі можливі помилки будуть витончено оброблятися.

Створимо аспект для перевірки всіх аргументів в публічних методах. Перш за все створимо pointcut (зрізи точок). Будемо використовувати pointcut myClass з попереднього прикладу і додамо pointcut для вибору конструкторів, які потребують перевірки аргументів, і методу відстані, який не повинен викликатися зі значенням NULL. На малюнку 6 показаний набір необхідних pointcut. Зверніть увагу, що другий pointcut визначає в якості мети pointcut екземпляр TwoDShape. Це означає, що цей pointcut вибирає в об'єктах тільки виклики методу відстані.

Малюнок 6. Pointcut (зрізи точок) для перевірки аргументів

Нарешті, необхідно додати відповідні advice (рекомендації). Для простоти виведемо повідомлення при виявленні неправильного аргументу, а потім, в разі theconstructor, змінимо фактичні значення на нуль і проіґноруймо виклик методу відстані при передачі значення NULL. На малюнку 7 показані два таких елемента advice.

Малюнок 7. Елемент advice (рекомендації) перевірки аргументів

При спробі виконати наступну пропозицію:

Circle c3 = new Circle (3.0,2.0, -2.0);

в програмі, отримує наступне повідомлення:

З повідомленнями про помилки можна зробити набагато більше, якщо в них вказати точну номер рядка і ім'я вихідного файлу, але цей приклад служить не для цього.

У великих проектах, де багато класів і використовується кілька інтерфейсів, код для аспектів, що реалізують перевірку аргументів, можна організувати в окремій папці. Можу уявити кілька способів організації аспектів для їх простий ідентифікації та обслуговування. При створенні системи для внутрішніх цілей можна використовувати конфігурацію внутрішньої конструкції, при створенні системи для зовнішніх клієнтів - конфігурацію, що включає аспекти. Eclipse AJDT дозволяє просто створювати нові конфігурації конструкцій.

Аспекти і шаблони проектування

jan / AODPs / можна завантажити код, який реалізує шаблони групи GOF.5. 5 Ніколас Лесецкі (Nicholas Lesiecki) також писав про шаблони проектування для Web-сайту IBM developerWorks. 6 У його статті наводиться більш повний опис в порівнянні з цією статтею.

Розглянемо дуже простий приклад реалізації стандартного шаблону проектування Adapter в AspectJ.

На малюнку 8 показана діаграма Unified Modeling Language (UML) для шаблону Adapter. У цьому шаблоні клієнту потрібно служба і для цього створюється запит. Може бути багато постачальників служби, і кожен з них може мати різне ім'я служби або будь-які нестандартні вимоги, яких слід дотримуватися запитуючої стороною. Гарне об'єктно-орієнтоване проектування передбачає, що запит служби инкапсулируется в цільової інтерфейс, програму для інтерфейсу і, при необхідності, створює адаптер, що діє як посередник між клієнтом і службою (на діаграмі це Adaptee).

Малюнок 8. Шаблон адаптера

Підхід з використанням адаптера здається цілком розумним і доцільним. Але що робити в разі застарілої системи, яка не призначена для роботи з шаблонами або адаптерами? Розробники цих систем не реалізували можливість майбутнього зміни. Виклики служби можуть бути розкидані по всьому додатку. Як реалізувати нову поліпшену службу? Без аспектів, ймовірно, доведеться відновлювати вихідний код системи, шукати всі виклики служби, розробляти адаптер і реалізовувати шаблон Adapter. Залежно від кількості викликів старої служби це може стати досить трудомістким завданням. Відновлення вихідного коду і його поліпшення - гідна мета, але дозволити таку розкіш можна далеко не завжди. Доводиться задовольнятися виділенням коду, це найкраще, що можна зробити в стислі терміни.

В цьому випадку можна створити АОП версію шаблону Adapter, негайно вирішальну проблему і дозволяє зробити крок вперед до більш організованою і краще спроектованої системі.

На малюнку 9 показаний простий клієнт, який використовує службу. Служба повертає відстань від однієї точки до поточного об'єкта Client.

Малюнок 9. Простий клієнт

Інтерфейс для служби описує окремий метод:

Новий покращений постачальник служби має метод з дещо відмінним назвою та іншими параметрами. Його інтерфейс:

Нам потрібно створити адаптер, який розташовується між викликами старої служби, отримує відповідні аргументи для нової служби, викликає нову службу і повертає результати клієнту. Клієнт при цьому не змінюється. Аспект, необхідний для цього, показаний на малюнку 10.

Малюнок 10. Аспект Adapter для виклику нової служби

Зверніть увагу на простоту аспекту. Оголосимо pointcut для ідентифікації кожного виклику методу useService вихідної служби. Потім скористаємося advice (рекомендацією) around для заміни цього виклику на виклик нової служби після вилучення з викликає клієнта необхідної інформації.

Такий підхід має свої переваги і недоліки. По-перше, за допомогою цього одного простого аспекту можна зробити зміни у всьому коді програми. Також можна инкапсулировать відношення для виклику служби з одного місця. Тепер, якщо нова служба буде замінена на новішу, потрібно буде змінити тільки код аспекту. У цьому полягає перевага для більш надійної системи.

Основний недолік полягає в тому, що старий клієнт як і раніше залишається в системі, навіть якщо він не використовується. При наявності часу (якого, схоже, немає ніколи) найбільш ймовірно, що доведеться повернутися і відновити вихідний код системи для використання стандартного шаблону Adapter. Найменше, можна змінити метод useService вихідної служби на код, який повертає фіктивне значення, наприклад, 0,0, так як цей метод ніколи не буде викликатися.

Застосування на професійному рівні

До сих пір розглядалися чітко обмежені, але все ж корисні приклади застосування АОП. Виникає питання, а наскільки добре цей метод масштабується. Зазначу і коротко опишу один відомий приклад. Більш докладний розгляд зажадає написання іншої статті.

Можливо, деякі з вас знайомі з Spring Framework, 7 представляє собою прикладну інфраструктуру, яка підтримує розробку корпоративних додатків. Spring Framework надає багаторівневу середу J2EE для створення комплексних корпоративних додатків. АОП є однією з основних технологій, що використовуються в Spring. У співтоваристві Spring розроблена власна аспектно-орієнтована реалізація, що дозволяє застосовувати до коду комплексну логіку під час виконання, а не під час компіляції, як це відбувається в AspectJ. Але при цьому є функції інтеграції, що дозволяють легко включити AspectJ в Spring Framework.

В даний час Spring використовується в безлічі організацій для створення корпоративних додатків, які краще спроектовані і вимагають менше часу на розробку. За моїми оцінками, це чудовий приклад того, як можна застосовувати аспекти до реальних проблем. 8

Що можна зробити далі?

На мій погляд, в майбутньому АОП стане частиною набору інструментальних засобів розробника програмного забезпечення. Не знаю, доберемося ми до моменту, коли будемо створювати системи з використанням АОП в якості основного механізму проектування, але думаю, ми знайдемо способи поліпшити за допомогою аспектів існуючі об'єктно-орієнтовані проекти. Прискорити процес можуть кілька моментів.

По-перше, необхідні стандартні стабільні реалізації АОП. Цей процес вже почався. Версія 5 AspectJ об'єднує два найбільш популярних мови АОП Java - AspectJ і AspectWerkz. Також допомагають стандартні реалізації в інших мовах, наприклад, C ++.

По-друге, необхідно розробити метрики, що дозволяють обґрунтовувати ефективність застосування АОП до окремих систем. Наприклад, чи буде повторна реалізація шаблонів проектування з використанням АОП краще стандартних об'єктно-орієнтованих шаблонів? В яких випадках шаблони краще, а в яких - ні? Які необхідно створити показники для отримання інформації про такі метриках і для їх розробки? Час простого підходу, коли об'єктно-проектована (або будь-яка інша обрана вами) система вважалася хорошою, (), пройшло. Необхідно створити проект і рішення по реалізації на основі емпіричних даних. 9

По-третє, необхідно продовжити розробку інструментів, що підтримують АОП. Я радий повідомити, що новий AJDT для Eclipse являє собою чудовий набір інструментів. У цих інструментах поліпшена підтримка, необхідна для ефективного і раціонального використання аспектів. Інструментальні засоби повинні також підтримувати нову технологію, яка використовує аспекти.

Аспекти повинні підтримуватися. Вони поки що не стали частиною основних додатків, але з кожним днем ​​стають до цього все ближче. Я рекомендую ознайомитися з аспектами і уважно вивчити їх.

Примітки

3 Група GOF - Еріх Гамма (Erich Gamma), Річард Хелм (Richard Helm), Ральф Джонсон (Ralph Johnson) і Джон Вліссідес ​​(John Vlissides), які написали книгу Design Patterns. Це основна книга про шаблони проектування;

7 Якщо читачі, які використовують АОП, захочуть поділитися своїм досвідом і надати дані для мого дослідження метрик АОП, звертайтеся до мене.

Схожі статті