Concept-oriented programming (CoP) is based on using concepts as the main programming construct while aspect-oriented programming (AOP) uses aspects. Although they are two almost completely different programming paradigms proceeding from their own general assumptions, it is still interesting to figure out how they relate. As usual there exist many alternative dimensions along which two methods can be compared. But here we consider only one very general issue which demonstrates how different these two approaches are.
Let us assume that the system consists of several modules such as classes (OOP), concepts (CoP) or aspects (AOP). Each module contains some state and/or functionality and they can use each other in one or another way. Modules are developed and added to the system sequentially so that initial modules are unaware of the modules that will be added later while new modules know the existing ones and can use their functions. In our example we can assume that there is one initial module called Base (base class or base concept) and several new modules Ext1, Ext2 and Ext3 (extensions) which are developed later and can use functions of Base. We say that Base is independent module while the other three modules depend on it.
Assume now that module Base contains some common functionality that needs to be automatically spread over some other modules such as Ext1, Ext2 and Ext3 by implicitly modifying their behaviour. In AOP, this functionality is said to be injected from the source module Base into target modules Ext1, Ext2 and Ext3. However, the most important thing is that the description of injection is part of the base module, i.e., module Base indicates the target modules where its functions have to be injected. This could be written as follows:
module Base inject_into Ext1, Ext2, Ext3 ...
Notice that we can define a module with its injection targets even if these targets are not yet defined, i.e., we use a kind of forward links to something unknown that will be added later.
In fact, in AOP injected code is defined using pieces of code called advices. And injection of advices is performed into special points during program execution called join points which are grouped into so called point cuts by means of some language. Therefore the following code is more realistic (although it is not any existing language) but it does not change the nature of the AOP approach we want to demonstrate:
aspect Base {
pointcut MyPointcut : Ext1::*, Ext2::*, Ext3::someMethod();
before : MyPointcut { print("Injected intermediate function."); }
}
This aspect means that before any method described in the pointcut is called, the specified advice will automatically intervene and print something.
In any case, it is the base module that knows the target modules while target modules are completely unaware of when and how their behaviour will be changed. In other words, from the definition of a new module, say, Ext3, it is not possible to determine whether its functions will be modified by other modules (aspects). On the other hand, if we take a base module (aspect) then its definition contains a specification of all target modules that will be influenced.
In contrast, CoP uses the conventional direction for this dependence where target modules themselves specify how their behaviour has to be changed by source modules. In other words, a base module is completely unaware where and how its common functions are injected or otherwise used because it is a responsibility of target modules to specify source (base) module that has to implicitly change their behaviour. This can be written as follows:
module Ext1 injects_from Base ... module Ext2 injects_from Base ... module Ext3 injects_from Base ...
In fact, CoP uses inclusion relation which generalizes inheritance (just as concepts generalize classes) so the previous code is written as follows:
concept Ext1 in Base ... concept Ext2 in Base ... concept Ext3 in Base ...
Inclusion means putting into the base space or environment which will implicitly change the behaviour of this concept, i.e., an environment (base concept) can affect functionality of its internal components. Yet it is the responsibility of internal components to specify a base environment where they want to live. As a new concept is developed, we need to provide an environment for it by including into some existing concept. In contrast, in AOP an environment has to specify all internal components into which its functions will be injected.
Thus we see that CoP and AOP use opposite directions for declaring code injection dependencies. In CoP the conventional direction is used (actually, the same as in OOP) where base modules can be developed independently of what will be added later while in AOP code injection is analogous to forward links to what may does not exist yet. This distinction is described in this paper, Section 9, page 39 (Fig. 17).
