www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Mixin Aspect-Orientation: Comments please!

reply Tony <tq tq.tq> writes:
Here is a quick outline of an idea of how the aspect-oriented programming
paradigm could be incorporated into D. What I’d like to propose is picking only
the most useful features of AOP while keeping D as lean as it is.
The big promise of AOP is the potential of keeping your code very clean even as
it grows by having your orthogonal concerns kept apart. The extensions to the
current D syntax that would be needed may not be that many:



Suppose you have this class:

class Foo
{
      int fun( int x )
      {
      }
}



Now let’s create some advice. Advice is code that is injected to handle some
specific concern. One reason complex programs easily become cluttered is that
they usually have many different concerns with little bits and pieces of them
everywhere. AOP solves this by abstracting concerns into separate units instead
of having each concern scattered all over the code. It’s a kind of modularity.


mixin template AdviceX()
{
      int fun( int x )
      scope( entry )
      {
      }
      scope( exit )
      {
      }
      scope( failure )
      {
            // undo changes here.
      }
      scope( success )( returnValue )
      {
            //  const access to return value.
      }
}


The new thing here would be the ability to append statements to the beginning
and end of a scope. By using the excellent scope construct different advice are
kept separate and yet well integrated with the rest of the code. Any exception
will be dealt with properly.


Here is how you would include the mixin advice:

class Foo
{
      mixin AdviceX;
      mixin AdviceY;

      int fun( int x )
      {
            // not replaced.
      }
}


The order in which the mixin advice are specified determines their nesting
order.


Please comment!
Jan 16 2011
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
You can already do that:

mixin template AdviceX() {
  int fun(int x) {
    ...
    return fun_without_advice();
  }
}

class Foo {
  mixin AdviceX;

  int fun_without_advice(int x) {
  }
}
Jan 16 2011
next sibling parent reply Tony <tq tq.tq> writes:
Hi, thanks for your reply but what you suggest is not enough.

With your solution you cannot add new advice without breaking stuff elsewhere.
You don't want to clutter the namespace with lots of new function names. What
you would want is to actually inject the code into the present functions.

What would make this even more modular is if you could use the mixin statement
outside of the scope that you want to inject into by specifying the location:
    mixin acme.nuclear.Lollipop SomeAdvice;

That way you could extend code without touching its source.

Tony



Ary Borenszweig Wrote:

 You can already do that:
 
 mixin template AdviceX() {
   int fun(int x) {
     ...
     return fun_without_advice();
   }
 }
 
 class Foo {
   mixin AdviceX;
 
   int fun_without_advice(int x) {
   }
 }

Jan 16 2011
parent Ary Borenszweig <ary esperanto.org.ar> writes:
Say you have this:

class Bar {
  int foo() { ... }
}

And you have your aspect-oriented mixin:

mixin template Aspect {
  int foo() { ... }
}

and you want to change foo's behaviour. You can't change Bar's
source code. How can you change Bar#foo's behaviour like that? At
least you have to put the "mixin Aspect!" somewhere. So that means
this approach for aspect oriented features doesn't work.

What I realized some days ago is that many people here (including me
:-P) try to get or have features from other languages, mostly
dynamic or "cool" languages, but that won't work here since
everything is statically compiled and determined once you compile
your code. So you can't later "inject" new funcionality, you can't
modify the funcionality of what it is compiled.
Jan 17 2011
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Tony <tq tq.tq> wrote:

 Hi, thanks for your reply but what you suggest is not enough.

 With your solution you cannot add new advice without breaking stuff  
 elsewhere. You don't want to clutter the namespace with lots of new  
 function names. What you would want is to actually inject the code into  
 the present functions.

 What would make this even more modular is if you could use the mixin  
 statement outside of the scope that you want to inject into by  
 specifying the location:
     mixin acme.nuclear.Lollipop SomeAdvice;

 That way you could extend code without touching its source.

D, by its static and compiled nature, does not support what you ask of it. :( There are however ways to do it. First thing that comes to my mind is a template that creates a subclass wherein member functions are wrapped in functions that mixin the wanted functionality. This functionality could then include function pointers or delegates that may be changed at runtime. -- Simen
Jan 17 2011