Чому "проти"? Це не "проти". Ви можете використовувати програмування, орієнтоване на аспекти, у поєднанні з функціональним програмуванням, але також у поєднанні з об'єктно-орієнтованим. Це не «проти», це «Аспект - орієнтоване програмування з об'єктно - орієнтованого програмування».
Для мене AOP - це якесь "метапрограмування". Все, що робить AOP, можна зробити і без цього, просто додавши більше коду. AOP просто економить при написанні цього коду.
У Вікіпедії є один з найкращих прикладів цього метапрограмування. Припустимо, у вас є графічний клас із безліччю методів "set ... ()". Після кожного встановленого методу дані графіки змінювались, таким чином графіка змінювалася і, таким чином, графіку потрібно оновлювати на екрані. Припустимо, щоб перефарбувати графіку, потрібно зателефонувати "Display.update ()". Класичний підхід - це вирішити, додавши більше коду . В кінці кожного набору методів ви пишете
void set...(...) {
:
:
Display.update();
}
Якщо у вас є три методи встановлення, це не проблема. Якщо у вас 200 (гіпотетичні), додавати це всюди стає боляче. Крім того, коли ви додаєте новий метод встановлення, ви повинні бути впевненим, що не забудьте додати це до кінця, інакше ви просто створили помилку.
AOP вирішує це, не додаючи тонни коду, замість цього ви додаєте аспект:
after() : set() {
Display.update();
}
І це все! Замість того, щоб писати код оновлення самостійно, ви просто повідомте системі, що після досягнення пункту set (), він повинен запустити цей код, і він запустить цей код. Не потрібно оновлювати 200 методів, не потрібно переконуватись, що ви не забудете додати цей код до нового методу set. Крім того, вам просто потрібна точка:
pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);
Що це означає? Це означає, що якщо метод називається "set *" (* означає, що будь-яке ім'я може слідувати після набору), незалежно від того, що метод повертає (перша зірочка) або які параметри він приймає (третя зірочка), і це метод MyGraphicsClass і це клас є частиною пакету "com.company. *", то це набір () пункту. І наш перший код говорить " після запуску будь-якого методу, який є заданою точкою, запустіть наступний код".
Подивіться, як AOP тут елегантно вирішує проблему? Насправді все, що описано тут, можна зробити під час компіляції. Препроцесор AOP може просто змінити ваше джерело (наприклад, додати Display.update () до кінця кожного методу встановлення заданих пунктів), перш ніж навіть компілювати сам клас.
Однак цей приклад також показує один із великих недоліків АОП. AOP насправді робить щось, що багато програмістів вважають " Анти-Шаблоном ". Точна схема називається " Дія на відстані ".
Дія на відстані - це антидіаграма (визнана поширена помилка), в якій поведінка в одній частині програми дико змінюється на основі складних або неможливих для ідентифікації операцій в іншій частині програми.
Як новачок у проекті, я можу просто прочитати код будь-якого набору методів і вважати його порушеним, оскільки він, здається, не оновлює дисплей. Я не бачу , просто подивившись на код набору методів, що після його виконання, якийсь інший код буде "магічно" виконаний для оновлення дисплея. Я вважаю це серйозним недоліком! Внесення змін до методу, можуть бути введені дивні помилки. Подальше розуміння потоку коду коду, де певні речі, здається, працюють правильно, але не очевидно (як я вже сказав, вони просто магічно працюють ... якось), насправді важко.
Оновлення
Просто для уточнення цього: У деяких людей може скластись враження, я кажу, що АОП - це щось погане, і його не слід використовувати. Це не те, що я говорю! AOP насправді є чудовою особливістю. Я просто кажу "Використовуй обережно". AOP спричинить проблеми лише в тому випадку, якщо ви змішаєте звичайний код та AOP для того ж аспекту . У наведеному вище прикладі маємо Аспект оновлення значень графічного об'єкта та фарбування оновленого об’єкта. Це насправді єдиний аспект. Кодування половини його як звичайного коду, а інша половина як аспекту - це те, що додає проблеми.
Якщо ви використовуєте AOP для зовсім іншого аспекту, наприклад, для ведення журналів, ви не зіткнетеся з проблемою антидіаграми. У цьому випадку новачок у проекті може задатися питанням "звідки беруться всі ці повідомлення журналу? Я не бачу жодного виводу журналу в коді", але це не є величезною проблемою. Зміни, які він вносить до логіки програми, навряд чи порушать об'єкт журналу, а зміни, внесені до засобу журналу, навряд чи порушать його логіку програми - ці аспекти повністю розділені. Використання AOP для ведення журналу має перевагу в тому, що ваш програмний код може повністю зосередитися на тому, щоб робити все, що він повинен робити, і ви все одно можете мати складний журнал, не маючи ваш код скрізь сотнями повідомлень журналу скрізь. Крім того, коли буде введено новий код, в потрібний час з потрібним вмістом з’являться повідомлення з чарівним журналом.
Тож хорошим використанням AOP у моєму прикладі було б завжди входити в журнал, якщо якесь значення було оновлено за допомогою встановленого методу. Це не створить антидіаграму і навряд чи колись стане причиною будь-якої проблеми.
Можна сказати, якщо ви легко можете зловживати AOP, щоб створити так багато проблем, погано використовувати це все. Однак якою технологією не можна користуватися? Ви можете зловживати інкапсуляцією даних, ви можете зловживати спадщиною. Практично кожну корисну програмувальну технологію можна зловживати. Розглянемо мову програмування настільки обмежено, що вона містить лише функції, якими не можна зловживати; мова, де функції можна використовувати лише так, як вони були спочатку призначені для використання. Така мова була б настільки обмеженою, що її можна сперечатися, якщо її навіть можна використовувати для програмування у реальному світі.