Програмно-орієнтоване програмування проти об'єктно-орієнтованого програмування


199

Як і більшість розробників тут і в усьому світі, я вже багато років розробляю програмні системи з використанням об'єктно-орієнтованого програмування (OOP). Отже, коли я читаю, що аспектно-орієнтоване програмування (AOP) вирішує багато проблем, які традиційний OOP не вирішує повністю або безпосередньо, я призупиняюсь і думаю, чи це реально?

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

Хтось має відповідь?


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

Відповіді:


323

Чому "проти"? Це не "проти". Ви можете використовувати програмування, орієнтоване на аспекти, у поєднанні з функціональним програмуванням, але також у поєднанні з об'єктно-орієнтованим. Це не «проти», це «Аспект - орієнтоване програмування з об'єктно - орієнтованого програмування».

Для мене 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, щоб створити так багато проблем, погано використовувати це все. Однак якою технологією не можна користуватися? Ви можете зловживати інкапсуляцією даних, ви можете зловживати спадщиною. Практично кожну корисну програмувальну технологію можна зловживати. Розглянемо мову програмування настільки обмежено, що вона містить лише функції, якими не можна зловживати; мова, де функції можна використовувати лише так, як вони були спочатку призначені для використання. Така мова була б настільки обмеженою, що її можна сперечатися, якщо її навіть можна використовувати для програмування у реальному світі.


4
Журнал видається одним із конкретних прикладів, коли AOP не призводить до дії на відстані. Наразі Вікіпедія є прикладом використання аспекту для таких речей, як перевірки безпеки, які дійсно змушують програму протікати набагато більше, щоб зрозуміти.
kizzx2

7
@ kizzx2: Чудовий момент ведення журналу, насправді - це найкращий приклад, який я бачив на сьогоднішній день сили АОП, не знаючи багато про АОП. Дякую, що поділились!
промахи

@Mecki, Ваш приклад надто спрощений і не відображає загального випадку використання. У вашому прикладі Display.updateаргументів не бере. Що робити, якщо нам потрібно передати аргументи (наприклад, зазвичай для logфункції потрібен messageпараметр)? Хіба нам тоді не потрібно було б додати багато кодових шаблонів, щоб зробити це AOP способом?
Pacerier

3
@Pacerier Мій приклад спрощений, тому що ТАК не є навчальним форумом. Я щойно відповідав на запитання запитувача, напевно, набагато детальніше, ніж треба було б. Якщо ви хочете дізнатися більше про AOP, спробуйте прочитати деяку документацію програміста, і якщо у вас є детальне запитання, чому б не задати його тут? Ні, не в коментарі, перейдіть і створіть нове запитання, тому що саме про це так. Я впевнений, що хтось зможе розвіяти ваші сумніви у відповіді.
Mecki

2
@Pacerier Вибачте, але я не бачу вашої точки зору. Дивіться тут: stackoverflow.com/a/8843713/15809 Цей код реєструє кожен виклик до кожного відкритого методу, включаючи всі типи та значення аргументів методу. Ви пишете це рівно один раз, і до будь-якого методу додається нульовий код котла, це просто код, який відображено у відповіді.
Mecki

29

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

Ви не повинні бачити AOP як заміну OOP, скоріше як приємне доповнення, що робить ваш код більш чистим, вільно пов'язаним та орієнтованим на бізнес-логіку. Отже, застосовуючи AOP, ви отримаєте 2 основні переваги:

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

  2. класи є більш чистими, оскільки вони містять код лише для їх основного питання (або основної функціональності), а вторинні проблеми перенесені на аспекти.


27

OOP і AOP не є взаємовиключними. AOP може бути хорошим доповненням до OOP. AOP особливо зручний для додавання стандартних кодів, таких як реєстрація, відстеження продуктивності тощо, до методів, не засмічуючи код методу цим стандартним кодом.


10

Я думаю, що на це питання немає загальної відповіді, але слід зазначити одне, що АОП не замінює ООП, а додає певні функції декомпозиції, які стосуються так званої тиранії домінуючого складу ( 1 ) (або перехресних проблем).

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

Одного разу Gregor Kiczales виступив із цікавою вступною бесідою про AOP на Google Tech Talks, яку рекомендую переглянути: Програмування, орієнтоване на аспекти: Радикальні дослідження в модульності .


8

Перш за все AOP не замінить OOP. AOP поширює OOP. Ідеї ​​та практики OOP залишаються актуальними. Хороший дизайн об'єкта, ймовірно, полегшить його розширення з аспектами.

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

Кілька динамічних мов, таких як Ruby і Python, мають мовні конструкції, як міксин, які вирішують ті самі проблеми. Це схоже на AOP, але краще інтегрується в мову.

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

Я не думаю, що вам доведеться навчитися абсолютно новій парадигмі, щоб використовувати AOP. Ідеї ​​цікаві, але повільно поглинаються наявними інструментами та мовами. Просто будьте в курсі та спробуйте ці інструменти.


1

AOP - нова парадигма програмування, що займається цією концепцією. Аспект - це програмне забезпечення, яке реалізує конкретну нефункціональну частину програми.

Я думаю, що ця стаття є хорошим місцем для початку з програмування, орієнтованого на аспекти: http://www.jaftalks.com/wp/index.php/introduction-to-aspect-oriented-programming/


1

Я запізнююсь на це питання, але це одна з моїх улюблених тем, тому дозвольте мені поділитися своєю думкою.

OOP використовується в основному для організації вашої бізнес-логіки, тоді як AOP допомагає організувати ваші нефункціональні речі, такі як аудит, ведення журналів, управління транзакціями, безпека тощо

Таким чином ви можете роз’єднати свою логіку бізнесу з не вигаданою логікою, яка робить код чистішим.

Перевага Otter полягає в тому, що ви можете застосовувати поради (наприклад, аудит) дуже послідовно, не застосовуючи жодного інтерфейсу, який дає велику гнучкість для модифікації, не торкаючись ділової логіки

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.