Re: [abc] Open modules revised

From: Neil Ongkingco <neil.ongkingco@keb.ox.ac.uk>
Date: Wed Mar 29 2006 - 17:44:47 BST

I agree with the use of abstract pointcuts as interfaces in the module
specifications. I think the use of aspects that contain nothing but such
named pointcuts (like XPIs) will mesh well with the current state of
open modules. It would allow one to write aspects without knowing too
much of the internal details of the classes to which it will apply.
CaesarJ also has a way of separating the aspect implementation from its
binding.

If, however, all aspect-base interactions are to occur through such
interfaces, it would be rather difficult to write inherently invasive
aspects for debugging and tracing (as you would have to explicitly
expose the points to which these aspects would apply). As many of the
current uses of AOP seem to revolve around such aspects, I believe that
any method for aspect composition would have to allow for such aspects
to be written easily. Invasive aspects are the main motivation for the
more 'dangerous' features (such as open and expose) of the openmod
extension.

There are some aspects of openmod that I am rather uncomfortable with.
The way open modules does specialization (i.e. changing the interface)
is upwards, using open and constrain. Julian has pointed out previously
that this is opposite to the direction of class specialization done
through subclassing. I have been thinking of a way to the specialize the
interface downwards (module m1 c/extends m2{...}, the effect being
similar to open and constrain) but doing so would force me to throw
precedence out the window (or at least find another way of specifying it).

Another is the fact that openmod is a pure source-level compile-time
construct, primarily because pointcuts are pure compile time structures
as well. They are dissimilar from method signatures in that once all the
aspects have been woven, pointcuts disappear (only their residues
remain). There might be some advantages if we could compile modules into
something like java interfaces, with the pointcuts still recoverable.
This does bring up the issue of how to represent pointcuts. Perhaps it
would be similar to what ajc does to support separate compilation.

Neil

Eric Bodden wrote:
> Hi all!
>
> I just wanted to report on a few insights and ideas I got from attending the Software Composition workshop at ETAPS. Besides the fact that they had much more presentations which were interesting to me than I originally thought, in the end we had a longer discussion about the possible conflicting ideas of AOP and component software (aspects breaking up components and inspecting their internals, not adhering to their public interface).
>
> It turned out that particularly for this community Open Modules is apparently *the* mechanism that is necessary for aspects to interact with components at all in a sound way. The overall consensus was that without such modules aspects just break encapsulation and one really cannot speak about a piece component software system any more.
>
> A talk by Eric Tanter inspired even more the way I thought about Open Modules: Thy proposed a mechanism for defining "Context aware aspects". This allows to expose context to an aspect (similar to "let" - and indeed some of there examples mapped quite well to a Tracematch with "let") and to have the aspect reconfigure its behavior depending on this context.
>
> The idea I got now was to combine this with the notion of Open Modules. The problem I see with OM right now is that yes, they do provide a public interface for a module which aspects can access, however any aspect using that interface still has to be at least somewhat aware of the internals of *every* module it advises. This is because the module spec only restricts the set of visible joinpoints, not more. What I propose now, looks as follows... (may sound a bit wild, but - hey - Gregor said, whe should go wild! :-) )
>
> 1.) An aspect consists of a public interface and an implementation.
> 2.) The aspect interface consists only of abstract pointcuts and (optionally) some temporal constraints over those abstract pointcuts in the form of a tracematch or something equivalent. The abstract pointcuts say what this aspect *requires* to apply to a module and the constraints say in *what order* the related joinpoints may occur in order to have the aspect function correctly.
> 3.) Any advice in the aspect may only use combinations (in the form of Boolean cominations, cflow and tracematches) of those abstract pointcuts - no concrete pointcuts at all!
>
> By providing such an interface, the whole abstract control flow and data flow of the aspect should be pretty regorously defined. However, of course the aspect does not do anything yet. That's where modules come into play...
>
> Now each module, an aspect should apply to explicitly states, what each abstract pointcut means *in the context of this module*. The simplest statement could be that the module is not interested in the aspect and hence all pointcut are empty. This could possibly be the default. However, the module can conretize the pointcut by advertising or exposing concrete pointcuts and at the same time binding those to the abstract ones. If the set of exposed pointcuts adheres to the interface of the aspect can be checked via the constraints of the aspect interface.
>
> Ok, maybe sounds nice, but what does it buy us? Well, the good thing in my p.o.v. about this approach is that you not only have a mechanism of hiding the internals of a component from aspects and exposing only what you need. Also, you can not have a truly GENERIC aspect, which can be deployed onto any given module that is compatible the aspect's interface. That way, the module can really be replaced by another one that shares the same interface. Moreover, also the aspect can be replaced by another one that shares the same aspect interface.
>
> An example:
>
> Imagine you have a generic observer aspect based on tracematches. So here we only say that we have types which we call observers and subjects and pointcuts which we call register, unegister and update. Then we declare a method which is required to be available on any module that wishes to use this aspects. Also we give temporal constraints which say in what temporal relations those three pointcuts are. (this is optional but recommended)
>
> aspect ObserverPattern {
>
> //this is the exposed part
> interface Observer{}
> interface Subject{}
>
> //feature does not exist yet, but was proposed as a lacking feature
> //in the BOF on reusable aspects
> abstract typepattern observers;
> abstract typepattern subjects;
>
> declare parents: observers extends Observer;
> declare parents: subjects extends Subject;
>
> abstract pointcut register(Observer o, Subject s);
>
> abstract pointcut unregister(Observer o, Subject s);
>
> abstract pointcut update(Subject s);
>
> //need this in order to decouple the call to notify
> //from the internals of the concrete observer;
> //the method must be provided by the module!
> require {
> void notify(Observer,Subject);
> }
>
> //temporal constraints on abstract pointcuts
> //never unregister(o,s) before register(o,s), etc ...
>
> //actual aspect implementation
> //here we can use any of the above pointcuts but no concrete ones
>
> tracematch(Observer o, Subject s) {
>
> sym reg after: register(o,s);
> sym ureg after: unregister(o,s);
> sym upd after: update(s);
>
> reg upd {
>
> module.notify(o,s);
>
> }
>
> }
>
> }
>
> So a module which uses this aspect could no look as follows:
>
> module WantsToBeObserved {
>
> apply ObserverPattern {
>
> //this does th actual binding between what the aspect
> //wants to do and what this means for this module
> typepattern observers: com.org.whatever.Observer+;
> typepattern subjects: com.org.whatever.Subject+;
>
> pointcut register(Observer o, Subject s):
> expose call(* com.org.whatever.Observer.register(
> com.org.whatever.Subject)) && target(o) && args(s);
> pointcut unregister(Observer o, Subject s):
> expose call(* com.org.whatever.Observer.deregister(
> com.org.whatever.Subject)) && target(o) && args(s);
> pointcut update(Subject s):
> advertise call(* com.org.whatever.Subject.add*(..))
> && target(s);
>
> notify(com.org.whatever.Observer o,
> com.org.whatever.Subject s) {
> o.wasUpdated(s);
> }
>
> }
>
> }
>
> So the benefit in this situation is that the aspect does not care about how an observer or subject is implemented AT ALL! It only says that there exist pointcuts which must match and in what order they must match. Also, the aspect can only call operations on the module, i.e. on the exposed public interface. The module itself can and must then state what this operation actually means for this module.
>
> That way you still have the benefit of being able to consistently implement a crosscutting concern, plus you do not break encapsulation plus the aspect becomes truly generic plus you can verify if it is used correctly (by the constraints).
>
>
> So if you read up till here, thanks for taking the time! I woul of course be grateful for any comments. I really like the idea, but maybe I am missing something.
>
> Eric
>
> --
> Eric Bodden
> Sable Research Group
> McGill University, Montréal, Canada
>
>
>
Received on Wed Mar 29 17:44:50 2006

This archive was generated by hypermail 2.1.8 : Tue Mar 06 2007 - 16:13:27 GMT