Аспектно-ориентированное программирование против объектно-ориентированного программирования

199

Как и большинство разработчиков здесь и во всем мире, я разрабатывал программные системы с использованием методов объектно-ориентированного программирования (ООП) в течение многих лет. Поэтому, когда я читаю, что аспектно-ориентированное программирование (AOP) решает многие проблемы, которые традиционные ООП не решают полностью или напрямую, я замираю и думаю, реально ли это?

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

У кого-нибудь есть ответ?

yeradis
источник
7
Все ответы были очень хорошими, это идеальный вариант для одного отредактированного сообщества ответа, который бы объединял их все. Все говорят одно и то же, но по-разному и используют разные примеры, которые увеличивают общую ценность
Винко Врсалович

Ответы:

323

Почему "против"? Это не "против". Вы можете использовать Аспектно-ориентированное программирование в сочетании с функциональным программированием, но также в сочетании с Объектно-ориентированным. Это не «против», это «Аспектно-ориентированное программирование с объектно-ориентированным программированием».

Для меня АОП - это своего рода «метапрограммирование». Все, что делает AOP, также может быть сделано без добавления кода. АОП просто спасает вас писать этот код.

В Википедии есть один из лучших примеров этого метапрограммирования. Предположим, у вас есть графический класс с множеством методов set ... (). После каждого метода установки данные графики менялись, поэтому графика менялась, и, следовательно, графика должна обновляться на экране. Предположим, что для перерисовки графики вы должны вызвать «Display.update ()». Классический подход состоит в том, чтобы решить эту проблему, добавив больше кода . В конце каждого метода набора вы пишете

void set...(...) {
    :
    :
    Display.update();
}

Если у вас есть 3 set-метода, это не проблема. Если у вас есть 200 (гипотетически), становится больно добавлять это везде. Кроме того, всякий раз, когда вы добавляете новый метод set, вы должны быть уверены, что не забыли добавить его в конец, иначе вы просто создали ошибку.

АОП решает это без добавления тонны кода, вместо этого вы добавляете аспект:

after() : set() {
   Display.update();
}

И это все! Вместо того, чтобы писать код обновления самостоятельно, вы просто сообщаете системе, что после достижения точки set () она должна запустить этот код и запустить этот код. Не нужно обновлять 200 методов, не нужно обязательно добавлять этот код в новый метод set. Кроме того, вам просто нужен pointcut:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

Что это значит? Это означает, что если метод называется «set *» (* означает, что после set может следовать любое имя), независимо от того, что метод возвращает (первая звездочка) или какие параметры он принимает (третья звездочка), и это метод MyGraphicsClass, и это class является частью пакета "com.company. *", тогда это pointcut set (). И наш первый код говорит: « после запуска любого метода, который является заданным pointcut, запустите следующий код».

Посмотрите, как АОП элегантно решает проблему здесь? На самом деле все описанное здесь может быть сделано во время компиляции. Препроцессор AOP может просто изменить ваш источник (например, добавив Display.update () в конец каждого метода set-pointcut), прежде чем даже скомпилировать сам класс.

Тем не менее, этот пример также показывает один из больших недостатков АОП. AOP на самом деле делает то, что многие программисты считают « Anti-Pattern ». Точная схема называется « Действие на расстоянии ».

Действие на расстоянии - это антишаблон (общепризнанная распространенная ошибка), при котором поведение в одной части программы сильно меняется в зависимости от того, трудно или невозможно идентифицировать операции в другой части программы.

Как новичок в проекте, я мог бы просто прочитать код любого метода set и считать его неисправным, так как кажется, что он не обновляет отображение. Я не вижу просто глядя на код метода set, что после его выполнения какой-то другой код будет «магическим образом» выполняться для обновления отображения. Я считаю это серьезным недостатком! При внесении изменений в метод могут появиться странные ошибки. Дальнейшее понимание потока кода, в котором некоторые вещи работают правильно, но не очевидно (как я уже сказал, они просто волшебным образом работают ... как-то), действительно сложно.

Обновить

Просто чтобы прояснить это: у некоторых людей может сложиться впечатление, что я говорю, что АОП - это что-то плохое и не должно использоваться. Это не то, что я говорю! АОП на самом деле отличная особенность. Я просто говорю «Используйте это осторожно». AOP вызовет проблемы, только если вы смешаете обычный код и AOP для одного и того же аспекта . В приведенном выше примере у нас есть аспект обновления значений графического объекта и рисования обновленного объекта. Это на самом деле один аспект. Кодирование половины этого как нормального кода, а другая половина как аспекта - вот что добавляет проблему.

Если вы используете AOP для совершенно другого аспекта, например, для регистрации, вы не столкнетесь с проблемой анти-паттернов. В этом случае новичок в проекте может спросить: «Откуда берутся все эти сообщения журнала? Я не вижу никакого вывода журнала в коде», но это не большая проблема. Изменения, которые он вносит в программную логику, вряд ли сломают средство ведения журнала, а изменения, внесенные в средство ведения журнала, вряд ли нарушат его логику программы - эти аспекты полностью разделены. Преимущество использования AOP для ведения журнала заключается в том, что программный код может полностью сконцентрироваться на выполнении всего, что он должен делать, и вы все равно можете вести сложную запись в журнал, при этом ваш код не будет загроможден сотнями сообщений журнала повсюду. Кроме того, когда вводится новый код, сообщения с магическим журналом будут появляться в нужное время с нужным содержанием.

Таким образом, хорошим примером использования AOP в моем примере было бы всегда регистрировать, если какое-либо значение было обновлено с помощью метода set. Это не создаст анти-паттерн и вряд ли когда-либо станет причиной каких-либо проблем.

Кто-то может сказать, что если вы можете легко злоупотреблять AOP, создавая так много проблем, плохая идея использовать все это. Однако какой технологией нельзя злоупотреблять? Вы можете злоупотреблять инкапсуляцией данных, вы можете злоупотреблять наследованием. Практически все полезные технологии программирования могут быть использованы неправильно. Рассмотрим язык программирования настолько ограниченный, что он содержит только те функции, которыми нельзя злоупотреблять; язык, на котором функции могут использоваться только так, как они изначально были предназначены для использования. Такой язык будет настолько ограничен, что спорно, если он может быть даже использовать для реального мира программирования.

Mecki
источник
4
Ведение журнала является одним из конкретных примеров, когда AOP не приводит к действиям на расстоянии. В настоящее время, википедия как пример использования аспекта для таких вещей, как проверки безопасности, которые действительно делают программу намного более понятной.
kizzx2
7
@ kizzx2: На самом деле, большое замечание при ведении журнала - это лучший пример, который я когда-либо видел, - сила АОП, даже не зная об АОП. Спасибо, что поделился!
промахи
@Mecki, Ваш пример слишком упрощен и не отражает общий вариант использования. В вашем примере Display.updateне принимаются никакие аргументы. Что если нам нужно передать аргументы (например, обычно logфункция требует messageпараметра)? Разве нам не нужно было бы добавить много шаблонного кода, чтобы сделать это способом АОП?
Pacerier
3
@Pacerier Мой пример упрощен, потому что SO - это не учебный форум. Я просто отвечал на вопрос спрашивающего, возможно, гораздо более подробно, чем было бы необходимо. Если вы хотите узнать больше об АОП, попробуйте прочитать документацию для программистов, и если у вас есть подробный вопрос, почему бы не задать его здесь? Нет, не в комментарии, иди и создай новый вопрос, потому что это то, что SO. Я уверен, что кто-то сможет развеять ваши сомнения в ответе.
Меки
2
@Pacerier Извините, но я не понимаю вашу точку зрения. См. Здесь: stackoverflow.com/a/8843713/15809 Этот код регистрирует каждый вызов каждого открытого метода, включая все типы и значения аргументов метода. Вы пишете это ровно один раз, и к любому методу добавляется нулевой стандартный код, это просто код, показанный в ответе.
Меки
29

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

Вы не должны рассматривать AOP как замену OOP, а скорее как хорошее дополнение, которое делает ваш код более чистым, слабосвязанным и ориентированным на бизнес-логику. Таким образом, применяя АОП, вы получите 2 основных преимущества:

  1. Логика каждой проблемы теперь в одном месте, а не разбросана по всей базе кода.

  2. классы более чистые, поскольку они содержат код только для своей основной задачи (или основной функциональности), а второстепенные проблемы перенесены в аспекты.

nkr1pt
источник
27

ООП и АОП не являются взаимоисключающими. АОП может быть хорошим дополнением к ООП. AOP особенно удобен для добавления стандартного кода, такого как ведение журнала, отслеживание производительности и т. Д., В методы без засорения кода метода этим стандартным кодом.

Норберт Б.
источник
10

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

Это, безусловно, помогает в определенных случаях, пока вы контролируете инструменты и языки, используемые для конкретного проекта, но также добавляет новый уровень сложности в отношении взаимодействия аспектов и необходимости дополнительных инструментов, таких как AJDT, чтобы все еще понимать ваша программа

Грегор Кикзалес однажды дал интересную вводную лекцию о АОПЕ в Google Tech Talks , которые я рекомендую смотреть: Aspect Oriented Programming: Radical Исследование в модульности .

FHE
источник
8

Прежде всего АОП не заменит ООП. АОП расширяет ООП. Идеи и практики ООП остаются актуальными. Хороший дизайн объекта, вероятно, облегчит его расширение аспектами.

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

Пара динамических языков, таких как Ruby и Python, имеют языковые конструкции, такие как миксины, которые решают те же проблемы. Это очень похоже на АОП, но лучше интегрировано в язык.

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

Я не думаю, что вам придется выучить совершенно новую парадигму, чтобы использовать АОП. Идеи интересны, но постепенно усваиваются существующими инструментами и языками. Просто будьте в курсе и опробуйте эти инструменты.

Mendelt
источник
1

АОП - это новая парадигма программирования, связанная с этой концепцией. Аспект представляет собой программный объект, реализующий конкретную нефункциональную часть приложения.

Я думаю, что эта статья - хорошее место, чтобы начать с Аспектно-ориентированного программирования: http://www.jaftalks.com/wp/index.php/introduction-to-aspect-oriented-programming/

JafTalks
источник
1

Я опоздал на этот вопрос, но это одна из моих любимых тем, поэтому позвольте мне поделиться своим мнением.

ООП в основном используется для организации вашей бизнес-логики, в то время как АОП помогает организовать ваши нефункциональные вещи, такие как аудит, ведение журнала, управление транзакциями, безопасность и т. Д.

Таким образом, вы можете отделить свою бизнес-логику от вымышленной логики, которая делает код чище.

Преимущество выдры заключается в том, что вы можете применять рекомендации (например, аудит) очень последовательно, не реализуя интерфейс, который дает большую гибкость для модификации, не затрагивая бизнес-логику

GPopat
источник