Концептно-ориентированное программирование (КОП) основано на использовании
концептов в качестве основной программной конструкции, тогда как
аспектно-ориентированое программирование (АОП) использует аспекты. Хотя это две практически полностью различные программные парадигмы, исходящие из своих собственных общих предположений, все-таки интересно выяснить, как они связаны. Как обычно существует множество различных размерностей, вдоль которых можно сравнить два подхода. Здесь однако мы рассмотрим только один весьма общий вопрос, который демонстрирует насколько отличаются эти два подхода.
Предположим, что система состоит из нескольких модулей таких как классы (ООП), концепты (КОП) или аспекты (АОП). Каждый модуль включает состояние и функции, и они могут использовать друг друга тем или иным способом. Модули разрабатываются и добавляются в систему последовательно так, что начальные модули ничего не знают о модулях, которые будут добавлены позже, тогда как новые модули знают о уж существующих и могут использовать их функции. В нашем примере можно предположить, что есть один начальный модуль Base (базовый класс или базовый концепт) и несколько новых модулей Ext1, Ext2 and Ext3 (расширения), которые разработаны позже и могут использовать функции Base. Модуль Base называется независимым тогда как другие три модуля от него зависят.
Предположим, что модуль Base содержит некоторые общие функции, которые должны быть автоматически распределены среди других модулей, например, Ext1, Ext2 и Ext3, путем неявного изменения их поведения. В АОП говорится, что эти общие функции впрыскиваются из исходного модуля Base в целевые модули Ext1, Ext2 и Ext3. Однако, самый важный момент состоит в том, что описание таких инъекций является частью базового модуля, т.е. Base указывает в своем определении целевые модули, куда его функции должны быть впрыснуты. Это может быть записано следующим образом:
module Base inject_into Ext1, Ext2, Ext3 ...
Заметим, что можно определить модуль с его целями даже, если эти целевые модули еще не определены, т.е. мы используем ссылки на то, что будет добавлено в будущем.
В действительности, в АОП инъецируемые функции определяются с помощью кода, который называется применением (advice). Инъекция применений выполняется в специальные точки программы (join points), которые группируются в так называемые срезы (pointcut) посредством некоторого языка. Поэтому следующий код является более реалистичным, но это все равно не меняет природу демонстрируемого подхода:
aspect Base {
pointcut MyPointcut : Ext1::*, Ext2::*, Ext3::someMethod();
before : MyPointcut { print("Инъецируемая функция."); }
}
Этот аспект означает, что перед вызовом любого метода из указанного среза будет выполнено заданное применение, и напечатано сообщение.
В любом случае именно базовый модуль знает о существовании целевых модулей, тогда как целевые модули находятся в полном неведении относительно того, когда и как их поведение будет изменено. Другими словами, из определения нового модуля, скажем, Ext3, невозможно определить, будут ли его функции модифицированы из других модулей (аспектов). С другой стороны, если взять базовый модуль (аспект), то его определение включает описание всех целевых модулей, на которые он будет влиять.
В отличие от этого, КОП использует обычное направление для таких зависимостей, когда сами целевые модули указывают, как их поведение должно быть изменено исходными модулями. Другими словами, базовый модуль не ведает, где и как его общие функции инъецируются или используются другим способом, поскольку именно целевые модули ответственны за указание исходного (базового) модуля, который должен неявно изменить их поведение. Это может быть записано следующим образом:
module Ext1 injects_from Base ...
module Ext2 injects_from Base ...
module Ext3 injects_from Base ...
В действительности, КОП использует
отношение включения, которое обобщает наследование (точно так же, как концепты обобщают классы), так что предыдущий код записывается так:
concept Ext1 in Base ...
concept Ext2 in Base ...
concept Ext3 in Base ...
Включение означает вложение в базовое пространство или среду, которое неявно влияет на поведение данного концепта, т.е. среда (базовый концепт) может менять функции его внутренних компонент. При этом каждая внутренняя компонента должна указать базовую среду, где она хочет жить. При определении каждого нового концепта, необходимо предоставить для него среду путем включения в какой-то существующий концепт. В отличие от этого, в АОП именно сама среда должна перечислить все внутренние компоненты, в которые ее функции будут внедрены.
Таким образом мы видим, что КОП и АОП используют противоположные направления для объявления зависимости инъекции кода. В КОП используется общепринятое направление (на самом деле такое же, как и в ООП), когда базовые модули могут разрабатываться независимо от того, что будет добавлено позже. В АОП инъекция кода аналогично ссылкам в будущее, т.е. на то, что еще не существует. Это отличие описывается в
этой статье, раздел 9, стр. 39, рис. 17.
--
http://conceptoriented.com