www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - AOP in D

reply "Greg Vanore" <dazden at.dazden.dot.org> writes:
Okay, I've been playing with mixins, and they are definitely an interesting
feature.

To get better AOP implementation in D, though, we need some way of
dynamically accessing functions, like Java's RTTI ability.  I'm not saying
that this is the holy grail that we should aim for, per se, but at least
something like it.

For example, a simple dynamic proxy would be great.

class Proxy(T)
{
    Object invoke(T sourceObj, Method method, Object[] args)
    {
        //...
        printf("invoked\n");
        return method.invoke(sourceObj, args);
    }
}

class C
{
    void run() { printf("run\n"); }
}

void main()
{
    Proxy!(C) q;
    q.run();
}

output:
invoked
run

Mixins offer a lot of power towards achieving aspect-oriented programming,
but in many cases still require tight coupling.  Of course, we could make a
program that generated code on top of a D application from a configuration
file, but developers tend to want direct control themselves.

I tried to play around with using delegates with mixins and am having
trouble getting dynamic function calls.  If I do find a way, I'm sure it'll
be hackish.

The best I've done so far is to create an aspect that implements around()
advice.  The drawback to this method is that it requires you to define
through delegates every function which takes advice, explicity.  The whole
idea is to remove cross-cutting concerns.  And on top of that, this code
doesn't compile.  Something is "nested."

template AspectAround(alias wrapFunc)
{
    bool proceed = true;
    Object retVal;

    void around()
    {
        before();
        if (proceed) retVal = wrapFunc();
        after();
    }

    Object run()
    {
        around();
        return retVal;
    }
}

interface Hey
{
    public:
        void hey();
}

class C : Hey
{
    public:
        void hey() { aroundHey.run(); }
    private:
        void heyFunction() { printf("hey\n"); }
        mixin AspectAround!(delegate { heyFunction(); }) aroundHey;
}

void main()
{
    C c = new C();
    c.hey();
}
May 18 2004
parent "Walter" <newshound digitalmars.com> writes:
"Greg Vanore" <dazden at.dazden.dot.org> wrote in message
news:c8db93$18qp$1 digitaldaemon.com...
 The best I've done so far is to create an aspect that implements around()
 advice.  The drawback to this method is that it requires you to define
 through delegates every function which takes advice, explicity.  The whole
 idea is to remove cross-cutting concerns.  And on top of that, this code
 doesn't compile.  Something is "nested."

The trouble with the code is the compiler tries to form a delegate inside the class, but has no 'this' pointer. It should issue a proper diagnostic rather than an assert.
 template AspectAround(alias wrapFunc)
 {
     bool proceed = true;
     Object retVal;

     void around()
     {
         before();
         if (proceed) retVal = wrapFunc();
         after();
     }

     Object run()
     {
         around();
         return retVal;
     }
 }

 interface Hey
 {
     public:
         void hey();
 }

 class C : Hey
 {
     public:
         void hey() { aroundHey.run(); }
     private:
         void heyFunction() { printf("hey\n"); }
         mixin AspectAround!(delegate { heyFunction(); }) aroundHey;
 }

 void main()
 {
     C c = new C();
     c.hey();
 }

May 18 2004